Cómo utilizar middlewares en Laravel
Los middlewares son una muy buena herramienta, la cual nos provee con un mecanismo para filtrar las requests HTTP. Laravel ya viene con algunos middlewares los cuales puede ver en la carpeta de app/Http/Middleware .
Como puede ver laravel tiene un middleware para la autenticación, para sacar los espacios en blanco, para verificar si tenemos el token csrf, para encriptar las cookies y otros mas. Con esto nos podemos dar cuenta de lo potente que puede ser usar meiddlewares.
Si quiere verlo como una analogía puede ver el middleware como el portero de un edificio tiene acceso entra sino no entra. También puede ver el conjunto de middlewares como las capas de una cebolla las cuales rodean nuestra aplicación.
Algo que debe saber de los middlewares es que se puede utilizar en todo el proyecto o en partes especificas. Ademas los middlewares se pueden aplicar antes o después de chequear si cumple una condición.
Los middleware pueden ser muy potentes suponga que debe chequear algo en el cache, una session, chequear una condición en el request, puede hacer muchísimas cosas con un middleware.
Creando un middleware
para crear un middleware nuevo solo tiene que usar el comando php artisan make:middleware.
La sintaxis para los middleware seria de esta manera:
Project Folderphp artisan make:middleware <middleware_name>
como dije antes un middleware se puede ejecutar antes o después de la el request.
Antes del middleware
Los middlewares que se ejecutan antes de el request se definen de la siguiente manera
<?php namespace App\Http\Middleware; use Closure; class BeforeMiddleware { public function handle($request, Closure $next) { // Perform action return $next($request); } }
Estamos sabiendo que el middleware se ejecuta antes del request por el return $next($request); que le esta diciendo que le devuelva el request.
Despues del middleware
Como podemos ver return devuelve la respuesta después de correr la funcion $next($request).
<?php namespace App\Http\Middleware; use Closure; class despuesDelMiddleware { public function handle($request, Closure $next) { $response = $next($request); // codigo return $response; } }
Parametros en Middleware.
A los middleware puede pasarle parámetros adicionales, estos pueden ser pasados después del argumento $next.
<?php namespace App\Http\Middleware; use Closure; class Ejemplo { /** * Handle the incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string $ejemplo * @return mixed */ public function handle($request, Closure $next, $ejemplo) { dd($ejemplo); return $next($request); } }
la funcion dd() significa die and dump y es el equivalente a hacer un var_dump() junto con die()
versiones anteriores a Laravel 8en la ruta para pasarle un parámetro debe hacer lo siguiente:
Aplicando un middleware Ejemplo con parametro holaRoute::get('ejemplo',ejemplo@show)->middleware('Ejemplo:hola');
En este ejemplo deberíamos obtener hola en pantalla.
Si tiene que pasar mas parámetros lo puede hacer de la siguiente manera
aplicando múltiples parametrosRoute::get('ejemplo',ejemplo@show)->middleware('Ejemplo:uno,dos,tres');
Se corresponderán con:
Ejemplo.phppublic function handle($request, Closure $next, $uno,$dos,$tres)
en nuestro middleware.
Laravel 8 y superioresen la ruta para pasarle un parámetro debe hacer lo siguiente:
aplicando un middleware ejemplo con parametro holaRoute::get('ejemplo',[EjemploController::class,'show'])->middleware('Ejemplo:hola');
en este ejemplo deberíamos obtener hola en pantalla.
Si tiene que pasar mas parametros lo puede hacer de la siguiente manera
aplicando múltiples parámetrosRoute::get('ejemplo',[EjemploController::class,'show'])->middleware('Ejemplo:uno,dos,tres');
Se corresponderán con:
/middlewares/Ejemplo.phppublic function handle($request, Closure $next, $uno,$dos,$tres)
en nuestro middleware.
¿Como uso un Middleware?
Para poder usar los middleware primero los tenemos que registrar. Hay varias maneras de registrar un middleware, estas son:
- Globalmente.
- Asignarlo a una ruta.
- Por grupo.
Registro de middlewares
Para registrar los middlewares debe ir a app/Http/Kernel.php.
Este es el archivo Kernel.php
app/Http/Kernel.php<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { /** * The application's global HTTP middleware stack. * * These middleware are run during every request to your application. * * @var array */ protected $middleware = [ \App\Http\Middleware\CheckForMaintenanceMode::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, \App\Http\Middleware\TrustProxies::class, ]; /** * 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\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ 'throttle:60,1', 'bindings', ], ]; /** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array */ protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, ]; /** * The priority-sorted list of middleware. * * This forces non-global middleware to always be in the given order. * * @var array */ protected $middlewarePriority = [ \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\Authenticate::class, \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, \Illuminate\Auth\Middleware\Authorize::class, ]; }
Middlewares Globales
Como puede ver los middlewares globales es decir los que se aplicaran en toda nuestra aplicación están en el array $middleware.
Agrupar middlewares
También puede agruparlos esto lo puede hacer dentro de $middlewareGroups solo tiene que decir sobre que nombre están agrupados, por ejemplo laravel viene con este grupo de middlewares que al llamar a «web» se ejecutaran.
Asignarle el middleware a una ruta
Tercero tenemos otro array asociativo $routeMiddleware que son los middleware que le asignamos una ruta.
Por ejemplo tomemos la ruta ‘auth’ (vea Kernel.php)
'auth' => \App\Http\Middleware\Authenticate::class
con esta ruta le estamos ordenando, corre el middleware Autenticate cuando llame a auth. Como ocurre esto un ejemplo simple.
aplicando un middleware a una rutaRoute::get('miperfil', function () { // })->middleware('auth');
En este ejemplo le estoy diciendo si estas Autenticado, 🤔 no se si existe esa palabra en español( si estas logueado y eres tu seria) podrás seguir hacia la ruta mipefil.
Asignarle el middleware a un controlador
otra de las cosas que podemos hacer es asignárselo a un controlado, esto se logra dentro de el constructor del controlador. Por ejemplo si tengo el controlador MiPerfilController.
MiPerfilController.phppublic function __construct(){ $this->middleware('auth'); }
seria la forma de asignarle el middleware auth dentro del controlador y ya no lo tendríamos que llamar dentro de la ruta. Esto puede ser practico ya que las rutas no nos quedarían tan sobrecargadas.
Prioridad de los middlewares
Y por ultimo tenemos las prioridades de los middlewares que como puede ver están en $middlewarePriority (esto solo definirá cual correr primero)
Mi consejo no toque los middleware que vienen por defecto en laravel, si necesita alguna particularidad es mejor agregar un nuevo middleware y llamar los 2.
Ejemplo de Middleware
porque no hacer un ejemplo con middleware, bien haremos un middleware que chequee si es admin o no.
haremos un middleware isAdmin así pues correremos el comando php artisan make:middleware isAdmin. Al usar make:middleware nos creara un archivo isAdmin.php en la carpeta Middleware con el siguiente código.
middleware/isAdmin.php<?php namespace App\Http\Middleware; use Closure; class isAdmin { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { return $next($request); } }
Como puede ver este es un middleware que se ejecutara antes de que se ejecute el request. Esto lo define el return que tiene $next($request)
referencia: libro – laravel up and running, laravel.com/middlewares .
Agradecimientos: gracias Matt por explicar tan bien este tema, Jeffry Way por los cursos en laracast.