Con*_*ech 4 php geolocation laravel eloquent laravel-5
我希望为我的"Candidate"Eloquent模型添加一个geolocation属性.我想根据他们的位置找到候选人.例如,找到距离旧金山20英里范围内的所有候选人.我的Eloquent模型应该如何将候选人的位置存储在数据库中?
如何根据候选人的位置查询候选人?我正在使用Laravel 5.3.
就个人而言,我之前通过存储一组纬度和经度坐标实现了这一目标.
你可以使用一个叫做Haversine公式的东西来计算一组指定坐标和你的情况下候选集之间的"乌鸦飞行"距离.
这是一个这样的查询的例子.例如,这个计算"距离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;
Run Code Online (Sandbox Code Playgroud)
最初在这里找到.
如果您要为您的候选模型添加lat/lng,可以很容易地调整以满足您的需求.
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;
Run Code Online (Sandbox Code Playgroud)
您可以将其实现为某种查询范围,例如(未经过测试且具有最小的输入清理)
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'
);
}
Run Code Online (Sandbox Code Playgroud)
注意:在这种情况下,3959是地球的半径(英里),公式将计算以英里为单位的距离.如果您需要距离为公里,请将3959更改为6371.感谢@Lionel在评论中指出这一点.