Laravel 5.8-如何排序(orderBy)多重关系

时间:2019-06-04 17:05:26

标签: php laravel laravel-5

我正在尝试按视频观看次数对序列进行排序。

关系: 序列号与序列号具有hasMany关系。 系列与剧集有hasMany关系。 情节与视频具有hasOne关系。 该视频与观看次数具有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

2 个答案:

答案 0 :(得分:0)

因为“ With”查询作为单独的查询(而不是以前建议的子查询)运行,因此将推算的fuax列从一个查询暴露给另一个查询变得非常棘手。我确定API文档中有未记录的解决方案,但我从未遇到过。您可以尝试将with和withCount放入orderBy:

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

但这也会变得棘手。由于这两种方法都会多次访问数据库,因此您自己执行分离并同时保持理智与执行性能相同。第一个查询使用左连接,原始分组依据和原始选择,因为我不希望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');

这将忽略所有对所有情节都无视的剧集,因此您可能要抓住这些情节并将其追加到末尾。不是我对“大众”的定义。

我希望看到一种更雄辩的方法来处理此问题,但这可以完成工作。

答案 1 :(得分:0)

实际上这是一个愚蠢的选择,但是我已经知道,在没有解决方法的情况下,实际上可以对集合进行多个-> sortBy排序。只是您需要颠倒它们的顺序。因此,要对带有专辑标题的艺术家目录进行排序,这就是解决方案...

而不是:

$collection->sortBy('artist')->sortBy('title');

执行此操作:

$collection->sortBy('title')->sortBy('artist');