Aujourd’hui on va voir un élément clef de tous les projets web : les middlewares parfois appelés filters. Simples à comprendre pour les développeurs un peu aguerris, ils représentent une difficulté pour les débutants.
C’est quoi un middleware ?
Pour faire simple, ce sont des fonctions qui permettent d’enrichir ou de vérifier une requête avant qu’elle arrive à votre controller.
Plusieurs middlewares sont fournis de base avec Laravel comme auth
pour autoriser l'accès à la route seulement aux requêtes liées à un utilisateur connecté.
Middlewares par défaut
Laravel inclut les middlewares suivant dans chaque nouveau projet Laravel :
- Authenticate : renvoie une 401 si la requête ne contient pas d'Authorization
- CheckForMaintenanceMode : Si l'application est en maintenance, vérifie si l'IP ou la requête est autorisée pour l'exécuter malgré la maintenance
- EncryptCookies : Encrypte les cookies
- RedirectIfAuthenticated : Redirige sur la route définie comme Home si la requête est un utilisateur connecté
- TrimStrings : Trim chaque champ du body de la requête
- TrustProxies : Liste des proxies qui envoie les requêtes à votre server
- VerifyCsrfToken : Vérifie le token Csrf fournit par la requête
Le framework lui même en contient de nombreux autres :
- AuthenticateWithBasicAuth
- Authorize
- EnsureEmailsVerified
- RequiredPassword
- AddQueuedCookiesToResponse
- ConvertEmptyStringToNull
- TransformRequest
- ValidatePostSize
- CheckResponseForModifications
- FrameGuard
- SetCacheHeadersd
- SubstituteBindings
- Throttle requests
- ThrottleRequestsWithRedis
- ValidateSignature
- AuthenticateSession
- StartSession
- ShareErrorsFromSession
Créer votre middleware
Avec artisan, il est possible de créer votre propre middleware avec la commande :
php artisan make:middleware CheckAge
Pour Lumen, il est possible de créer directement le fichier dans app/Http/Middleware
.
<?php
namespace App\Http\Middleware;
use Closure;
class CheckAge
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->age <= 200) {
return redirect('home');
}
return $next($request);
}
}
Cette classe dispose d'une fonction handle
qui sera appelé par le framework quand vous allez utiliser votre middleware. Le plus important est l'appel au callback next
qui permet de continuer la requête.
Il est possible d'ajouter des paramètres à la fonction handle
que vous pourrez définir quand vous l'appelerez.
`
<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
/**
* Handle the incoming request.
*
* @param
\Illuminate\Http\Request $request
* @param
\Closure $next
* @param
string $role
* @return mixed
*/
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
// Redirect...
}
return $next($request);
}
}
`
Une fois votre middleware créé, il ne nous reste plus qu'à l'enregistrer pour qu'il soit reconnu par Laravel.
Enregistrer votre middleware
En fonction de votre besoin, il existe plusieurs manières d'enregistrer votre middleware :
- pour toute votre application
- pour une seule route
- dans un groupe de middleware
Enregistrer un middleware pour toute votre application
Pour qu'il se déclenche à chaque requête, il faut l'enregistrer dans l'attribut $middleware
dans le fichier app/Http/Kernel.php
.
Enregistrer un middleware pour une seule route
La liste des middlewares utilisable pour vos routes ou groupes de route se trouve dans l'attribut $routeMiddleware
de la classe App\Http\Kernel
. Elle prend la forme d'un tableau associatif où la clef est une chaîne qui va servir d'identifiant et la valeur est la classe de votre middleware.
Ensuite on peut l'utiliser directement lorsqu'on enregistre nos routes.
Route::get('admin/profile', "MonController@fonction")->middleware('auth');
Il est possible d'utiliser le nom de la classe plutôt que la clé du tableau pour bénéficier de l'autocompletion.
Route::get('admin/profile', "MonController@fonction")->middleware(CheckAge::class);
Il est également possible d'enregistrer plusieurs middlewares pour une même route.
Route::get('/', function () {})->middleware('first', 'second');
Enfin, il est possible d'empêcher l'exécution d'un middleware d'un groupe pour une de ses routes.
`
Route::middleware([CheckAge::class])->group(function () {
Route::get('/', function () {});
Route::get('admin/profile', function () {})->withoutMiddleware([CheckAge::class]);
});
`
Enregistrer un middleware pour un groupe de requêtes
Dans le cas de middlewares que vous allez utiliser ensemble, il est possible de créer un groupe de middlewares dans la propriété $middlewareGroups
. Il vous suffira ensuite d'appeler uniquement ce groupe pour appliquer tous ses middlewares.
C'est ce que fait Laravel par défaut avec les groupes web
et api
.
`
/**
- The application's route middleware groups. *
-
@var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],'api' => [
'throttle:60,1',
'auth:api',
],
];
`
Passer des arguments à votre middleware
L'ensemble des arguments se passe à votre middleware avec un :
après l'identifiant du middleware. S'il y a plusieurs arguments, on les sépare par des ,
.
Route::put('post/{id}', function ($id) {})->middleware('role:editor');
Top comments (2)
Salut, Nicolas. Les filtres en cascade sont importants. Il permet de traiter progressivement les données entrantes. Et éliminez la complexité du code. Il est important d'apprendre comment le framework le gère. Sinon, de nombreuses erreurs peuvent se produire. Et la sécurité peut être brisée.
Pourrais-tu m'aider s'il te plaît. J'ai besoin d'un examen de #showdev sur dev.to. Merci)
Merci pour cet article claire et précis, j’en ressort plus connaissant :-)