我有一个相对简单的数据库结构,包括国家,地区和仓库。每个库都分配给操作员和区域:
运营商
+----+------------+
| 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();
如果孩子不存在,有没有什么方法可以不急切地加载父母?或者是我执行上述查询然后手动循环结果的情况?
修改
所以经过几个小时后,我终于找到了一种方法来达到预期的效果。但它看起来真的很脏。这真的是最好的方式吗?
$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();
编辑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 :(得分:1)
您可以随时使用延迟加载:
$depots = Country::whereHas('regions.depots', function($q) use ($opID) {
$q->where('operator_id',$opID);
})->get()->load('regions.depots');