- How do I install spatie/laravel-permission in a Laravel 12 app?
- Install with composer require spatie/laravel-permission, then publish the config and migration stub via the vendor:publish command for Spatie\Permission\PermissionServiceProvider and run php artisan migrate. Add the HasRoles trait to your User model, or to any other Eloquent model that needs roles and permissions. On Laravel 11 and 12 you also register the role, permission, and role_or_permission middleware aliases in bootstrap/app.php. Plan to spend most of your setup time on defining and seeding the permission taxonomy rather than on wiring.
- Does laravel-permission work with Laravel policies, gates, and Blade @can?
- Yes. The package registers every stored permission on Laravel's Gate, so enforcement stays on the native surface: $user->can('edit articles'), policies, middleware, and Blade @can directives. It does not introduce a parallel authorization system, so adopting it does not obsolete existing policies or can() checks in your controllers and views. This makes it a thin persistence layer behind the authorization patterns you already use.
- Which PHP and Laravel versions does laravel-permission v7 require?
- Version 7 targets Laravel 12 and requires PHP ^8.4, although the PHP floor has shifted between releases, with 7.3.0 relaxing it to ^8.3 before reverting. Pin a minimum of 7.2.2, which contains a wildcard-index cache invalidation fix, and audit any custom code touching package classes because v7 renamed several of them (for example PermissionAttached became PermissionAttachedEvent and CacheReset became CacheResetCommand). The maintainers have signalled a future v8 with larger breaking changes, so keep an upgrade cadence in mind.
- Why are users still seeing old permissions after I updated the database?
- Permission resolution is cached under a single key, so any direct database write, manual SQL fix, or seeder that bypasses the package API leaves stale grants behind. Always change assignments through the package methods such as givePermissionTo, assignRole, and syncRoles, which reset the cache automatically. After out-of-band changes, run php artisan permission:cache-reset to force a fresh read. This invalidation discipline is the most common source of production incidents with this package.
- How do I protect routes with the role and permission middleware in Laravel 11 and 12?
- Register the role, permission, and role_or_permission aliases in bootstrap/app.php, then attach them to routes or groups, for example ->middleware('role:admin') or ->middleware('permission:edit articles'). They accept pipe-separated values and can also be applied inside controllers. Because they sit on top of the Gate, results stay consistent with policies and @can checks elsewhere in the app.
- Do I need the teams feature for multi-tenant role scoping?
- Only if users must hold different roles per tenant, because enabling teams changes the pivot schema to include team_id and is genuinely painful to retrofit later. If global roles are sufficient for your product, leave teams disabled and keep your options open. Note that the teams code path is less battle-tested than the core path, with 7.4.1 shipping as a hotfix for teams() throwing when the feature is disabled. Decide this before you seed production data.
- Is spatie/laravel-permission safe to use with Laravel Octane?
- Yes, but pin at least 7.2.2. A time-of-check to time-of-use race condition in permission loading under Octane was fixed in 6.22.0, and a wildcard-index cache invalidation bug was fixed in 7.2.2. Both are resolved, but they show the caching fast path has had correctness edges under concurrency and role-sync operations. Re-run your authorization tests if you enable Octane or scale to a multi-node fleet.
- Can I assign roles without building an admin UI first?
- Yes. The package ships artisan commands for assigning and revoking roles and permissions, which gives you a working admin path on day one. That is usually enough for internal tools or the early phase of a project, letting you defer UI work while the permission taxonomy stabilises. You can also seed roles and permissions programmatically in your seeders using the same API.
- Does laravel-permission keep an audit trail of who granted a permission and when?
- No. The package stores current assignments only, not a history of changes or the actor who made them. If you need compliance-grade auditing, listen for the role and permission attach and detach events fired by the package and persist them to your own log table. Design that table early, because backfilling history after the fact is not possible.
- Should I build my own roles and permissions instead of using this package?
- For an Eloquent-based Laravel app, buying over building is the right call: this space is well solved and a 3 to 5 day integration is typical, most of it taxonomy and seeding work. Laravel's native Gate handles abilities but not database-backed role storage, so a custom build mostly re-implements tables, traits, caching, and middleware that already exist and are widely used across the ecosystem, including in Laravel starter kits. Build your own only if your authorization model is purely attribute or policy driven with no role taxonomy at all.