Laravel Tutorial

Implementing Role-Based Permissions in Laravel with Spatie Package

Admin User
Admin User
Apr 27, 2026
2 min read

Key Takeaways

  • ## 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 ac...

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

FAQs

Do I need to run any command after adding new permissions?
Yes, run `php artisan permission:cache-reset` to clear the permission cache so new permissions are recognized.
Can I assign multiple roles to a single user?
Absolutely. Use `$user->assignRole(['admin', 'editor']);` or `$user->syncRoles([...]);` to manage multiple roles.

Want more content like this?

Explore more tutorials in the Laravel section.

Explore Laravel

You might also like