Commit a57f50d3 authored by Fabien Potencier's avatar Fabien Potencier

udpated docs

Replaced the term filter by middleware (so now, we have application
middlewares and route middlewares).

Middleware documentation has been moved to its own chapter. This is not
optimal yet as middleware are needed for some part of the usage chapter
(which comes first).
parent 8772cbca
Changelog
=========
* **2012-11-04**: Removing the default exception handler should now be done
* **2012-11-05**: Filters have been renamed to application middlewares in the
documentation.
* **2012-11-05**: The ``before()``, ``after()``, ``error()``, and ``finish()``
listener priorities now set the priority of the underlying Symfony event
instead of a custom one before.
* **2012-11-05**: Removing the default exception handler should now be done
via its ``disable()`` method:
Before:
......
......@@ -48,7 +48,7 @@ Parsing the request body
The request body should only be parsed as JSON if the ``Content-Type`` header
begins with ``application/json``. Since we want to do this for every request,
the easiest solution is to use a before filter.
the easiest solution is to use an application before middleware.
We simply use ``json_decode`` to parse the content of the request and then
replace the request data on the ``$request`` object::
......
......@@ -6,6 +6,7 @@ Silex
intro
usage
middlewares
services
providers
testing
......
......@@ -28,7 +28,7 @@ to hook into the Symfony2 `HttpKernel
<http://api.symfony.com/master/Symfony/Component/HttpKernel/HttpKernel.html>`_
events. This allows fetching the ``Request``, converting string responses into
``Response`` objects and handling Exceptions. We also use it to dispatch some
custom events like before/after filters and errors.
custom events like before/after middlewares and errors.
Controller
~~~~~~~~~~
......
Middlewares
===========
Silex allows you to run code, that changes the default Silex behavior, at
different stages during the handling of a request through *middlewares*:
* *Application middlewares* are triggered independently of the current handled
request;
* *Route middlewares* are triggered when their associated route is matched.
Application Middlewares
-----------------------
The application middlewares are 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) {
// ...
});
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::EARLY_EVENT);
Of course, 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 Middlewares
-----------------
Route middlewares are added to routes or route collections and they are 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 middlewares::
$before = function (Request $request) use ($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 middlewares::
$after = function (Request $request, Response $response) use ($app) {
// ...
};
$app->get('/somewhere', function () {
// ...
})
->after($after);
Middlewares Priority
--------------------
You can add as many middlewares 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 middlewares won't be run, neither the route
callback), and the Response is passed to the after middlewares 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::
If a before middleware does not return a Response or ``null``, a
``RuntimeException`` is thrown.
......@@ -183,7 +183,8 @@ don't want to mess with most of them.
$id = $app['request']->get('id');
This is only available when a request is being served, you can only access
it from within a controller, before filter, after filter or error handler.
it from within a controller, an application before/after middlewares, or an
error handler.
* **routes**: The `RouteCollection
<http://api.symfony.com/master/Symfony/Component/Routing/RouteCollection.html>`_
......
......@@ -383,112 +383,6 @@ really be used. You can give a route a name by calling ``bind`` on the
It only makes sense to name routes if you use providers that make use of
the ``RouteCollection``.
Before, after and finish filters
--------------------------------
Silex allows you to run code before, after every request and even after the
response has been sent. This happens through ``before``, ``after`` and
``finish`` filters. All you need to do is pass a closure::
$app->before(function () {
// set up
});
$app->after(function () {
// tear down
});
$app->finish(function () {
// after response has been sent
});
The before filter has access to the current Request, and can short-circuit the
whole rendering by returning a Response::
$app->before(function (Request $request) {
// redirect the user to the login screen if access to the Resource is protected
if (...) {
return new RedirectResponse('/login');
}
});
The after filter has access to the Request and the Response::
$app->after(function (Request $request, Response $response) {
// tweak the Response
});
The finish filter has access to the Request and the Response::
$app->finish(function (Request $request, Response $response) {
// send e-mails ...
});
.. note::
The filters are only run for the "master" Request.
Route middlewares
-----------------
Route middlewares are PHP callables which are triggered when their associated
route is matched:
* ``before`` middlewares are fired just before the route callback, but after
the application ``before`` filters;
* ``after`` middlewares are fired just after the route callback, but before
the application ``after`` filters.
This can be used for a lot of use cases; for instance, here is a simple
"anonymous/logged user" check::
$mustBeAnonymous = function (Request $request) use ($app) {
if ($app['session']->has('userId')) {
return $app->redirect('/user/logout');
}
};
$mustBeLogged = function (Request $request) use ($app) {
if (!$app['session']->has('userId')) {
return $app->redirect('/user/login');
}
};
$app->get('/user/subscribe', function () {
...
})
->before($mustBeAnonymous);
$app->get('/user/login', function () {
...
})
->before($mustBeAnonymous);
$app->get('/user/my-profile', function () {
...
})
->before($mustBeLogged);
The ``before`` and ``after`` methods can be called several times for a given
route, in which case they are triggered in the same order as you added them to
the route.
For convenience, the ``before`` middlewares are called with the current
``Request`` instance as an argument and the ``after`` middlewares are called
with the current ``Request`` and ``Response`` instance as arguments.
If any of the before middlewares returns a Symfony HTTP Response, it will
short-circuit the whole rendering: the next middlewares won't be run, neither
the route callback. You can also redirect to another page by returning a
redirect response, which you can create by calling the Application
``redirect`` method.
.. note::
If a before middleware does not return a Symfony HTTP Response or
``null``, a ``RuntimeException`` is thrown.
Global Configuration
--------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment