Laravel:过滤嵌套关系?

时间:2016-10-20 10:47:56

标签: laravel relationship

我不明白为什么这不起作用:

Device::with(['travel.move.position' => function($q) use ($start, $end) {
    return $q->whereBetween('created_date', [$start, $end]);
}]);

我认为它应该为我提供travel->move->position关系的所有设备,但只包含position.datetime介于$start$end

之间的设备

我试过像

这样的东西
Device::whereHas('travel.move.position', function($q) use ($start, $end) {
    return $q->whereBetween('created_date', [$start, $end]);
});

我得到了预期的结果,但我没有得到热切的关系。

为答案增加了查询1:

select * 
from `devices` 
where exists (
    select * from `travels` 
    inner join `travel_info` on `travel_info`.`id` = `travels`.`info_id` 
    where `devices`.`id` = `travel_info`.`device_id` 
    and exists (
        select * 
        from `moves` 
        where `moves`.`travel_id` = `travels`.`id` 
        and exists (
            select * from `positions` 
            where `moves`.`position_id` = `positions`.`id` and `created_at`
            between ? and ?
        )
    ) 

查询是完美的(就像whereHas一样)但是什么时候使用with():

select `travels`.*, `travel_info`.`device_id` 
from `travels` 
inner join `travel_info` on `travel_info`.`id` = `travels`.`info_id` 
where `travel_info`.`device_id` in (?, ?, ?) 

.... 
select * from `moves` where `moves`.`travel_id` in (?, ..., ?)
....
select * from `positions` where `positions`.`id` in (?, ..., ?)

1 个答案:

答案 0 :(得分:2)

好的,经过与问题作者的长时间讨论,我们发现问题不是查询本身,而是with()语句中关系的不正确加载。

我想出了以下似乎返回预期结果的查询。它首先执行主查询以使所有设备与过滤条件匹配,然后将相同的过滤器应用于我们急切加载所需的每个关系:

$start = '2016-10-01';
$end = '2016-10-31';

$devices = Device::whereHas('travel.move.position', function($q) use ($start, $end) {
    $q->whereBetween('created_at', [$start, $end]);
})->with([
    'travel' => function($q1) use ($start, $end) {
        $q1->whereHas('move.position', function($q2) use ($start, $end) {
            $q2->whereBetween('created_at', [$start, $end]);
        });
    },
    'travel.move' => function($q1) use ($start, $end) {
        $q1->whereHas('position', function($q2) use ($start, $end) {
            $q2->whereBetween('created_at', [$start, $end]);
        });
    },
    'travel.move.position' => function($q1) use ($start, $end) {
        $q1->whereBetween('created_at', [$start, $end]);
    }
])->get();
相关问题