Introduction #
In modern web applications you often need to control what each user can do. Laravel provides a simple gate system, but for complex role‑based access the spatie/laravel-permission package is the most popular choice.
Installation #
composer require spatie/laravel-permission
Publishing the config and migrations #
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
Setting up roles and permissions #
Add the HasRoles trait to your User model:
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
}
Create roles and permissions, for example in a seeder:
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
Permission::create(['name' => 'edit articles']);
Permission::create(['name' => 'delete articles']);
$admin = Role::create(['name' => 'admin']);
$admin->givePermissionTo(['edit articles', 'delete articles']);
$author = Role::create(['name' => 'author']);
$author->givePermissionTo('edit articles');
Assigning roles to users #
$user = User::find(1);
$user->assignRole('admin'); // or
$user->syncRoles(['author']);
Using middleware #
Add the middleware to app/Http/Kernel.php:
protected $routeMiddleware = [
// …
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
];
Protect routes:
Route::group(['middleware' => ['role:admin']], function () {
Route::delete('/articles/{id}', 'ArticleController@destroy');
});
Route::get('/articles/{id}/edit', 'ArticleController@edit')
->middleware('permission:edit articles');
Checking permissions in Blade #
@can('edit articles')
<a href="{{ route('articles.edit', $article) }}">Edit</a>
@endcan
@role('admin')
<button>Delete</button>
@endrole
Testing #
public function test_admin_can_delete_article()
{
$admin = User::factory()->create()->assignRole('admin');
$article = Article::factory()->create();
$this->actingAs($admin)
->delete(route('articles.destroy', $article))
->assertRedirect();
}
Conclusion #
With spatie/laravel-permission you can implement a clean, database‑driven permission system in minutes. Remember to cache permissions in production for best performance:
php artisan permission:cache-reset