Middleware
Middleware používej pro společná HTTP pravidla, připojuj ho k routám nebo skupinám a nenechávej v něm business logiku.
K čemu middleware slouží
V Lemonade je middleware PSR-15 vrstva kolem zpracování HTTP requestu. Hodí se pro podmínky nad requestem, hlavičky, CSRF nebo kontrolu přístupu před controllerem. Hranici drž jasnou: middleware = společné HTTP chování, controller = konkrétní HTTP use case a orchestrace, service = aplikační nebo business operace. Pro kompletní příklad formuláře s CSRF pokračuj na Formuláře a POST zpracování.
Připoj middleware k routě nebo skupině
Route middleware použij, když jedno pravidlo potřebuje konkrétní endpoint. Group middleware se hodí, když stejné pravidlo sdílí více rout. V obou případech registruješ třídy jménem a runtime je načte z containeru před controllerem.
<?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);
};Pořadí a předčasné ukončení
Middleware běží v pořadí registrace. Na pořadí záleží, protože jedna vrstva může upravit request, přidat hlavičky do response nebo pipeline ukončit dřív. Volání return $handler->handle($request); pošle request dál. Vlastní response naopak danou větev ukončí bez spuštění zbytku 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();Napiš malý vlastní middleware
Vlastní middleware implementuje MiddlewareInterface a závislosti získává přes constructor injection. Drž ho malý a čistě zaměřený na HTTP. Jakmile začne řešit persistenci nebo znovupoužitelnou business logiku, přesuň ji do aplikační 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);
}
}