Laravel

Laravel is a powerful and popular PHP framework that simplifies and accelerates web application development. Its elegant syntax, robust features like Eloquent ORM, Blade templating, and built-in security tools help developers create efficient and scalable apps. With strong community support and extensive documentation, Laravel is an ideal choice for both novice and experienced developers

Laravel Route Middleware

15 May 2025 | Category:

Middleware in Laravel acts as a filter for HTTP requests, allowing you to perform tasks like authentication, authorization, logging, or input validation before a request reaches a controller or after a response is generated. Route middleware specifically applies to routes defined in routes/web.php or routes/api.php, providing a powerful way to control access and modify request/response behavior. This SEO-friendly, plagiarism-free guide explains Laravel route middleware, how to create and use it, and best practices. Based on Laravel 11 (as of May 2025), this tutorial is designed for beginners and intermediate developers.


What is Route Middleware?

Route middleware is a layer of code that runs during the HTTP request lifecycle, either before the request is processed by a controller or after the response is prepared. It’s called “route middleware” when applied to specific routes or route groups, enabling fine-grained control over request handling.

Common Use Cases

  • Authentication: Restrict access to authenticated users.
  • Authorization: Check if a user has permission for an action.
  • Rate Limiting: Limit API requests to prevent abuse.
  • Logging: Record request details for debugging.
  • Input Validation: Sanitize or validate input data.
  • CSRF Protection: Secure form submissions (applied by default in web routes).

How Middleware Works

Middleware sits between the HTTP request and the application’s core logic:

  1. Request Phase: Middleware can inspect, modify, or reject the request before it reaches the controller.
  2. Response Phase: Middleware can modify the response after the controller processes the request.

Laravel provides built-in middleware (e.g., auth, throttle) and allows you to create custom middleware for specific needs.


Built-In Middleware

Laravel includes several middleware in the app/Http/Middleware/ directory and the framework itself. Common examples:

  • auth: Ensures the user is authenticated.
  • guest: Restricts access to unauthenticated users.
  • throttle: Limits the number of requests (e.g., 60 requests per minute).
  • verified: Ensures the user’s email is verified (used with auth).
  • can: Authorizes actions using Laravel’s Gate or policies.
  • web: Applied to web.php routes, includes session handling and CSRF protection.
  • api: Applied to api.php routes, includes throttling.

Middleware is registered in app/Http/Kernel.php, which defines:

  • Global Middleware: Runs on every request (e.g., CheckForMaintenanceMode).
  • Route Middleware: Assigned to specific routes or groups (e.g., auth, throttle).
  • Middleware Groups: Bundles like web and api.

Applying Route Middleware

Route middleware can be applied to individual routes, route groups, or controllers.

1. Middleware on Individual Routes

Assign middleware using the middleware method in routes/web.php or routes/api.php.

Example (in web.php):

use App\Http\Controllers\PostController;

Route::get('/posts', [PostController::class, 'index'])->middleware('auth');
  • Only authenticated users can access the /posts route.

Multiple middleware:

Route::get('/posts', [PostController::class, 'index'])->middleware(['auth', 'verified']);

2. Middleware on Route Groups

Group routes with shared middleware for cleaner code.

Example:

Route::middleware(['auth', 'verified'])->group(function () {
    Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
    Route::get('/posts/create', [PostController::class, 'create'])->name('posts.create');
});
  • All routes in the group require authentication and email verification.

Prefix Example (Admin routes):

Route::middleware('auth')->prefix('admin')->group(function () {
    Route::get('/dashboard', [AdminController::class, 'index'])->name('admin.dashboard');
});
  • Routes like /admin/dashboard are protected.

3. Middleware in Controllers

Apply middleware in a controller’s constructor to affect all or specific methods.

Example:

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PostController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth')->except(['index', 'show']);
        $this->middleware('verified')->only(['create', 'store']);
    }

    public function index() { /* Logic */ }
    public function show($id) { /* Logic */ }
    public function create() { /* Logic */ }
    public function store(Request $request) { /* Logic */ }
}
  • auth: Required for all methods except index and show.
  • verified: Required only for create and store.

4. Middleware with Resource Routes

Apply middleware to resource controllers:

