测试中使用Spatie Permissions时用户关联角色却无权限问题
问题:用户关联角色但无法获取角色权限
场景概述
我通过RolesAndPermissionsSeeder创建权限与角色,创建新Employer时会同步生成关联用户并为其分配Employer角色,但测试中发现:用户已成功关联角色,角色本身也配置了对应权限,但调用用户的权限方法时返回空集合。
1. 权限与角色生成代码(RolesAndPermissionsSeeder)
class RolesAndPermissionsSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions(); $permissions = [ 'employers.index', 'employers.show', 'employers.create', 'employers.edit', 'employers.destroy', ]; foreach ($permissions as $permission) { Permission::create(['name' => $permission]); } $role = Role::create(['name' => "Employer"]); $role->givePermissionTo(Permission::all()->except(['employers.index', 'employers.destroy'])); } }
2. Employer模型代码(关联用户并分配角色)
class Employer extends Model { use HasFactory; public function user() { return $this->belongsTo(User::class); } protected static function booted() { static::created(function ($employer) { $employer->user->assignRole('Employer'); }); } }
3. 权限测试代码(EmployerTest)
class EmployerTest extends TestCase { use RefreshDatabase; use WithFaker; public function setUp(): void { parent::setUp(); $this->app->make(\Spatie\Permission\PermissionRegistrar::class)->registerPermissions(); $this->seed(RolesAndPermissionsSeeder::class); } public function test_permission() { $employer = \App\Models\Employer::factory()->create(); dump(Role::all()); // <-- 正确显示所有角色 dump(Permission::all()); // <-- 正确显示所有权限 dump(Role::where('name', 'Employer')->first()->permissions->pluck('name')->toArray()); // <-- 正确显示角色已分配的权限 dump($employer->user->hasRole('Employer')); // <-- 返回true dd($employer->user->getPermissionNames()); } }
问题现象
测试中dd($employer->user->getPermissionNames())返回items: [],不符合预期——用户应继承Employer角色的权限。
问题排查与解决方案
1. 检查User模型是否引入权限Trait
这是最常见的原因:Spatie权限包要求用户模型必须引入HasRoles Trait,否则无法继承角色权限,也无法使用getPermissionNames()这类方法。
修改User模型:
use Spatie\Permission\Traits\HasRoles; class User extends Authenticatable { use HasRoles; // 必须添加该Trait // ...其他代码 }
2. 刷新权限缓存
测试环境中权限缓存可能未及时更新,导致权限读取异常。调整测试的setUp方法,确保缓存被清空后再注册权限:
public function setUp(): void { parent::setUp(); $registrar = $this->app->make(\Spatie\Permission\PermissionRegistrar::class); $registrar->forgetCachedPermissions(); // 先清空缓存 $registrar->registerPermissions(); $this->seed(RolesAndPermissionsSeeder::class); }
3. 确保用户关联被正确加载
在Employer的created事件中,$employer->user可能处于延迟加载状态,尝试先加载用户再分配角色:
static::created(function ($employer) { $employer->load('user'); // 强制加载用户关联 $employer->user->assignRole('Employer'); });
内容的提问来源于stack exchange,提问作者JanBoehmer
相关产品推荐
相关产品推荐

