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

Laravel按用户坐标排序获取附近餐厅的功能实现问询

实现按用户坐标距离排序餐厅的方案

步骤1:修改函数参数,接收用户坐标

先给get_restaurants方法新增用户纬度($user_lat)和经度($user_lng)参数,让API调用时能传入这两个坐标值。

步骤2:在查询中计算距离并排序

利用MySQL的地理函数计算餐厅与用户的直线距离,再按距离由近到远排序。推荐用ST_Distance_Sphere(MySQL 5.7+支持,计算精度高,返回单位为米),如果是旧版本MySQL则用Haversine公式兼容。

修改后的完整代码

<?php

namespace App\CentralLogics;

use App\Models\Restaurant;
use App\Models\OrderTransaction;

class RestaurantLogic
{
    // 新增$user_lat和$user_lng参数
    public static function get_restaurants($zone_id, $filter, $user_lat, $user_lng, $limit = 10, $offset = 1, $type='all')
    {
        $paginator = Restaurant::
        withOpen()
        ->with(['discount'=>function($q){
            return $q->validate();
        }])->whereIn('zone_id', $zone_id)
        ->when($filter=='delivery', function($q){
            return $q->delivery();
        })
        ->when($filter=='take_away', function($q){
            return $q->takeaway();
        })
        ->Active()
        ->type($type)
        // 根据是否传入坐标切换排序逻辑
        ->when(isset($user_lat) && isset($user_lng), function($q) use ($user_lat, $user_lng) {
            // 计算距离(米)并作为distance字段返回,按距离升序排序
            return $q->selectRaw('*, ST_Distance_Sphere(point(longitude, latitude), point(?, ?)) as distance', [$user_lng, $user_lat])
                     ->orderBy('distance', 'asc');
        }, function($q) {
            // 未传入坐标时保留原有排序逻辑
            return $q->orderBy('open', 'desc');
        })
        ->paginate($limit, ['*'], 'page', $offset);

        return [
            'total_size' => $paginator->total(),
            'limit' => $limit,
            'offset' => $offset,
            'restaurants' => $paginator->items()
        ];
    }
}

可选:旧版本MySQL兼容方案(Haversine公式)

如果你的MySQL版本低于5.7,把上面的selectRaw替换为以下代码(计算结果为公里,地球半径取6371公里):

selectRaw('*, 
    6371 * acos(cos(radians(?)) * cos(radians(latitude)) * cos(radians(longitude) - radians(?)) + sin(radians(?)) * sin(radians(latitude))) as distance', 
    [$user_lat, $user_lng, $user_lat])

注意事项

  1. 确保Restaurant对应的数据库表存在latitude和longitude字段,推荐字段类型为DECIMAL(10,8)。
  2. 调用该方法的API接口需要同步传入user_lat和user_lng参数。
  3. 返回的餐厅数据会新增distance字段,前端可直接用该值展示距离信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 09:35:16