Route::resource('posts', PostController::class)->middleware('auth');
  • All CRUD routes (index, store, etc.) require authentication.

Creating Custom Middleware

You can create custom middleware for specific requirements, such as checking user roles or logging requests.

Step 1: Generate Middleware

Use Artisan to create a middleware class:

php artisan make:middleware EnsureUserIsAdmin

This creates EnsureUserIsAdmin.php in app/Http/Middleware/:

<?php

namespace App\Http\Middleware;

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

class EnsureUserIsAdmin
{
    public function handle(Request $request, Closure $next): Response
    {
        if (! $request->user() || ! $request->user()->is_admin) {
            abort(403, 'Unauthorized: Admin access required.');
        }

        return $next($request);
    }
}
  • handle: The main method that processes the request.
  • $request: The incoming HTTP request.
  • $next: Passes the request to the next middleware or controller.
  • abort(403): Rejects unauthorized users with a 403 error.

Step 2: Register Middleware

Register the middleware in app/Http/Kernel.php under $routeMiddleware:

protected $routeMiddleware = [
    // Other middleware...
    'admin' => \App\Http\Middleware\EnsureUserIsAdmin::class,
];

Step 3: Apply Middleware

Use the middleware in routes or controllers:

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

Or in a controller:

public function __construct()
{
    $this->middleware('admin');
}

Example: Middleware with Parameters

Middleware can accept parameters for dynamic behavior.

Middleware:

public function handle(Request $request, Closure $next, $role): Response
{
    if (! $request->user() || $request->user()->role !== $role) {
        abort(403, 'Unauthorized: Invalid role.');
    }

    return $next($request);
}

Register in Kernel.php:

'role' => \App\Http\Middleware\CheckRole::class,

Apply:

Route::get('/editor/posts', [PostController::class, 'index'])->middleware('role:editor');
  • Only users with the editor role can access the route.

Modifying Responses in Middleware

Middleware can also modify responses after the controller processes the request.

Example:

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

    // Add a custom header to the response
    $response->header('X-Custom-Header', 'MyApp');

    return $response;
}

Terminating Middleware

Some middleware runs after the response is sent to the browser (e.g., for logging). Define it as terminating middleware in Kernel.php:

protected $middleware = [
    \App\Http\Middleware\LogRequests::class,
];

Example:

public function handle(Request $request, Closure $next): Response
{
    return $next($request);
}

public function terminate(Request $request, Response $response): void
{
    \Log::info('Request processed: ' . $request->url());
}

Best Practices for Route Middleware

  1. Keep Middleware Focused: Each middleware should handle one responsibility (e.g., authentication, role checking).
  2. Use Descriptive Names: Name middleware clearly (e.g., EnsureUserIsAdmin instead of Check).
  3. Leverage Middleware Groups: Use groups like web or api for common functionality.
  4. Avoid Heavy Logic: Move complex logic to services or helpers to keep middleware lightweight.
  5. Test Middleware: Write tests to ensure middleware behaves as expected.
  6. Secure APIs: Use throttle and token-based authentication (e.g., Sanctum) for api.php routes.
  7. Use Route Model Binding: Combine middleware with route model binding for cleaner authorization checks.

Debugging Middleware

If middleware isn’t working as expected:

  • Check Registration: Ensure the middleware is registered in Kernel.php.
  • Verify Application: Confirm it’s applied to the correct route or controller.
  • Debug with Logs: Add \Log::info('Middleware reached') in the handle method.
  • Check Order: Middleware runs in the order listed in Kernel.php or route definitions.

Conclusion

Route middleware in Laravel is a powerful tool for controlling HTTP requests and responses, enabling secure, modular, and maintainable applications. By using built-in middleware like auth and throttle, creating custom middleware for specific needs, and applying them to routes or controllers, you can enforce access control, validate input, and enhance functionality. Whether building web interfaces or APIs, middleware ensures your application is robust and efficient.

Next Steps:

  • Create a custom middleware: php artisan make:middleware CheckRole.
  • Apply middleware to routes in web.php or api.php.
  • Explore Laravel’s official documentation for advanced middleware features.

For further learning, connect with the Laravel community on platforms like X or dive into the official Laravel documentation. Start securing your routes with middleware today!