In this example, I will explain to How to create roles and permissions in laravel from scratch. Here we build user management system with roles and permission. You can control the access of user display different UI for the different user.
How to create roles and permissions in laravel from scratch
We are going to Configure Laravel Project.
#1: Download Laravel Project
Establish Laravel Project by the typing following command.
composer create-project --prefer-dist laravel/laravel laravelacl
#2: Database Setup and Migrations
For this tutorial the database information section of the .env
looks like this:
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravelacl DB_USERNAME=root DB_PASSWORD=
First, we define authentication so type following command in cmd.
php artisan make:auth
So we can add table one by one. Type following commands in your cmd.
For permission table :
php artisan make:migration create_permissions_table --create=permissions
It will create a create_permissions_table.php migration file.
//create_permissions_table public function up() { Schema::create('permissions', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); }
For role table:
php artisan make:migration create_roles_table --create=roles
It will create a create_roles_table.php migration file.
//create_roles_table public function up() { Schema::create('roles', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); }
For users permissions table:
php artisan make:migration create_user_permissions_table --create=user_permissions
It will create a create_user_permissions_table.php migration file.
//create_user_permissions_table.php public function up() { Schema::create('user_permissions', function (Blueprint $table) { $table->integer('user_id')->unsigned(); $table->integer('permission_id')->unsigned(); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade'); $table->primary(['user_id','permission_id']); }); }
For users roles table:
php artisan make:migration create_user_roles_table --create=user_roles
It will create a create_user_roles_table.php migration file.
//create_user_roles_table.php public function up() { Schema::create('user_roles', function (Blueprint $table) { $table->integer('user_id')->unsigned(); $table->integer('role_id')->unsigned(); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); $table->primary(['user_id','role_id']); }); }
For roles permissions table:
php artisan make:migration create_role_permissions_table --create=role_permissions
It will create a create_role_permissions_table.php migration file.
//create_role_permissions_table.php public function up() { Schema::create('role_permissions', function (Blueprint $table) { $table->integer('role_id')->unsigned(); $table->integer('permission_id')->unsigned(); $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade'); $table->primary(['role_id','permission_id']); }); }
Save and run.
php artisan migrate
Next, you would find the following tables in your database.
migrations
: This keeps track of migration process that has runpassword_resets
: Holds token information when users demand a new passwordusers
: This holds the user’s data of the applicationpermissions
: This holds the various permissions required in the applicationroles
: This holds the roles in our applicationrole_permission
: This is a pivot table that contains relationship information between the permissions table and the role tableuser_roles
: Also a pivot table, holds relationship information between the roles and the user’s table.user_permissions
: Also a pivot table, holds relationship information between the user’s table and the permissions table.
#3: Build Model
php artisan make:model Role
It will create a Role.php file.
php artisan make:model Permission
It will create a Permission.php file.
Users have permission and roles. So let’s focus on permission. Add following code in Permission.php file.
//Permission.php <?php namespace App; use Illuminate\Database\Eloquent\Model; class Permission extends Model { public function roles() { return $this->belongsToMany(Role::class , 'role_permissions'); } }
Now we can reverse because roles have multiple permissions. So add following code in Role.php file.
//Role.php <?php namespace App; use Illuminate\Database\Eloquent\Model; class Role extends Model { public function permissions() { return $this->belongsToMany(Permission::class , 'role_permissions'); } }
Regarding users have many roles, users have many permissions, roles have many users, permission has may users, and role has many users. Next, we can add two functions in User.php file. Add following code User.php file.
//User.php <?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; use App\Role; use App\Permission; class User extends Authenticatable { use Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; public function roles() { return $this->belongsToMany(Role::class,'user_roles'); } public function permissions() { return $this->belongsToMany(Permission::class,'user_permissions'); } }
Here we define two methods likes roles() and permissions(). We represent many to many relationships because users have many roles and users have many permissions.
#4: Check User Role
Based on user we can check that if a user has a particular role so add following code in User.php file.
//User.php public function hasRole(...$roles) { // dd($roles); foreach($roles as $role) { if($this->roles->contains('name',$role)) { return true; } } return false; }
Add following code in the web.php file.
web.php Route::get('/', function (\Illuminate\Http\Request $request) { $user = $request->user(); dd($user->hasRole('User')); });
Here we define user role as a User. You can also define admin as per your requirement. In hasRole() method if user role match with the established role then returns true otherwise false. First, you can register yourself. In this example we add record manually you can see in below screenshot.
Roles table:
user_roles table:
You can see that we define a user as a role. In roles table, User id is 1 and in the user_roles table, role_id is 1 it means when you can run the application in http://localhost:8000/ it returns true.
#5: Check User Permission
Based on user we can check that if a user has a particular permission to do something so add following code in User.php file.
//User.php public function hasPermission($permission) { return (bool) $this->permissions->where('name',$permission->name)->count(); }
Add following code in the web.php file.
//web.php Route::get('/', function (\Illuminate\Http\Request $request) { $user = $request->user(); dd($user->can('delete')); });
Here we check user to have specific permission, also use laravel can method it work with laravel authorization. Also, we can add permission manually so check below screenshot.
Permissions table:
user_permissions table:
Next, we can add Permission service provider so fire below command in terminal.
php artisan make:provider PermissionServiceProvider
Add service provide in config/app.php file.
'providers' => [ App\Providers\PermissionServiceProvider::class, ]
Add following code in Providers/PermissionServiceProvider.php file.
//PermissionServiceProvider.php <?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use App\Permission; use Gate; class PermissionServiceProvider extends ServiceProvider { /** * Bootstrap services. * * @return void */ public function boot() { Permission::get()->map(function ($permission){ Gate::define($permission->name,function($user) use ($permission) { return $user->hasPermission($permission); }); }); } /** * Register services. * * @return void */ public function register() { // } }
Everytime service provider calls and check specific user has specific permission if it is true it means the user has permission otherwise return false.
#6: Check Permission Through Roles
Now, we check permission through roles so first manually add data into the role_permission table.
It means user role as a User and permission as a Delete.
Add following code in User.php file.
//User.php public function hasPermissionThroughRole($permission) { foreach($permission->roles as $role) { if($this->roles->contains($role)) { return true; } } return false; }
Add hasPermissionThroughRole() method in hasPermission() function.
//User.php public function hasPermission($permission) { return $this->hasPermissionThroughRole($permission) || (bool) $this->permissions->where('name',$permission->name)->count(); }
Add following code in the web.php file.
//web.php Route::get('/', function (\Illuminate\Http\Request $request) { $user = $request->user(); dd($user->can('edit')); });
If you check user have edit permission, then it will return false because we define user permission as a delete.
#7: Modify Permission
In this step we discuss user modify permission and delete the permission which assigns to the user.
Add following code into User.php file.
//User.php public function givePermission(...$permission) { $permissions = $this->getPermissions(array_flatten($permission)); if($permissions === null) { return $this; } $this->permissions()->saveMany($permissions); return $this; } public function getPermissions(array $permissions) { return Permission::whereIn('name',$permissions)->get(); }
First get all permission which user assign if the user does not have any permission then it returns blank.
Add below code in a web.php file.
//web.php Route::get('/', function (\Illuminate\Http\Request $request) { $user = $request->user(); $user->givePermission(); });
When you run the project, then it returns blank because we do not give any permission to the user.
Next, we remove the permission so add following code in User.php file.
//User.php public function removePermission(...$permission) { $permissions = $this->getPermissions(array_flatten($permission)); $this->permissions()->detach($permissions); return $this; }
Here we detach the permission whatever you assign the permission to the user.
Add below code into the web.php file.
//web.php Route::get('/', function (\Illuminate\Http\Request $request) { $user = $request->user(); $user->removePermission('delete'); });
Save and run the project in http://localhost:8000/
You can see in user_permission table remove the delete the user_id and permissio_id.
Again we can permit the user So already we have created the method to use this method in the web.php file.
//web.php Route::get('/', function (\Illuminate\Http\Request $request) { $user = $request->user(); $user->givePermission('delete'); });
You can see in the database user_permissions table add the permission.
Next, we can modify the permission so add modifyPermission() method in User.php file.
//User.php public function modifyPermission(...$permissions) { $this->permissions()->detach(); return $this->givePermission($permissions); }
First, we detach all permission assign the user then give permission which we want. Add below code in the web.php file.
//web.php Route::get('/', function (\Illuminate\Http\Request $request) { $user = $request->user(); $user->modifyPermission('edit'); });
We change permission to edit. So you can see below screenshot that user_permissions table modify.
#8: Change in View File
Now we can modify view file as user permission if the user as edit permission then displays different view then other permissions. So add following code in the home.blade.php file.
//home.blade.php @extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">Dashboard</div> <div class="card-body"> @if (session('status')) <div class="alert alert-success" role="alert"> {{ session('status') }} </div> @endif @can('edit') Hello You can edit the post. @endcan </div> </div> </div> </div> </div> @endsection
You can see the output like below screenshot.
If your permission as a delete then you can see output like below screen.
Next, we can change the view as per user role so modify the code in the app.blade.php file.
//app.blade.php <ul class="navbar-nav ml-auto"> <!-- Authentication Links --> @guest <li class="nav-item"> <a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a> </li> <li class="nav-item"> <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a> </li> @else @if(auth()->user()->hasRole('User')) <li> <a href=""> User </a> </li> @endif <li class="nav-item dropdown"> <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> {{ Auth::user()->name }} <span class="caret"></span> </a> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> {{ __('Logout') }} </a> <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;"> @csrf </form> </div> </li> @endguest </ul>
If login user role as a user role then you can see below screenshot.
If you log in as an admin, then you don’t see user link in the navigation.
At last, we have completed create roles and permissions in laravel is over.

Krunal Lathiya is an Information Technology Engineer by education and web developer by profession. He has worked with many back-end platforms, including Node.js, PHP, and Python. In addition, Krunal has excellent knowledge of cloud technologies including Google Cloud, Firebase, AWS, and Azure, and various softwares and tools.
Working great
Looks goods what about the gating concept
why are you giving user_id, role_id, and permission_id as a primary key?
Hi. How can we cache the permissions and roles so that we dont hit the db each time we are checking user permissions/ roles?
how about vue
Check this out for for managing user roles and permissions in Vue: https://github.com/victorybiz/vue-simple-acl