如何在Laravel Eloquent查询中获取带KM单位的格式化距离值
解决Laravel查询中距离数值格式化问题
我来帮你搞定这个距离格式化的需求,有几种实用的方法可以实现把0.05205731665026305转换成类似1.2KM的格式,咱们一个个来看:
方法一:直接在SQL查询中格式化
你可以修改selectRaw语句,用SQL的函数直接把计算出的距离值保留一位小数并拼接单位。注意不同数据库的字符串拼接函数不一样,这里分两种情况:
如果你用的是MySQL:
$salons = Salon::select('salons.*') ->selectRaw('CONCAT(ROUND(6371* acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ), 1), "KM") AS distance', [$lat, $lng, $lat]) ->havingRaw("distance + 0 < 25") // 因为现在distance是字符串,要转成数值比较 ->where("category_Id" , "=" , $id) ->get();
注意:这里
havingRaw里要把distance转成数值(用distance + 0),不然字符串比较会出逻辑错误。
如果你用的是PostgreSQL:
$salons = Salon::select('salons.*') ->selectRaw('ROUND(6371* acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ), 1) || \'KM\' AS distance', [$lat, $lng, $lat]) ->havingRaw("distance::numeric < 25") // 把字符串转成数值类型比较 ->where("category_Id" , "=" , $id) ->get();
这种方式的好处是数据库直接返回格式化后的结果,不用PHP再额外处理,效率更高。
方法二:用Laravel模型访问器(推荐)
如果不想修改查询语句,可以在Salon模型里定义一个访问器,自动格式化distance字段:
// app/Models/Salon.php public function getDistanceFormattedAttribute() { // 先判断distance是否存在,避免报错 if (!isset($this->distance)) { return null; } return round($this->distance, 1) . 'KM'; }
然后查询的时候还是保留原来的distance字段:
$salons = Salon::select('salons.*') ->selectRaw('( 6371* acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ) AS distance', [$lat, $lng, $lat]) ->havingRaw("distance < 25") ->where("category_Id" , "=" , $id) ->get();
之后你就可以通过$salon->distance_formatted拿到格式化后的字符串,比如对应你给出的0.052...数值会输出0.1KM。这种方式符合Laravel的Eloquent设计规范,代码更优雅,也方便后续复用。
方法三:查询后遍历处理
如果只是临时需求,不想改模型也不想改SQL,可以在查询结果返回后用map方法遍历处理:
$salons = Salon::select('salons.*') ->selectRaw('( 6371* acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ) AS distance', [$lat, $lng, $lat]) ->havingRaw("distance < 25") ->where("category_Id" , "=" , $id) ->get() ->map(function ($salon) { $salon->distance = round($salon->distance, 1) . 'KM'; return $salon; });
这样返回的$salons集合里,每个模型的distance字段就是你想要的格式了。
内容的提问来源于stack exchange,提问作者Farhan Anees
相关产品推荐
相关产品推荐

