繁体   English   中英

Laravel 5 雄辩的 hasManyThrough/belongsToManyThrough 关系

[英]Laravel 5 eloquent hasManyThrough / belongsToManyThrough relationships

在 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;

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

我开发了一个自定义的BelongsToManyThrough关系,您可能会感兴趣。 您需要添加新的关系类(在我的要点中给出;粘贴在这里太长了),并且还需要按照要点中的描述覆盖您的基本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 查询问题。

从您共享的源代码看来,您之间存在Many to Many关系: UserRole以及RoleTask

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;

而不是使用array_merge()

一种方法是添加一个getTasksAttribute()方法,并使用集合。

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

这可以通过$user->tasks访问

如果你有 3 个模型

用户、角色、权限

用户属于多角色

角色属于多用户

权限属于多角色

角色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();
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM