[英]Laravel 5 eloquent hasManyThrough / belongsToManyThrough relationships
在 Laravel 5.2 应用程序中,我有三个模型: User
、 Role
和Task
。 一个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
关系: User
和Role
以及Role
和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;
而不是使用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.