2017-02-12 21 views
0

У меня есть относительно простая структура БД, включая страны, регионы и базы. Каждые депо присвоенный оператора и регион: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(); 

ответ

0

Вы всегда можете использовать отложенной загрузки:

$depots = Country::whereHas('regions.depots', function($q) use ($opID) { 
    $q->where('operator_id',$opID); 
})->get()->load('regions.depots'); 
+0

Спасибо, но это, кажется, имеют те же результаты, как и в моей исходной кодовый блок – Ian