Объединить 'с' и 'whereHas' в Laravel 5
У меня есть этот код в Laravel 5, используя Eloquent, который отлично работает:
$filterTask = function($query) use ($id) {
$query->where('taskid', $id);
};
User::whereHas('submissions', $filterTask)->with(['submissions' => $filterTask])->get();
В основном цель состоит в том, чтобы получить только тех пользователей, у которых есть свои отфильтрованные материалы, в которых есть какие-либо из них.
Тем не менее, кажется, что тратить время на запуск как whereHas, так и с помощью с той же функцией обратного вызова. Есть ли способ упростить его?
Спасибо.
Ответы
Ответ 1
В плане производительности вы ничего не можете оптимизировать здесь (за исключением случаев, когда вам нужно перейти от красноречивых отношений к объединениям). С помощью или без whereHas
будут выполняться два запроса. Один, чтобы выбрать всех пользователей другой, чтобы загрузить связанные модели. Когда вы добавляете условие whereHas
, добавляется подзапрос, но все еще два запроса.
Однако синтаксически вы можете немного оптимизировать это, добавив область запроса к своей модели (или даже базовую модель, если вы хотите использовать это чаще):
public function scopeWithAndWhereHas($query, $relation, $constraint){
return $query->whereHas($relation, $constraint)
->with([$relation => $constraint]);
}
Использование:
User::withAndWhereHas('submissions', function($query) use ($id){
$query->where('taskid', $id);
})->get();
Ответ 2
" Макробный " способ (Laravel 5. 4+)
Добавьте это в метод boot()
поставщика услуг.
\Illuminate\Database\Eloquent\Builder\Eloquent::macro('withAndWhereHas', function($relation, $constraint){
return $this->whereHas($relation, $constraint)->with([$relation => $constraint]);
});
Ответ 3
Я хочу расширить ответ от @lukasgeiter, используя статические функции.
public static function withAndWhereHas($relation, $constraint){
return (new static)->whereHas($relation, $constraint)
->with([$relation => $constraint]);
}
Использование такое же
User::withAndWhereHas('submissions', function($query) use ($id){
$query->where('taskid', $id);
})->get();