2016-12-28 96 views
2

我正在为我的“候选人”雄辩模型添加地理位置属性。我想根据他们的位置找到候选人。例如,找到旧金山20英里范围内的所有候选人。我的Eloquent模型应该如何在数据库中存储候选人的位置?如何通过Laravel 5中的地理位置查询?

如何根据他们的位置查询候选人?我正在使用Laravel 5.3。

回答

4

就我个人而言,我之前通过存储一组经纬度坐标来实现此目的。

你可以使用一种叫做Haversine formula的东西来计算一组指定坐标之间的“作为乌鸦”距离,在你的情况下是一组候选。

下面是这样一个查询的例子。例如,这个计算“距离37,-122坐标25英里半径内最近的20个位置”。

SELECT id, (3959 * acos(cos(radians(37)) * cos(radians(lat)) 
* cos(radians(lng) - radians(-122)) + sin(radians(37)) * sin(radians(lat)))) AS distance 
FROM markers 
HAVING distance < 25 
ORDER BY distance 
LIMIT 0 , 20; 

最初发现here

如果您要将lat/lng添加到Candidate模型中,可以很容易地根据您的需要对其进行调整。

SELECT *, (3959 * acos(cos(radians(37)) * cos(radians(lat)) 
* cos(radians(lng) - radians(-122)) + sin(radians(37)) * sin(radians(lat)))) AS distance 
FROM candidates 
ORDER BY distance 
LIMIT 0, 20; 

你或许可以实现这个作为某种查询范围,例如, (未测试和具有最小的输入清理)

public function scopeClosestTo($query, $lat, $lng) 
{ 
    return $query->orderByRaw(
     '(3959 * acos(cos(radians(' . floatval($lat) . ')) * cos(radians(lat)) * cos(radians(lng) - radians(' . floatval($lng) . ')) + sin(radians(' . intval($lat) . ')) * sin(radians(lat)))) ASC' 
    ); 
} 

注: 3959在这种情况下是地球的以英里半径和式将计算以英里的距离。如果您需要距离为公里,请将3959更改为6371.感谢@Lionel在评论中指出了这一点。

+2

请注意,3959是以英里为单位的地球半径。如果您在KM中需要它,只需将其更改为6371(KM)。 –

+0

好有意思。这似乎很深奥,但看起来这是做到这一点的最佳方式!必须制作一些SQL语句。谷歌地图有一个教程,他们也写了一个类似的SQL查询:https://developers.google.com/maps/articles/phpsqlsearch_v3谢谢 –

+0

是的,谷歌地图教程是我最初发现的Haversine的SQL版本公式:)没问题。 – Jonathon