Basic roles and permissions is a succinct and flexible way to add Role-based Permissions
To get the latest version of Laravel Permissions package, simply require the project using Composer:
$ composer require isakzhanov-r/laravel-permissions
Instead, you can, of course, manually update the dependency block require
in composer.json
and run composer update
if you want to:
{
"require-dev": {
"isakzhanov-r/laravel-permissions": "^1.0"
}
}
If you don't use auto-discovery, add the ServiceProvider
to the providers array in config/app.php
:
IsakzhanovR\Permissions\ServiceProvider::class;
Copy the package config to your local config with the publish command:
php artisan vendor:publish --provider="IsakzhanovR\Permissions\ServiceProvider"
You can create the DB tables by running the migrations:
php artisan migrate
This command will create such roles
, permissions
, user_roles
and permissible
tables.
But you can also use the command for automatic installation
php artisan laravel-permissions:migrate
This command will publish the configuration file. Run the migration command, generate models for tables, and change the User model . all configuration of the package will happen automatically. after executing this command, you don't need to configure anything.
Role.php
Permission.php
Permissible.php
To further customize table names and model namespaces, edit the config/laravel_permissions.php
after you run command
php artisan vendor:publish --provider="IsakzhanovR\Permissions\ServiceProvider
before you run the command php artisan migrate
four new tables will be present:
-
tables
users
- the default table for the relationship to the userroles
- stores role recordspermissions
- stores permission recordsuser_roles
- stores many-to-many relations between roles and userspermissible
- stores many-to-manypolymorphic relations between another essences (User,Role, ...) and permissions
-
foreign_key
- the key relationships in the tables -
models
- references to model classes
- Create a Role model, using the following example:
namespace App\Models;
use IsakzhanovR\Permissions\Models\Role as LaravelRole;
final class Role extends LaravelRole
{
protected $fillable = [
'title',
'slug',
'description',
];
}
- After creating model set the model reference in file
config/laravel_permissions
return [
//...
'models' => [
//....
'role' => App\Models\Role::class, // or use string 'App\\Models\\Role'
//....
],
];
- Or use command
php artisan laravel-permissions:migrate
to generate this automaticaly
The Role
model has three main attributes:
slug
— Unique name for the Role, used for looking up role information in the application layer. For example: "admin", "owner", "manager".title
— Human readable name for the Role. Not necessarily unique and optional. For example: "User Administrator", "Project Owner", "Project Manager".description
— A more detailed explanation of what the Role does. Also optional. And description are optional; its field is nullable in the database.
Base model IsakzhanovR\Permissions\Models\Role
use trait HasPermissions
- Create a Permission model, using the following example:
namespace App\Models;
use IsakzhanovR\Permissions\Models\Permission as LaravelPermission;
final class Permission extends LaravelPermission
{
protected $fillable = [
'title',
'slug',
'description',
];
}
- After creating model set the model reference in file
config/laravel_permissions
return [
//...
'models' => [
//....
'permission' => App\Models\Permission::class,
//....
],
//....
];
- Or use command
php artisan laravel-permissions:migrate
to generate this automaticaly
The Permission
model has the same three attributes as the Role:
slug
— Unique name for the Permission, used for looking up role information in the application layer. For example: "create-user", "update-user", "delete-user".title
— Human readable name for the Permission. Not necessarily unique and optional. For example: "Create User", "Update User", "Delete User".description
— A more detailed explanation of what the Permission does.
if you look at the default model IsakzhanovR\Permissions\Models\Permission
, you will
see morphedByMany relationships for users and roles. You can extend this list with your
own entities.
Example :
final class Permission extends LaravelPermission
{
....
public function posts()
{
return $this->morphedByMany(PostType::class, 'permissible', 'permissible');
}
....
}
And PostType
model must use trait HasPermissions
This is the standard polymorph pivot model The Permissible
model has the same three attributes:
permission_id
— Foreign key for the Permission.permissible_type
— Belong to model (Class name).permissible_id
— Belong to model (key).
You also need to create a model Permissible
and inherit from IsakzhanovR\Permissions\Models\Permissible
use IsakzhanovR\Permissions\Models\Permissible as LaravelPermissible;
final class Permissible extends LaravelPermissible
{
}
After creating model you also need to append link in config file
return [
//...
'models' => [
//....
"permissible" => App\Models\Permissible::class,
//....
],
];
Or use the command to automatically install the package and generate models and a configuration file
Let's start by creating the following Roles
and Permissions
:
use \App\Models\Role;
$admin = new Role();
$admin->slug = 'admin';
$admin->title = 'Administrator';
$admin->description = 'User is the administrator of a project'; // optional
$admin->save();
$manager = new Role();
$manager->title = 'Project Manager';
// if you do not specify 'slug' from title 'project-manager' by the method setSlugAttribute()
$manager->description = 'User is the manager of a given project'; // optional
$manager->save();
Now we just need to creat permissions: We will create permissions without a description, and slug is created from title
use \App\Models\Permission;
$createPost = new Permission();
$createPost->title = 'Create Post'; // slug = create-post
$createPost->save();
$createNews = new Permission();
$createNews->title = 'Create News'; // slug = create-news
$createNews->save();
$updatePost = new Permission();
$updatePost->title = 'Update Post'; // slug = update-post
$updatePost->save();
$updateNews = new Permission();
$updateNews->title = 'Update News'; // slug = update-news
$updateNews->save();
$updateProfile = new Permission();
$updateProfile->title = 'Update Profile'; // slug = update-profile
$updateProfile->save();
$deletePost = new Permission();
$deletePost->title = 'Delete Post'; // slug = delete-post
$deletePost->save();
$deleteNews = new Permission();
$deleteNews->title = 'Delete News'; // slug = delete-news
$deleteNews->save();
First, use the IsakzhanovR\Permissions\Traits\HasPermissions
and IsakzhanovR\Permissions\Traits\HasRoles
traits to your User
model.
If you use the command php artisan laravel-permissions:migrate
, these changes will occur automatically and your User
model will look like this:
use Illuminate\Foundation\Auth\User as Authenticatable;
use IsakzhanovR\Permissions\Traits\HasPermissions;
use IsakzhanovR\Permissions\Traits\HasRoles;
use IsakzhanovR\Permissions\Contracts\PermissibleContract;
use IsakzhanovR\Permissions\Contracts\RoleableContract;
final class User extends Authenticatable implements PermissibleContract, RoleableContract
{
use HasRoles, HasPermissions; // add this traits to your user model
....
}
This package allows users to be associated with permissions and roles. Each role is associated with several permissions. in this case, the User
can have a separate Permission
that is not included in the list of permissions for the role.
Role
and Permission
are the usual Eloquent models.
So, when the roles are created let's assign them to the users. Thanks to the HasRoles
trait this is as easy as:
use \App\Models\User;
$user = User::find(1);
// abstraction over a method $user->roles()->attach($admin->id)
$user->attachRole($admin); // parameter can be an Role object, id or slug
// you can also add multiple user roles
// equivalent to $user->roles()->sync(array($admin->id, $manager->id));
$user->attachRoles($admin,$manager,...);
The method $user->attachRole()
accepts an argument that can be an id
, slug
, or instance of Role
the model
$user->attachRole(1); // id
//Or
$user->attachRole('project-manager'); // slug
//Or
$user->attachRole(Role::find(1)); // instance of Role
//Multiple
$user->attachRoles(1,2,3);
//Or
$user->attachRoles('admin','manager','owner');
//Or
$user->attachRoles(Role::find(1),Role::find(2),Role::find(3));
Let's start adding permissions to roles and users:
$admin->attachPermissions($createPost,$createNews,$updateProfile);
$manager->attachPermissions($updatePost,$updateNews);
$user->attachPermissions($deletePost,$deleteNews);
So we added permissions for the admin and manager roles and also gave personal permissions for the user.
All entities that use trait HasPermission
have access to permission relationships and the following methods for adding permissions:
$subject->attachPermission(1); // id
//Or
$subject->attachPermission('create-post'); // slug
//Or
$subject->attachPermission(Permission::find(1)); // instance of Permission
//Multiple
$subject->attachPermissions(1,'create-post',Permission::find(1),Permission::query()->get());
To revoke roles and permissions, use the following methods:
$user->detachRole(1); // id
//Or
$user->detachRole('project-manager'); // slug
//Or
$user->detachRole(Role::find(1)); // instance of Role
//Multiple
$user->detachRoles(1,'admin',Role::find(1),Role::query()->whereIn('id',[1,2,3])->get());
$subject->detachPermission(1); // id
//Or
$subject->detachPermission('create-post'); // slug
//Or
$subject->detachPermission(Permission::find(1)); // instance of Permission
//Multiple
$subject->detachPermissions(1,2,3);
To synchronization roles and permissions, use the following methods:
$user->syncRoles([1,2,3]); // array roles ids
$role->syncPermissions([1,2,3,4]); //array permissions ids
$subject->syncPermissions([1,2,3,4]); //array permissions ids
Now we can check for roles and permissions simply by doing:
$user = User::find(1);
// with role slug:
$user->hasRole('project-manager'):bool
// with role id:
$user->hasRole(1):bool
// with role instance:
$user->hasRole(Role::find(1)): bool
You can have as many roles as you want for each user, and Vice versa.
$user = User::find(1);
// with roles slug, id or instance:
$user->hasRoles('project-manager',2, Role::find(3)):bool
// if user has only 'admin' role return false
$user->hasRoles('project-manager','admin'):bool
We can check permissions for entities using the following method:
$user = User::find(1);
// with permission slug or id or instance:
$subject->hasPermission('create-post'):bool
// Or use `can`
$subject->can('create-post'):bool
// with permission slug, id or instance:
$user->hasPermissions('create-post',2, Permission::find(3)):bool
You can also use placeholders (wildcards) to check any matching permission by doing:
$user = User::find(1);
// match any create permission:
$subject->matchPermissions('create*'):bool
// match any permission about post
$subject->matchPermissions('*post'):bool
You can use a middleware to filter routes and route groups by permission or role. Add middlewares in $routeMiddleware
of app/Http/Kernel.php
file:
use IsakzhanovR\Permissions\Http\Middleware\Permission;
use IsakzhanovR\Permissions\Http\Middleware\Permissions;
use IsakzhanovR\Permissions\Http\Middleware\Role;
use IsakzhanovR\Permissions\Http\Middleware\Roles;
use IsakzhanovR\Permissions\Http\Middleware\Ability;
protected $routeMiddleware = [
// ...
'role' => Role::class, // Checks for all of the specified roles.
'roles' => Roles::class, // Checks for the presence of one of the specified roles.
'permission' => Permission::class, // Checks whether all of the specified permissions are entered.
'permissions' => Permissions::class, // Checks whether one of the specified permissions has been entered.
'ability' => Ability::class, // Checks for matches in both roles and permissions.
]
You can use a middleware to filter routes and route groups by permission or role
// Example, user has been a `seo-manager` `project-manager` roles and a `create-post` `update-post` permissions
// success access
app('router')
->middleware('role:project-manager,seo-manager', 'permission:create-post,update-post')
->get(...)
// failed access because user has not role `admin`
app('router')
->middleware('role:project-manager,admin')
->get(...)
// failed access because user has not permission `delete-post`
app('router')
->middleware('permission:create-post,update-post,delete-post')
->get(...)
If you need to check whether there are matches in permissions use ability
// Example, user has been a `seo-manager` `project-manager` roles and a `create-post` `update-post` permissions
// success access
app('router')
->middleware('ability:*manager')
->get(...)
// success access
app('router')
->middleware('ability:*post')
->get(...)
// failed access because user has not permission `delete` anything
app('router')
->middleware('ability:delete*')
->get(...)
You can create a role or a permission from a console with artisan commands:
php artisan laravel-permissions:create-role {name}
php artisan laravel-permissions:create-permission {name}
You can also invoke the creation of roles and permissions from your application:
Artisan::call('laravel-permissions:create-role', ['name' => $name]); Artisan::call('laravel-permissions:create-permission', ['name' => $name]);
This package was written under Andrey Helldar supervision under the MIT License.