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
相关产品推荐
相关产品推荐

