You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中为自定义SELECT查询添加分页器问题求助

我来帮你解决这个Laravel分页集成的问题!你现在用的是原生SELECT查询,DB::select()返回的是结果数组,没法直接调用Laravel内置的paginate()方法,这里给你两种可行的解决方案:

方法一:将原生查询转换为查询构造器(推荐)

这种方式更符合Laravel的开发习惯,而且能直接利用框架的分页功能,代码也更易维护。你可以把原生SQL里的字段选择、关联逻辑用查询构造器的方法重写,比如:

$results = DB::table('shop_product')
    // 根据你的实际关联关系调整join条件,这里假设shop_product和shops通过shop_id关联
    ->join('shops', 'shop_product.shop_id', '=', 'shops.id')
    // 用selectRaw写入距离计算的SQL片段
    ->selectRaw('(6371 * acos( cos( radians(23.0376279) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(72.5102283) ) + sin( radians(23.0376279) ) * sin( radians( latitude ) ) )) AS distance')
    // 选择你需要的其他字段
    ->select(
        'shop_product.stock',
        'shop_product.price',
        'shops.id AS shopId',
        // 补充你原查询里的其他字段
    )
    // 可选:按距离排序
    ->orderBy('distance', 'asc')
    // 设置每页显示条数,这里是10,你可以按需修改
    ->paginate(10);

这样$results就是一个标准的Laravel分页器实例,你可以直接在视图里用{!! $results->links() !!}渲染分页链接,也能使用分页器的所有方法(比如currentPage()、lastPage()等)。

方法二:手动创建分页器(适合坚持用原生查询的场景)

如果你不想修改原生查询,可以手动构建LengthAwarePaginator来实现分页,步骤如下:

// 获取当前页码,默认是1
$page = request()->get('page', 1);
// 设置每页显示的记录数
$perPage = 10;
// 计算偏移量
$offset = ($page - 1) * $perPage;

// 执行带分页参数的原生查询,注意在SQL末尾加上LIMIT和OFFSET
$results = DB::select(
    'SELECT distances.* FROM (SELECT ( 6371 * acos( cos( radians(23.0376279 ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(72.5102283 ) ) + sin( radians(23.0376279 ) ) * sin( radians( latitude ) ) ) ) AS distance, shopdatabase.shop_product.stock, shopdatabase.shop_product.price AS price, shopdatabase.shops.id AS shopId, shopdatabase... ) AS distances LIMIT ? OFFSET ?',
    [$perPage, $offset]
);

// 获取总记录数,需要写对应的计数查询(把原查询的SELECT部分替换为COUNT(*))
$total = DB::selectOne(
    'SELECT COUNT(*) AS total FROM (SELECT ( 6371 * acos( cos( radians(23.0376279 ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(72.5102283 ) ) + sin( radians(23.0376279 ) ) * sin( radians( latitude ) ) ) ) AS distance, shopdatabase.shop_product.stock, shopdatabase.shop_product.price AS price, shopdatabase.shops.id AS shopId, shopdatabase... ) AS distances'
)->total;

// 创建LengthAwarePaginator实例
$paginator = new \Illuminate\Pagination\LengthAwarePaginator(
    $results,
    $total,
    $perPage,
    $page,
    [
        'path' => \Illuminate\Pagination\Paginator::resolveCurrentPath(),
        'pageName' => 'page',
    ]
);

// 之后你可以把$paginator传给视图,用法和普通分页器一致
return view('your-view', ['results' => $paginator]);

注意事项

  • 方法一优先推荐,因为查询构造器会自动处理表前缀(如果你在config里设置了的话),而且能更好地预防SQL注入。
  • 如果你的距离计算需要作为筛选条件(比如只显示距离X公里内的店铺),可以在查询构造器里加->having('distance', '<=', $maxDistance)(需要配合groupBy,或者在Laravel 8+里可以直接用havingWithoutGroupBy)。

内容的提问来源于stack exchange,提问作者Subrata Mallik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:21:05