2016-10-20 2 views
3

Я не понимаю, почему это не работает:Laravel: Фильтровать вложенные отношения?

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]); 
}); 

, и я получаю ожидаемый результат, но я не получаю нетерпеливых отношений.

ADDED QUERY ДЛЯ ОТВЕТА 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), но когда делать с():

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 (?, ..., ?) 
+0

Этот код только фильтрование 'position', а не 'device'. Таким образом, вы все равно получите все устройства, но внутри каждого устройства -> перемещение -> перемещение, вы увидите только позиции, соответствующие вашему фильтру. –

+0

Действительно ли ваше поле называется 'datetime'? Поскольку это зарезервированное слово в mysql: http://dev.mysql.com/doc/refman/5.7/en/keywords.html Я думаю, что вам может потребоваться процитировать его 'whereBetween ('' datetime'', [$ start, $ end]); ' – Cyclonecode

+0

попробуйте добавить' с ('travel.move.position') 'к вашему второму запросу. Затем он дает ожидаемый результат и нетерпеливые загруженные отношения. –

ответ

2

Ok, после долгого обсуждения с автор вопроса, мы обнаружили, что проблема заключается не в самом запросе, а в некорректной загрузке отношений в операторе 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(); 
+0

Спасибо, но то же самое: Я получаю устройство-> travel-> move-> position-> created_at == '2016-09- 23 ' – kanashin

+0

Не могли бы вы включить ведение журнала запросов к базе данных и проверить SQL-запрос для кода выше и опубликовать его в своем вопросе? –

+0

Можно ли переместить несколько позиций? –

Смежные вопросы