How Laravel Middleware Works

Middleware is a filtering layer that every HTTP request passes through before reaching the controller, and every response passes through before it is sent back to the user. Think o...

How Laravel Middleware Works

Middleware is a filtering layer that every HTTP request passes through before reaching the controller, and every response passes through before it is sent back to the user. Think of it as a checkpoint: you can verify that a user is logged in, check permissions, write logs, or switch the application language — all in one place, without cluttering your controllers. This article explains how middleware works in Laravel 10/11 with real, practical examples.

1. Where Middleware Sits in the Request Lifecycle

When a request arrives, Laravel runs it through a chain of middleware in layers (like an onion). The flow is roughly: Request in → global middleware → group/route middleware → controller → response → middleware (on the way back) → Response out. Because of this layered structure, a single middleware can run code before the request is forwarded and after the response is created.

2. Creating Middleware

Use the following artisan command to scaffold a middleware:

php artisan make:middleware EnsureUserIsActive

A new file appears at app/Http/Middleware/EnsureUserIsActive.php with a single handle() method. The $next parameter is a closure that forwards the request to the next layer:

public function handle(Request $request, Closure $next): Response
{
    if (! $request->user() || ! $request->user()->is_active) {
        return redirect('/login')
            ->with('error', 'Your account is inactive.');
    }

    return $next($request);
}

The key insight: if you call return $next($request), the request continues to the controller. If you return redirect() or abort() first, the request stops right here.

3. Registering Middleware

Registration differs between Laravel 10 and 11. In Laravel 11, everything is registered in bootstrap/app.php:

->withMiddleware(function (Middleware $middleware) {
    // alias for per-route use
    $middleware->alias([
        'active' => \App\Http\Middleware\EnsureUserIsActive::class,
    ]);

    // global middleware (runs for every request)
    $middleware->append(\App\Http\Middleware\LogRequests::class);
})

In Laravel 10, registration happens in app/Http/Kernel.php via the $middlewareAliases, $middleware (global), and $middlewareGroups properties.

Applying to Routes

Once aliased, attach it to a route or a route group:

Route::get('/dashboard', [DashboardController::class, 'index'])
    ->middleware(['auth', 'active']);

Route::middleware(['auth', 'active'])->group(function () {
    Route::resource('products', ProductController::class);
});

4. Before vs After Middleware

The difference is when your logic runs relative to $next($request).

Before middleware runs code before the request is forwarded — ideal for permission checks:

public function handle(Request $request, Closure $next): Response
{
    // this runs BEFORE the controller
    Log::info('Incoming request: '.$request->path());

    return $next($request);
}

After middleware runs code after the response is built — ideal for adding headers or logging the status:

public function handle(Request $request, Closure $next): Response
{
    $response = $next($request);

    // this runs AFTER the controller
    $response->headers->set('X-App-Version', '1.0');

    return $response;
}

5. Middleware with Parameters

Middleware can accept arguments — the most common pattern is a role gate. Add a parameter after $next:

public function handle(Request $request, Closure $next, string $role): Response
{
    if ($request->user()->role !== $role) {
        abort(403, 'You do not have access.');
    }

    return $next($request);
}

Pass the parameter from the route using a colon:

Route::get('/admin', [AdminController::class, 'index'])
    ->middleware('role:admin');

Need multiple values? Separate them with commas: middleware('role:admin,editor') then capture with ...$roles.

6. Real Example: A Locale Middleware

Middleware is great for switching the application language based on a user preference or URL parameter. A simple example:

public function handle(Request $request, Closure $next): Response
{
    $locale = $request->query('lang', session('locale', 'id'));

    if (in_array($locale, ['id', 'en'])) {
        app()->setLocale($locale);
        session(['locale' => $locale]);
    }

    return $next($request);
}

Register it as global middleware or inside the web group so every page respects the user's language choice.

7. Common Mistakes to Avoid

  • Forgetting return $next($request): the request never reaches the controller and you only see a blank page.
  • Putting heavy logic in global middleware: since it runs on every request, database queries there can slow down the whole app.
  • Wrong order: the auth middleware must run before any middleware that accesses $request->user(), otherwise it will be null.

By understanding middleware, you gain a powerful tool for separating security, logging, and request transformation concerns from your business logic. Your controllers stay lean, and cross-cutting rules live in one place that is easy to test.

Yudhi
Written by
Yudhi
Founder & Lead Developer, GudangCode

Yudhi is the founder of GudangCode and a Laravel developer who has built dozens of ready-to-use business information systems — from POS and HRIS to management apps. He writes guides and articles on GudangCode to help Indonesian developers run, understand, and deploy Laravel source code correctly.

LaravelPHPMySQLSistem Informasi Bisnis See all articles by Yudhi
Want the full source code & apps?

Sign up free to download ready-to-use business applications, information systems, and Laravel source code.

Sign Up Free & Download
Middleware Laravel Programming & Laravel
Share this article
Back to Blog
📚 Free Learning Hub

Learn Coding for Free at DhieCoderWeb

Explore Laravel, PHP, JavaScript tutorials, source code, web development guides, and practical programming tips.

DhieCoderWeb
100+
Tutorials
Free
Learning
SEO
Tips
Visit Dhiecoderweb.com →

Get Full Access Now!

Join our membership and unlock exclusive access to all premium features. Fast, easy, and ready to use instantly.

Join Membership Now
Tim Support
Online
Isi data dulu untuk mulai chat:
Beri rating & testimoni sebelum menutup:
Live chat by gudangcode.com