一、sql根据经纬度
DB::select("SELECT *, ACOS(
COS(RADIANS('$latitude')) *
COS(RADIANS(latitude)) *
COS(RADIANS(longitude) - RADIANS('$longitude')) +
SIN(RADIANS('$latitude')) *
SIN(RADIANS(latitude))
) * 6378 as distance FROM 表 ORDER BY distance ASC limit 10");
二、使用 redis-Geo
public function test(){
$arr = Request::instance()->post();
$latitude = $arr['latitude'];
$longitude = $arr['longitude'];
$redis = $this->redis;
try {
$param_a = array('areaCache');
$ret = call_user_func_array(array($redis, 'EXISTS'), $param_a);
if($ret){
$param = array('georadius', 'areaCache', $longitude, $latitude, 55000, 'm', 'WITHDIST', 'WITHCOORD','ASC');
$nearbyList = call_user_func_array(array($redis, 'rawCommand'), $param);
//半径50000、单位m/km可选、距离显示、排序规则
return getjson('1', '查找到排序:', $nearbyList);
}else{
return getjson('1', '没有查询到:','异常!' );
}
} catch (Exception $e){
}
}
注:方法:call_user_func_array( callable $callback , array $param_arr )
把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入。
或者获取腾讯位置服务 WebService API | 腾讯位置服务
public function address(){
try {
//获取经纬度
$lat = request()->get('lat');
$lng = request()->get('lng');
//调用第三方获取周边信息
$message = file_get_contents("https://apis.map.qq.com/ws/place/v1/search?keyword=学校&boundary=nearby($lat,$lng,1000)&key=BR5BZ-2XUES-O5HOT-62FWR-LFWZJ-ARFLN");
$message=json_decode($message,true)['data'];
//周边景点存入redis
foreach ($message as $v){
Redis::rawCommand('geoadd','address',$v['location']['lng'],$v['location']['lat'],$v['title']);
}
//计算两点排序
$data = Redis::rawCommand('GEORADIUS','address',$lng,$lat,'1000','km','withdist','asc');
if (!$data){
return json_encode(['code'=>200,'msg'=>'排序成功','data'=>$data]);
}
return json_encode(['code'=>200,'msg'=>'排序成功','data'=>$data]);
}catch (\Exception $exception){
return json_encode(['code'=>2001,$exception->getMessage(),'data'=>'']);
}
}
三、调用地图API接口
/**
* 根据起点坐标和终点坐标测距离[http://lbs.qq.com/webservice_v1/guide-distance.html]
* @param [array] $from [起点坐标(经纬度),例如:array(118.012951,36.810024)]
* @param [array] $to [终点坐标(经纬度)]
* @return [string] 距离数值
*/
function get_distance($from,$to){
sort($from);
sort($to);
$from = implode(",", $from);
$to = implode(",", $to);
$curl = 'http://apis.map.qq.com/ws/distance/v1/?mode=driving&from='.$from.'&to='.$to.'&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77';
$content = request($curl);
$result = json_decode($content,true);
return $result['result']['elements']['distance'];
}
四、数学计算
/**
* 根据起点坐标和终点坐标测距离
* @param [array] $from [起点坐标(经纬度),例如:array(118.012951,36.810024)]
* @param [array] $to [终点坐标(经纬度)]
* @param [bool] $km 是否以公里为单位 false:米 true:公里(千米)
* @param [int] $decimal 精度 保留小数位数
* @return [string] 距离数值
*/
function get_distance($from,$to,$km=true,$decimal=2){
sort($from);
sort($to);
$EARTH_RADIUS = 6370.996; // 地球半径系数
$distance = $EARTH_RADIUS*2*asin(sqrt(pow(sin( ($from[0]*pi()/180-$to[0]*pi()/180)/2),2)+cos($from[0]*pi()/180)*cos($to[0]*pi()/180)* pow(sin( ($from[1]*pi()/180-$to[1]*pi()/180)/2),2)))*1000;
if($km){
$distance = $distance / 1000;
}
return round($distance, $decimal);
}