У меня есть относительно простая структура БД, включая страны, регионы и базы. Каждые депо присвоенный оператора и регион:Laravel/Eloquent: Ограничьте загруженную загрузку, чтобы не включать пустых родителей.
операторы
+----+------------+
| ID | name |
+----+------------+
| 1 | Operator 1 |
| 2 | Operator 2 |
+----+------------+
страна
+----+----------------+------+
| ID | country_id | code |
+----+----------------+------+
| 1 | United Kingdom | gb |
| 2 | France | fr |
+----+----------------+------+
регионы
+----+-----------------+-------+
| ID | country_id (FK) | name |
+----+-----------------+-------+
| 1 | 1 | North |
| 2 | 1 | South |
| 3 | 1 | East |
| 4 | 1 | West |
| 5 | 2 | North |
| 6 | 2 | South |
| 7 | 2 | East |
| 8 | 2 | West |
+----+-----------------+-------+
депо
+----+----------------+------------------+-----------+
| ID | region_id (FK) | operator_id (FK) | name |
+----+----------------+------------------+-----------+
| 1 | 1 | 1 | Newcastle |
| 2 | 8 | 2 | Nantes |
+----+----------------+------------------+-----------+
Я настроил свои красноречивые отношения успешно в соответствующих моделях.
Я хочу загрузить каждое депо, сгруппированное по соответствующим регионам и странам, и отфильтровать конкретный оператор.
$depots = Country::with('regions.depots')->whereHas('regions.depots', function($query) use ($opID) {
$query->where('operator_id',$opID);
})->get();
Это делает трюк, однако, так как хотят загрузки складов, это также жадная загрузка всех регионов, в том числе без складов, возложенных на них. НАПРИМЕР. когда выше выполняются, когда $opID = 1
, вы получите этот результат:
name: United Kingdom,
regions: [
{
name: North,
depots: [{
name: Newcastle
}]
}, {
name: South,
depots: []
}, {
name: East,
depots: []
}, {
name: West,
depots: []
}
]
То, что я хотел бы это Возвращено, но без тех регионов, где нет ни одного депо.
Я много играл с ограничениями как with
, так и whereHas
, но не могу получить желаемую структуру данных. Почему код ниже не имеет желаемого эффекта?
$depots = Country::with(['regions.depots' => function($query) use ($opID) {
$query->where('depots.operator_id',$opID);
}])->get();
Есть ли какой-либо способ не загружать родителя, если ребенок не существует? Или это случай выполнения вышеуказанного запроса, как и у меня, и затем циклический результат вручную?
EDIT
Так после нескольких часов я, наконец, нашел способ, чтобы получить нужный мне результат. Но это кажется действительно грязным. Это действительно лучший способ?
$depots = Country::whereHas('regions.depots', function($q) use ($opID) {
$q->where('operator_id',$opID);
})->with(['regions' => function($q) use ($opID) {
$q->with('depots')->whereHas('depots', function($q2) use ($opID) {
$q2->where('operator_id',$opID);
});
}])->get();
EDIT 2
Так получается, первая правка была фактически запрашивая operator_id
на все, кроме depots
стола, а это означало, как только я добавил еще один склад, принадлежащий другому оператору в том же регионе, который появился, когда я этого не хотел.Нижеследующее кажется даже более грязным, но оно работает. Это интересно поговорив с собой;) Надеюсь, что это помогает кто-то один день ...
$depots = Country::has('regions.depots')
->with(['regions' => function($q) use ($opID) {
$q->with(['depots' => function($q2) use ($opID) {
$q2->where('operator_id',$opID);
}])->has('depots');
}])->get();
Спасибо, но это, кажется, имеют те же результаты, как и в моей исходной кодовый блок – Ian