简体   繁体   English

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

[英]Laravel 5.8 - How sort (orderBy) multiple relationship

I am trying to sort the serials by video views. 我正在尝试按视频观看次数对序列进行排序。

Relations: The Serial has a hasMany relationship to series. 关系:系列与系列有hasMany关系。 The Series has a hasMany relationship to episodes. 系列与剧集有hasMany关系。 The Episodes has a hasOne relationship to video. 情节与视频具有hasOne关系。 The Video has a hasMany relationship to viewcounts. 视频与观看次数具有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);
}


?>

I expect the sorted serials by video views (series.episodes.video.videoViews), but the actual output is not sorted. 我希望按视频视图(series.episodes.video.videoViews)对已排序的序列进行排序,但实际输出未排序。

Laravel 5.8 PHP 7 Laravel 5.8 PHP 7

Because "With" queries run as seperate queries (not subqueries as previously suggested), exposing extrapolated fuax-columns from one query to the other gets rather tricky. 因为“ With”查询是作为单独的查询(而不是以前建议的子查询)运行的,所以将外推的fuax列从一个查询公开到另一个查询会变得非常棘手。 I'm sure there's non-documented solution in the API docs but I've never come across it. 我确定API文档中有未记录的解决方案,但我从未遇到过。 You could try putting your with and withCount in the orderBy: 可以尝试将with和withCount放在orderBy中:

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

But that too will get tricky. 但这也将变得棘手。 Since either approach will hit the database multiple times, it would be just as performant to do the separation yourself and keep your sanity at the same time. 由于这两种方法都会多次访问数据库,因此您自己执行分离并同时保持理智与执行性能相同。 This first query uses a left join, raw group by and raw select because I don't want laravel running the with query as a separate query (the problem in the first place). 第一个查询使用左连接,原始分组依据和原始选择,因为我不希望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');

This will ignore any series that has no views for all episodes, so you may want to grab those and append it to the end. 这将忽略所有对所有情节都没有视图的系列,因此您可能希望抓住这些情节并将其附加到末尾。 Not my definition of "popular". 不是我对“大众”的定义。

I'd love to see a more eloquent way of handling this, but this would do the job. 我希望看到一种更有说服力的方式来处理此问题,但这可以完成工作。

This is a silly one actually but I've learnt that multiple ->sortBy on collections actually are possible with no workarounds. 这实际上是一个愚蠢的做法,但是我已经知道,在没有解决方法的情况下,实际上可以对集合执行多个-> sortBy。 It's just that you need to reverse the order of them. 只是您需要颠倒它们的顺序。 So, to sort a catalogue of artists with their album titles this would be the solution... 因此,要对具有专辑名称的艺术家目录进行排序,这就是解决方案...

Instead of : 代替 :

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

Do this : 做这个 :

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM