Middleware en Laravel 11: Una Guía Completa
Victor Arana Flores
06 Aug 2024
Introducción al Middleware en Laravel 11
El middleware en Laravel 11 proporciona un mecanismo conveniente para inspeccionar y filtrar las solicitudes HTTP que ingresan a su aplicación. Por ejemplo, Laravel incluye un middleware que verifica si el usuario de su aplicación está autenticado. Si el usuario no está autenticado, el middleware lo redirigirá a la pantalla de inicio de sesión de su aplicación. Sin embargo, si el usuario está autenticado, el middleware permitirá que la solicitud continúe más allá en la aplicación.
Definición de Middleware en Laravel 11
Para crear un nuevo middleware en Laravel 11, use el comando Artisan make:middleware
:
php artisan make:middleware EnsureTokenIsValid
Este comando colocará una nueva clase EnsureTokenIsValid
dentro del directorio app/Http/Middleware
. En este middleware, solo permitiremos el acceso a la ruta si el token suministrado coincide con un valor específico. De lo contrario, redirigiremos a los usuarios de nuevo al URI /home
:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureTokenIsValid
{
public function handle(Request $request, Closure $next): Response
{
if ($request->input('token') !== 'my-secret-token') {
return redirect('/home');
}
return $next($request);
}
}
Como puede ver, si el token dado no coincide con nuestro token secreto, el middleware devolverá una redirección HTTP al cliente; de lo contrario, la solicitud se pasará más allá en la aplicación.
Middleware y Respuestas en Laravel 11
Un middleware en Laravel 11 puede realizar tareas antes o después de pasar la solicitud más allá en la aplicación. Por ejemplo, el siguiente middleware realizaría una tarea antes de que la solicitud sea manejada por la aplicación:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class BeforeMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Realizar acción
return $next($request);
}
}
Mientras que este middleware realizaría su tarea después de que la solicitud sea manejada por la aplicación:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class AfterMiddleware
{
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
// Realizar acción
return $response;
}
}
Registro de Middleware en Laravel 11
Middleware Global en Laravel 11
Si desea que un middleware se ejecute durante cada solicitud HTTP a su aplicación en Laravel 11, puede agregarlo a la pila de middleware global en el archivo bootstrap/app.php
de su aplicación:
use App\Http\Middleware\EnsureTokenIsValid;
->withMiddleware(function (Middleware $middleware) {
$middleware->append(EnsureTokenIsValid::class);
})
Asignación de Middleware a Rutas en Laravel 11
Si desea asignar middleware a rutas específicas en Laravel 11, puede invocar el método middleware
al definir la ruta:
use App\Http\Middleware\EnsureTokenIsValid;
Route::get('/profile', function () {
// ...
})->middleware(EnsureTokenIsValid::class);
Puede asignar varios middleware a la ruta pasando un arreglo de nombres de middleware al método middleware
:
Route::get('/', function () {
// ...
})->middleware([First::class, Second::class]);
Exclusión de Middleware en Laravel 11
Al asignar middleware a un grupo de rutas, ocasionalmente puede necesitar evitar que el middleware se aplique a una ruta individual dentro del grupo. Puede lograr esto usando el método withoutMiddleware
:
use App\Http\Middleware\EnsureTokenIsValid;
Route::middleware([EnsureTokenIsValid::class])->group(function () {
Route::get('/', function () {
// ...
});
Route::get('/profile', function () {
// ...
})->withoutMiddleware([EnsureTokenIsValid::class]);
});
También puede excluir un conjunto de middleware de un grupo entero de definiciones de rutas:
use App\Http\Middleware\EnsureTokenIsValid;
Route::withoutMiddleware([EnsureTokenIsValid::class])->group(function () {
Route::get('/profile', function () {
// ...
});
});
Grupos de Middleware en Laravel 11
A veces puede querer agrupar varios middleware bajo una sola clave para hacer que sea más fácil asignarlos a rutas en Laravel 11. Puede lograr esto usando el método appendToGroup
dentro de su archivo bootstrap/app.php
:
use App\Http\Middleware\First;
use App\Http\Middleware\Second;
->withMiddleware(function (Middleware $middleware) {
$middleware->appendToGroup('group-name', [
First::class,
Second::class,
]);
})
Los grupos de middleware pueden asignarse a rutas y acciones del controlador usando la misma sintaxis que los middleware individuales:
Route::get('/', function () {
// ...
})->middleware('group-name');
Route::middleware(['group-name'])->group(function () {
// ...
});
Alias de Middleware en Laravel 11
Puede asignar alias a los middleware en Laravel 11 dentro de su archivo bootstrap/app.php
. Los alias de middleware permiten definir un alias corto para una clase de middleware dada, lo que puede ser especialmente útil para middleware con nombres de clase largos:
use App\Http\Middleware\EnsureUserIsSubscribed;
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
'subscribed' => EnsureUserIsSubscribed::class
]);
})
Una vez que el alias del middleware se ha definido en el archivo bootstrap/app.php
de su aplicación, puede usar el alias al asignar el middleware a las rutas:
Route::get('/profile', function () {
// ...
})->middleware('subscribed');
Ordenación de Middleware en Laravel 11
En raras ocasiones, es posible que necesite que su middleware se ejecute en un orden específico en Laravel 11 pero no tener control sobre su orden cuando se asignan a la ruta. En estas situaciones, puede especificar la prioridad de su middleware usando el método priority
en su archivo bootstrap/app.php
:
->withMiddleware(function (Middleware $middleware) {
$middleware->priority([
\Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
\Illuminate\Cookie\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class,
\Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
\Illuminate\Auth\Middleware\Authorize::class,
]);
})
Parámetros de Middleware en Laravel 11
El middleware en Laravel 11 también puede recibir parámetros adicionales. Por ejemplo, si su aplicación necesita verificar que el usuario autenticado tenga un determinado "rol" antes de realizar una acción dada, podría crear un middleware EnsureUserHasRole
que reciba un nombre de rol como argumento adicional:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureUserHasRole
{
public function handle(Request $request, Closure $next, string $role): Response
{
if (!$request->user()->hasRole($role)) {
// Redirigir...
}
return $next($request);
}
}
Los parámetros adicionales del middleware se pasarán al middleware después del argumento $next
:
Route::put('/post/{id}', function (string $id) {
// ...
})->middleware('role:editor');
Múltiples parámetros pueden delimitarse con comas:
Route::put('/post/{id}', function (string $id) {
// ...
})->middleware('role:editor,publisher');
Middleware Terminable en Laravel 11
A veces un middleware en Laravel 11 puede necesitar hacer algún trabajo después de que la respuesta HTTP haya sido enviada al navegador. Si define un método terminate
en su middleware y su servidor web está usando FastCGI, el método terminate
se llamará automáticamente después de que la respuesta haya sido enviada al navegador:
<?php
namespace Illuminate\Session\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class TerminatingMiddleware
{
public function handle(Request $request, Closure $next): Response
{
return $next($request);
}
public function terminate(Request $request, Response $response): void
{
// ...
}
}
El método terminate
debe recibir tanto la solicitud como la respuesta. Una vez que haya definido un middleware terminable, debe agregarlo a la lista de rutas o middleware globales en su archivo bootstrap/app.php
.
Al llamar al método terminate
en su middleware, Laravel resolverá una nueva instancia del middleware desde el contenedor de servicios. Si desea usar la misma instancia del middleware cuando se llaman los métodos handle
y terminate
, registre el middleware con el contenedor usando el método singleton
del contenedor. Normalmente esto debería hacerse en el método register
de su AppServiceProvider
:
use App\Http\Middleware\TerminatingMiddleware;
public function register(): void
{
$this->app->singleton(TerminatingMiddleware::class);
}
Con esta guía completa sobre middleware en Laravel 11, ahora tiene una comprensión clara de cómo crear, registrar y usar middleware en su aplicación. El middleware es una herramienta poderosa para manejar solicitudes HTTP y garantizar que su aplicación funcione de manera segura y eficiente.