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

如何在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

相关产品推荐
方舟 Agent Plan

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

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