直接使用spatie/laravel-permission,它覆盖95% RBAC场景,稳定轻量;需执行三步安装迁移、正确配置User模型的HasRoles trait、规范角色权限分配与校验,并注意缓存重置和对象级权限需配合Policy。

安装与迁移必须一次跑通
执行三步缺一不可:
- 安装包:composer require spatie/laravel-permission
- 发布迁移文件:php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="permission-migrations"(注意是
permission-migrations,不是旧版migrations) - 运行迁移:php artisan migrate
迁移后检查数据库是否生成了 5 张表:roles、permissions、role_has_permissions、model_has_roles、model_has_permissions。少一张,assignRole() 就会报错或静默失败。
特别注意:roles 和 permissions 表里的 guard_name 字段必须和你的守卫一致(如 web 或 api)。不一致会导致权限判断始终为 false,可手动 update 或重跑带 --force 的迁移。
User 模型要正确引入 HasRoles trait
在 App\Models\User(或你实际使用的用户模型路径)中:
立即学习“PHP免费学习笔记(深入)”;
- 引入 trait:use Spatie\Permission\Traits\HasRoles;(拼写是
HasRoles,不是HasRole) - 在 class 定义中使用:use HasFactory, Notifiable, HasRoles;
- trait 要放在 use 列表靠后位置,避免和
Notifiable等含__call()的 trait 冲突
如果项目用了自定义路径(如 App\Models\Auth\User),必须在那个文件里加,而不是默认的 App\Models\User。
角色与权限分配要规范
权限是最小操作单位(如 edit-post),角色是权限集合(如 editor):
- 创建权限:Permission::create(['name' => 'edit-post'])
- 创建角色:Role::create(['name' => 'editor'])
- 把权限赋予角色:$editor->givePermissionTo('edit-post')
- 给用户分配角色:$user->assignRole('editor')(支持数组:
['editor', 'viewer'])
⚠️ 避免混用:$user->givePermissionTo('delete-user') 是绕过角色的直授,会导致权限来源不可追溯、无法批量回收。审计和维护时会很被动。
权限校验要注意上下文和缓存
$user->can('edit-post') 和 Blade 中的 @can('edit-post') 默认走缓存:
- 每次调用
Permission::create()或Role::givePermissionTo()后,必须执行:php artisan permission:cache-reset - Blade 中
@can前必须先@auth,未登录时@can不会自动跳过,可能报错或逻辑异常 - API 路由用
can中间件时,第二个参数是路由变量名(如post),不是类名:middleware => ['can:edit-post,post'](对应Route::get('/posts/{post}', ...))
对象级权限(如“只能编辑自己的文章”)不能只靠角色,必须配合 Laravel Policy 实现,@can('update', $post) 才能触发策略中的 update() 方法。



















