laminas/laminas-httphandlerrunner
Executes PSR-15 HTTP request handlers by bridging PSR-7 requests/responses with common PHP runtimes. Provides runners for SAPI and other environments, simplifying bootstrap, emitting responses, and integrating middleware/handler apps in Laminas or any PSR stack.
## Getting Started
### Minimal Setup
1. **Installation** (PHP 8.5 compatible):
```bash
composer require laminas/laminas-httphandlerrunner:^2.13
Add to composer.json under require if not using autoloader.
First Use Case (PHP 8.5 syntax compatible):
use Laminas\HttpHandlerRunner\Emitter\SapiEmitter;
use Laminas\HttpHandlerRunner\RequestHandlerRunner;
use Laminas\Diactoros\Response;
use Laminas\Diactoros\ServerRequestFactory;
// Create a request from globals
$request = ServerRequestFactory::fromGlobals();
// Create a simple handler (PHP 8.5 compatible)
$handler = static fn (\Psr\Http\Message\ServerRequestInterface $request) => new Response('Hello, World!');
// Run the handler and emit
$runner = new RequestHandlerRunner($handler);
$response = $runner($request);
$emitter = new SapiEmitter();
$emitter->emit($response);
Where to Look First:
Laminas\HttpHandlerRunner\RequestHandlerRunner for core execution logic.Laminas\HttpHandlerRunner\Emitter interfaces for response emission.Leverage RequestHandlerRunner with modern PHP syntax:
use Laminas\HttpHandlerRunner\RequestHandlerRunner;
$middlewareStack = [
static fn (\Psr\Http\Message\ServerRequestInterface $request, callable $next) => $next($request),
static fn (\Psr\Http\Message\ServerRequestInterface $request, callable $next) => $next($request),
];
$runner = new RequestHandlerRunner($middlewareStack);
$response = $runner($request);
Use in Laravel middleware with type safety:
// app/Http/Middleware/ExampleMiddleware.php
public function handle(
ServerRequestInterface $request,
Closure $next
): ResponseInterface {
$runner = new RequestHandlerRunner($next);
return $runner($request);
}
Extend with modern attributes:
#[Attribute]
class CustomEmitter implements EmitterInterface {
public function emit(ResponseInterface $response): void {
// Custom logic
}
}
Register with modern container syntax:
// app/Providers/AppServiceProvider.php
$this->app->bind(RequestHandlerRunner::class, function () {
return new RequestHandlerRunner($this->app->make(RequestHandlerInterface::class));
});
PHP 8.5 Breaking Changes:
array() constructor syntax is now discouraged. Use [] instead.static fn syntax is now fully supported for handlers.Response Emission:
$emitter = new SapiEmitter();
$emitter->emit($response);
Middleware Order:
array_unshift() behavior is preserved. Reverse arrays explicitly:
$middlewareStack = array_reverse($stack);
$body = $response->getBody()->getContents();
\Log::debug('Response', ['body' => $body, 'status' => $response->getStatusCode()]);
Custom Error Handling (PHP 8.5):
class CustomRunner extends RequestHandlerRunner {
public function __invoke(ServerRequestInterface $request): ResponseInterface {
return match (true) {
$request->getMethod() === 'HEAD' => new Response('', 200, [], false),
default => parent::__invoke($request),
};
}
}
Async Support (PHP 8.5):
$loop = React\EventLoop\Factory::create();
$reactEmitter = new ReactEmitter($loop);
$reactEmitter->emit($response);
$loop->run();
Testing (PHP 8.5):
$this->expectException(InvalidArgumentException::class);
$runner(new class implements RequestHandlerInterface {
public function __invoke(ServerRequestInterface $request): ResponseInterface {
throw new InvalidArgumentException();
}
});
SapiEmitter now defaults to strict type checking. Disable with:
$emitter = new SapiEmitter(['strict_types' => false]);
UPGRADE.md with PHP 8.5 migration notes.
NO_UPDATE_NEEDED would not apply here as the PHP 8.5 compatibility update warrants significant adjustments to the assessment.
How can I help you explore Laravel packages today?