What Is Middleware in Laravel – and How to Create Your Own

What middleware is and how to create your own in Laravel 11/12 – bootstrap/app.php registration, aliases, groups, parameters, and before/after logic.

laravel middleware

Last updated: July 2026 — registration updated for Laravel 11/12 (bootstrap/app.php)

Middleware is a filter every HTTP request passes through before (or after) reaching your controller. Authentication, CSRF verification, CORS — all middleware. Think of it as airport security layers between the entrance (request) and the gate (controller).

Create one

php artisan make:middleware EnsureUserIsSubscribed
<?php
// app/Http/Middleware/EnsureUserIsSubscribed.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnsureUserIsSubscribed
{
    public function handle(Request $request, Closure $next): Response
    {
        if (! $request->user()?->subscribed) {
            return redirect()->route('pricing');
        }

        return $next($request);   // pass the request onward
    }
}

Code before $next($request) runs before your controller; to act after the response is built:

public function handle(Request $request, Closure $next): Response
{
    $response = $next($request);
    $response->headers->set('X-Frame-Options', 'DENY');
    return $response;
}

Register it — this changed in Laravel 11

There is no app/Http/Kernel.php anymore. Registration lives in bootstrap/app.php:

->withMiddleware(function (Middleware $middleware) {
    // alias for use on routes
    $middleware->alias([
        'subscribed' => \App\Http\Middleware\EnsureUserIsSubscribed::class,
    ]);

    // or run on every request
    $middleware->append(\App\Http\Middleware\SecurityHeaders::class);

    // or add to the web group
    $middleware->web(append: [\App\Http\Middleware\TrackLastActivity::class]);
})

(On Laravel 10 or older, the same three registrations go in Kernel.php$middlewareAliases$middleware$middlewareGroups.)

Use it on routes

Route::get('/dashboard', DashboardController::class)->middleware('subscribed');

Route::middleware(['auth', 'subscribed'])->group(function () {
    Route::get('/reports', [ReportController::class, 'index']);
});

Middleware parameters

Extra route arguments arrive after $next:

public function handle(Request $request, Closure $next, string $role): Response
{
    abort_unless($request->user()?->hasRole($role), 403);
    return $next($request);
}
Route::get('/admin', AdminController::class)->middleware('role:admin');

When middleware is the right tool

Cross-cutting checks tied to requests: auth and roles, locale switching, forcing HTTPS, logging, rate limiting, response headers. If the logic is business-rule-shaped (“can this user edit this post?”), use a Policy instead — middleware guards the road, policies guard the data.

Comments

comments