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

Laravel 9.x中如何从User模型正确关联Permission模型?

问题描述

数据库结构

user
    user_id
    
office
    office_id

project
    project_id

role
    role_id

permission
    permission_id
    
role_permission
    role_id
    permission_id
    
office_user
    office_user_id
    office_id
    user_id
    role_id

project_user
    project_user_id
    project_id
    user_id
    role_id

对应模型

User, Project, Office, Role, Permission

我想从User模型直接访问Permission模型,但写的代码里,officeUserPermissions()和projectUserPermissions()方法获取的role_id值一直出错,代码如下:

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    public function projects()
    {
        return $this->belongsToMany(Project::class, 'project_user', 'user_id');
    }

    public function offices()
    {
        return $this->belongsToMany(Office::class, 'office_user', 'user_id');
    }

    public function officeRole()
    {
        return $this->belongsToMany(Role::class, 'office_user');
    }

    public function projectRole()
    {
        return $this->belongsToMany(Role::class, 'project_user');
    }

    public function officeUserPermissions()
    {
        return $this->belongsToMany(Permission::class, 'role_permission', 'role_id');
    }

    public function projectUserPermissions()
    {
        return $this->belongsToMany(Permission::class, 'role_permission', 'role_id');
    }
}
解决方案

你之前的写法错在直接跳过角色关联,想让User和Permission直接通过role_permission表关联,但role_permission里根本没有user_id字段,自然拿不到正确的role_id。得通过用户关联的角色(办公/项目角色)间接关联权限,以下是正确实现方式:

第一步:完善Role模型的权限关联

先在Role模型里定义好和Permission的多对多关联:

class Role extends Model
{
    public function permissions()
    {
        return $this->belongsToMany(Permission::class, 'role_permission');
    }
}

第二步:在User模型里关联权限

1. 获取办公场景下的权限

有两种实现方式:

  • 方式一:嵌套关联(先拿角色,再取角色对应的权限)
public function officePermissions()
{
    return $this->officeRole()->with('permissions');
}

调用时$user->officePermissions会返回所有办公角色及对应的权限集合。

  • 方式二:直接关联出所有办公权限(自动去重)
public function officePermissions()
{
    return $this->belongsToMany(Permission::class, 'office_user')
        ->join('role_permission', 'office_user.role_id', '=', 'role_permission.role_id')
        ->select('permissions.*')
        ->distinct();
}

调用时$user->officePermissions直接返回Permission模型的集合,无需嵌套遍历。

2. 获取项目场景下的权限

和办公场景逻辑一致:

  • 方式一:嵌套关联
public function projectPermissions()
{
    return $this->projectRole()->with('permissions');
}
  • 方式二:直接关联权限
public function projectPermissions()
{
    return $this->belongsToMany(Permission::class, 'project_user')
        ->join('role_permission', 'project_user.role_id', '=', 'role_permission.role_id')
        ->select('permissions.*')
        ->distinct();
}

3. 获取用户的所有权限(办公+项目)

如果需要一次性拿到用户所有权限,用union合并两个查询:

public function allPermissions()
{
    return Permission::query()
        ->join('role_permission', 'permissions.permission_id', '=', 'role_permission.permission_id')
        ->join('office_user', 'role_permission.role_id', '=', 'office_user.role_id')
        ->where('office_user.user_id', $this->user_id)
        ->union(
            Permission::query()
                ->join('role_permission', 'permissions.permission_id', '=', 'role_permission.permission_id')
                ->join('project_user', 'role_permission.role_id', '=', 'project_user.role_id')
                ->where('project_user.user_id', $this->user_id)
        )
        ->distinct();
}

内容的提问来源于stack exchange,提问作者Валерий Новожилов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 04:50:30