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.