Laravel Eloquent分页使用withCount查询返回重复数据问题
问题根因
该问题核心是排序规则不稳定导致的分页数据重复:
- 当前仅按聚合出来的
count字段降序排序,当多个关注者的未读帖子数完全相同时,数据库没有次级排序规则约束行的返回顺序,每次分页查询时相同排序值的行返回顺序随机,不同分页区间就会出现重复的用户数据。 get()是一次性拉取全量数据,不存在分页偏移跳转逻辑,所以不会触发该问题。
修复方案
1. 追加稳定次级排序规则(首选方案)
给排序逻辑追加用户表唯一主键ID作为次级排序条件,保证不管第一排序值是否重复,整体排序结果固定,不会出现分页偏移混乱:
Auth::user()->followers()->withCount([ 'posts AS count' => fn($posts) => $posts ->where('status_id', 1) ->whereDoesntHave('views', fn($view) => $view->where('visitor', Auth::id())) ]) ->orderBy('count', 'DESC') // 追加唯一键作为次级排序,升序降序都可以,只要固定规则即可 ->orderBy('id', 'ASC') ->paginate(8);
2. 手动生成分页器(复杂查询场景备选)
如果你的关联逻辑非常复杂,存在分页count统计和实际数据查询逻辑不一致的情况,可以手动指定分页逻辑,避免框架自动生成count查询时出错:
$baseQuery = Auth::user()->followers()->withCount([ 'posts AS count' => fn($posts) => $posts ->where('status_id', 1) ->whereDoesntHave('views', fn($view) => $view->where('visitor', Auth::id())) ])->orderBy('count', 'DESC')->orderBy('id', 'ASC'); $perPage = 8; $currentPage = request()->input('page', 1); $total = $baseQuery->count(); $pageData = $baseQuery->forPage($currentPage, $perPage)->get(); $paginator = new \Illuminate\Pagination\LengthAwarePaginator( $pageData, $total, $perPage, $currentPage, ['path' => request()->url(), 'query' => request()->query()] );
效果验证
修改完成后可以分别拉取前两页的用户ID集合,检查两个集合是否存在交集,无交集则说明排序规则稳定,分页重复问题已解决。
内容的提问来源于stack exchange,提问作者kazemm
相关产品推荐
相关产品推荐

