一、準備
授權獲取用戶的經緯度並存入數據庫(lng 字段、lat 字段)。
二、查詢
1. 原生查詢
SELECT
*, CONVERT (
2 * 6378.137 * ASIN(
SQRT(
POW(
SIN(
3.1415926535898 * (" . $_GET['lat'] . " - lat) / 360
),
2
) + COS(
3.1415926535898 * " . $_GET['lat'] . " / 180
) * COS(lat * 3.1415926535898 / 180) * POW(
SIN(
3.1415926535898 * (" . $_GET['lng'] . " - lng) / 360
),
2
)
)
),
DECIMAL (10, 2)
) AS distance
FROM
`user`
WHERE
lat > 0 AND lng > 0
ORDER BY
distance ASC
LIMIT 0, 10
查詢的數據過濾掉指點距離的數據即可,也可使用 where 條件篩選,但 as 的別名不可以作爲 條件字段,需要又將計算的語句再寫一遍。TP框架爲例
2. ThinkPHP5+
// 獲取附近 1000m 的人
public function getLists(){
$lat = $_GET["lat"] ?? 0;
$lng = $_GET["lng"] ?? 0;
if(!$lat || !$lng){
return [];
}
$geoSql = <<<geo
CONVERT (
2 * 6378.137 * ASIN(
SQRT(
POW(
SIN(
3.1415926535898 * (" . $lat . " - lat) / 360
),
2
) + COS(
3.1415926535898 * " . $lat . " / 180
) * COS(lat * 3.1415926535898 / 180) * POW(
SIN(
3.1415926535898 * (" . $lng . " - lng) / 360
),
2
)
)
),
DECIMAL (10, 2)
)
geo;
$rs = User::field("*," . $geoSql . "as distance")
->where("lng&lat",">",0)
->where($geoSql . " < 1000")
->page($params["page"] ?? 1 , $params["limit"] ?? 10)
->orderRaw("distance asc")
->select();
return $rs;
}