Blog de programación, errores, soluciones

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 autenticacion, 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:

php 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()

en la ruta para pasarle un parametro debe hacer lo siguiente:

Route::get('ejemplo',ejemplo@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

Route::get('ejemplo',ejemplo@show)->middleware('Ejemplo:uno,dos,tres');

se corresponderán con:

public 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

<?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.

Route::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.

public 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.

<?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.

Ayudame: Por favor deja un comentario antes de irte, tu opinión es bienvenida. Si te gusta el contenido comparte.