需求: 要求做个根据用户当前位置获取周围商家地址,并且按照由近到远排序,
方法一: 代码层实现
封装方法:
/** * @desc 根据两点间的经纬度计算距离 * @param float $lat 纬度值 * @param float $lng 经度值 * @param $status true KM,M显示;false 只返回M */ function system_getdistance($lat1, $lng1, $lat2, $lng2, $status = true, $single = true) { $earthRadius = 6367000; //approximate radius of earth in meters $lat1 = (floatval($lat1) * pi()) / 180; $lng1 = (floatval($lng1) * pi()) / 180; $lat2 = (floatval($lat2) * pi()) / 180; $lng2 = (floatval($lng2) * pi()) / 180; $calcLongitude = $lng2 - $lng1; $calcLatitude = $lat2 - $lat1; $stepOne = pow(sin($calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude / 2), 2); $stepTwo = 2 * asin(min(1, sqrt($stepOne))); $calculatedDistance = $earthRadius * $stepTwo; if (!$single) { return round($calculatedDistance); exit; } //把大于1000米的转换成km if ($status) { $m = round($calculatedDistance) / 1000; return $m > 1 ? round($m, 1) . "km" : ($m * 1000) . "m"; //return round($m,2); //这个是我在程序中用的,以为排序比较方便,大家根据需求选用 } else { return round($calculatedDistance) . "m"; } }
调用:
/** * @param Request $request * @return array * 获取分类商店,并按距离排序 */ function getShop(Request $request){ $c_id = $request->get(‘c_id‘); $lat1 = $request->get(‘lat‘); $lng1 = $request->get(‘lng‘); $lat1U = floatval($lat1)+0.01; $lat1D = floatval($lat1)-0.01; $lng1U = floatval($lng1)+0.01; $lng1D = floatval($lng1)-0.01; $data = db(‘store‘) ->where(‘c_id‘,$c_id) ->where(‘lat‘,‘<‘,$lat1U) //获取周围经纬度差0.01的商家距离 ->where(‘lat‘,‘>‘,$lat1D) ->where(‘lng‘,‘<‘,$lng1U) ->where(‘lng‘,‘>‘,$lng1D) ->find(); $res = json_encode($data); $arr1 = json_decode($res,true); $arr = []; foreach ($arr1 as $k=>$v){ $res = $this->system_getdistance($lat1,$lng1,$v[‘lat‘],$v[‘lng‘]); $arr1[$k][‘km‘] = $res.‘km‘; $arr[$k] = $res; } asort($arr); $arr2 = []; foreach($arr as $k=>$v){ $arr2[] = $arr1[$k]; } return $arr2; }
方法二: sql 层实现
SELECT id, lat, lng, ROUND( 6378.138 * 2 * ASIN( SQRT( POW( SIN( ( $lat * PI() / 180 - lat * PI() / 180 ) / 2 ), 2 ) + COS($lat * PI() / 180) * COS(lat * PI() / 180) * POW( SIN( ( $lng * PI() / 180 - lng * PI() / 180 ) / 2 ), 2 ) ) ) * 1000 ) AS distance FROM store ORDER BY distance asc
检索五公里范围以内的s q l
select * from (
SELECT
id,
lat,
lng,
ROUND(
6378.138 * 2 * ASIN(
SQRT(
POW(
SIN(
(
$lat * PI() / 180 - lat * PI() / 180
) / 2
),
2
) + COS($lat * PI() / 180) * COS(lat * PI() / 180) * POW(
SIN(
(
$lng * PI() / 180 - lng * PI() / 180
) / 2
),
2
)
)
) * 1000
) AS distance
FROM
store
ORDER BY
distance asc
) as a where a.distance<=5000