Mastering Laravel Middleware: From Basics to Advanced Usage
This guide explains how Laravel middleware filters HTTP requests, shows how to create custom middleware with artisan, demonstrates pre‑ and post‑processing, registers global and route middleware, configures middleware groups, priority ordering, parameter passing, and terminable middleware for advanced request handling.
Middleware Overview
Middleware provides a convenient mechanism to filter incoming HTTP requests before they reach the application. Common uses include authentication, CORS header injection, and request logging. Laravel ships with several built‑in middleware located in app/Http/Middleware.
Defining a Middleware
Run php artisan make:middleware CheckAge to generate a new class in app/Http/Middleware. The generated CheckAge middleware checks whether the request's age parameter is greater than 200; if not, it redirects to the home route, otherwise it forwards the request via $next($request).
<?php
namespace App\Http\Middleware;
use Closure;
class CheckAge
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->age <= 200) {
return redirect('home');
}
return $next($request);
}
}The middleware acts like a series of HTTP checks; each layer decides whether to allow the request to continue.
All middleware are resolved through the service container, so you may type‑hint any dependencies in the constructor.
Pre & Post Middleware
Pre‑middleware runs before the application handles the request, while post‑middleware runs after. Example pre‑middleware:
<?php
namespace App\Http\Middleware;
use Closure;
class BeforeMiddleware
{
public function handle($request, Closure $next)
{
// perform tasks
return $next($request);
}
}Example post‑middleware:
<?php
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// perform tasks
return $response;
}
}Registering Middleware
Global Middleware
Add a class to the $middleware array in app/Http/Kernel.php to have it run on every HTTP request.
Route Middleware
Assign a key in the $routeMiddleware array of app/Http/Kernel.php. Custom middleware can be added by appending a new entry, e.g.:
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
// ... other Laravel defaults ...
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
];Use the key when defining routes:
Route::get('admin/profile', function () {
// ...
})->middleware('auth');Multiple middleware can be chained:
Route::get('/', function () {})->middleware('first', 'second');Middleware Groups
Group several middleware under a single key via the $middlewareGroups property. Laravel provides web and api groups out of the box.
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,
],
'api' => [
'throttle:60,1',
'auth:api',
],
];Apply a group to a route or a route group:
Route::get('/', function () {})->middleware('web');
Route::group(['middleware' => ['web']], function () {
// routes
});Middleware Priority
When order matters, define $middlewarePriority in app/Http/Kernel.php to enforce a specific execution sequence.
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];Middleware Parameters
Middleware can accept additional parameters after $next. Example CheckRole middleware receives a role name:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
// redirect or abort
}
return $next($request);
}
}Pass parameters when defining the route:
Route::put('post/{id}', function ($id) {})->middleware('role:editor');Terminable Middleware
Some middleware need to act after the response is prepared. Implement a terminate method that receives both the request and response. Laravel will call it automatically when using FastCGI.
<?php
namespace Illuminate\Session\Middleware;
use Closure;
class StartSession
{
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
// Store the session data...
}
}Remember to add terminable middleware to the global list in app/Http/Kernel.php if you want it applied to all routes.
Tip: The RouteServiceProvider automatically applies the web middleware group to routes defined in routes/web.php .
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Laravel Tech Community
Specializing in Laravel development, we continuously publish fresh content and grow alongside the elegant, stable Laravel framework.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
