Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Permission Laravel Package

spatie/laravel-permission

Database-backed roles and permissions for Laravel. Assign roles and permissions to users, sync them to the Gate, and check abilities with Laravel’s built-in can()/authorize features. Includes migrations, caching, teams, and flexible model setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-permission
    

    Run migrations:

    php artisan migrate
    
  2. Publish Config (Optional):

    php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
    

    Configure config/permission.php (e.g., enable/disable teams, cache).

  3. First Use Case: Assign a role to a user in a controller:

    use Spatie\Permission\Models\Role;
    use Spatie\Permission\Models\Permission;
    
    $role = Role::create(['name' => 'admin']);
    $permission = Permission::create(['name' => 'edit articles']);
    $role->givePermissionTo($permission);
    
    $user = User::find(1);
    $user->assignRole($role);
    
  4. Check Permissions:

    if ($user->can('edit articles')) {
        // Grant access
    }
    

Implementation Patterns

Core Workflows

1. Role-Based Access Control (RBAC)

  • Assign Roles:
    $user->assignRole('admin'); // Single role
    $user->assignRole(['editor', 'moderator']); // Multiple roles
    
  • Check Roles:
    if ($user->hasRole('admin')) { ... }
    if ($user->hasAnyRole(['editor', 'moderator'])) { ... }
    

2. Permission-Based Access Control

  • Grant Permissions:
    $user->givePermissionTo('edit articles');
    $user->givePermissionTo(['create posts', 'delete comments']);
    
  • Check Permissions:
    if ($user->can('edit articles')) { ... }
    if ($user->can(['edit articles', 'publish posts'])) { ... }
    

3. Role-Permission Hybrid

  • Attach Permissions to Roles:
    $role = Role::findByName('editor');
    $role->givePermissionTo('edit articles');
    
  • Sync Roles/Permissions:
    $user->syncRoles(['admin', 'editor']); // Replace all roles
    $user->syncPermissions(['edit articles', 'publish posts']); // Replace all permissions
    

4. Middleware Integration

  • Route-Level Protection:
    Route::get('/admin', function () {
        // ...
    })->middleware(['role:admin']);
    
  • Custom Middleware:
    public function handle(Request $request, Closure $next)
    {
        if (!$request->user()->can('manage users')) {
            abort(403);
        }
        return $next($request);
    }
    

5. Teams (Optional)

  • Enable in config/permission.php:
    'teams' => [
        'enabled' => true,
    ],
    
  • Assign roles to teams:
    $team = Team::find(1);
    $team->assignRole('admin');
    

6. Wildcard Permissions

  • Define wildcard permissions (e.g., posts.*):
    $user->givePermissionTo('posts.*');
    
  • Check wildcard matches:
    $user->can('posts.create'); // Returns true
    

7. Policy Integration

  • Use Laravel’s policies with permissions:
    class PostPolicy {
        public function update(User $user, Post $post) {
            return $user->can('edit posts');
        }
    }
    

Integration Tips

1. Seeding Permissions

  • Use DatabaseSeeder to predefine roles/permissions:
    public function run()
    {
        $admin = Role::create(['name' => 'admin']);
        $admin->givePermissionTo(Permission::all());
    
        $user = User::find(1);
        $user->assignRole($admin);
    }
    

2. API Gatekeeper

  • Protect API endpoints:
    Route::middleware(['auth:sanctum', 'can:manage users'])->group(function () {
        // Admin-only routes
    });
    

3. Blade Directives

  • Create custom Blade directives for permissions:
    Blade::directive('permission', function ($expression) {
        return "<?php if(auth()->user()->can({$expression})): ?>";
    });
    
    Usage:
    @permission('edit articles')
        <button>Edit</button>
    @endpermission
    

4. Event Listeners

  • Listen for permission changes:
    public function handle(PermissionAttachedEvent $event)
    {
        Log::info("User {$event->user->name} gained permission {$event->permission->name}");
    }
    

5. Caching

  • Cache permissions for performance:
    $user->getAllPermissions(); // Cached by default
    
    Clear cache when needed:
    php artisan permission:cache-reset
    

Gotchas and Tips

Pitfalls

1. Case Sensitivity

  • Permission/role names are case-sensitive by default. Normalize names (e.g., strtolower()) if needed.

2. Wildcard Overhead

  • Wildcard permissions (e.g., posts.*) can slow down checks if overused. Test performance in high-traffic apps.

3. Team Feature Quirks

  • Teams require additional setup (teams table, team_user pivot). Ensure teams.enabled is true in config.
  • Gotcha: Disabling teams mid-project may break existing team-related logic.

4. Migration Conflicts

  • If extending the users table, ensure morphTo() relationships (for teams) are added after Spatie’s migrations.

5. Permission Caching

  • Cached permissions may not reflect real-time changes. Use permission:cache-reset after bulk updates.

6. Laravel 12+ Quirks

  • Policy Binding: Use ->middleware('can:permission') instead of ->middleware('can:permission,name') (deprecated).
  • Service Provider: Spatie now uses PackageServiceProvider (no register method in AppServiceProvider).

Debugging Tips

1. Permission Not Working?

  • Verify the permission exists:
    $permission = Permission::where('name', 'edit articles')->first();
    dd($permission); // Check if null
    
  • Check user-permission relationships:
    $user->permissions; // Inspect loaded permissions
    

2. Role Not Assigning?

  • Ensure the role exists:
    $role = Role::findByName('admin');
    dd($role); // Check if null
    
  • Check pivot table (model_has_roles):
    SELECT * FROM model_has_roles WHERE model_type = 'App\Models\User' AND model_id = 1;
    

3. Wildcard Not Matching?

  • Wildcards must end with .* (e.g., posts.*). Test with:
    $user->can('posts.create'); // Should return true if 'posts.*' is assigned
    

4. Middleware Failing Silently

  • Add logging to middleware:
    public function handle(Request $request, Closure $next)
    {
        Log::debug('User can:', [$request->user()->can('edit articles')]);
        return $next($request);
    }
    

Extension Points

1. Custom Models

  • Extend Permission/Role models:
    class CustomPermission extends Permission {
        protected $table = 'custom_permissions';
    }
    
    Register in AuthServiceProvider:
    $this->registerPolicies();
    Permission::useModel(CustomPermission::class);
    

2. Custom Guards

  • Use PermissionGuard for non-standard auth:
    $guard = app('auth')->guard('api');
    if ($guard->user()->can('access api')) { ... }
    

3. Custom Permission Resolver

  • Override permission resolution logic:
    class CustomPermissionResolver implements PermissionResolver {
        public function resolve($user, $permission) {
            // Custom logic
            return true;
        }
    }
    
    Bind in AppServiceProvider:
    $this->app->bind(PermissionResolver::class, CustomPermissionResolver::class);
    

4. Custom Events

  • Extend event classes (e.g., PermissionAttachedEvent):
    class CustomPermissionAttachedEvent extends PermissionAttachedEvent {
        public function __construct(User $user, Permission $permission, array $extra) {
            parent::__construct($user, $permission);
            $this->extra = $extra;
        }
    }
    

5. Custom Commands

  • Extend existing commands (e.g., AssignRoleCommand):
    class CustomAssignRoleCommand extends AssignRole
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai