Obsolète depuis la version 3.3.0: Depuis la version 3.3.0 , les Filtres de Dispatcher sont dépréciés. Vous devriez maintenant utiliser le Middleware à la place.
Il y a plusieurs raisons de vouloir exécuter un bout de code avant que tout code de controller ne soit lancé ou juste avant que la réponse ne soit envoyée au client, comme la mise en cache de la réponse, le tunning de header, une authentification spéciale ou juste pour fournir l’accès à une réponse de l’API critique plus rapidement qu’avec un cycle complet de dispatch de requêtes.
CakePHP fournit une interface propre et extensible pour de tels cas pour attacher les filtres au cycle de dispatch, de la même façon qu’une couche middleware pour fournir des services empilables ou des routines pour chaque requête. Nous les appelons Dispatcher Filters.
CakePHP fournit plusieurs filtres de dispatcher intégrés. Ils gèrent des fonctionnalités habituelles dont toutes les applications vont avoir besoin. Les filtres intégrés sont:
AssetFilter
vérifie si la requête fait référence au fichier d’asset de
plugin ou du theme, comme un fichier CSS, un fichier JavaScript ou une image
stockée soit dans le dossier webroot d’un plugin ou celui qui correspond pour
un Theme. Il va servir le fichier correspondant s’il est trouvé, stoppant le
reste du cycle de dispatch:
// Utilisez options pour définir le cacheTime de vos assets statiques
// S'il n'est pas défini, il est de 1 heure (+1 hour) par défaut.
DispatcherFactory::add('Asset', ['cacheTime' => '+24 hours']);
RoutingFilter
applique les règles de routing de l’application pour l’URL
de la requête. Remplit $request->getParam()
avec les résultats de routing.
ControllerFactory
utilise $request->getParam()
pour localiser le
controller qui gère la requête courante.
LocaleSelector
active le langage automatiquement en changeant le header
Accept-Language
envoyé par le navigateur.
Les filtres sont habituellement activés dans le fichier bootstrap.php de
votre application, mais vous pouvez les charger à n’importe quel moment avant
que la requête ne soit dispatchée. Ajouter et retirer les filtres se fait avec
Cake\Routing\DispatcherFactory
. Par défaut, le template d’une
application CakePHP est fourni avec un couple de classes filter déjà activées
pour toutes les requêtes; Regardons la façon dont elles sont ajoutées:
DispatcherFactory::add('Routing');
DispatcherFactory::add('ControllerFactory');
// La syntaxe de plugin est aussi possible
DispatcherFactory::add('PluginName.DispatcherName');
// Utilisez les options pour définir la priorité
DispatcherFactory::add('Asset', ['priority' => 1]);
Les filtres Dispatcher avec une priorité priority
supérieure (nombres les
plus faibles) - seront exécutés les premiers. La priorité est par défaut à
10
.
Alors qu’utiliser le nom de la chaîne est pratique, vous pouvez aussi passer les
instances dans add()
:
use Cake\Routing\Filter\RoutingFilter;
DispatcherFactory::add(new RoutingFilter());
Lors de l’ajout de filtres, vous pouvez contrôler l’ordre dans lequel ils sont
appelés en utilisant les priorités du gestionnaire d’event. Alors que les
filtres peuvent définir une priorité par défaut en utilisant la propriété
$_priority
, vous pouvez définir une priorité spécifique quand vous attachez
le filtre:
DispatcherFactory::add('Asset', ['priority' => 1]);
DispatcherFactory::add(new AssetFilter(['priority' => 1]));
Plus la priorité est haute, plus le filtre sera appelé tardivement.
Si vous ne voulez pas exécuter un filtre sur chaque requête, vous pouvez
utiliser des conditions pour les appliquer seulement certaines fois. Vous
pouvez appliquer les conditions en utilisant les options for
et when
.
L’option for
vous laisse faire la correspondance sur des sous-chaines d’URL,
alors que l’option when
vous permet de lancer un callable:
// Only runs on requests starting with `/blog`
DispatcherFactory::add('BlogHeader', ['for' => '/blog']);
// Only run on GET requests.
DispatcherFactory::add('Cache', [
'when' => function ($request, $response) {
return $request->is('get');
}
]);
The callable provided to when
should return true
when the filter should
run. The callable can expect to get the current request and response as
arguments.
Pour créer un filtre, définissez une classe dans src/Routing/Filter. Dans cet exemple, nous allons créer un filtre qui ajoute un cookie de tracking pour la page d’accueil. Premièrement, créez le fichier. Son contenu doit ressembler à ceci:
namespace App\Routing\Filter;
use Cake\Event\Event;
use Cake\Routing\DispatcherFilter;
class TrackingCookieFilter extends DispatcherFilter
{
public function beforeDispatch(Event $event)
{
$request = $event->getData('request');
$response = $event->getData('response');
if (!$request->getCookie('landing_page')) {
$response->cookie([
'name' => 'landing_page',
'value' => $request->here(),
'expire' => '+ 1 year',
]);
}
}
}
Enregistrez ce fichier sous src/Routing/Filter/TrackingCookieFilter.php. Comme vous pouvez le voir, à l’image des autres classes dans CakePHP, les filtres de dispatcher suivent quelques conventions:
Les noms de classes finissent par Filter
.
Les classes sont dans le namespace Routing\\Filter
. Par exemple,
App\\Routing\\Filter
.
Généralement, les filtres étendent Cake\\Routing\\DispatcherFilter
.
DispatcherFilter
expose deux méthodes qui peuvent être surchargées dans les
sous-classes qui sont beforeDispatch()
et afterDispatch()
. Ces méthodes
sont exécutées respectivement avant et après l’exécution de tout controller.
les deux méthodes reçoivent un objet Cake\Event\Event
contenant
les objets ServerRequest
et Response
(instances de Cake\Http\ServerRequest
et
Cake\Http\Response
) dans la propriété data
.
Alors que notre filtre était relativement simple, il y a quelques autres choses
intéressantes que nous pouvons réaliser dans les méthodes de filtre. En
renvoyant un objet Response
, vous pouvez court-circuiter le process de
dispatch et empêcher le controller d’être appelé. Lorsque vous renvoyez une
response, n’oubliez pas d’appeler $event->stopPropagation()
pour que les
autres filtres ne soient pas appelés.
Note
Lorsque la méthode beforeDispatch renvoie une response, le controller, et l’event afterDispatch ne seront pas appelés.
Créons maintenant un autre filtre pour modifier l’en-tête de response de
n’importe quelle page publique, dans notre cas ce serait tout ce qui est
servi depuis le PagesController
:
namespace App\Routing\Filter;
use Cake\Event\Event;
use Cake\Routing\DispatcherFilter;
class HttpCacheFilter extends DispatcherFilter
{
public function afterDispatch(Event $event)
{
$request = $event->getData('request');
$response = $event->getData('response');
if ($response->statusCode() === 200) {
$response->sharable(true);
$response->expires(strtotime('+1 day'));
}
}
}
// Dans notre bootstrap.php
DispatcherFactory::add('HttpCache', ['for' => '/pages'])
Ce filtre enverra un en-tête d’expiration pour 1 jour dans le futur pour toutes
responses produites pour le controller pages. Vous pourriez bien entendu faire
la même chose dans un controller, ce n’est qu’un exemple de ce qui peut être
réalisé avec les filtres. Par exemple, au lieu d’altérer la response, vous
pourriez la mettre en cache en utilisant Cake\Cache\Cache
en
servant la response depuis le callback beforeDispatch()
.
Bien que très puissants, les filtres du dispatcher peuvent également compliquer la maintenance de votre application. Les filtres sont des outils extrêmement puissants lorsqu’ils sont utilisés sagement et ajouter des gestionnaires de responses pour chaque URL dans votre application n’est pas une bonne utilisation. Gardez à l’esprit que tout n’a pas besoin d’être un filtre; Les Controllers et les Components sont souvent un choix plus précis pour ajouter tout code de gestionnaire de requête à votre application.