PHP+MySQL获取坐标范围内的数据

1.收到的参数

@param latitude 纬度
@param longitude 经度

2.将经纬度换算成范围及范围距离

/**
     * @desc 根据传入的经纬度,和距离范围,返回所有在距离范围内的经纬度的取值范围
     * @param $lng              坐标点经度
     * @param $lat              坐标点纬度
     * @param $distance         范围直径单位:km
     * @return array
     */
    public function location_range($lng, $lat,$distance=0){

        //不传默认1km
        $distance = $distance??1;

        $earthRadius = 6378.137;//单位km,地球的直径
        $d_lng =  2 * asin(sin($distance / (2 * $earthRadius)) / cos(deg2rad($lat)));
        $d_lng = rad2deg($d_lng);
        $d_lat = $distance/$earthRadius;
        $d_lat = rad2deg($d_lat);

        //开始跟结束不能乱,BETWEEN查询必须从小到大
        return array(
            'lat_start' => sprintf("%.6f",$lat - $d_lat),//纬度开始
            'lat_end' => sprintf("%.6f",$lat + $d_lat),//纬度结束
            'lng_start' => sprintf("%.6f",$lng - $d_lng),//纬度开始
            'lng_end' => sprintf("%.6f",$lng + $d_lng),//纬度结束
            'distance' => $distance*1000 //限制的距离
        );
    }

3.查询数据库

/**
    * 获取范围内的数据列表
    * @param latitude string 纬度 
    * @param longitude string 经度    
    */
    public function get_range_list($data)
    {
        $where = "u.status = 1";//查询条件
        $param = [];//参数化条件
        
        $scope = $this->location_range($data['longitude'],$data['latitude']);
        
        $where .= " and (u.longitude between :lng_start and :lng_end )
        and (u.latitude between :lat_start and :lat_end )";
        $param['lng_start'] = $scope['lng_start'];
        $param['lng_end'] = $scope['lng_end'];
        $param['lat_start'] = $scope['lat_start'];
        $param['lat_end'] = $scope['lat_end'];

        //限制的距离(加上该条件,搜索范围才会被限制在一个圈内)
        $where .= " and ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN((:latitude_1 * PI() / 180 - u.latitude * PI() / 180 ) / 2),2) + COS(:latitude_2
             * PI() / 180) * COS(u.latitude * PI() / 180) * POW(SIN((:longitude_1 * PI() / 180 - u.longitude * PI() / 180) / 2),2))) * 1000) <= :distance";
        $param['distance'] = $scope['distance'];
        $param['latitude_1'] = $data['latitude'];
        $param['latitude_2'] = $data['latitude'];
        $param['longitude_1'] = $data['longitude'];
        
        $sql = "SELECT
                    u.id,
                    ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN(({$data['latitude']} * PI() / 180 - u.latitude * PI() / 180 ) / 2),2) + COS({$data['latitude']}
                                 * PI() / 180) * COS(u.latitude * PI() / 180) * POW(SIN(({$data['longitude']} * PI() / 180 - u.longitude * PI() / 180) / 2),2))) * 1000) AS distance
                FROM
                    USER AS u
                WHERE
                    { $where }
                LIMIT 0, 10";
                 
        return DB::select($sql, $param);//laravel框架的一种写法     
    }

您可能还会喜欢: