在公里范围内搜索用户无法正常工作

时间:2017-11-23 11:01:49

标签: php mysql laravel

我有脚本,我想在特定城市的给定公里范围内搜索用户。数据库中的用户具有城市,经度和纬度。用户1有纽约,用户2有华盛顿特区。我甚至可以给1000公里的距离而且它没有工作。为什么呢?

$user = User::with('user_data');
if ($request->has('city')) {
    $user->whereHas('user_data', function($query) use ($request) {
       return $query->where('residence', $request->city);
   });
}

if ($request->has('city')) {

    $latitude = app('geocoder')->geocode($request->city)->get()->first()->getCoordinates()->getLatitude(); 
    $longitude = app('geocoder')->geocode($request->city)->get()->first()->getCoordinates()->getLongitude();

    $user->whereHas('user_data', function($query) use ($request, $latitude, $longitude) {

        return $query->whereRaw("( 6371 * acos ( cos ( radians(".$latitude.") ) * cos( radians( residence_latitude ) ) * cos( radians( residence_longitude ) - radians(".$longitude.") ) + sin ( radians(".$latitude.") ) * sin( radians( residence_latitude ) ) ) <= ". $request->distance .")");
   });
}

DB

json

1 个答案:

答案 0 :(得分:1)

看起来您的距离计算公式基于Haversine公式。

我们可以开始使用提供的样本数据测试距离计算公式。

SELECT ( 6371 * acos ( cos ( radians(53.3364746) ) * cos( radians( 53.4285438 ) ) * cos( radians( 14.5528116 ) - radians(15.05037771) ) + sin ( radians(53.3364746) ) * sin( radians( 53.4285438 ) ) )

返回

3534.1964590146517

(见http://sqlfiddle.com/#!9/72188/8

根据国家飓风中心网站(http://www.nhc.noaa.gov/gccalc.shtml)提供的计算器,答案(四舍五入到最接近的整数)应为:

35

所以我认为你只需要在你的公式中加一点来将你的答案除以100,以便以公里为单位:

SELECT ( 6371 * acos ( cos ( radians(53.3364746) ) * cos( radians( 53.4285438 ) ) * cos( radians( 14.5528116 ) - radians(15.05037771) ) + sin ( radians(53.3364746) ) * sin( radians( 53.4285438 ) ) ) / 100

有关更新版本,请参阅http://sqlfiddle.com/#!9/72188/9

现在返回

35.34196459014652

这是正确答案。

转换为PHP,您只需更改一行,如下所示:

return $query->whereRaw("( 6371 * acos ( cos ( radians(".$latitude.") ) * cos( radians( residence_latitude ) ) * cos( radians( residence_longitude ) - radians(".$longitude.") ) + sin ( radians(".$latitude.") ) * sin( radians( residence_latitude ) ) ) / 100 <= ". $request->distance .")");