Courses

[FREE] Laravel 11 For Beginners: Your First Project

Middleware and Route Groups

Now, let's talk about Middleware and authentication. We created an administrator user, so let's assign access to that user to manage categories.


We have already seen the auth Middleware, which allows only logged-in users to access Routes. The auth is one of the Middlewares offered by the Laravel framework.

Middleware runs some checks before Routes, and if it returns false, it shows errors or redirect to some error page. For example, if someone wants to visit the /dashboard URL, protected with auth Middleware, they will automatically get redirected to the login page.

Laravel has some default Middlewares. You can always check them in the official documentation.

The web Middleware Group
Illuminate\Cookie\Middleware\EncryptCookies
Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse
Illuminate\Session\Middleware\StartSession
Illuminate\View\Middleware\ShareErrorsFromSession
Illuminate\Foundation\Http\Middleware\ValidateCsrfToken
Illuminate\Routing\Middleware\SubstituteBindings

We should assign our category resource route to the auth Middleware. We could add the middleware() method to the Route and provide the Middleware, or if the Route has multiple Middlewares, they can be provided as an array. But let's use Route group instead.

In the routes/web.php, we already have one Route group for the profile links. We can move all the Routes to that group. The syntax to have grouped Routes is to use what you need on a Route facade like middleware, prefix, etc., and then have a group method with a closure and add all the Routes in the closure.

routes/web.php:

Route::get('/', function () {
return view('welcome');
});
 
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
 
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
 
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
 
Route::resource('categories', \App\Http\Controllers\CategoryController::class);
});
 
require __DIR__.'/auth.php';
 
Route::resource('categories', \App\Http\Controllers\CategoryController::class);

If you try to access any of these routes as a guest, you should be redirected to the login page.


Now, let's create our custom Middleware to check if a user is an admin. Middleware can be created using an artisan command.

php artisan make:middleware IsAdminMiddleware

Middlewares are created in the app/Http/Middleware folder. The default structure of the Middleware is the handle(), which returns the next request. Before the return, you can add conditions that your application needs and abort the next request if needed.

In our created Middleware, if the is_admin field in the User table is false, we must abort with the forbidden status. The currently authenticated user can be obtained using Laravel helpers auth()->user() and then call the needed field.

app/Http/Middleware/IsAdminMiddleware.php:

class IsAdminMiddleware
{
public function handle(Request $request, Closure $next): Response
{
if (! auth()->user()->is_admin) {
abort(403);
}
 
return $next($request);
}
}

Next, we must register our Middleware to use it as an alias. Middleware is registered in the bootstrap/app.php file.

bootstrap/app.php:

return Application::configure(basePath: dirname(__DIR__))
->withProviders()
->withRouting(
web: __DIR__.'/../routes/web.php',
// api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
// channels: __DIR__.'/../routes/channels.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
'is_admin' => \App\Http\Middleware\IsAdminMiddleware::class,
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();

Now, we can use is_admin Middleware in our application. Because we need to restrict access only to category routes, Middleware needs to be used on that route instead of a group.

routes/web.php:

Route::get('/', function () {
return view('welcome');
});
 
Route::middleware('auth')->group(function () {
// ...
 
Route::resource('categories', \App\Http\Controllers\CategoryController::class)->middleware('is_admin');
});
 
require __DIR__.'/auth.php';

Another option to apply Middleware instead of using aliases pass the Middleware class.

routes/web.php:

Route::get('/', function () {
return view('welcome');
});
 
Route::middleware('auth')->group(function () {
// ...
 
Route::resource('categories', \App\Http\Controllers\CategoryController::class)->middleware(\App\Http\Middleware\IsAdminMiddleware::class);
});
 
require __DIR__.'/auth.php';

If you try to access categories Routes with a user who isn't an admin, you will see a forbidden error message.

avatar

After add the middleware IsAdminMiddleware, then it show errors: Attempt to read property "is_admin" on null

avatar

is_admin value cannot be null. It should be true (1) or false (0)