所以我有User
& Role
模型具有多对多关系,我有3个角色:super
,admin
和moderator
,有4个用户,请说:{{1} },John
,Mike
和James
。
Larry
是John
,super
有Mike
和admin
个角色,moderator
是James
和{{ 1}}是admin
。要显示没有特定角色的用户,我创建了此范围:
Larry
当我致电moderator
以获取没有public function scopeDoesntHaveRoles($query, $roles = [], $column = 'id') {
return $query->whereDoesntHave('roles')->orWhereHas('roles', function ($q) use ($roles, $column) {
$q->whereNotIn($column, $roles);
});
}
角色的用户时,它会运作并返回:
User::doesntHaveRoles([1])->lists('name', 'id')
但是,当我尝试列出没有super
角色{"2":"Mike","3":"James","4":"Larry"}
的用户时,那里没有显示是admin
但是他出现了User::doesntHaveRoles([2])->lists('name', 'id')
实际上有James
角色:
Mike
我认为这是因为admin
也有{"1":"John","2":"Mike","4":"Larry"}
角色,您认为我的范围有问题吗?或者你有其他解决方案吗?
由于
修改 这是我的支点架构
Mike
moderator
型号
Schema::create('user_roles', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->primary([
'user_id', 'role_id'
]);
});
User
模型
public function roles()
{
return $this->belongsToMany(Role::class, 'user_roles');
}
答案 0 :(得分:2)
我会使用whereNotIn
代替whereDoesntHave
。
如果Role
存储在变量$role
中,您可以获得所有不具备该角色的用户:
/* @var Role $role */
User::whereNotIn(function('id', $query) use ($role) {
$query->select('user_id')
->from('user_roles')
->where('role_id', $role->id);
});
内部查询将返回具有给定角色的所有用户ID。使用whereNotIn
将返回相反的用户集。将创建以下查询:
select *
from users
where user_id not in (
select user_id
from user_roles
where role_id = ?
);
现在Collection
中存储了$roles
个角色,您可以获得所有不具备以下任何角色的用户:
/* @var Collection|Role[] $roles */
User::whereNotIn(function('id', $query) use ($roles) {
$query->select('user_id')
->from('user_roles')
->whereIn('role_id', $roles->pluck('id');
});
内部选择将返回在集合中具有其中一个角色的所有用户的ID。使用whereNotIn
,您将再次获得相反的结果。您还可以使用一组角色ID而不是$roles->pluck('id')
。
构建器将创建一个类似
的查询select *
from users
where user_id not in (
select user_id
from user_roles
where role_id in (?, ?, ..)
);