laravel 中用 spatie permission 包实现 rbac 权限控制:先安装、发布并运行迁移,配置 user 模型和中间件,再创建角色、分配权限,最后通过中间件和 blade 指令控制访问。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

在 Laravel 项目中管理协作成员,核心不是手动维护用户列表,而是通过角色(Role)与权限(Permission)的组合控制访问边界——比如让“内容编辑”能改文章但不能删用户,“运维人员”可清缓存却无法进后台表单。
安装并初始化 Spatie Permission 包
执行命令安装依赖:composer require spatie/laravel-permission
发布迁移文件:php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="permission-migrations"
运行迁移创建五张表:php artisan migrate。这一步【必须完成】,否则后续 assignRole() 会因缺少 roles 表而报 SQLSTATE[42S02] 错误。
清空配置缓存:php artisan config:clear,否则 config/permission.php 中的缓存设置不生效。
打开 app/Models/User.php,确认已引入 trait 并混入模型:use Spatie\Permission\Traits\HasRoles;,且类定义为 class User extends Authenticatable { use HasRoles; }。
创建角色并分配给协作成员
方法一:用 Tinker 批量创建基础角色
运行 php artisan tinker,输入以下代码:
Role::create(['name' => 'admin']);<br>Role::create(['name' => 'editor']);<br>Role::create(['name' => 'reviewer']);
方法二:在 Seeder 中预置角色(适合团队首次拉取项目)
生成 seeder:php artisan make:seeder PermissionSeeder,在 run() 方法中写入角色创建逻辑,再执行 php artisan db:seed --class=PermissionSeeder。
为现有用户分配角色:User::find(1)->assignRole('admin'); 或批量赋多个角色:User::find(2)->assignRole(['editor', 'reviewer']);。注意:【assignRole() 只能对已保存的模型实例调用】,新建未 save 的 User 对象直接调用会报错。
通过中间件限制协作成员的路由访问
第一步:注册中间件别名
在 app/Http/Kernel.php 的 $routeMiddleware 数组中添加:'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class, 和 'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class。
第二步:在路由中应用中间件
web.php 中写:Route::get('/dashboard', [DashboardController::class, 'index'])->middleware('role:admin');
api.php 中写:Route::post('/articles', [ArticleController::class, 'store'])->middleware('permission:create articles');
第三步:验证中间件是否生效
用非 admin 用户访问 /dashboard,应返回 403 Forbidden;若仍能进入,检查是否忘了运行 php artisan config:clear 或中间件名拼写错误(如写成 'roles' 而非 'role')。
在 Blade 模板中动态控制协作成员可见区域
使用 @role 指令显示角色专属内容:
@role('admin')<br> <a href="https://www.php.cn/link/59ff15c69ad138635326c3f8267af16e">用户管理</a><br>@endrole
使用 @can 指令按权限控制元素:
@can('delete articles')<br> <button onclick="confirmDelete()">删除</button><br>@endcan
混合判断更灵活:
@if(auth()->user()->hasRole('editor') && auth()->user()->can('publish articles'))<br> <x-publish-button></x-publish-button><br>@endif
注意:@role 是精确匹配,不继承子角色;@can 则会自动合并该用户所有角色+直授权限的结果。
动态更新协作成员权限后刷新缓存
当通过代码修改了角色权限(例如 $role->givePermissionTo('export reports')),已登录用户的权限缓存不会自动更新。
手动清除指定用户缓存:$user->forgetCachedPermissions();
或全局关闭权限缓存(仅开发环境推荐):在 config/permission.php 中设 'cache' => ['expiration_time' => 0]。
生产环境切勿设为 0,应结合事件监听,在权限变更后主动调用 app(\Spatie\Permission\PermissionRegistrar::class)->forgetCachedPermissions();。








