In Laravel, you often need to check things before users reach the Controller. For that, you would use Middleware. Let me explain how it works with examples.
Here are the examples you would check:
- Is the user logged in?
- Does the user have admin rights?
- Is the API request valid?
So, Middleware can help as a security checkpoint that can inspect, modify, or reject requests.
Example: Built-in "Auth" Middleware
Example code without Middleware:
routes/web.php:
Route::get('/dashboard', function () { if (!auth()->check()) { return redirect('/login'); } return view('dashboard');});
Same example with auth
Middleware that comes with Laravel:
routes/web.php:
Route::get('/dashboard', function () { return view('dashboard');})->middleware('auth');
Using Middleware is shorter and may be reusable in multiple routes.
The auth
Middleware is an example from the framework core, and there are a few more useful built-in Middleware classes:
-
auth
- User must be logged in:->middleware('auth')
-
guest
- The opposite - user must NOT be logged in:->middleware('guest')
-
throttle
- Rate limiting how many attempts per minute:->middleware('throttle:60,1')
-
can
- Permission Gate/Policy check:->middleware('can:edit,post')
-
verified
- Email verified:->middleware('verified')
You can also create your custom Middleware.
Custom Middleware Example
Goal: Restrict certain features to admin users only.
Generate the Middleware:
php artisan make:middleware CheckAdmin
Define the logic:
app/Http/Middleware/CheckAdmin.php:
namespace App\Http\Middleware; use Closure;use Illuminate\Http\Request;use Symfony\Component\HttpFoundation\Response; class CheckAdmin{ public function handle(Request $request, Closure $next): Response { if (!$request->user() || !$request->user()->isAdmin()) { abort(403, 'Admin access required'); } return $next($request); }}
As you can see, in the handle()
method, you either restrict access or allow the request to proceed with the return $next($request);
statement.
Registering Middleware with Alias
In Laravel 11+, all Middleware configuration happens in the bootstrap/app.php
file using the withMiddleware()
method.
You come up with an alias name for your Middleware class, to be used in the Routes, like the auth
example above.
bootstrap/app.php
use App\Http\Middleware\CheckAdmin; return Application::configure(basePath: dirname(__DIR__)) ->withMiddleware(function ($middleware) { $middleware->alias([ 'admin' => CheckAdmin::class, ]); }) ->create();
Then, use that alias in the routes:
routes/web.php:
// Single MiddlewareRoute::get('/admin/users', [UserController::class, 'index'])->middleware('admin'); // Multiple MiddlewareRoute::get('/admin/settings', SettingController::class) -> Middleware (['auth', 'admin']);
Using Middleware with No Alias
Creating the alias is optional. You can also use Middleware by directly referencing the full class name.
routes/web.php:
use App\Http\Middleware\CheckAdmin; // ... Route::get('/admin/users', [UserController::class, 'index'])->middleware(CheckAdmin::class);
You can also combine the alias and non-alias references.
routes/web.php:
use App\Http\Middleware\ValidateApiToken; // ... Route::get('/api/data', function () { return response()->json(['data' => 'example']);})->middleware([ValidateApiToken::class, 'throttle:60,1']);
Middleware on Route Groups
Apply Middleware to multiple routes at once:
routes/web.php:
Route::middleware(['auth', 'admin'])->group(function () { Route::get('/admin/dashboard', function () { return view('admin.dashboard'); }); Route::get('/admin/users', function () { return view('admin.users'); });});
Middleware with Parameters
Some Middleware requires additional data to work properly. For example, you can check for a role by passing $role
as a parameter.
app/Http/Middleware/CheckRole.php
namespace App\Http\Middleware; use Closure;use Illuminate\Http\Request;use Symfony\Component\HttpFoundation\Response; class CheckRole{ public function handle(Request $request, Closure $next, string $role): Response { if (!$request->user()->hasRole($role)) { abort(403, "Requires {$role} role"); } return $next($request); }}
routes/web.php:
Route::put('/posts/{post}', function ($post) { // Edit post})->middleware('role:editor');
Global Middleware
You may also want to add global Middleware that runs on every HTTP request to your application.
bootstrap/app.php
use App\Http\Middleware\LogRequests; ->withMiddleware(function ($middleware) { $middleware->append(LogRequests::class);})
More in the Docs
For more options and features of Middleware, please read the official Laravel documentation.
Thank you