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

Laravel 5.4中同时使用having与paginate方法时查询构造器报错

解决Laravel 5.4中havingRaw与paginate一起使用的报错问题

嘿,这个坑我之前踩过!你遇到的问题根源在于Laravel分页机制的一个小细节:当你调用paginate()时,框架会自动执行两条SQL——一条是获取当前页的数据,另一条是计算总记录数。而默认的count查询只会执行count(*),不会包含你在select里定义的distance计算字段,可你的havingRaw又依赖这个字段,所以数据库就会抛出“字段不存在”的错误。

先优化你的原代码(可选但推荐)

首先,你可以把havingRaw里重复的计算公式改成用别名,这样代码更简洁,也减少出错概率:

DB::table('nearbies')
    ->select(DB::raw('( 6371 * acos ( cos ( radians(9.955308) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(76.302331) )+ sin ( radians(9.955308) ) * sin( radians( latitude ) ))) AS distance,id,name,location'))
    ->havingRaw('distance < 10') // 直接用别名代替重复公式
    ->orderBy('distance','asc')
    ->paginate(3);

不过这还解决不了分页的问题,得用下面的方案:

方案一:将查询转为子查询(最简洁可靠)

把原来的过滤查询作为子查询,让分页操作基于这个包含distance字段的临时表来执行,这样count查询就能正确识别字段了:

// 先定义基础查询
$baseQuery = DB::table('nearbies')
    ->select(DB::raw('( 6371 * acos ( cos ( radians(9.955308) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(76.302331) )+ sin ( radians(9.955308) ) * sin( radians( latitude ) ))) AS distance,id,name,location'))
    ->havingRaw('distance < 10')
    ->orderBy('distance','asc');

// 基于子查询进行分页
$results = DB::table(DB::raw("({$baseQuery->toSql()}) as temp_nearbies"))
    ->mergeBindings($baseQuery) // 绑定原查询的参数(这里虽然没参数,但好习惯要保持)
    ->select('*')
    ->paginate(3);

方案二:重写分页的count查询

如果你不想用子查询,可以手动告诉Laravel怎么计算总记录数,确保count查询也包含havingRaw的过滤条件:

$results = DB::table('nearbies')
    ->select(DB::raw('( 6371 * acos ( cos ( radians(9.955308) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(76.302331) )+ sin ( radians(9.955308) ) * sin( radians( latitude ) ))) AS distance,id,name,location'))
    ->havingRaw('distance < 10')
    ->orderBy('distance','asc')
    ->paginate(3, ['*'], null, null, function ($countQuery) {
        // 自定义count查询的逻辑
        $countQuery->select(DB::raw('count(*)'))
            ->from('nearbies')
            ->havingRaw('( 6371 * acos ( cos ( radians(9.955308) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(76.302331) )+ sin ( radians(9.955308) ) * sin( radians( latitude ) ))) < 10');
    });

为什么移除paginate就正常?

因为当你不使用分页时,Laravel只会执行你写的那条完整SQL——select里包含了distance字段,havingRaw能正常找到这个别名;但分页时自动生成的count查询没有这个字段,导致数据库无法解析having条件,所以报错。

内容的提问来源于stack exchange,提问作者Sandeep Nambiar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:58:50