Deep dive into middlewares in Laravel 
Tags: laravel, php, programming, software
Published: 2017-12-13 22:48:00

---
title: Deep dive into middlewares in Laravel 
published: true
description: A short guide on Laravel middlewares
tags: Laravel, PHP, Programming, Software
---

Deep dive into middlewares in Laravel

What is a Laravel middleware?

It is a feature in Laravel which provides a mechanism for filtering HTTP requests entering your application. This allows you to hook into Laravel request processing work flow to perform some kind of logic that decides how your application works.

What would you use middleware for?

- Protecting your routes
- Setting headers on HTTP responses
- Logging requests to your application
- Sanitizing incoming parameters
- Enable site-wide maintenance mode
- Manipulating responses generated by your application


How to create a custom middleware?

Creating a middleware in Laravel is as simple as running the following command

    php artisan make:middleware <MiddlewareName>
    //MiddlewareName should be replaced with actual name of the middleware

This creates a middleware with the specified name in the middleware folder located in app. 
Luckily, Laravel scaffolds the basic things needed to start customizing your middleware.


    <?php
    namespace App\Http\Middleware;
    use Closure;
    class RedirectIfSuperAdmin
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            return $next($request);
        }
    }
    

Notice the `handle` function which accepts two parameters `$request`  and `$next` . The `$request` parameter holds the incoming request URI in your application while `$next` parameter is used to pass the request deeper into the application. The logic needed is written within the handle function and that brings us to types of middleware-`before middleware` and `after middleware`.

`Before middleware` as the name suggests handles some set of logic before forwarding the request deeper into the application. On the other hand `after middleware` runs after the request has been handled by the application and the response built.

Before middleware:

    <?php
    namespace App\Http\Middleware;
    use Closure;
    class RedirectIfSuperAdmin
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            //Your logic goes here
            return $next($request);
        }
    }

After middleware:

    <?php
    namespace App\Http\Middleware;
    use Closure;
    class RedirectIfSuperAdmin
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            $response = $next($request);
            //Your logic goes here e.g return redirect('/)
            
            return $response;
        }
    }

 
Categories of Middleware

- Global middleware
- Route middleware

Global middlewares run for every single request that hits the application. Laravel comes with most of these middlewares such as `ValidatePostSize`, `TrimStrings`,`CheckForMaintenanceMode` etc.

Route middlewares run only on routes they are attached to e.g `redirectIfAuthenticated`.


Registering a Middleware

Any middleware created has to be registered as that is the only way Laravel knows that such exists. To register a middleware simply open the file named `kernel.php` which is located inside Http folder like so:

![kernel.php location on Laravel](https://d2mxuefqeaa7sj.cloudfront.net/s_154FD755AC9D5ECE9FD43EEB0CC805AC89CA32D2C242B146361CA35EF3505A84_1507618543348_PrtScr+capture_2.jpg)


This file contains list of all registered middlewares that come with Laravel by default. it contains three major arrays which include `$middleware` , `$middlewareGroups` and `$routeMiddleware`


    <?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 = [
            \Illuminate\Foundation\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' => \Illuminate\Auth\Middleware\Authenticate::class,
            'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
            'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
            'can' => \Illuminate\Auth\Middleware\Authorize::class,
            'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
            'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
            //the just created middlware
            'superadmin' => \App\Http\Middleware\RedirectIfSuperAdmin::class, 
        ];
    }
    

The `$middleware` array holds global middlewares which runs for every single HTTP request to the application, so if you want a middleware to run for every request you should register it here. The `$middlewareGroups` makes it possible to register middlewares in groups making it easier to attach lots of middlewares to a route by using the group name. The `$routeMiddleware` array holds individual registered middlewares.


Assigning a Middleware

Once a middleware is registered it can be attached to a route in two major ways

- Through the constructor method in a controller
- Through the route 


Middleware assignment through constructor

Middleware assignment via a constructor on a controller gives more flexibility as it offers two important functions `except($parameters)` and `only($parameters)` which can be used to prevent or allow the middleware to apply to some helper functions in that controller. Without using the helper functions the middleware applies to every single function on that controller.


    <?php
    use Illuminate\Http\Request;
    
    class ForumController extends Controller
    {
        
        public function __construct(){
          /**in this case the middleware named auth is applied
           to every single function within this controller
           */
            $this->middleware('auth');
        }
        
        public function viewForum(){
          
          return view('index');
        }
        
        public function edit($id){
          
        }
        
        public function delete($id){
        
        }
        
    }

With the `except` and `only` functions we can select which functions the middleware will apply to as shown below:


    <?php
    use Illuminate\Http\Request;
    
    class ForumController extends Controller
    {
        
        public function __construct(){
          /**the authentication middleware here applies to all functions but
           viewForums() and viewForumDetails() and the opposite of this happens
           when you use only()
           */
            $this->middleware('auth')->except(['viewForums', 'viewForumDetails']);
        }
        
        public function viewForums(){
          
          return view('index');
        }
        
        public function edit($id){
          
        }
        
        public function delete($id){
        
        }
        
        public function viewForumDetails(){
        
        }
    }


Middleware assignment through routes

Provided a middleware has been registered in can be attached to the route directly as show below:

    <?php
    //method 1
    Route::get('admin/profile', function () {
      //action
    })->middleware('auth');
    
    /**method 2
    or using the fully qualified class name like so:
    */
    use App\Http\Middleware\CheckAge;
    
    Route::get('admin/profile', function () {
        // action
    })->middleware(CheckAge::class);
    
    //method 3
    Route::group(['middleware' => ['web']], function () {
        //action
    });
    

N:B Middleware groups can be assigned to a route the same way as a single middleware


Middleware Parameters

Additional parameters can be passed to a middleware. A typical example is where each user id is assigned to a role and the middleware checks the role of a user to determine if he/she has access to the requested URI. Parameters can be passed to a middleware as shown below:

    <?php
    //First method (Through route)
    Route::get('admin/profile', function () {
      //action
    })->middleware('auth:<role>'); //<role> here should be replaced by whatever parameter the user intends to pass.
    
    //Second method (Through a controller)
    use Illuminate\Http\Request;
    
    class ForumController extends Controller
    {
        
        public function __construct(){
            $this->middleware('auth:<role>');
        }
      }

Multiple parameters can be passed to a middleware by separating each parameter by a comma.


    <?php
    Route::get('admin/profile', function () {
      //action
    })->middleware('auth:<role>,<age>,<country>'); //<role>, <age>, <country> here should be replaced by whatever parameters the user intends to pass.

These parameters are passed to the handle function of the middleware after the `$next` variable


    <?php
    class RedirectIfSuperAdmin
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next, $role, $age, $country)
        {   
            //Logic for the middleware using the parsed parameters
            return $next($request);
        }
    }


Summary

To create a middleware you go through the following processes

- Create the middleware with artisan command `php artisan make:middleware <Middleware Name>`.
- Register the middleware in kernel.php located in the app→Http folder
- Write your logic in the created middleware
-  Assign middleware to a route or controller


Conclusion

Laravel middlewares make it easier to protect our routes, sanitize input and do a whole lot of other stuffs without writing so much logic. Checkout the official Laravel documentation [here](https://laravel.com/docs/5.5/middleware) for more features of middlewares and most importantly practice.