需求: 要求作個根據用戶當前位置獲取周圍商家地址,而且按照由近到遠排序,git
方法一: 代碼層實現sql
封裝方法:json
/** * @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"; } }
調用:app
/** * @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 層實現this
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 lspa
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