#php #mysql #laravel #eloquent
Вопрос:
У меня есть users
таблица с отделом и ролью. Это отношения «многие ко многим». Итак, ниже приведены таблицы,
- Пользователи
- отделы
- роли
- users_departments
- users_roles
Со следующими моделями,
- Пользователь
- Роль
- Отдел
В пользовательской модели у меня есть следующее
class User extends Authenticatable
{
public function scopeSearch($query, $searchValues)
{
return $query->where('first_name','like', '%'.$searchValues.'%')
->orWhere('last_name','like', '%'.$searchValues.'%')
->orWhere('email','like', '%'.$searchValues.'%');
}
public function departments()
{
return $this->belongsToMany(Department::class, 'users_departments', 'user_id', 'department_id');
}
public function roles()
{
return $this->belongsToMany(Role::class, 'users_roles', 'user_id', 'role_id');
}
}
У меня есть необработанный запрос, который работает для меня, вы можете увидеть его ниже
SELECT users.id as id, users.first_name as first_name, users.last_name as last_name, users.email as email, roles.title as `role`, departments.title as department
FROM users INNER JOIN users_departments ON users_departments.user_id = users.id
INNER JOIN departments ON departments.id = users_departments.department_id
INNER JOIN users_roles ON users_roles.user_id = users.id
INNER JOIN roles ON roles.id = users_roles.role_id
WHERE `departments`.`title` LIKE '%".$search."%'
OR `roles`.`title` LIKE '%".$search."%'
OR `first_name` LIKE '%".$search."%'
OR `last_name` LIKE '%".$search."%'
OR `email` LIKE '%".$search."%'
GROUP BY users.id
ORDER BY " . $orderColumnName. " " . $order
Что я пробовал?
Я пытаюсь выполнить следующий запрос, который ничего не возвращает,
$query = User::with([
'roles' => function($query) use($searchValues) {
return $query->where('title', 'LIKE','%'.$searchValues.'%');
},
'departments' => function($query) use($searchValues) {
return $query->where('title', 'LIKE','%'.$searchValues.'%');
}
])
->search($searchValues)
->orderBy($orderColumnName,$order)
->limit($request->length)
->get();
может кто-нибудь любезно подсказать мне, в чем проблема, чтобы я мог ее исправить? Я признателен, если кто-нибудь поможет мне это исправить.
Спасибо
Комментарии:
1. Что такое
search
метод в вашем запросе? Это область видимости?2. @MichalOravec да, верно, я упомянул в вопросе. Вы можете видеть в пользовательской модели
3. При работе со сложными запросами я сначала правильно выполняю запрос, как вы это сделали, а затем выгружаю созданный sql, чтобы вы могли сравнить его. Затем просто продолжайте уточнять, пока не получите то же самое.
4. Просто чтобы добавить к этому, я думаю, вы обнаружите, что ->with() не даст желаемого результата. Вам нужно внутреннее соединение, поэтому я бы попробовал -> join() .
Ответ №1:
Всегда будьте осторожны с orWhere
.
https://laravel.com/docs/8.x/queries#logical-grouping
Вы всегда должны группировать вызовы orWhere, чтобы избежать неожиданного поведения при применении глобальных областей.
Но в вашем случае это желаемое поведение.
Вам не хватает фильтрации ваших отношений, вы можете сделать это с orWhereHas
помощью .
https://laravel.com/docs/8.x/eloquent-relationships#querying-relationship-existence
$users = User::with(['roles' => $closure = function ($query) use ($searchValues) {
return $query->where('title', 'LIKE', "%{$searchValues}");
}, 'departments' => $closure
])->orWhereHas('roles', $closure)
->orWhereHas('departments', $closure)
->search($searchValues)
->orderBy($orderColumnName, $order)
->limit($request->length)
->get();
Я сохранил закрытие переменной, потому что оно повторяется в запросе.
Комментарии:
1. Спасибо за ваш ответ, я попробовал. К сожалению, он не работает
2. «Это не работает» не очень полезно.