Laravel: 过滤嵌套关系?
Laravel: Filter nested relationships?
我不明白为什么这不起作用:
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 (?, ..., ?)
好的,经过与问题作者的长时间讨论,我们发现问题不在于查询本身,而是在 with()
语句中加载关系不正确。
我提出了以下似乎 return 预期结果的查询。它首先执行一个主查询以获取所有符合过滤条件的设备,然后将相同的过滤器应用于我们需要预先加载的每个关系:
$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();
我不明白为什么这不起作用:
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 (?, ..., ?)
好的,经过与问题作者的长时间讨论,我们发现问题不在于查询本身,而是在 with()
语句中加载关系不正确。
我提出了以下似乎 return 预期结果的查询。它首先执行一个主查询以获取所有符合过滤条件的设备,然后将相同的过滤器应用于我们需要预先加载的每个关系:
$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();