Laravel使用Spatie Permission报错:web守卫无名为create的权限
问题原因
运行Seeder抛出该错误的核心诱因是权限分配逻辑的传参错误:
- 你调用
$role->givePermissionTo($permissions)时,传入的是自定义的权限配置二维数组,Spatie Permissions扩展包的givePermissionTo方法仅支持传入「权限模型实例」「权限名称字符串」,或由这两类值组成的数组/集合,无法识别你传入的带display_name、key等自定义字段的原始配置结构。 - 包内部匹配权限时,会误将配置数组内的字段值作为权限名检索,最终触发找不到名为
create(即你配置里的display_name字段值)、guard为web的权限报错。
修复方案
调整权限创建、分配的逻辑即可,两种写法任选:
写法1:传入已创建的权限实例
创建权限时收集返回的模型实例,直接传入实例完成分配:
public function run() { $user = User::create([ 'name' => 'admin', 'email' => 'instructor@gmail.com', 'email_verified_at' => now(), 'password' => 'password', 'remember_token' => Str::random(10), 'type' => User::TYPE_INSTRUCTOR, ]); $permissions = [ [ 'name' => 'methods_create', 'display_name' => 'create', 'key' => 'methods', ], [ 'name' => 'methods_update', 'display_name' => 'update', 'key' => 'methods', ], [ 'name' => 'methods_delete', 'display_name' => 'delete', 'key' => 'methods', ], ]; $role = Role::create(['name'=>'Instructor']); $permissionModels = []; foreach($permissions as $permission){ $permissionModels[] = Permission::create($permission); } // 传入权限实例集合分配 $role->givePermissionTo($permissionModels); $user->assignRole($role); }
写法2:传入权限名称数组
从配置数组中提取所有权限的name字段值,传入权限名数组完成分配:
public function run() { $user = User::create([ 'name' => 'admin', 'email' => 'instructor@gmail.com', 'email_verified_at' => now(), 'password' => 'password', 'remember_token' => Str::random(10), 'type' => User::TYPE_INSTRUCTOR, ]); $permissions = [ [ 'name' => 'methods_create', 'display_name' => 'create', 'key' => 'methods', ], [ 'name' => 'methods_update', 'display_name' => 'update', 'key' => 'methods', ], [ 'name' => 'methods_delete', 'display_name' => 'delete', 'key' => 'methods', ], ]; $role = Role::create(['name'=>'Instructor']); foreach($permissions as $permission){ Permission::create($permission); } // 提取所有权限名传入 $role->givePermissionTo(array_column($permissions, 'name')); $user->assignRole($role); }
额外排查项
如果修改代码后仍报错,依次做以下检查:
- 运行Seeder前先执行
php artisan permission:cache-reset清除权限缓存,Spatie Permissions会缓存权限注册表,旧缓存会导致新创建的权限无法被识别。 - 如果项目使用了多guard,创建Role、Permission时需要显式传入
guard_name字段,确保和用户模型使用的guard一致。 - 检查自定义扩展的Permission模型,确认
$fillable属性包含你需要写入的display_name、key等自定义字段,避免自定义字段写入失败。
内容的提问来源于stack exchange,提问作者mohamed sahleya
相关产品推荐
相关产品推荐

