laravel-permission-development by spatie/laravel-permission
npx skills add https://github.com/spatie/laravel-permission --skill laravel-permission-development当使用 spatie/laravel-permission 处理授权、角色、权限、访问控制、中间件守卫或 Blade 权限指令时,请使用此技能。
$user->can('permission-name')(通过 Gate 支持超级管理员)。HasRoles trait(包含 HasPermissions)被添加到用户模型中。将 HasRoles trait 添加到你的用户模型:
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
}
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
$role = Role::create(['name' => 'writer']);
$permission = Permission::create(['name' => 'edit articles']);
// findOrCreate 是幂等的(对种子数据安全)
$role = Role::findOrCreate('writer', 'web');
$permission = Permission::findOrCreate('edit articles', 'web');
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// 为用户分配角色
$user->assignRole('writer');
$user->assignRole('writer', 'admin');
$user->assignRole(['writer', 'admin']);
$user->syncRoles(['writer', 'admin']); // 替换所有角色
$user->removeRole('writer');
// 为角色分配权限(推荐方式)
$role->givePermissionTo('edit articles');
$role->givePermissionTo(['edit articles', 'delete articles']);
$role->syncPermissions(['edit articles', 'delete articles']);
$role->revokePermissionTo('edit articles');
// 反向分配
$permission->assignRole('writer');
$permission->syncRoles(['writer', 'editor']);
$permission->removeRole('writer');
// 权限检查(推荐 - 通过 Gate 支持超级管理员)
$user->can('edit articles');
$user->canAny(['edit articles', 'delete articles']);
// 直接包方法(绕过 Gate,不支持超级管理员)
$user->hasPermissionTo('edit articles');
$user->hasAnyPermission(['edit articles', 'publish articles']);
$user->hasAllPermissions(['edit articles', 'publish articles']);
$user->hasDirectPermission('edit articles');
// 角色检查
$user->hasRole('writer');
$user->hasAnyRole(['writer', 'editor']);
$user->hasAllRoles(['writer', 'editor']);
$user->hasExactRoles(['writer', 'editor']);
// 获取分配的角色和权限
$user->getRoleNames(); // 角色名称字符串的集合
$user->getPermissionNames(); // 权限名称字符串的集合
$user->getDirectPermissions(); // 仅直接权限
$user->getPermissionsViaRoles(); // 通过角色继承的权限
$user->getAllPermissions(); // 直接和继承的权限
$users = User::role('writer')->get();
$users = User::withoutRole('writer')->get();
$users = User::permission('edit articles')->get();
$users = User::withoutPermission('edit articles')->get();
在 bootstrap/app.php 中注册中间件别名:
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
'role' => \Spatie\Permission\Middleware\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class,
]);
})
在路由中使用(管道 | 表示 OR 逻辑):
Route::middleware(['permission:edit articles'])->group(function () { ... });
Route::middleware(['role:manager|writer'])->group(function () { ... });
Route::middleware(['role_or_permission:manager|edit articles'])->group(function () { ... });
// 使用特定守卫
Route::middleware(['role:manager,api'])->group(function () { ... });
对于单一权限,Laravel 内置的 can 中间件也有效:
Route::middleware(['can:edit articles'])->group(function () { ... });
优先使用 @can(基于权限)而非 @role(基于角色):
@can('edit articles')
{{-- 用户可以编辑文章(支持超级管理员) --}}
@endcan
@canany(['edit articles', 'delete articles'])
{{-- 用户至少能做其中一项 --}}
@endcanany
@role('admin')
{{-- 仅用于超级管理员类型的检查 --}}
@endrole
@hasanyrole('writer|admin')
{{-- 拥有 writer 或 admin 角色 --}}
@endhasanyrole
在 AppServiceProvider::boot() 中使用 Gate::before:
use Illuminate\Support\Facades\Gate;
public function boot(): void
{
Gate::before(function ($user, $ability) {
return $user->hasRole('Super Admin') ? true : null;
});
}
这使得 $user->can() 和 @can 对超级管理员始终返回 true。必须返回 null(而非 false)以允许对其他用户进行正常检查。
在策略方法内部使用 $user->can() 来检查权限:
class PostPolicy
{
public function update(User $user, Post $post): bool
{
if ($user->can('edit all posts')) {
return true;
}
return $user->can('edit own posts') && $user->id === $post->user_id;
}
}
enum RolesEnum: string
{
case WRITER = 'writer';
case EDITOR = 'editor';
}
enum PermissionsEnum: string
{
case EDIT_POSTS = 'edit posts';
case DELETE_POSTS = 'delete posts';
}
// 创建时需要 ->value
Permission::findOrCreate(PermissionsEnum::EDIT_POSTS->value, 'web');
// 大多数方法直接接受枚举
$user->assignRole(RolesEnum::WRITER);
$user->hasRole(RolesEnum::WRITER);
$role->givePermissionTo(PermissionsEnum::EDIT_POSTS);
$user->hasPermissionTo(PermissionsEnum::EDIT_POSTS);
填充数据时始终刷新权限缓存:
class RolesAndPermissionsSeeder extends Seeder
{
public function run(): void
{
// 重置缓存
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// 创建权限
Permission::findOrCreate('edit articles', 'web');
Permission::findOrCreate('delete articles', 'web');
// 创建角色并分配权限
Role::findOrCreate('writer', 'web')
->givePermissionTo(['edit articles']);
Role::findOrCreate('admin', 'web')
->givePermissionTo(Permission::all());
}
}
在运行迁移之前在 config/permission.php 中启用:
'teams' => true,
在中间件中设置活动团队:
setPermissionsTeamId($teamId);
切换团队时,取消设置缓存的关系:
$user->unsetRelation('roles')->unsetRelation('permissions');
在 config/permission.php 中启用:
'events_enabled' => true,
可用事件:位于 Spatie\Permission\Events 命名空间中的 RoleAttachedEvent、RoleDetachedEvent、PermissionAttachedEvent、PermissionDetachedEvent。
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions()Permission::insert() 以提高速度,但之后要刷新缓存。每周安装量
79
代码仓库
GitHub 星标数
12.9K
首次出现
2026年2月13日
安全审计
已安装于
opencode77
gemini-cli76
amp76
github-copilot76
codex76
kimi-cli76
Use this skill when working with authorization, roles, permissions, access control, middleware guards, or Blade permission directives using spatie/laravel-permission.
$user->can('permission-name') for all authorization checks (supports Super Admin via Gate).HasRoles trait (which includes HasPermissions) is added to User models.Add the HasRoles trait to your User model:
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
}
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
$role = Role::create(['name' => 'writer']);
$permission = Permission::create(['name' => 'edit articles']);
// findOrCreate is idempotent (safe for seeders)
$role = Role::findOrCreate('writer', 'web');
$permission = Permission::findOrCreate('edit articles', 'web');
// Assign roles to users
$user->assignRole('writer');
$user->assignRole('writer', 'admin');
$user->assignRole(['writer', 'admin']);
$user->syncRoles(['writer', 'admin']); // replaces all
$user->removeRole('writer');
// Assign permissions to roles (preferred)
$role->givePermissionTo('edit articles');
$role->givePermissionTo(['edit articles', 'delete articles']);
$role->syncPermissions(['edit articles', 'delete articles']);
$role->revokePermissionTo('edit articles');
// Reverse assignment
$permission->assignRole('writer');
$permission->syncRoles(['writer', 'editor']);
$permission->removeRole('writer');
// Permission checks (preferred - supports Super Admin via Gate)
$user->can('edit articles');
$user->canAny(['edit articles', 'delete articles']);
// Direct package methods (bypass Gate, no Super Admin support)
$user->hasPermissionTo('edit articles');
$user->hasAnyPermission(['edit articles', 'publish articles']);
$user->hasAllPermissions(['edit articles', 'publish articles']);
$user->hasDirectPermission('edit articles');
// Role checks
$user->hasRole('writer');
$user->hasAnyRole(['writer', 'editor']);
$user->hasAllRoles(['writer', 'editor']);
$user->hasExactRoles(['writer', 'editor']);
// Get assigned roles and permissions
$user->getRoleNames(); // Collection of role name strings
$user->getPermissionNames(); // Collection of permission name strings
$user->getDirectPermissions(); // Direct permissions only
$user->getPermissionsViaRoles(); // Inherited via roles
$user->getAllPermissions(); // Both direct and inherited
$users = User::role('writer')->get();
$users = User::withoutRole('writer')->get();
$users = User::permission('edit articles')->get();
$users = User::withoutPermission('edit articles')->get();
Register middleware aliases in bootstrap/app.php:
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
'role' => \Spatie\Permission\Middleware\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class,
]);
})
Use in routes (pipe | for OR logic):
Route::middleware(['permission:edit articles'])->group(function () { ... });
Route::middleware(['role:manager|writer'])->group(function () { ... });
Route::middleware(['role_or_permission:manager|edit articles'])->group(function () { ... });
// With specific guard
Route::middleware(['role:manager,api'])->group(function () { ... });
For single permissions, Laravel's built-in can middleware also works:
Route::middleware(['can:edit articles'])->group(function () { ... });
Prefer @can (permission-based) over @role (role-based):
@can('edit articles')
{{-- User can edit articles (supports Super Admin) --}}
@endcan
@canany(['edit articles', 'delete articles'])
{{-- User can do at least one --}}
@endcanany
@role('admin')
{{-- Only use for super-admin type checks --}}
@endrole
@hasanyrole('writer|admin')
{{-- Has writer or admin --}}
@endhasanyrole
Use Gate::before in AppServiceProvider::boot():
use Illuminate\Support\Facades\Gate;
public function boot(): void
{
Gate::before(function ($user, $ability) {
return $user->hasRole('Super Admin') ? true : null;
});
}
This makes $user->can() and @can always return true for Super Admins. Must return null (not false) to allow normal checks for other users.
Use $user->can() inside policy methods to check permissions:
class PostPolicy
{
public function update(User $user, Post $post): bool
{
if ($user->can('edit all posts')) {
return true;
}
return $user->can('edit own posts') && $user->id === $post->user_id;
}
}
enum RolesEnum: string
{
case WRITER = 'writer';
case EDITOR = 'editor';
}
enum PermissionsEnum: string
{
case EDIT_POSTS = 'edit posts';
case DELETE_POSTS = 'delete posts';
}
// Creation requires ->value
Permission::findOrCreate(PermissionsEnum::EDIT_POSTS->value, 'web');
// Most methods accept enums directly
$user->assignRole(RolesEnum::WRITER);
$user->hasRole(RolesEnum::WRITER);
$role->givePermissionTo(PermissionsEnum::EDIT_POSTS);
$user->hasPermissionTo(PermissionsEnum::EDIT_POSTS);
Always flush the permission cache when seeding:
class RolesAndPermissionsSeeder extends Seeder
{
public function run(): void
{
// Reset cache
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Create permissions
Permission::findOrCreate('edit articles', 'web');
Permission::findOrCreate('delete articles', 'web');
// Create roles and assign permissions
Role::findOrCreate('writer', 'web')
->givePermissionTo(['edit articles']);
Role::findOrCreate('admin', 'web')
->givePermissionTo(Permission::all());
}
}
Enable in config/permission.php before running migrations:
'teams' => true,
Set the active team in middleware:
setPermissionsTeamId($teamId);
When switching teams, unset cached relations:
$user->unsetRelation('roles')->unsetRelation('permissions');
Enable in config/permission.php:
'events_enabled' => true,
Available events: RoleAttachedEvent, RoleDetachedEvent, PermissionAttachedEvent, PermissionDetachedEvent in the Spatie\Permission\Events namespace.
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions()Permission::insert() for speed, but flush the cache afterward.Weekly Installs
79
Repository
GitHub Stars
12.9K
First Seen
Feb 13, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode77
gemini-cli76
amp76
github-copilot76
codex76
kimi-cli76
Azure PostgreSQL 无密码身份验证配置指南:Entra ID 迁移与访问管理
34,800 周安装