我有3张图库,评论和投票表,我的投票表是多态的,因为投票可以添加到图库或评论中,它们看起来像这样:
评论:
id
user_id
gallery_id
content
投票:
id
user_id
votable_type
votable_id
status
状态可以是“upvote”或“downvote”。每条评论都可以上调或下调。评论点数的数量是从计数('upvote')计算的 - 计数('downvote')。 votable_type可以是'App \ Gallery'或'App \ Comment'
我希望获得所有评论并按点数排序,评分最高点数位于顶部。
我该怎么做?到目前为止,我有这个简单的代码,但它没有按点数计算投票数或评论顺序:
Comment::with('votes')->with('owner')
->where('gallery_id', $gallery->id)
->paginate(5);
答案 0 :(得分:0)
您可以对集合使用sortBy
方法,遗憾的是,在这种情况下您无法使用标准分页:
Comment::with('votes')->with('owner')
->where('gallery_id', $gallery->id)
->sortBy(function($comment,$key){
return $comment->votes->count();
});
这将返回一个集合,其中包含按投票数排序的所有评论。
答案 1 :(得分:0)
我认为你可以使用带有分组和排序的连接在查询构建器中完成此操作,但我相信查询会相当困难,并且在您查看代码时半年后不易消化。
更简单的选择是在Comment
模型上创建一个返回点数的方法,类似于以下内容:
public function getPointsAttribute()
{
$points = 0;
foreach ($this->votes AS $vote) {
$points = $vote->status == 'upvote' ? $votes + 1 : $votes - 1;
}
return $points;
}
然后在从数据库中获取Comments
之后对其进行排序:
Comment::where('gallery_id', $gallery->id)->get()->sortBy('points');
您可以使用forPage()
对该集合进行分页,请参阅docs。
答案 2 :(得分:0)
我明白了,这就是诀窍:
$comments = Comment::with('votes')->with('owner')
->where('gallery_id', $gallery->id)
->leftJoin('votes', 'votes.votable_id', '=', 'comments.id')
->selectRaw(
'comments.*, count(case votes.status when "upvote" then 1 else null end) - count(case votes.status when "downvote" then 1 else null end) as points'
)
->where('votes.votable_type','App\Comment')
->groupBy('comments.id')
->orderBy('points', 'desc')
->paginate(5);