Почему Eloquent разделяет запросы при активной загрузке? - PullRequest
0 голосов
/ 24 января 2020

Например, у меня есть два запроса:

return $this->model->where('closed_at', null)
            ->whereHas('users', function ($query) {
                $query->where('id', '=', auth()->user()->id);
            })         
            ->with(['product:id,title', 'in_works' => function ($query) {
                $query->where('user_id', '=', auth()->user()->id);
            }])
           ->get();

хорошо работает и возвращает 1 запрос с объединением (полная загрузка):

select * from `order` where `closed_at` is null and exists (select * from `user` inner join `user_order` on `user`.`id` = `user_order`.`user_id` where `order`.`id` = `user_order`.`order_id` and `id` = ?)

, но аналогично запрос

return $this->model->where('closed_at', null)
            ->with(['product:id,title', 'in_works' => function ($query) {
                $query->where('closed_at', '=', null);
            }])->get();

вернуть 3 запроса, почему?

select * from `order` where `closed_at` is null
select `id`, `title` from `product` where `product`.`id` in (1, 2)
select * from `in_work` where `in_work`.`order_id` in (1, 2) and `closed_at` is null

1 Ответ

1 голос
/ 25 января 2020

Каждое отношение, добавленное в модель с помощью активной загрузки (т. Е. С использованием with), запрашивается с помощью дополнительного запроса.

Вот что у вас есть:

  1. Запрос модели
select * from `order` where `closed_at` is null -- Model 
с product:id,title запросом
select `id`, `title` from `product` where `product`.`id` in (1, 2)
с in_works query
select * from `in_work` where `in_work`.`order_id` in (1, 2) and `closed_at` is null

Обратите внимание, что в случаях (2) и (3) (1,2) соответствует идентификаторам order, которые были получены из первого запроса.

whereHas позволит дополнительно уточнить исходный запрос модели и, следовательно, повлиять на общий результат. В вашем случае следующее является результатом запроса whereHas('users',...):

select * from `order` where `closed_at` is null and exists (select * from `user` inner join `user_order` on `user`.`id` = `user_order`.`user_id` where `order`.`id` = `user_order`.`order_id` and `id` = ?)

Если запрос модели фактически не дает никаких результатов, тогда запросы отношения не выполняются, что и происходит в этом случае.

...