Laravel 5.8 - Как сортировать (orderBy) множественные отношения - PullRequest
2 голосов
/ 04 июня 2019

Я пытаюсь отсортировать сериалы по просмотрам видео.

Отношения: Серийный имеет отношение hasMany к серии. Сериал имеет много отношения к эпизодам. Эпизоды имеет одно отношение к видео. Видео имеет отношение hasMany к количеству просмотров.

<?php
//sort method:
public function mostPopular()
    {

        $serials = Serial::with(['series.episodes.video' => function ($query) {
            $query->withCount(['videoViews' => function($query) {
            }])->orderBy('video_views_count', 'desc');
        }])->get();

        return $serials;
}

//Serial model:
public function series()
{
   return $this->hasMany(Series::class);
}


//Series model:
public function episodes()
{
   return $this->hasMany(Episode::class);
}

public function serial()
{
   return $this->belongsTo(Serial::class);
}

//Episode model:
public function video()
{
   return $this->hasOne(Video::class);
}

public function series()
{
   return $this->belongsTo(Series::class);
}

//Video model:
public function videoViews()
{
   return $this->hasMany(VideoView::class);
}

public function episode()
{
   return $this->belongsTo(Episode::class);
}


?>

Я ожидаю отсортированные сериалы по просмотрам видео (series.episodes.video.videoViews), но фактический вывод не отсортирован.

Laravel 5.8 PHP 7

1 Ответ

0 голосов
/ 04 июня 2019

Поскольку запросы «С» выполняются как отдельные запросы (а не подзапросы, как предлагалось ранее), экспонирование экстраполированных столбцов fuax из одного запроса в другой становится довольно сложным. Я уверен, что в документах API есть недокументированное решение, но я никогда с ним не сталкивался. Вы могли бы попытаться выставить свой с и с счетом в порядке:

Serial::orderBy(function($query) { some combo of with and withCount })

Но это тоже будет сложно. Поскольку любой из этих подходов попадет в базу данных несколько раз, было бы столь же эффективно выполнить разделение самостоятельно и в то же время сохранить здравомыслие. Этот первый запрос использует левое соединение, raw group by и raw select, потому что я не хочу, чтобы laravel выполнял запрос with как отдельный запрос (проблема в первую очередь).

$seriesWithViewCounts = VideoView::leftJoin('episodes', 'episodes.id', '=', 'video_views.episode_id')
                ->groupBy(DB::raw('episodes.series_id'))
                ->selectRaw("episodes.series_id, count(video_views.id) as views")
                ->get();
$series = Series::findMany($seriesWithViewCounts->pluck('series_id'));
foreach($series as $s) {
    $s->view_count = $seriesWithViewCounts->first(function($value, $key) use ($s) {
       return $value->series_id = $s->id
    })->video_views_count;
});
$sortedSeries = $series->sortBy('video_views_count');

При этом будут проигнорированы все серии, в которых нет просмотров для всех эпизодов, поэтому вы можете захотеть взять их и добавить в конец. Не мое определение «популярный».

Я бы хотел увидеть более красноречивый способ справиться с этим, но это бы сработало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...