Middleware in Laravel: Main Things to Know

In Laravel, you often need to check things before users reach the Controller. For that, you would use Middleware. Let me explain how it works with examples.

Here are the examples you would check:

  • Is the user logged in?
  • Does the user have admin rights?
  • Is the API request valid?

So, Middleware can help as a security checkpoint that can inspect, modify, or reject requests.


Example: Built-in "Auth" Middleware

Example code without Middleware:

routes/web.php:

Route::get('/dashboard', function () {
if (!auth()->check()) {
return redirect('/login');
}
return view('dashboard');
});

Same example with auth Middleware that comes with Laravel:

routes/web.php:

Route::get('/dashboard', function () {
return view('dashboard');
})->middleware('auth');

Using Middleware is shorter and may be reusable in multiple routes.

The auth Middleware is an example from the framework core, and there are a few more useful built-in Middleware classes:

  • auth - User must be logged in: ->middleware('auth')
  • guest - The opposite - user must NOT be logged in: ->middleware('guest')
  • throttle - Rate limiting how many attempts per minute: ->middleware('throttle:60,1')
  • can - Permission Gate/Policy check: ->middleware('can:edit,post')
  • verified - Email verified: ->middleware('verified')

You can also create your custom Middleware.


Custom Middleware Example

Goal: Restrict certain features to admin users only.

Generate the Middleware:

php artisan make:middleware CheckAdmin

Define the logic:

app/Http/Middleware/CheckAdmin.php:

namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
 
class CheckAdmin
{
public function handle(Request $request, Closure $next): Response
{
if (!$request->user() || !$request->user()->isAdmin()) {
abort(403, 'Admin access required');
}
 
return $next($request);
}
}

As you can see, in the handle() method, you either restrict access or allow the request to proceed with the return $next($request); statement.


Registering Middleware with Alias

In Laravel 11+, all Middleware configuration happens in the bootstrap/app.php file using the withMiddleware() method.

You come up with an alias name for your Middleware class, to be used in the Routes, like the auth example above.

bootstrap/app.php

use App\Http\Middleware\CheckAdmin;
 
return Application::configure(basePath: dirname(__DIR__))
->withMiddleware(function ($middleware) {
$middleware->alias([
'admin' => CheckAdmin::class,
]);
})
->create();

Then, use that alias in the routes:

routes/web.php:

// Single Middleware
Route::get('/admin/users',
[UserController::class, 'index']
)->middleware('admin');
 
// Multiple Middleware
Route::get('/admin/settings', SettingController::class)
-> Middleware (['auth', 'admin']);

Using Middleware with No Alias

Creating the alias is optional. You can also use Middleware by directly referencing the full class name.

routes/web.php:

use App\Http\Middleware\CheckAdmin;
 
// ...
 
Route::get('/admin/users',
[UserController::class, 'index']
)->middleware(CheckAdmin::class);

You can also combine the alias and non-alias references.

routes/web.php:

use App\Http\Middleware\ValidateApiToken;
 
// ...
 
Route::get('/api/data', function () {
return response()->json(['data' => 'example']);
})->middleware([ValidateApiToken::class, 'throttle:60,1']);

Middleware on Route Groups

Apply Middleware to multiple routes at once:

routes/web.php:

Route::middleware(['auth', 'admin'])->group(function () {
Route::get('/admin/dashboard', function () {
return view('admin.dashboard');
});
 
Route::get('/admin/users', function () {
return view('admin.users');
});
});

Middleware with Parameters

Some Middleware requires additional data to work properly. For example, you can check for a role by passing $role as a parameter.

app/Http/Middleware/CheckRole.php

namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
 
class CheckRole
{
public function handle(Request $request, Closure $next, string $role): Response
{
if (!$request->user()->hasRole($role)) {
abort(403, "Requires {$role} role");
}
 
return $next($request);
}
}

routes/web.php:

Route::put('/posts/{post}', function ($post) {
// Edit post
})->middleware('role:editor');

Global Middleware

You may also want to add global Middleware that runs on every HTTP request to your application.

bootstrap/app.php

use App\Http\Middleware\LogRequests;
 
->withMiddleware(function ($middleware) {
$middleware->append(LogRequests::class);
})

More in the Docs

For more options and features of Middleware, please read the official Laravel documentation.

avatar
Loganathan Natarajan

Thank you

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 78 courses
  • 95 long-form tutorials
  • access to project repositories
  • access to private Discord

Recent New Courses