Kei*_*dge 3 php mysql geolocation laravel eloquent
我知道这已被问过很多次了.但我根本不需要根据自己的需要做出决定.
我需要从其他用户查询最近的用户.基本上,我有一个users表,这个表one to one与表有关系users_locations,有一个纬度和经度字段.
所以我看过这个 https://laravel.io/forum/04-23-2014-convert-this-geolocation-query-to-query-builder-for?page=1 这可能是最好的解决方案.
但我的基本查询是:
\App\Model\User::whereNotIn('id', $ids)
->where('status', 1)
->whereHas('user_location', function($q) use ($lat, $lng, $radius) {
/** This is where I'm stuck to write the query **/
})->select('id', 'firstname')
->get();
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我不知道如何实现解决方案.
预先感谢您的帮助
编辑 更清楚:我需要获得半径5公里的用户.
Kei*_*dge 12
感谢EddyTheDove和Ohgodwhy,我找到了解决方案.
所以就是这样:
\App\Model\User::whereNotIn('id', $ids)
->where('status', 1)
->whereHas('user_location', function($q) use ($radius, $coordinates) {
$q->isWithinMaxDistance($coordinates, $radius);
})->select('id', 'firstname')
->get();
Run Code Online (Sandbox Code Playgroud)
在我的UserLocation模型中,我有这个本地范围
public function scopeIsWithinMaxDistance($query, $coordinates, $radius = 5) {
$haversine = "(6371 * acos(cos(radians(" . $coordinates['latitude'] . "))
* cos(radians(`latitude`))
* cos(radians(`longitude`)
- radians(" . $coordinates['longitude'] . "))
+ sin(radians(" . $coordinates['latitude'] . "))
* sin(radians(`latitude`))))";
return $query->select('id', 'users_id', 'cities_id')
->selectRaw("{$haversine} AS distance")
->whereRaw("{$haversine} < ?", [$radius]);
}
Run Code Online (Sandbox Code Playgroud)
Ohgodwhy的原始答案在这里: Laravel中两点之间的Haversine距离计算
编辑
在MySQL中使用存储函数执行它的另一种方法:
DELIMITER $$
DROP FUNCTION IF EXISTS haversine$$
CREATE FUNCTION haversine(
lat1 FLOAT, lon1 FLOAT,
lat2 FLOAT, lon2 FLOAT
) RETURNS FLOAT
NO SQL DETERMINISTIC
COMMENT 'Returns the distance in degrees on the Earth
between two known points of latitude and longitude'
BEGIN
RETURN DEGREES(ACOS(
COS(RADIANS(lat1)) *
COS(RADIANS(lat2)) *
COS(RADIANS(lon2) - RADIANS(lon1)) +
SIN(RADIANS(lat1)) * SIN(RADIANS(lat2))
));
END$$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)
我乘以111.045将结果转换为km.(我不确定这个值是对的,我发现很多其他的值离这个不远,所以如果有人对它有精确的话,它可能会很好)
原始文章:https://www.plumislandmedia.net/mysql/stored-function-haversine-distance-computation/
然后使用雄辩的:
\App\Model\User::whereNotIn('id', $ids)
->where('status', 1)
->whereHas('user_location', function($q) use ($radius, $coordinates) {
$q->whereRaw("111.045*haversine(latitude, longitude, '{$coordinates['latitude']}', '{$coordinates['longitude']}') <= " . $radius]);
})->select('id', 'firstname')
->get();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4496 次 |
| 最近记录: |