Laravel:有效地总结嵌套关系(渴望加载)

时间:2018-06-05 19:02:49

标签: php laravel laravel-5 laravel-5.6

我在Laravel 5.6中有许多嵌套的hasMany关系。我正在寻找一种有效的方法来对关系中每个最外层节点的属性求和。

例如,每个都由hasMany链接。

Country - > States - > Cities - > Streets - > Houses

如果我想对给定House->bedrooms中的所有Country求和,那么最有效的方法是什么?

目前我在内存中有一个渴望加载的Country,如下所示:

$country->load('states.cities.streets.houses');

我试过了:

$country->states->cities->streets->houses->pluck('bedrooms')->sum()

但得到了:

  

此集合实例上不存在Property [cities]。

我可以通过各种关系的foreach循环来做到这一点,但感觉必须在Laravel中内置一个更加代码有效的方法。我错过了什么?

由于

4 个答案:

答案 0 :(得分:2)

如果结果很大,则不应在应用层中获得它们的总和。尝试使用SQL Sum函数。

如果你想以雄辩的方式做到这一点,这应该是你最好的解决方案:

Country::with(['states.cities.streets.houses' => function ($query) {
    $query->select('bedrooms');
}])->sum('bedrooms');

如果不使用这样的数据库查询:

DB::table('countries')
    ->join('states', '..', '..')
    ->join('cities', '..', '..')
    ->join('streets', '..', '..')
    ->join('houses', '..', '..')
    ->selectRaw('SUM(bedrooms) as sum')
    ->pluck('sum')[0]

答案 1 :(得分:0)

您可以尝试以下代码。

Country::with(['states.cities.streets.houses' => function ($query) {
    $query->select('bedrooms', '...');
}])->sum('bedrooms');

答案 2 :(得分:0)

我目前正在使用hasManyThroughState上的City解决此问题,然后:

$country->load('cities.houses');
echo $country->cities->sum(function ($city) {
                    return $city->houses->sum('bedrooms');
                });

但它仍然感觉不好。任何更好的答案都非常赞赏。

答案 3 :(得分:0)

我创建了一个HasManyThrough级的无限关系:Repository on GitHub

安装后,您可以像这样使用它:

class Country extends Model {
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function houses() {
        return $this->hasManyDeep(House::class, [State::class, City::class, Street::class]);
    }
}

$sum = $country->houses()->sum('bedrooms');