Documentation menu
On this page
Components · v1.x
Middleware
A middleware runs before and after the controller. It can modify the request, return a response without calling the controller, or modify the response. Middlewares are global (every request) or attached to routes, and are referenced by class, alias or group.
Writing a middleware
<?php
declare(strict_types=1);
namespace App\Middleware;
use NeoPHP\Component\Http\Request\Request;
use NeoPHP\Component\Http\Response\RedirectResponse;
use NeoPHP\Component\Http\Response\Response;
use NeoPHP\Component\Middleware\Attribute\AsMiddleware;
use NeoPHP\Component\Middleware\Contract\MiddlewareInterface;
use NeoPHP\Component\Middleware\Contract\RequestHandlerInterface;
use NeoPHP\Component\Session\Contract\SessionInterface;
#[AsMiddleware(name: 'auth')]
class AuthMiddleware implements MiddlewareInterface
{
public function __construct(protected SessionInterface $session)
{
}
public function process(Request $request, RequestHandlerInterface $handler): Response
{
if (!$this->session->has('user_id')) {
return new RedirectResponse('/login');
}
$response = $handler->handle($request);
$response->setHeader('Cache-Control', 'no-store');
return $response;
}
}
The interfaces mirror PSR-15 without dependency:
| Interface | Method |
|---|---|
Contract\MiddlewareInterface |
process(Request $request, RequestHandlerInterface $handler): Response |
Contract\RequestHandlerInterface |
handle(Request $request): Response (calls the next middleware, then the controller) |
Middlewares are built by the container: their dependencies are autowired (see the Container documentation). A class that does not implement MiddlewareInterface throws a MiddlewareException.
Global middlewares
Global middlewares run on every request, before the routing (they also run for a 404).
config/framework/middleware.yaml
global:
- App\Middleware\MaintenanceMiddleware
aliases:
auth: App\Middleware\AuthMiddleware
groups:
admin: [auth, App\Middleware\AdminMiddleware]
| Key | Description |
|---|---|
global |
middlewares (classes, aliases or groups) run on every request, in this order |
aliases |
short name => class |
groups |
name => list of middlewares (classes, aliases or other groups) |
A middleware can also declare itself with #[AsMiddleware], discovered in src/:
| Argument | Default | Description |
|---|---|---|
name |
null |
alias of the middleware (auth) |
global |
false |
runs the middleware on every request |
priority |
0 |
order of the global middlewares declared with the attribute (highest first) |
#[AsMiddleware(global: true, priority: 10)]
class MaintenanceMiddleware implements MiddlewareInterface
The global middlewares of middleware.yaml run first, in their order, then the global middlewares declared with #[AsMiddleware]. An alias of middleware.yaml wins over an alias declared with the attribute. The discovery is cached in var/cache/middleware/ (rebuilt in debug when a file of src/ changes).
Aliases and groups
A middleware is referenced by its alias, a group or its class name, everywhere: global, groups, routes and attributes. A group is expanded into its middlewares, recursively; a group that contains itself throws a MiddlewareException.
Route middlewares
With the #[Middleware] attribute, on the controller class or on an action (repeatable, variadic):
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Middleware\TwoFactorMiddleware;
use NeoPHP\Component\Controller\Contract\AbstractController;
use NeoPHP\Component\Http\Response\Response;
use NeoPHP\Component\Middleware\Attribute\Middleware;
use NeoPHP\Component\Routing\Attribute\Route;
#[Middleware('auth')]
class AdminController extends AbstractController
{
#[Route('/admin/users', name: 'admin_users', middlewares: ['audit'])]
#[Middleware('admin', TwoFactorMiddleware::class)]
public function users(): Response
{
return $this->render('admin/users');
}
}
With the middlewares option of #[Route] or of config/routes.yaml (see the Routing documentation):
admin:
resource: ../src/Admin/Controller/
type: attribute
prefix: /admin
middlewares: [admin]
legacy:
path: /legacy
controller: App\Controller\LegacyController::index
middlewares: [auth]
Order of execution
- global middlewares of
middleware.yaml - global middlewares declared with
#[AsMiddleware(global: true)] middlewaresof the YAML import, then of the YAML routemiddlewaresof#[Route]on the class, then on the method#[Middleware]on the class, then on the method- the controller
A middleware is never run twice: a middleware already global is ignored on the route, and a middleware listed twice runs once. An unknown alias throws a MiddlewareException.
Listing middlewares
php bin/neo middleware:list
Displays the global middlewares in their order, the aliases and the groups.
API
NeoPHP\Component\Middleware\Contract\MiddlewareManagerInterface (service, also aliased as MiddlewareManager):
| Method | Description |
|---|---|
handle(Request $request, array $middlewares, callable $handler): Response |
runs the middlewares, then $handler(Request): Response |
resolve(array $middlewares): array |
expands aliases and groups into unique class names |
getGlobal(): array |
classes of the global middlewares |
forController(mixed $controller, array $middlewares = []): array |
classes of the route middlewares: $middlewares then the #[Middleware] attributes of the controller, without the global ones |
addAlias(string $name, string $class): static |
adds an alias |
addGroup(string $name, array $middlewares): static |
adds a group |
addGlobal(string $middleware): static |
adds a global middleware |
getAliases(): array |
name => class |
getGroups(): array |
name => middlewares |
MiddlewareManager::__construct(?ContainerInterface $container = null, array $global = [], array $aliases = [], array $groups = []).
Other classes:
| Class | Description |
|---|---|
Pipeline\Pipeline |
RequestHandlerInterface running a list of middleware classes: __construct(array $middlewares, callable $handler, callable $resolver) |
Discovery\MiddlewareDiscovery |
__construct(array $paths), discover(): array (['aliases' => [...], 'global' => [...]]), getResources() |
Exceptions
NeoPHP\Component\Middleware\Exception\MiddlewareException extends FrameworkException. It is thrown for an unknown middleware, a class that does not implement MiddlewareInterface, or a circular group.
Changelog
- v1.7.0 — Middlewares: PSR-15 style interfaces, global middlewares (
middleware.yaml,#[AsMiddleware]), aliases and groups, route middlewares (#[Middleware],#[Route(middlewares)],routes.yaml),middleware:listcommand.