Si vous avez suivi mes précédents articles de blog sur Laravel 5.0, vous avez peut-être remarqué que les filtres de route ont d’abord été déplacés pour devenir leur propre répertoire et structure de classe, puis ils ont finalement mystérieusement disparu. Vous avez peut-être même remarqué que des références au middleware apparaissaient à leur place.
L’ajout d’intergiciels personnalisés à votre application Laravel existe depuis un certain temps. Pour une excellente introduction au middleware et au fonctionnement du middleware dans Laravel 4.1, consultez le middleware HTTP de Chris Fidao dans Laravel 4.1.
REMARQUE : les filtres existent toujours dans la base de code, vous peut les utilisez toujours, mais le middleware devient la pratique et la façon de penser préférées pour décorer vos itinéraires.
Qu’est-ce qu’un middleware ?
Le middleware est en fait un peu difficile. Jetez un œil au graphique ci-dessous, de StackPHP. Si votre application (votre routage, vos contrôleurs, votre logique métier) est le cercle vert au centre, vous pouvez voir que la demande de l’utilisateur passe par plusieurs couches de middleware, atteint votre application, puis passe par d’autres couches de middleware. Tout middleware donné peut fonctionner avant la logique d’application, après celle-ci ou les deux.
Donc, le middleware est une série d’encapsuleurs autour de votre application qui décorent les requêtes et les réponses d’une manière qui ne fait pas partie de la logique de votre application.
(attribution de l’image StackPHP.com)
La façon dont cela fonctionne est que le middleware implémente un modèle de décorateur : il prend la requête, fait quelque chose et renvoie un autre objet de requête à la couche suivante de la pile.
Laravel utilise un middleware par défaut pour gérer le chiffrement/déchiffrement et la mise en file d’attente des cookies, ainsi que les sessions de lecture et d’écriture, mais vous pouvez également l’utiliser pour ajouter n’importe quel type de couche que vous souhaitez à votre cycle de requête/réponse : limitation du débit, analyse personnalisée des requêtes, et beaucoup plus.
Comment écrire un middleware ?
artisan make:middleware MyMiddleware
Cela générera un simple fichier middleware :
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Routing\Middleware;
class MyMiddleware implements Middleware {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
//
}
}
Comme vous pouvez le voir, la base de tout middleware est la handle
méthode, qui prend deux paramètres : $request
qui est un objet Illuminate Request, et $next
qui est une fermeture (fonction anonyme) qui exécute la requête dans le reste de la pile middleware.
Vous souvenez-vous de mon exemple absurde d’un objet ValidatesWhenResolved qui bloque les ports de requête impairs ? Eh bien, nous le ramenons, à la manière d’un middleware.
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Routing\Middleware;
class MyMiddleware implements Middleware {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// Test for an even vs. odd remote port
if (($request->server->get('REMOTE_PORT') / 2) % 2 > 0)
{
throw new \Exception("WE DON'T LIKE ODD REMOTE PORTS");
}
return $next($request);
}
}
Comment utiliser le middleware ?
Il existe deux façons principales de lier le middleware dans Laravel 5. Les deux commencent par App\Http\Kernel
.
Vous remarquerez que ce nouveau Kernel
classe a deux propriétés : $middleware
et $routeMiddleware
. Les deux sont des tableaux de middleware ; les intergiciels dans $middleware
exécuter sur chaque demande et les middlewares dans $routeMiddleware
doivent être activés.
Au moment d’écrire ces lignes, cinq middlewares s’exécutent par défaut :
protected $middleware = [
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
'Illuminate\Cookie\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken',
];
et trois sont disponibles en option :
protected $routeMiddleware = [
'auth' = 'App\Http\Middleware\Authenticate',
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'guest' => 'App\Http\Middleware\RedirectIfAuthenticated',
];
Comme vous pouvez le voir, les routes facultatives disponibles par défaut sont les mêmes que les filtres qui étaient facultatifs par défaut, sauf que – ce qui est important – la protection CSRF a maintenant été activée par défaut pour Al itinéraires..
Exécution du middleware à chaque requête
Alors, commençons par exécuter notre middleware à chaque requête. Ajoutez-le simplement à $middleware
:
protected $middleware = [
'App\Http\Middleware\MyMiddleware',
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
'Illuminate\Cookie\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken',
];
… et maintenant il fonctionnera à chaque requête.
Exécution de middleware sur des routes spécifiques
OK, maintenant déplaçons notre middleware personnalisé vers la pile optionnelle, avec une clé :
protected $routeMiddleware = [
'auth' = 'App\Http\Middleware\Authenticate',
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'guest' => 'App\Http\Middleware\RedirectIfAuthenticated',
'absurd' => 'App\Http\Middleware\MyMiddleware',
];
Et maintenant nous pouvons l’appliquer en utilisant le $this->middleware()
méthode sur la base Controller
ou dans routes.php
.
Annotation de route middleware (supprimée)
Remarque : les annotations ne font plus partie du cœur de Laravel 5, de sorte que l’annotation de route middleware n’est plus prise en charge sans l’utilisation d’un package externe.
Vous pouvez annoter un contrôleur ou une route pour utiliser un middleware spécifique :
/**
* @Resource("foobar/photos")
* @Middleware("auth")
* @Middleware("absurd", except={"update"})
* @Middleware("csrf", only={"index"})
*/
class FoobarPhotosController
{}
Vous pouvez annoter une seule méthode de contrôleur :
/**
* @Middleware("auth.basic")
*/
public function index() {}
$this->intergiciel()
Ou, vous pouvez utiliser le $this->middleware()
méthode sur n’importe quel contrôleur (ou ses méthodes) si le contrôleur étend le contrôleur de base :
...
use Illuminate\Routing\Controller;
class AwesomeController extends Controller {
public function __construct()
{
$this->middleware('csrf');
$this->middleware('auth', ['only' => 'update'])
}
}
Ajout de middleware dans routes.php
Vous pouvez également affecter un middleware à exécuter sur une route dans routes.php
:
// Routes.php
// Single route
$router->get("/awesome/sauce", "AwesomeController@sauce", ['middleware' => 'auth']);
// Route group
$router->group(['middleware' => 'auth'], function() {
// lots of routes that require auth middleware
});
Comment puis-je mettre en œuvre avant contre. après des filtres dans le middleware ?
Il m’a fallu une minute pour suivre cela, mais Taylor a souligné que la différence entre un middleware “avant” et un middleware “après” est basée sur le fait que l’action du middleware se produise avant ou après le demande c’est passé :
...
class BeforeMiddleware implements Middleware {
public function handle($request, Closure $next)
{
// Do Stuff
return $next($request);
}
}
...
class AfterMiddleware implements Middleware {
public function handle($request, Closure $next)
{
$response = $next($request);
// Do stuff
return $response;
}
}
Comme vous pouvez le voir, le middleware avant fonctionne et alors transmet la demande. Le middleware après, quant à lui, permet de traiter la requête, et alors opère dessus.
01000011 01101111 01101110 01100011 01101100 01110101 01110011 01101001 01101111 01101110
Si vous n’êtes pas familier avec cela, cela peut prendre une minute pour comprendre le concept de middleware. Les filtres sont un peu plus faciles à dépasser de notre réflexion normale sur les demandes de route du contrôleur. Mais le middleware – le concept de la pile qui ne transmet qu’une requête, lui permettant d’être décorée pièce par pièce – est plus propre, plus simple et plus flexible.
Non seulement cela, mais le middleware n’est qu’une autre façon de travailler avec votre demande d’une manière qui est à la fois puissamment efficace dans vos applications Laravel, mais joue bien ailleurs. La syntaxe du middleware Laravel 5.0 n’est pas à la perfection compatible avec la syntaxe StackPHP, mais si vous structurez votre pile de requêtes/réponses le long de la structure organisationnelle des middlewares, c’est un travail supplémentaire dans le sens de la séparation des préoccupations – et la modification d’un middleware Laravel pour qu’il fonctionne dans une syntaxe distincte de style StackPHP, serait prendre un minimum d’effort.
Des questions? Commentaires? Je suis @stauffermatt sur Twitter.