You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

测试中使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 23:10:25