Laravel Permission
Getting started
Installation
This package can be used with Laravel 5.8 or higher.
1. Consult the Prerequisites page for important considerations regarding your User models!
2. This package publishes a
config/permission.php
file. If you already have
a file by that name, you must rename or remove it.
3. You can install the package via composer:
composer require spatie/laravel-permission
4. Optional: The service provider will automatically get
registered. Or you may manually add the service provider in
your config/app.php
file:
'providers' => [
// ...
Spatie\Permission\PermissionServiceProvider::class,
];
5. You should publish
the migration
and the config/permission.php
config file with:
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
6. NOTE: If you are using UUIDs, see the Advanced section of the docs on UUID steps, before you continue. It explains some changes you may want to make to the migrations and config file before continuing. It also mentions important considerations after extending this package’s models for UUID capability.
7. Run the migrations: After the config and migration have been published and configured, you can create the tables for this package by running:
php artisan migrate
8. Add the necessary trait to your User model: Consult the Basic Usage section of the docs for how to get started using the features of this package.
Basic Usage
First, add the
Spatie\Permission\Traits\HasRoles
trait to your
User
model(s):
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
// ...
}
This package allows for users to be associated with permissions and roles. Every role is associated with multiple permissions. A Role and a Permission are regular Eloquent models. They require a name and can be created like this:
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
$role = Role::create(['name' => 'writer']);
$permission = Permission::create(['name' => 'edit articles']);
A permission can be assigned to a role using 1 of these methods:
$role->givePermissionTo($permission);
$permission->assignRole($role);
Multiple permissions can be synced to a role using 1 of these methods:
$role->syncPermissions($permissions);
$permission->syncRoles($roles);
A permission can be removed from a role using 1 of these methods:
$role->revokePermissionTo($permission);
$permission->removeRole($role);
If you’re using multiple guards the guard_name attribute needs to be set as well. Read about it in the using multiple guards section of the readme.
The HasRoles
trait adds Eloquent relationships
to your models, which can be accessed directly or used as a
base query:
// get a list of all permissions directly assigned to the user
$permissionNames = $user->getPermissionNames(); // collection of name strings
$permissions = $user->permissions; // collection of permission objects
// get all permissions for the user, either directly, or from roles, or from both
$permissions = $user->getDirectPermissions();
$permissions = $user->getPermissionsViaRoles();
$permissions = $user->getAllPermissions();
// get the names of the user's roles
$roles = $user->getRoleNames(); // Returns a collection
The HasRoles
trait also adds a
role
scope to your models to scope the query to
certain roles or permissions:
$users = User::role('writer')->get(); // Returns only users with the role 'writer'
The role
scope can accept a string, a
\Spatie\Permission\Models\Role
object or an
\Illuminate\Support\Collection
object.
The same trait also adds a scope to only get users that have a certain permission.
$users = User::permission('edit articles')->get(); // Returns only users with the permission 'edit articles' (inherited or directly)
The scope can accept a string, a
\Spatie\Permission\Models\Permission
object or
an \Illuminate\Support\Collection
object.
Using a middleware
This package comes with RoleMiddleware
,
PermissionMiddleware
and
RoleOrPermissionMiddleware
middleware. You can
add them inside your app/Http/Kernel.php
file.
protected $routeMiddleware = [
// ...
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];
Then you can protect your routes using middleware rules:
Route::group(['middleware' => ['role:super-admin']], function () {
//
});
Route::group(['middleware' => ['permission:publish articles']], function () {
//
});
Route::group(['middleware' => ['role:super-admin','permission:publish articles']], function () {
//
});
Route::group(['middleware' => ['role_or_permission:super-admin|edit articles']], function () {
//
});
Route::group(['middleware' => ['role_or_permission:publish articles']], function () {
//
});
Alternatively, you can separate multiple roles or permission
with a |
(pipe) character:
Route::group(['middleware' => ['role:super-admin|writer']], function () {
//
});
Route::group(['middleware' => ['permission:publish articles|edit articles']], function () {
//
});
Route::group(['middleware' => ['role_or_permission:super-admin|edit articles']], function () {
//
});
You can protect your controllers similarly, by setting desired middleware in the constructor:
public function __construct()
{
$this->middleware(['role:super-admin','permission:publish articles|edit articles']);
}
public function __construct()
{
$this->middleware(['role_or_permission:super-admin|edit articles']);
}
Blade directives
Permissions
This package doesn’t add any permission-specific Blade
directives. Instead, use Laravel’s native
@can
directive to check if a user has a certain
permission.
@can('edit articles')
//
@endcan
or
@if(auth()->user()->can('edit articles') && $some_other_condition)
//
@endif
You can use @can
, @cannot
,
@canany
, and @guest
to test for
permission-related access.
Roles
As discussed in the Best Practices section of the docs, it is strongly recommended to always use permission directives, instead of role directives.
Additionally, if your reason for testing against Roles is for a Super-Admin, see the Defining A Super-Admin section of the docs.
If you actually need to test for Roles, this package offers some Blade directives to verify whether the currently logged in user has all or any of a given list of roles.
Optionally you can pass in the guard
that the
check will be performed on as a second argument.
Blade and Roles
Check for a specific role:
@role('writer')
I am a writer!
@else
I am not a writer...
@endrole
is the same as
@hasrole('writer')
I am a writer!
@else
I am not a writer...
@endhasrole
Check for any role in a list:
@hasanyrole($collectionOfRoles)
I have one or more of these roles!
@else
I have none of these roles...
@endhasanyrole
// or
@hasanyrole('writer|admin')
I am either a writer or an admin or both!
@else
I have none of these roles...
@endhasanyrole
Check for all roles:
@hasallroles($collectionOfRoles)
I have all of these roles!
@else
I do not have all of these roles...
@endhasallroles
// or
@hasallroles('writer|admin')
I am both a writer and an admin!
@else
I do not have all of these roles...
@endhasallroles
Alternatively, @unlessrole
gives the reverse
for checking a singular role, like this:
@unlessrole('does not have this role')
I do not have the role
@else
I do have the role
@endunlessrole