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

Laravel中获取用户在各团队的指定角色异常问题

问题:用户团队角色关联出现意外角色

我正在实现一套包含**团队专属角色(team-specific roles)和用户专属角色(user-specific roles)**的权限系统,需要列出某用户所属的所有团队,以及该用户在每个团队中被分配的角色。数据涉及model_has_roles表与roles表。

要求:例如ID为1的用户在指定团队中应仅拥有ID为4和5的角色,结果需仅显示这些角色;若用户属于多个团队,需包含其在每个团队内的所有指定角色。

现有关联代码

Team模型

public function userRoles(): BelongsToMany
{
    return $this->belongsToMany(Role::class, 'model_has_roles', 'team_id', 'role_id')->distinct();
}

User模型

public function teams(): BelongsToMany
{
    return $this->belongsToMany(Team::class, 'model_has_roles', 'model_id', 'team_id')->distinct();
}

public function teamsWithRoles(): Collection
{
    $this->loadMissing(['teams', 'teams.userRoles']);

    return $this->teams;
}

测试代码与异常结果

执行检查代码:

$user->teamsWithRoles()->pluck('userRoles', 'id')->map(fn($collection) => $collection->pluck('name', 'id'))->dd()

得到结果:

{"1":{"4":"user","8":"user"},"2":{"5":"system"}}

结果中出现意外角色(ID 8),需确保用户在指定团队中仅关联其被分配的角色(ID 4和5)。


解决方案

问题根源在于Team模型的userRoles关联未限定当前用户,会取出该团队下所有用户的角色,而非当前用户在该团队的角色。以下是三种修复方案:

方案一:在User模型中直接关联团队角色

定义关联直接获取用户在各团队的角色,再加载团队时筛选对应角色:

// User模型
public function teamRoles(): BelongsToMany
{
    return $this->belongsToMany(Role::class, 'model_has_roles', 'model_id', 'role_id')
        ->withPivot('team_id')
        ->whereNotNull('team_id');
}

public function teamsWithRoles(): Collection
{
    $userRoleIds = $this->teamRoles()->pluck('id');
    $this->load(['teams' => function ($query) use ($userRoleIds) {
        $query->with(['roles' => fn($q) => $q->whereIn('id', $userRoleIds)]);
    }]);

    return $this->teams;
}

方案二:在Team模型中添加用户专属角色关联

给Team模型定义带用户ID参数的关联,加载时传入当前用户ID:

// Team模型
public function userSpecificRoles($userId): BelongsToMany
{
    return $this->belongsToMany(Role::class, 'model_has_roles', 'team_id', 'role_id')
        ->where('model_has_roles.model_id', $userId)
        ->distinct();
}

// User模型
public function teamsWithRoles(): Collection
{
    $userId = $this->id;
    $this->load(['teams' => function ($query) use ($userId) {
        $query->with(['userSpecificRoles' => fn($q) => $q->where('model_has_roles.model_id', $userId)]);
    }]);

    return $this->teams;
}

方案三:嵌套关联筛选(最简洁)

在User的teams关联中直接嵌套角色筛选,确保只加载当前用户在该团队的角色:

// User模型
public function teams(): BelongsToMany
{
    return $this->belongsToMany(Team::class, 'model_has_roles', 'model_id', 'team_id')
        ->distinct()
        ->with(['roles' => function ($query) {
            $query->join('model_has_roles', 'roles.id', '=', 'model_has_roles.role_id')
                ->where('model_has_roles.model_id', $this->id)
                ->whereColumn('model_has_roles.team_id', 'teams.id');
        }]);
}

public function teamsWithRoles(): Collection
{
    $this->loadMissing('teams');
    return $this->teams;
}

执行原测试代码后,将得到符合预期的结果:

{"1":{"4":"user"},"2":{"5":"system"}}

内容的提问来源于stack exchange,提问作者Moxley

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 19:30:54