163 lines
4.3 KiB
ReStructuredText
163 lines
4.3 KiB
ReStructuredText
|
Middleware
|
||
|
==========
|
||
|
|
||
|
Silex allows you to run code, that changes the default Silex behavior, at
|
||
|
different stages during the handling of a request through *middleware*:
|
||
|
|
||
|
* *Application middleware* is triggered independently of the current handled
|
||
|
request;
|
||
|
|
||
|
* *Route middleware* is triggered when its associated route is matched.
|
||
|
|
||
|
Application Middleware
|
||
|
----------------------
|
||
|
|
||
|
Application middleware is only run for the "master" Request.
|
||
|
|
||
|
Before Middleware
|
||
|
~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
A *before* application middleware allows you to tweak the Request before the
|
||
|
controller is executed::
|
||
|
|
||
|
$app->before(function (Request $request, Application $app) {
|
||
|
// ...
|
||
|
});
|
||
|
|
||
|
By default, the middleware is run after the routing and the security.
|
||
|
|
||
|
If you want your middleware to be run even if an exception is thrown early on
|
||
|
(on a 404 or 403 error for instance), then, you need to register it as an
|
||
|
early event::
|
||
|
|
||
|
$app->before(function (Request $request, Application $app) {
|
||
|
// ...
|
||
|
}, Application::EARLY_EVENT);
|
||
|
|
||
|
In this case, the routing and the security won't have been executed, and so you
|
||
|
won't have access to the locale, the current route, or the security user.
|
||
|
|
||
|
.. note::
|
||
|
|
||
|
The before middleware is an event registered on the Symfony *request*
|
||
|
event.
|
||
|
|
||
|
After Middleware
|
||
|
~~~~~~~~~~~~~~~~
|
||
|
|
||
|
An *after* application middleware allows you to tweak the Response before it
|
||
|
is sent to the client::
|
||
|
|
||
|
$app->after(function (Request $request, Response $response) {
|
||
|
// ...
|
||
|
});
|
||
|
|
||
|
.. note::
|
||
|
|
||
|
The after middleware is an event registered on the Symfony *response*
|
||
|
event.
|
||
|
|
||
|
Finish Middleware
|
||
|
~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
A *finish* application middleware allows you to execute tasks after the
|
||
|
Response has been sent to the client (like sending emails or logging)::
|
||
|
|
||
|
$app->finish(function (Request $request, Response $response) {
|
||
|
// ...
|
||
|
// Warning: modifications to the Request or Response will be ignored
|
||
|
});
|
||
|
|
||
|
.. note::
|
||
|
|
||
|
The finish middleware is an event registered on the Symfony *terminate*
|
||
|
event.
|
||
|
|
||
|
Route Middleware
|
||
|
----------------
|
||
|
|
||
|
Route middleware is added to routes or route collections and it is only
|
||
|
triggered when the corresponding route is matched. You can also stack them::
|
||
|
|
||
|
$app->get('/somewhere', function () {
|
||
|
// ...
|
||
|
})
|
||
|
->before($before1)
|
||
|
->before($before2)
|
||
|
->after($after1)
|
||
|
->after($after2)
|
||
|
;
|
||
|
|
||
|
Before Middleware
|
||
|
~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
A *before* route middleware is fired just before the route callback, but after
|
||
|
the *before* application middleware::
|
||
|
|
||
|
$before = function (Request $request, Application $app) {
|
||
|
// ...
|
||
|
};
|
||
|
|
||
|
$app->get('/somewhere', function () {
|
||
|
// ...
|
||
|
})
|
||
|
->before($before);
|
||
|
|
||
|
After Middleware
|
||
|
~~~~~~~~~~~~~~~~
|
||
|
|
||
|
An *after* route middleware is fired just after the route callback, but before
|
||
|
the application *after* application middleware::
|
||
|
|
||
|
$after = function (Request $request, Response $response, Application $app) {
|
||
|
// ...
|
||
|
};
|
||
|
|
||
|
$app->get('/somewhere', function () {
|
||
|
// ...
|
||
|
})
|
||
|
->after($after);
|
||
|
|
||
|
Middleware Priority
|
||
|
-------------------
|
||
|
|
||
|
You can add as much middleware as you want, in which case they are triggered
|
||
|
in the same order as you added them.
|
||
|
|
||
|
You can explicitly control the priority of your middleware by passing an
|
||
|
additional argument to the registration methods::
|
||
|
|
||
|
$app->before(function (Request $request) {
|
||
|
// ...
|
||
|
}, 32);
|
||
|
|
||
|
As a convenience, two constants allow you to register an event as early as
|
||
|
possible or as late as possible::
|
||
|
|
||
|
$app->before(function (Request $request) {
|
||
|
// ...
|
||
|
}, Application::EARLY_EVENT);
|
||
|
|
||
|
$app->before(function (Request $request) {
|
||
|
// ...
|
||
|
}, Application::LATE_EVENT);
|
||
|
|
||
|
Short-circuiting the Controller
|
||
|
-------------------------------
|
||
|
|
||
|
If a *before* middleware returns a ``Response`` object, the request handling is
|
||
|
short-circuited (the next middleware won't be run, nor the route
|
||
|
callback), and the Response is passed to the *after* middleware right away::
|
||
|
|
||
|
$app->before(function (Request $request) {
|
||
|
// redirect the user to the login screen if access to the Resource is protected
|
||
|
if (...) {
|
||
|
return new RedirectResponse('/login');
|
||
|
}
|
||
|
});
|
||
|
|
||
|
.. note::
|
||
|
|
||
|
A ``RuntimeException`` is thrown if a before middleware does not return a
|
||
|
Response or ``null``.
|