Laravel Middleware: Put in Routes, Controller, or Elsewhere? (4 Options)

If you have a Middleware, where you should use it: in the Routes file or in the Controller? Here are the FOUR options.

I will give you the example of the default auth middleware, but the same principles apply to any Laravel or Custom Middleware class.


Option 1. Routes File.

If you read the official docs on Middleware, this is the main recommended way.

Examples:

// Single route
Route::get('/profile', [UserController::class, 'profile'])->middleware('auth');
 
// Route resource
Route::resource('users', UserController::class)->middleware('auth');
 
// Route group
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'index']);
Route::post('/profile', [ProfileController::class, 'update']);
});

Option 2. Controller Constructor

It's not mentioned in the documentation for Middleware, but the docs about Controllers show this option:

class UserController extends Controller
{
public function __construct()
{
// Assign to ALL methods in this Controller
$this->middleware('auth');
 
// Assign only to ONE method in this Controller
$this->middleware('auth')->only('create');
 
// Assign only to specific methods in this Controller
$this->middleware('auth')->only(['create', 'store']);
 
// Assign to all EXCEPT specific methods in this Controller
$this->middleware('auth')->except('index');
}
}

Notice that $this->middleware() works only if you assign it in the Constructor. If you call $this->middleware() from a specific Controller method, it will not throw any errors but Middleware will not actually work.

This option is totally valid, but personally, I prefer to put all the Middlewares in the Routes, because it's then clear where to look for all the Middlewares in one place, and not jump between Routes/Controllers to double-check. It's just a habit: always use one of the ways and don't let this question bother you.


Option 3. For All Route File: Service Provider or Kernel

There's also a global Middleware for all the Routes file, which you can assign in the RouteServiceProvider. In fact, Laravel is doing that already by default, take a look at the file that comes with Laravel:

app/Provider/RouteServiceProvider.php:

class RouteServiceProvider extends ServiceProvider
{
public function boot()
{
$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
 
Route::middleware('web')
->group(base_path('routes/web.php'));
});
}
}

See those middleware('api') and middleware('web')? So, you can assign any custom Middleware to any of the routes/xxxxx.php files.

In fact, those web and api are not individual Middlewares, they are Middleware groups. So, if you want to add your Middleware to be executed with web/api Routes only, another option is to add it to the array in the Kernel.php file:

app/Http/Kernel.php:

class Kernel extends HttpKernel
{
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,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
 
// <- Your middleware here
],
 
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
 
// <- Your middleware here
],
];
}

Option 4. Globally in Kernel.php

Even more globally, you can assign the Middleware to be executed for every request.

As in the previous example, Laravel comes with some of such Middleware by default, their array is in the app/Http/Kernel.php:

app/Http/Kernel.php:

class Kernel extends HttpKernel
{
/**
* These middleware are run during every request to your application.
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
}
avatar

Since Laravel 10, in Kernel.php there is also '$middlewareAliases' array. By default, the $middlewareAliases property of this class contains entries for the middleware included with Laravel. You may add your own middleware to this list and assign it an alias of your choosing

$middlewareAliases = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, ... , ];

Prior to Laravel 10, this array had a name: '$routeMiddleware'.

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 59 courses (1056 lessons, total 44 h 09 min)
  • 78 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent Premium Tutorials