User role in Laravel 8

A very simple approach

Laravel has some great packages for roles and permissions like SPATIE. However, sometimes we may need a very simple and easy to implement approach.

In this example we add column role in the users table and then we implement a middleware class in order to check if the currently logged in user can visit a route or not.
In this example we assume three roles:

  • user
  • moderator
  • admin

and their respective pages:

  • user has access to the user page
  • moderator has access to the moderator, and user pages
  • admin has access to the admin, moderator, and user pages

Source code on GitHub: github.com/codingsummer21/userroles

Create new project

An article on building a simple project in Laravel

composer create-project laravel/laravel roles

Configure the database (use your own credentials here)

DB_DATABASE=roles
DB_USERNAME=roles_user
DB_PASSWORD=1111

Migrate, add breeze (for authentication scaffolding) and run the server

php artisan migrate
composer require laravel/breeze --dev
php artisan breeze:install
npm install
npm run dev
php artisan serve

Add the role column to users table

In order to modify the structure of database table we need a new migration:

php artisan make:migration add_role_to_users_table --table=users

this command will tell to artisan that we plan to modify the table users.

Then, in the created migration specify the new column in the up method:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('role')->default('user');
    });
}

and run a new migration:

php artisan migrate

Now that the new column is created, register some users. As the default role value is user get into the database and change someone to moderator and another one to admin.

Create the CheckRole middleware

Middleware provide a convenient mechanism for inspecting and filtering HTTP requests entering your application. (Laravel documentation) So, we can add a middleware to check if the currently logged in user's role has permission to view the requested page.

Create the middleware class:

php artisan make:middleware CheckRole

Then complete the handle method:

public function handle(Request $request, Closure $next, ...$roles)
{
    return collect($roles)->contains(auth()->user()->role) ? $next($request) : redirect('login');
}

The third parameter, ...$roles, means that we can pass a variable number of arguments to the method, hence, to check against many roles.

So, this function checks if the provided roles collection contains the current user's role and if yes, proceeds to the next middleware (if any) or to the request, otherwise, if redirects to the login page. (Note: an error page might be more appropriate here).

Finally, register the middleware to the $routeMiddleware list in the Kernel.php file:

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

Create a page for each role

In the resources folder create a subfolder pages and inside this folder add the following pages:

  • user.blade.php
  • moderator.blade.php
  • admin.blade.php

Add a Controller

Create a new controller:

php artisan make:controller PagesController

and in this controller add a method to invoke each page. For example for the admin page create the method:

public function adminPage() {
    return view("pages.admin");
}

Specify the routes

Now, we need to add routes for these pages. As all if them require access by authenticated users they are added to a group which requires middleware auth first, then for each route add the roles middleware specifying the appropriate roles.

Route::middleware(['auth'])->group(function () 
{
    Route::get('/user', [PagesController::class, 'userPage'])->middleware('roles:user,moderator,admin');
    Route::get('/moderator', [PagesController::class, 'moderatorPage'])->middleware('roles:moderator,admin');
    Route::get('/admin', [PagesController::class, 'adminPage'])->middleware('roles:admin');
});

Test the application using different users of any role type and check if the respective pages are accessible or not.

Endnote

This is a very simple example of roles in Laravel 8 without the use of a package. It is not a perfect solution but it's useful in order to understand the mechanism of middleware.
Also, it might be useful for some simple applications that don't require complicated roles and permissions.