Laravel, join, where в отношении
Есть такие таблицы
users
| id | email |
roles
| id | title | group_id |
groups
| id | title | server_id |
user_role - Связь пользователя с ролью
| user_id | role_id |
Надо получать роли пользователя из группы определенного сервера
class User extends Authenticatable{
...
public function roleGroup(){
$server = request()->get('server');
return $this->hasOneThrough(Role::class, UserRole::class, 'user_id', 'id', 'id', 'role_id')
->join('groups', 'roles.group_id', 'groups.id')
->where('groups.server_id', $server->id);
}
...
}
Но это не работает т.к. where не видит join, если это делать через отношение
Если просто добавить метод, то при многократном вызова плодятся запросы к БД
class User extends Authenticatable{
...
public function roleGroup(){
$server = request()->get('server');
$userRole = UserRole::join('groups', 'user_role.group_id', 'groups.id')
->where('user_role.user_id', $this->id)
->where('groups.server_id', $server->id)
->first();
$user_group_role = Role::find($userRole->role_id);
return $user_group_role;
}
...
}
Подскажите, как такое лучше сделать.
Ответы (2 шт):
Тут скорее всего можно обойтись без отношения roleGroup в классе User, достаточно использовать whereHas() внутри with()
class User extends Authenticatable {
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
class Role extends Model {
public function roleGroup()
{
return $this->belongsTo(RoleGroup::class, 'group_id');
}
}
В месте получения запросов:
$users = User
::with(['roles' => function ($query) {
$query->whereHas('roleGroup', function ($query) {
$query->where('server_id', request('server'));
});
})
->get();
foreach ($users as $user) {
foreach ($user->roles as $role) {
}
}
Логика: для юзеров подгрузить только те роли, у которых группа ролей имеет server_id равный server_id в запросе.
Решил это так. Выше описал не все нюансы. На сервере, пользователь может состоять только в одной группе У пользователя тогда есть еще отношение $user->group и это отношение учитывает сервер
public function roleGroup(){
$groupId = $user->group ? $user->group->id : 0;
return $this->hasOneThrough(Role::class, UserRole::class, 'user_id', 'id', 'id', 'role_id')
->where('roles.group_id', $groupId);
}