首页 文章

Laravel 5 eloquent hasManyThrough / belongsToManyThrough关系

提问于
浏览
3

在Laravel 5.2应用程序中,我有三个模型: UserRoleTask . User 与多个 Roles 关联, Role 与多个 Tasks 关联 . 因此,每个用户通过他们的角色与多个任务相关联 .

我试图通过他们的角色访问与 User 相关联的所有 Tasks .

我模型的相关部分如下:

class User extends Authenticatable
{    
    public function roles()
    {
        return $this->belongsToMany('App\Role');
    }

    public function tasks()
    {
        return $this->hasManyThrough('App\Task', 'App\Role');
    }
}

class Role extends Model
{
    public function tasks()
    {
        return $this->belongsToMany('App\Task');
    }

    public function users()
    {
        return $this->belongsToMany('App\User');
    }
}

class Task extends Model
{    
    public function roles()
    {
        return $this->belongsToMany('App\Role');
    } 
}

以下返回SQL错误;

Column not found: 1054 Unknown column 'roles.user_id'

它似乎试图通过Role模型中的(不存在的)外键来访问关系,而不是通过数据透视表 .

$user = Auth::user;
$tasks = $user->tasks;

如何通过这些关系访问与用户相关的所有任务?

2 回答

  • 1

    我开发了一个你可能感兴趣的custom BelongsToManyThrough relationship . 您需要添加新的关系类(在我的要点中给出;它在此处粘贴太长),并且还覆盖您的基础 Model 类,如实现 belongsToManyThrough 中所述 .

    然后(假设您使用的是Laravel的默认表命名方案 - 如果没有,您也可以指定连接表),您可以将关系定义为:

    public function tasks()
    {
        return $this->belongsToManyThrough(
            'App\Task',
            'App\Role');
    }
    

    belongsToManyThrough 不仅会为您提供用户的任务列表,还会告诉您每个用户每个任务的角色 . 例如,如果你有:

    $user->tasks()->get()

    输出看起来像:

    [
        {
            "id": 2,
            "name": "Ban spammers",
            "roles_via": [
                {
                    "id": 2,
                    "slug": "site-admin",
                    "name": "Site Administrator",
                    "description": "This role is meant for \"site administrators\", who can basically do anything except create, edit, or delete other administrators."
                },
                {
                    "id": 3,
                    "slug": "group-admin",
                    "name": "Group Administrator",
                    "description": "This role is meant for \"group administrators\", who can basically do anything with users in their same group, except other administrators of that group."
                }
            ]
        },
        {
            "id": 13,
            "name": "Approve posts",
            "roles_via": [
                {
                    "id": 3,
                    "slug": "group-admin",
                    "name": "Group Administrator",
                    "description": "This role is meant for \"group administrators\", who can basically do anything with users in their same group, except other administrators of that group."
                }
            ]
        },
        {
            "id": 16,
            "name": "Reboot server",
            "roles_via": [
                {
                    "id": 2,
                    "slug": "site-admin",
                    "name": "Site Administrator",
                    "description": "This role is meant for \"site administrators\", who can basically do anything except create, edit, or delete other administrators."
                }
            ]
        }
    ]
    

    我的自定义关系只有少量查询才能有效地执行此操作,而不是涉及 foreach 的其他解决方案,这会产生n+1 query问题 .

  • 0

    从您共享的源代码中可以看出, User 和_2745444之间以及 RoleTask 之间存在 Many to Many 关系 .

    hasManyThrough 方法需要两个 One to Many 关系 .

    获取所有 User 相关 Task 的可能方法是:(在 User 类中)

    public function getTasksAttribute()
    {
        $tasks = [];
        foreach ($this->roles as $role) {
            $tasks = array_merge($tasks, $role->tasks);
        }
        return $tasks;
     }
    

    然后,您可以使用以下命令访问任务:

    $user->tasks;
    

相关问题