- Assuming we have freshly created following tables
- users
- Now create 2 following models along with its migrations
- roles table
- permissions table
php artisan make:model Role -m
php artisan make:model Permission -m
- Migration table of above table (Role and Permission) would be:
Schema::create('permissions', function (Blueprint $table) {
$table->increments('id');
$table->string('slug'); //edit-posts
$table->string('name'); // edit posts
$table->timestamps();
});
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('slug'); //web-developer
$table->string('name'); //Web Developer
$table->timestamps();
});
4. User can have Permission (Pivot Table)
Create migration file for users_permissions
php artisan make:migration create_users_permissions_table --create=users_permissions
Schema would be:
Schema::create('users_permissions', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('permission_id')->unsigned();
//FOREIGN KEY CONSTRAINTS
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');
//SETTING THE PRIMARY KEYS
$table->primary(['user_id','permission_id']);
});
5. User can have Role ( Pivot Table)
Create migration file for users_roles
php artisan make:migration create_users_roles_table --create=users_roles
Schema would be:
Schema::create('users_roles', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('role_id')->unsigned();
//FOREIGN KEY CONSTRAINTS
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
//SETTING THE PRIMARY KEYS
$table->primary(['user_id','role_id']);
});
6. Under a particular Role, User may have specific Permission
For example, a user may have the permission for post a topic, and an admin may have the permission to edit or delete a topic. In this case, let’s setup a new table for roles_permissions to handle this complexity.
Create migration file for roles_permissions
php artisan make:migration create_roles_permissions_table --create=roles_permissions
Schema would be:
Schema::create('roles_permissions', function (Blueprint $table) {
$table->integer('role_id')->unsigned();
$table->integer('permission_id')->unsigned();
//FOREIGN KEY CONSTRAINTS
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
$table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');
//SETTING THE PRIMARY KEYS
$table->primary(['role_id','permission_id']);
});
7. Setting Model Relations
Role Model
public function permissions(){
return $this->belongsToMany(Permission::class,'roles_permissions');
}
Permission Model
public function roles(){
return $this->belongsToMany(Role::class,'roles_permissions');
}
8. Creating Trait
Inside of our app directory, let’s create a new directory and name it as Permissions and create a new file namely HasPermissionsTrait.php
<?php
namespace App\Permissions;
use App\Permission;
use App\Role;
trait HasPermissionsTrait {
public function roles() {
return $this->belongsToMany(Role::class,'users_roles');
}
public function permissions() {
return $this->belongsToMany(Permission::class,'users_permissions');
}
public function hasRole( ... $roles ) {
foreach ($roles as $role) {
if ($this->roles->contains('slug', $role)) {
return true;
}
}
return false;
}
protected function hasPermissionTo($permission) {
return $this->hasPermission($permission);
}
protected function hasPermission($permission) {
return (bool) $this->permissions->where('slug', $permission->slug)->count();
}
public function hasPermissionThroughRole($permission) {
foreach ($permission->roles as $role){
if($this->roles->contains($role)) {
return true;
}
}
return false;
}
// public function hasPermissionTo($permission) {
// return $this->hasPermissionThroughRole($permission) || $this->hasPermission($permission);
// }
public function givePermissionsTo(... $permissions) {
$permissions = $this->getAllPermissions($permissions);
dd($permissions);
if($permissions === null) {
return $this;
}
$this->permissions()->saveMany($permissions);
return $this;
}
public function deletePermissions( ... $permissions ) {
$permissions = $this->getAllPermissions($permissions);
$this->permissions()->detach($permissions);
return $this;
}
}
9. Service Proivder
We’ll be utilizing the Laravel’s “can” directive to check if the User have Permission. and instead of using $user->hasPermissionTo(), we’ll use $user->can() To do so, we need to create a new PermissionsServiceProvider for authorization.
php artisan make:provider PermissionsServiceProvider
Writing following code inside PermissionsServiceProvider:
public function boot(){
Permission::get()->map(function($permission){
Gate::define($permission->slug, function($user) use ($permission){
return $user->hasPermissionTo($permission);
});
});
Blade::directive('role', function ($role){
return "<?php if(auth()->check() && auth()->user()->hasRole({$role})) { ?>";
});
Blade::directive('endrole', function ($role){
return "<?php } ?>";
});
}
Register above written Service Provider inside “app\config\app.php” :
'providers' => [
App\Providers\PermissionsServiceProvider::class,
],
10. Middleware – Role and Permission for Route
php artisan make:middleware RoleMiddleware
Code written inside middleware:
public function handle($request, Closure $next, $role, $permission = null)
{
if(!$request->user()->hasRole($role)){
abort(404);
}
if($permission !== null && !$request->user()->can($permission)) {
abort(404);
}
return $next($request);
}
===========================================
View part ==> verify using role
@role('admin')
<h1>Hello from the admin</h1>
@endrole
Route part==> verify through middleware
Route::group(['middleware' => 'role:admin'], function() {
Route::get('/admin', function() {
return 'Welcome Admin';
});
});
Others are:
dd($user->hasRole('developer')); //will return true, if user has role
dd($user->givePermissionsTo('create-tasks')); // will return permission, if not null
dd($user->can('create-tasks')); // will return true, if user has permission