Did you ever find yourself writing the same checks in multiple controllers? Like formatting inputs, blocking access, or tracking user a...
Did you ever find yourself writing the same checks in multiple controllers? Like formatting inputs, blocking access, or tracking user activity? It all starts feeling repetitive, right?... and it gets old fast.
That’s where middleware comes in. Think of it as a bouncer for your app—checking, modifying, or rejecting requests before they hit your controllers. Or even after a request is handled (many people don't know this). Instead of cluttering controllers with repeated logic or separating that logic in traits, middleware helps you add functionality across multiple routes in a cleaner, more maintainable way.
The real power of middleware isn’t just cleaner controllers—it’s when the code runs:
__construct()
, the controller is already instantiated before they run.So, when should you create custom middleware? Let’s break it down.
Before jumping into the examples, let’s see how to create and apply middleware so you know exactly where the code goes.
1. Generate middleware:
php artisan make:middleware YourMiddlewareName
This creates a file in app/Http/Middleware/YourMiddlewareName.php
where we’ll write our logic.
2. Register it inside app/Http/Kernel.php
:
protected $routeMiddleware = [
'yourMiddleware' => \App\Http\Middleware\YourMiddlewareName::class,
];
Now, we can apply it to routes like this:
Route::get('/some-route', 'SomeController@index')->middleware('yourMiddleware');
Alright, now that we know where to put the code, let’s go over when you should create middleware.
Laravel’s built-in authentication is great, but sometimes you need extra checks. Maybe you want to allow only verified users or restrict access based on roles, permissions, or subscription plans.
💡 Example: Only premium users can access certain pages
public function handle(Request $request, Closure $next)
{
if (!$request->user() || !$request->user()->is_premium) {
return redirect('/upgrade');
}
return $next($request);
}
How to use it:
Route::get('/premium-content', function () {
return view('premium');
})->middleware('checkPremiumUser');
Now, only premium users can access this page.
Want to track incoming requests for analytics or debugging? Middleware lets you log request details without cluttering your controllers.
💡 Example: Log every visited URL with a timestamp
public function handle(Request $request, Closure $next)
{
\Log::info('User visited: ' . $request->url());
$request->user()?->update(['last_seen' => now()]);
return $next($request);
}
How to use it:
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware('trackActivity');
Now, every visit is logged automatically!
Modify or sanitize user input before it gets processed. This is great for data consistency across your app.
💡 Example: Convert all email inputs to lowercase
public function handle(Request $request, Closure $next)
{
if ($request->has('email')) {
$request->merge(['email' => strtolower($request->email)]);
}
return $next($request);
}
How to use it:
Route::post('/register', 'AuthController@register')->middleware('normalizeEmail');
Now, all email inputs are automatically converted to lowercase.
Need to temporarily block users while performing updates but continue access to specific IPs (like your dev team).
💡 Example: Allow only users from a specific office IP
public function handle(Request $request, Closure $next)
{
$allowedIps = ['123.456.789.1']; // Replace with your office IP
if (!in_array($request->ip(), $allowedIps)) {
return response('Site is under maintenance', 503);
}
return $next($request);
}
How to use it:
Route::get('/admin', function () {
return view('admin.dashboard');
})->middleware('restrictByIp');
Now, only approved IPs can access the admin panel.
Want to switch the app language based on user request? Middleware can detect the lang
query parameter and set the language automatically.
💡 Example: If a user visits /?lang=fr
, the app switches to French
public function handle(Request $request, Closure $next)
{
if ($request->has('lang')) {
app()->setLocale($request->lang);
}
return $next($request);
}
How to use it:
Route::get('/', function () {
return view('welcome');
})->middleware('setLanguage');
Now, the app automatically sets the language based on the URL parameter.
Middleware isn’t just for before requests—it can also run after the response is sent. This is useful for tasks like logging, cleanup, or modifying the response before it's sent back to the user.
💡 Example: Log response time for performance monitoring
Want to measure how long a request takes to process? Middleware can track the time and log it for performance insights.
public function handle(Request $request, Closure $next)
{
$start = microtime(true); // Record start time
$response = $next($request);
$duration = microtime(true) - $start; // Calculate execution time
\Log::info("Request to {$request->path()} took {$duration} seconds");
return $response;
}
Now, every request logs its execution time, helping you spot slow endpoints.
If you're copy-pasting the same logic in multiple controllers, stop right there. Middleware is made for this. Your controllers should focus on actual business logic, not random repetitive tasks—middleware keeps it that way.
So next time you think, “I need to do this before or after every request," — that’s your signal to create a middleware! 🚀
Subscribe to our "Article Digest". We'll send you a list of the new articles, every week, month or quarter - your choice.
What do you think about this?
Wondering what our community has been up to?