composer require carthage-software/elissa-bundle and enable the bundle in config/bundles.php.use Psr\Http\Message\RequestFactoryInterface;
public function __construct(private RequestFactoryInterface $requestFactory) {}
app/src/Handler/MyHandler.php) and tag it as a controller in Symfony’s DI container:
# config/services.yaml
services:
App\Handler\MyHandler:
tags: ['controller']
StreamFactoryInterface, ResponseFactoryInterface).kernel.middleware config or as services tagged kernel.middleware.controller and use them like Symfony controllers.public function createRequest(string $method, string $uri): ServerRequestInterface {
$request = $this->requestFactory->createServerRequest($method, $uri);
return $request->withHeader('X-Custom', 'Value');
}
// src/Handler/MyHandler.php
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
final class MyHandler implements RequestHandlerInterface {
public function handle(ServerRequestInterface $request): ResponseInterface {
return new ResponseFactory()->createResponse(200)
->withBody($this->streamFactory->createStream('Hello, PSR-15!'));
}
}
any: /api/hello App\Handler\MyHandler).# config/packages/framework.yaml
framework:
http_client:
middleware:
- CarthageSoftware\ElissaBundle\Middleware\MyMiddleware
brick/varnish).StreamFactoryInterface to create streams from strings, files, or resources.$stream = $this->streamFactory->createStream('{"key": "value"}');
$response = $this->responseFactory->createResponse(200)->withBody($stream);
UploadedFileFactoryInterface.$uploadedFile = $this->uploadedFileFactory->createUploadedFile(
$_FILES['file']['tmp_name'],
$_FILES['file']['name'],
$_FILES['file']['type'],
$_FILES['file']['size'],
$_FILES['file']['error']
);
Middleware Order Matters:
kernel.middleware runs before Symfony’s built-in middleware. Use framework.http_client.middleware for HTTP client middleware or framework.middleware for global middleware.config/packages/framework.yaml:
framework:
middleware: [MyMiddleware, AnotherMiddleware]
PSR-15 Handlers vs. Symfony Controllers:
Request or Response objects. Use PSR-7 factories instead.ServerRequestFactoryInterface and ResponseFactoryInterface into handlers.Stream Detachment:
$stream->detach(); // Call this when done with the stream.
UploadedFile Limitations:
UploadedFileFactoryInterface works with $_FILES data. For custom uploads (e.g., from S3), create a Psr\Http\Message\UploadedFileInterface manually or use a library like league/glide.Caching Factories:
Middleware Debugging:
debug:router and debug:container commands to verify middleware tags and services.php bin/console debug:container CarthageSoftware\ElissaBundle\Middleware\MyMiddleware
Handler Resolution:
controller and are autowired. Use:
php bin/console debug:container --tag=controller
Stream Issues:
RuntimeExceptions. Use StreamInterface::isWritable() to verify stream state.Custom Factories:
config/services.yaml:
services:
Psr\Http\Message\StreamFactoryInterface: '@App\Factory\CustomStreamFactory'
Middleware Decorators:
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
final class LoggingMiddleware implements MiddlewareInterface {
public function __construct(private MiddlewareInterface $decorated) {}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
// Log request
return $this->decorated->process($request, $handler);
}
}
services.yaml:
services:
App\Middleware\LoggingMiddleware:
decorates: 'some.middleware'
arguments: ['@.inner']
Event Listeners:
kernel.request and kernel.response events to inspect/modify PSR-7 messages:
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
$eventDispatcher->addListener(KernelEvents::REQUEST, function (RequestEvent $event) {
$request = $event->getRequest();
if ($request instanceof ServerRequestInterface) {
// Modify PSR-7 request
}
});
Testing:
Nyholm\Psr7\Factory\Psr17Factory for testing PSR-7 objects:
use Nyholm\Psr7\Factory\Psr17Factory;
$factory = new Psr17Factory();
$request = $factory->createServerRequest('GET', '/test');
$this->mockBuilder()
->disableOriginalCloneMethods()
->getMockBuilder(StreamFactoryInterface::class)
->addMethods(['createStream'])
->getMock();
How can I help you explore Laravel packages today?