为什么在急切加载中雄辩地分隔查询?

时间:2020-01-24 15:45:55

标签: laravel eloquent eloquent-relationship

例如,我有两个查询:

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();

它工作正常,并通过join(急切加载)返回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 个答案:

答案 0 :(得分:1)

通过急切加载(即使用with)添加到模型的每个关系都通过附加查询来查询。

这是您拥有的:

  1. 模型查询
select * from `order` where `closed_at` is null -- Model 
  1. 使用product:id,title查询
select `id`, `title` from `product` where `product`.`id` in (1, 2)
  1. 使用in_works查询
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` = ?)

当模型查询实际上未产生任何结果时,则实际上不执行任何关系查询。