如何将附近地点查询SQL转换为Laravel Eloquent ORM?
问题分析与解决方案
你遇到的A non-numeric value encountered错误,根源是直接在PHP代码里尝试执行数据库的数学函数,同时把数据库字段名(如latitude)当成字符串做数值运算,PHP无法识别这些字段的数值,自然抛出非数值错误;另外having和orderBy里的distance也没有正确声明为查询别名。
以下是正确的Laravel Eloquent转换代码:
方法一:使用DB::raw()+参数绑定
首先确保控制器顶部引入DB门面:
use Illuminate\Support\Facades\DB;
然后编写查询:
$vehicles = $vehicles->select('*', DB::raw('(3956 * 2 * ASIN(SQRT( POWER(SIN(( :lat - latitude) * pi()/180 / 2), 2) +COS( :lat * pi()/180) * COS(latitude * pi()/180) * POWER(SIN(( :lng - longitude) * pi()/180 / 2), 2) ))) AS distance')) ->setBindings([ 'lat' => $request->location_lat, 'lng' => $request->location_long ]) ->having('distance', '<=', 10) ->orderBy('distance', 'ASC') ->get();
方法二:使用selectRaw()简化写法
$vehicles = $vehicles->selectRaw('*, (3956 * 2 * ASIN(SQRT( POWER(SIN(( ? - latitude) * pi()/180 / 2), 2) +COS( ? * pi()/180) * COS(latitude * pi()/180) * POWER(SIN(( ? - longitude) * pi()/180 / 2), 2) ))) AS distance', [ $request->location_lat, $request->location_lat, $request->location_long ]) ->having('distance', '<=', 10) ->orderBy('distance', 'ASC') ->get();
关键说明
DB::raw()/selectRaw()的作用:将距离计算的SQL片段包裹起来,让Laravel直接把这段内容发送给数据库执行,而非在PHP中尝试解析(PHP不认识ASIN/POWER这类数据库函数)。- 参数绑定:用
占位符传递经纬度,既避免SQL注入风险,又确保数值正确传递给数据库。 having/orderBy的写法:将distance作为字符串参数传入,Laravel会正确识别为查询中的别名。
内容的提问来源于stack exchange,提问作者kumari shwetha
相关产品推荐
相关产品推荐

