Laravel 5 eloquent hasManyThrough / belongsToManyThrough关系

时间:2016-02-10 03:18:59

标签: php laravel laravel-5 eloquent many-to-many

在Laravel 5.2应用程序中,我有三个模型:<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" style="position: absolute;left:0;top:0;transition:all 450ms cubic-bezier(.29,.48,.29,.3)" _v-e8b2cbd2="" _v-71032799=""> <ellipse cx="50%" cy="50%" _v-e8b2cbd2="" stroke-width="0%" rx="50%" stroke="" ry="50%" fill="#3D92EA"></ellipse> <ellipse _v-e8b2cbd2="" stroke="white" stroke-width="2%" cx="25%" cy="30%" rx="3%" ry="3%" fill="white"></ellipse> <ellipse _v-e8b2cbd2="" fill="white" stroke="white" stroke-width="2%" cx="25%" cy="50%" rx="3%" ry="3%"></ellipse> <ellipse _v-e8b2cbd2="" cx="25%" fill="white" stroke="white" stroke-width="2%" cy="70%" rx="3%" ry="3%"></ellipse> <line id="line" fill="none" _v-e8b2cbd2="" y2="30%" x2="78%" y1="30%" x1="38%" stroke-width="5%" stroke="white"></line> <line fill="none" _v-e8b2cbd2="" y2="50%" x2="78%" y1="50%" x1="38%" stroke-width="5%" stroke="white"></line> <line fill="none" _v-e8b2cbd2="" y2="70%" x2="78%" y1="70%" x1="38%" stroke-width="5%" stroke="white"></line> </svg> let L2Frames = [ {x1: '0%', y1: '0%', x2: '0%', y2: '0%'}, {x1: '30%', y1: '30%', x2: '80%', y2: '80%'} ] UserRoleTask与多个User相关联,Roles与多个Role相关联。 因此,每个用户通过他们的角色与多个任务相关联。

我正在尝试通过他们的角色访问与Tasks相关联的所有Tasks

我模型的相关部分如下:

User

以下内容返回SQL错误;

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');
    } 
}

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

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

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

4 个答案:

答案 0 :(得分:2)

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

然后(假设您正在使用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问题。

答案 1 :(得分:0)

从您分享的源代码中,您似乎在Many to ManyUser之间以及RoleRole之间存在Task个关系。

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;

答案 2 :(得分:0)

代替使用array_merge()

一种实现此目的的方法是添加一个getTasksAttribute()方法并使用集合。

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

可以通过$user->tasks

进行访问

答案 3 :(得分:0)

如果你有 3 个模型

用户、角色、权限

用户belongsToMany角色

角色 belongsToMany 用户

权限belongsToMany角色

角色belongsToMany权限

检查用户是否有特定权限我在用户模型

中做了这个功能
 public function hasPermission($permission)
    {
        return Permission::where('name', $permission)->whereHas('roles', function ($query) {
            $query->whereHas('users', function ($query) {
                $query->where('users.id', $this->id);
            });
        })->exists();
    }