Laravel: эффективно суммировать вложенные отношения (загруженные) - PullRequest
0 голосов
/ 05 июня 2018

У меня есть несколько вложенных hasMany отношений в Laravel 5.6.Я ищу эффективный способ суммирования атрибута на каждом из самых внешних узлов отношений.

Например, каждый из них связан с hasMany.

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

Если я хочу суммировать все House->bedrooms в данном Country, каков наиболее эффективный способ?

На данный момент у меня в памяти есть загруженная Country следующая строка:

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

И я попробовал:

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

Но получил:

Свойство [города] не существует в этом экземпляре коллекции.

Я мог бы сделать это с помощью foreach циклов по различным отношениям, но кажется, что должно быть большеэффективный код встроен в Laravel.Чего мне не хватает?

Спасибо

Ответы [ 4 ]

0 голосов
/ 29 июня 2018

Я создал HasManyThrough отношение с неограниченными уровнями: Репозиторий на 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');
0 голосов
/ 05 июня 2018

Я в настоящее время решаю эту проблему, используя hasManyThrough на State и City, а затем:

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

Но это все равно не очень хорошо.Любые лучшие ответы очень ценятся.

0 голосов
/ 05 июня 2018

Если у вас большой результат, вы не должны получать их сумму на прикладном уровне.Попробуйте использовать функцию 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]
0 голосов
/ 05 июня 2018

Вы можете попробовать следующий код.

Country::with(['states.cities.streets.houses' => function ($query) {
    $query->select('bedrooms', '...');
}])->sum('bedrooms');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...