sho*_*mes 9 nested relationships laravel eloquent
我试图访问嵌套关系的子对象,从父对象返回许多结果.
假设我有4个模型:国家 - 省 - 城市 - 市政
他们的关系如下:
国家模式
class Country extends Eloquent
{
protected $table = 'countries';
public function provinces()
{
return $this->hasMany('Province');
}
}
Run Code Online (Sandbox Code Playgroud)
省模型
class Province extends Eloquent
{
protected $table = 'provinces';
public function cities()
{
return $this->hasMany('City');
}
public function country()
{
return $this->belongsTo('Country');
}
}
Run Code Online (Sandbox Code Playgroud)
城市模型
class City extends Eloquent
{
protected $table = 'cities';
public function municipalities()
{
return $this->hasMany('Municipality');
}
public function province()
{
return $this->belongsTo('Province');
}
}
Run Code Online (Sandbox Code Playgroud)
市政模式
class Municipality extends Eloquent
{
protected $table = 'municipalities';
public function cities()
{
return $this->belongsTo('City');
}
}
Run Code Online (Sandbox Code Playgroud)
现在我要做的是让一个拥有超过9000人口的特定国家的所有城市都位于被认为是西部的省份.
到目前为止,我有这样的事情:
$country_id = 1;
$country = Country::whereHas('provinces', function($query){
$query->where('location', 'West');
$query->whereHas('cities', function($query){
$query->whereHas('municipalities', function($query){
$query->where('population', '>', 9000);
});
});
})->find($country_id);
Run Code Online (Sandbox Code Playgroud)
现在我可以很容易地获得各省,$country->provinces但我不能更深入.
EDIT1:修复了Jarek注意到的belongsTo关系.
编辑2:除了Jarek的回答,我想分享我也发现的东西,但Jarek可能是更合适的方法.
而不是试图从上到下(国家 - >市政)我决定尝试另一种方式(市政 - >国家)这里是如何工作(我测试它,也工作)
$municipalities = Municipality::where('population', '>', 9000)
->whereHas('city', function($q) use ($country_id){
$q->whereHas('province', function($q) use ($country_id){
$q->where('location', 'West');
$q->whereHas('country', function($q) use ($country_id){
$q->where('id', $country_id);
});
});
})->get();
Run Code Online (Sandbox Code Playgroud)
我不知道这是否是一种实际的正确方式,或者性能是否会被接受,但它似乎对我有用,但Jarek的答案看起来更优雅.
Jar*_*zyk 10
你的Municipality- City很可能belongsTo,hasMany不像粘贴.
无论如何,您可以使用hasManyThrough关系来访问远远相关的集合:
Country - City
Province - Municipality
Run Code Online (Sandbox Code Playgroud)
不幸的是,3级嵌套没有关系,所以你不能这样做.
接下来,您的代码whereHas不限制provinces到west和municipalities到9000+,但只限制countries于那些,那些与他们有关.在您的情况下,这意味着结果将是Country(如果其关系符合这些要求)或null其他.
所以如果你真的想限制相关的集合,那么你需要这个:
$country = Country::with(['provinces' => function($query){
$query->where('location', 'West');
}, 'provinces.cities.municipalities' => function ($query){
$query->where('population', '>', 9000);
}])->find($country_id);
Run Code Online (Sandbox Code Playgroud)
这正在应用急切的加载约束,它的作用是:
1. loads only West provinces for country with id 1
2. loads all the cities in these provinces
3. loads only 9k+ municipalities in these cities
Run Code Online (Sandbox Code Playgroud)
由于您对城市不感兴趣,您可以hasManyThrough在省内使用:
// Province model
public function municipalities()
{
return $this->hasManyThrough('Municipality', 'City');
}
Run Code Online (Sandbox Code Playgroud)
然后:
$country = Country::with(['provinces' => function($query){
$query->where('location', 'West');
}, 'provinces.municipalities' => function ($query){
$query->where('population', '>', 9000);
}])->find($country_id);
Run Code Online (Sandbox Code Playgroud)
但是,在这两种情况下,您都无法直接访问市政当局,但仅限于此:
// 1 classic
$country->provinces->first()->cities->first()->municipalities;
// 2 hasManyThrough
$country->provinces->first()->municipalities;
Run Code Online (Sandbox Code Playgroud)
话虽这么说,如果你想与所有这些城市合作,你需要这个技巧:
$country = Country::with(['provinces' => function($query){
$query->where('location', 'West');
}, 'provinces.municipalities' => function ($query) use (&$municipalities) {
// notice $municipalities is passed by reference to the closure
// and the $query is executed using ->get()
$municipalities = $query->where('population', '>', 9000)->get();
}])->find($country_id);
Run Code Online (Sandbox Code Playgroud)
这将运行额外的查询,但现在所有的城市都是单一,扁平的集合,所以它很容易使用.否则你可能会得到一堆foreach循环.
| 归档时间: |
|
| 查看次数: |
11741 次 |
| 最近记录: |