我在User
和Role
模型之间存在多对多的关系,并希望检查用户是否具有给定列表的任何角色。
所以我输入了模型:
public function hasAnyRoles(array $roles) {
return $this->roles()->whereIn('name', $roles)->exists();
}
并UserController
:
// User has only "manager" role.
$user->hasAnyRoles(['admin', 'manager']) // true
问题是在某些部分我需要验证用户是否具有给定列表的所有角色。例如:
// User has only "manager" role.
$user->hasRoles(['admin', 'manager']) // false
我在" lazy"模式,生成n + 1
个查询:
public function hasRolesLazy($roles) {
return array_reduce($roles, function ($initial, $role) {
return $this->roles()->where('name', $role)->exists();
}, false);
}
如何构造hasRoles(array $roles)
方法只在数据库中执行一个查询?我是SQL的新手,所以我无法找到很多解决方案。
答案 0 :(得分:0)
试试这个:
public function hasAnyRoles(array $roles) {
return $this->whereHas('roles', function ($query) use ($roles) {
return $query->whereIn('name', $roles);
})->isNotEmpty();
}
答案 1 :(得分:0)
我的建议是,使用关系加载用户的所有角色。当您通过将其称为属性来加载关系时,Laravel会将其缓存在引擎盖下,因此它不会重复任何查询。然后,您可以简单地使用加载的角色来实现两种方法:
public function hasAnyRoles(array $roles)
{
// When you call $this->roles, the relationship is cached. Run through
// each of the user's roles.
foreach ($this->roles as $role) {
// If the user's role we're looking at is in the provided $roles
// array, then the user has at least one of them. Return true.
if (in_array($role->name, $roles) {
return true;
}
}
// If we get here, the user does not have any of the required roles.
// Return false.
return false;
}
和第二种方法:
public function hasRoles(array $roles)
{
// Run through each of the roles provided, that the user MUST have
foreach ($roles as $role) {
// Call the $this->roles relationship, which will return a collection
// and be cached. Find the first role that has the name of the role
// we're looking at.
$found = $this->roles->first(function ($r) use ($role) {
return $r->name == $role;
});
// If a role could not be found in the user's roles that matches the
// one we're looking, then the user does not have the role, return
// false
if (!$found) {
return false;
}
}
// If we get here, the user has all of the roles provided to the method
return true;
}
当然有许多不同的方法来实现这些方法,特别是Collection
类中的方法对您有所帮助,但重点是使用$this->roles
只会产生一个查询。