将Laravel中DB::Select原生查询转换为Query Builder以实现分页
将原生SQL转换为Laravel Query Builder并实现分页
当然可以把这段原生查询转成Query Builder,这样就能直接使用Laravel的分页功能了。转换后的代码如下:
public function getPopularBook() { $books = DB::with('totalReview', function ($query) { $query->select('book_id', DB::raw('count(id) as review_count')) ->from('review') ->groupBy('book_id'); }) ->select('x.review_count', 'y.*') ->from('totalReview as x') ->leftJoinSub(function ($query) { $query->select('b.*', DB::raw(' case when ((now() >= d.discount_start_date and now() <= d.discount_end_date) or (now() >= d.discount_start_date and d.discount_end_date is null)) then (b.book_price - d.discount_price) else b.book_price end as final_price ')) ->from('book as b') ->rightJoin('discount as d', 'd.book_id', '=', 'b.id'); }, 'y', 'x.book_id', '=', 'y.id') ->orderBy('x.review_count', 'desc') ->orderBy('y.final_price', 'asc') ->paginate(8); return $books; }
关键转换点说明:
- 用
DB::with()定义原SQL中的CTE(totalReview),给评论数字段加了review_count别名,避免后续排序/查询时的歧义。 - 用
leftJoinSub()处理原查询里的子查询逻辑,保持了原有的discount右连book的关联关系,确保所有书籍都被包含。 - 排序逻辑完全复刻原SQL,先按评论数降序,再按最终价格升序。
- 最后用
paginate(8)替换原有的LIMIT 8,Laravel会自动处理分页参数(比如URL中的page参数),返回包含分页导航信息的集合。
如果需要自定义分页的页码参数名、显示字段或分页路径,可以给paginate()传递额外参数,比如:
->paginate(8, ['*'], 'page_num', request()->get('page_num', 1));
内容的提问来源于stack exchange,提问作者quocanhcute
相关产品推荐
相关产品推荐

