大家是如何使用PHP 搜索附近的人

216 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情
日常应用中我们很多时候都需要查找附近的人、与商品。最近用tp框架开发附近的人功能。具体代码如下: 一、根据经纬度和半径计算出范围,需要给定经纬度、距离半径,返回对应范围。

/**
 * 根据经纬度和半径计算出范围
 * @param string $lat 纬度
 * @param String $lng 经度
 * @param float $radius 半径
 * @return Array 范围数组
 * 24901*1609   地球周长*英里系数
 * M_PI/180   M_PI或pi()代表圆周率
 */
private function calcScope($lat, $lng, $radius) {
    $degree = (24901*1609)/360.0;
    $dpmLat = 1/$degree;

    $radiusLat = $dpmLat*$radius;
    $minLat = $lat - $radiusLat;       // 最小纬度
    $maxLat = $lat + $radiusLat;       // 最大纬度

    $mpdLng = $degree*cos($lat * (M_PI/180));
    $dpmLng = 1 / $mpdLng;
    $radiusLng = $dpmLng*$radius;
    $minLng = $lng - $radiusLng;      // 最小经度
    $maxLng = $lng + $radiusLng;      // 最大经度

    /** 返回范围数组 */
    $scope = array(
        'minLat'    =>  $minLat,
        'maxLat'    =>  $maxLat,
        'minLng'    =>  $minLng,
        'maxLng'    =>  $maxLng
        );
    return $scope;
}

二、根据经纬度和半径查询在此范围内的所有的电站

/**
 * 根据经纬度和半径查询在此范围内的所有的电站
 * @param  String $lat    纬度
 * @param  String $lng    经度
 * @param  float $radius 半径
 * @return Array         计算出来的结果
 */
public function searchByLatAndLng($lat, $lng, $radius) {
    $scope = $this->calcScope($lat, $lng, $radius);     // 调用范围计算函数,获取最大最小经纬度
    /** 查询经纬度在 $radius 范围内的电站的详细地址 */
    $sql = 'SELECT `字段` FROM `表名` WHERE `Latitude` < '.$scope['maxLat'].' and `Latitude` > '.$scope['minLat'].' and `Longitude` < '.$scope['maxLng'].' and `Longitude` > '.$scope['minLng'];

    $stmt = self::$db->query($sql);
    $res = $stmt->fetchAll(PDO::FETCH_ASSOC);       // 获取查询结果并返回
    return $res;
}

三、获取两个经纬度之间的距离

/**
 * 获取两个经纬度之间的距离
 * @param  string $lat1 纬一
 * @param  String $lng1 经一
 * @param  String $lat2 纬二
 * @param  String $lng2 经二
 * @return float  返回两点之间的距离
 */
public function calcDistance($lat1, $lng1, $lat2, $lng2) {
    /** 转换数据类型为 double */
    $lat1 = doubleval($lat1);
    $lng1 = doubleval($lng1);
    $lat2 = doubleval($lat2);
    $lng2 = doubleval($lng2);
    /** 以下算法是 Google 出来的,与大多数经纬度计算工具结果一致 */
    $theta = $lng1 - $lng2;
    $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
    $dist = acos($dist);
    $dist = rad2deg($dist);
    $miles = $dist * 60 * 1.1515;
    return ($miles * 1.609344);
}

四.
1.经纬度范围的计算方法是在百度上查找的,目前尚没有找到标准的计算工具,因此该算法无法求证,但大多数帖子基本上采用的这种计算方式。
2.经纬度距离的计算方式是在 Google 上查找的,计算结果与大多数计算工具结果相近。之所以在 Google 中查找,是因为我曾在百度上查找过多种计算方式,结果都不尽人意。
3.通过半径和经纬度计算范围时,半径的单位是m;计算距离时,得到的结果是km。因此,要注意单位变化。