Middleware
Middleware používaj na spoločné HTTP pravidlá, pripájaj ho k routám alebo skupinám a nenechávaj v ňom business logiku.
Na čo middleware slúži
V Lemonade je middleware PSR-15 vrstva okolo spracovania HTTP requestu. Hodí sa na podmienky nad requestom, hlavičky, CSRF alebo kontrolu prístupu pred controllerom. Hranicu drž jasnú: middleware = spoločné HTTP správanie, controller = konkrétny HTTP use case a orchestration, service = aplikačné alebo business operácie. Kompletný príklad formulára s CSRF nájdeš vo Formulároch a POST spracovaní.
Pripoj middleware k route alebo skupine
Route middleware použi, keď jedno pravidlo potrebuje konkrétny endpoint. Group middleware sa hodí, keď rovnaké pravidlo zdieľa viac rout. V oboch prípadoch registruješ triedy menom a runtime ich načíta z containeru pred controllerom.
<?php
use App\Controllers\ArticleController;
use App\Controllers\ProfileController;
use App\Http\Middleware\RequirePreviewHeaderMiddleware;
use App\Http\Middleware\RequireProfileHeaderMiddleware;
use Lemonade\Framework\Routing\Router;
return static function (Router $router): void {
$router
->getNamed('articles.preview', '/articles/preview', ArticleController::class . '@preview')
->middleware(RequirePreviewHeaderMiddleware::class);
$router
->group('/profile', static function (Router $router): void {
$router->getNamed('profile.show', '', ProfileController::class . '@show');
$router->postNamed('profile.update', '/edit', ProfileController::class . '@update');
})
->middleware(RequireProfileHeaderMiddleware::class);
};Poradie a predčasné ukončenie
Middleware beží v poradí registrácie. Na poradí záleží, pretože jedna vrstva môže upraviť request, pridať hlavičky do response alebo pipeline ukončiť skôr. Volanie return $handler->handle($request); pošle request ďalej. Vlastná response naopak danú vetvu ukončí bez spustenia zvyšku pipeline.
<?php
use App\Http\Middleware\RequestIdMiddleware;
use Lemonade\Framework\Core\Context\ApplicationContextFactory;
use Lemonade\Framework\Core\KernelFactory;
use Lemonade\Framework\Http\Middleware\ErrorHandlingMiddleware;
use Lemonade\Framework\Http\Middleware\MiddlewareStack;
$context = (new ApplicationContextFactory())->fromGlobals(__DIR__);
$kernel = (new KernelFactory())->create($context);
$kernel->framework()->middleware(static function (MiddlewareStack $stack): void {
$stack->insertAfter(ErrorHandlingMiddleware::class, RequestIdMiddleware::class);
});
$kernel->handle();Napíš malý vlastný middleware
Vlastný middleware implementuje MiddlewareInterface a závislosti získava cez constructor injection. Drž ho malý a zameraný na HTTP. Keď začne riešiť persistenciu alebo znovupoužiteľnú business logiku, presuň ju do aplikačnej služby.
<?php
declare(strict_types=1);
namespace App\Http\Middleware;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
final class RequirePreviewHeaderMiddleware implements MiddlewareInterface
{
public function __construct(
private readonly ResponseFactoryInterface $responses,
) {}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if ($request->getHeaderLine('X-Preview-Mode') !== 'allow') {
return $this->responses->createResponse(403);
}
return $handler->handle($request);
}
}