Tutorial

Understanding Laravel Middleware

Draft updated on Invalid Date
author

Samuel Oloruntoba

Understanding Laravel Middleware

This tutorial is out of date and no longer maintained.

Introduction

HTTP Middlewares provide a convenient mechanism for filtering HTTP requests entering your application. Laravel, for example, has a middleware for verifying a user’s authentication.

Some Middleware Use Cases

These are some cases where I have had to resort to using middleware. There are many more cases where you would like to use a middleware.

  • Using a middleware to confirm the incoming route request API key. Assuming you are building an API.
  • Rate-limiting a service call.
  • Change the site language based on locale.
  • Enable site-wide maintenance.
  • Sniffing bot traffic.
  • Logging.

By the end of this article, you should be able to create a middleware, register it, and use it in your projects. We will be illustrating the creation till usage of middlewares by creating one of our own. Our middleware will enable maintenance either site-wide or on some routes.

Creating a Middleware

Thanks to artisan, creating middlewares in Laravel is easy. All we need to do is open a terminal in the project root and run the following command.

  1. php artisan make:middleware <MiddlewareName>

Replace <MiddlewareName> with the actual name of the middleware.

This command creates our middleware class in app/Http/Middleware. To create our own middleware (which we will call DownForMaintenance, we can.

  1. php artisan make:middleware DownForMaintenance

So we can now open our middleware class and add our logic to the middleware. Remember, our middleware handles site maintenance mode. We need to first import the HttpException first. At the top of the file, we can do this

use Symfony\Component\HttpKernel\Exception\HttpException;

In the handle method of our middleware, we can just do this.

public function handle($request, Closure $next)
{
    throw new HttpException(503);
}

By throwing this exception, Laravel knows to load the 503.blade.php file. This should contain the message for maintenance mode.

Registering a Middleware

Now that we’ve created a middleware, we need to let the application know the middleware exists. If you want a middleware to run on every request, go to app/Http/kernel.php and add the middleware FQN to Kernel class $middleware property.

protected $middleware = [
    ...
    \App\Http\Middleware\DownForMaintenance::class
];

By doing this, the user will see a message for every page they visit.

If you want the middleware to trigger on some routes, we can name the middleware and use that as a reference mechanism to add it to some routes. To name the middleware, while still in the app/Http/kernel.php, add the keyed property to the $routeMiddleware array. The array key is the name of the middleware, while the value should be the FQN of the middleware.

protected $routeMiddleware = [
    ...
    'down.for.maintenance' => \App\Http\Middleware\DownForMaintenance::class,
    ...
];

Attaching a Middleware to a Route

Take this route for example,

Route::get('posts/{something}', 'PostController@getPost');

the getPost method on the PostController class fires when the url matches posts/{something}.

We could add our down.for.maintenance middleware by changing the second parameter of Route::get to an array that contains a middleware property and closure which processes the route.

Route::get('posts/{something}', ['middleware' => 'grown.ups.only', function () {
    return "Only big boys/girls can see this.";
}]);

By doing this, only routes matching posts/{something} will show the down for maintenance error.

Another to add middleware to routes is to call a middleware method on the route definition. Like this.

Route::get('posts/{something}', function () {
    //
})->middleware(['first', 'second']);

Middleware Parameters

Passing parameters to middlewares is quite easy. Say, for example, our middleware validates the role of a user before allowing access to a page. We could also pass a list of allowed roles to the middleware.

To pass a parameter to our middleware, after the $request and Closure parameters, we then add our variables.

public function handle($request, Closure $next, $role)
{
    if (! $request->user()->hasRole($role)) {
        // Redirect...
    }

    return $next($request);
}

To pass the variable, when attaching our middleware to routes, we do this.

Route::put('post/{id}', ['middleware' => 'role:editor', function ($id) {
    //
}]);

Grouping Middlewares

At times, there might be a bunch of middlewares you apply to a couple of routes. It would be better if we could combine or group middlewares. This allows us to reuse that group of middlewares.

To group middlewares, we add a $middlewareGroups property (if it does not exist) to the Kernel class. This property takes a key-value pair array. The key represents the group name, and the value is an array of middleware FQNs. By default, Laravel provides a web, and api group.

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,
    ],

    'api' => [
        'throttle:60,1',
        'auth:api',
    ],
];

If we need to use this group in our application, we can then do this.

Route::group(['middleware' => ['web']], function () {
    //
});

Deferring Middlewares Response

If you noticed, throughout this article, we perform an action then execute our middleware. But we could also execute our middleware first before returning a response.

public function handle($request, Closure $next)
{
    $response = $next($request);
    
    /**
    * Perform actions here
    */
    
    return $response;
}

By doing this, we first execute our middleware then we perform our action and return the response.

Conclusion

The use cases mentioned above are just a few examples. You can create a middleware to do so much more than what I have listed above.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Samuel Oloruntoba

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.