如何按点赞、评论、分享总数对Post模型结果排序?
按点赞+评论+分享总和排序帖子的解决方案
方法一:利用withCount结合orderByRaw(推荐,简单直观)
先通过withCount同时获取三个关联表的计数,再用orderByRaw直接计算总和并排序,这种方法保留了分页功能,代码简洁:
$per_page = 10; // 替换为你的每页显示数量 $posts = Post::withCount(['likes', 'comments', 'shares']) ->orderByRaw('(likes_count + comments_count + shares_count) DESC') ->paginate($per_page);
注意:确保你的Post模型已经正确定义了以下关联关系:
// Post.php public function likes() { return $this->hasMany(Like::class); } public function comments() { return $this->hasMany(Comment::class); } public function shares() { return $this->hasMany(Share::class); }
如果需要给不同互动类型设置权重(比如点赞权重为2,评论和分享为1),只需调整排序公式:
->orderByRaw('(likes_count * 2 + comments_count + shares_count) DESC')
方法二:子查询计算总和(适合大数据量场景)
如果帖子数据量较大,子查询方式可以避免加载多余的计数字段到模型中,减少内存占用:
$per_page = 10; $posts = Post::select('posts.*') ->selectRaw('( (SELECT COUNT(*) FROM likes WHERE likes.post_id = posts.id) + (SELECT COUNT(*) FROM comments WHERE comments.post_id = posts.id) + (SELECT COUNT(*) FROM shares WHERE shares.post_id = posts.id) ) AS total_interactions') ->orderByDesc('total_interactions') ->paginate($per_page);
注意事项
- 不要使用普通
join方式计算总和,因为多表join会产生笛卡尔积,导致计数结果不准确(比如一个帖子有3个点赞、2个评论,join后会生成6条数据,最终计数会被放大)。 - 如果需要频繁按这个总和排序,可以考虑在
posts表中新增一个字段(比如total_interactions),通过模型事件(如created、updated)或者定时任务更新该字段的值,这样排序时直接按字段排序,性能会更优。
内容的提问来源于stack exchange,提问作者mohamed ammar
相关产品推荐
相关产品推荐

