Как оказалось, я работал над некоторыми проектами, которые делали очень похожие вещи, и собрал несколько вспомогательных функций, которые могут помочь.Существует алгоритм, который вычисляет расстояния между двумя наборами координат, поэтому эти помощники либо выполнят это за вас, либо создадут SQL, необходимый для его выполнения в базе данных.distance_sql()
звучит как то, что вы ищете.Заставив запрос выполнять работу вместо сценария, вы получаете возможность сортировать и разбивать на страницы набор результатов перед его возвратом.Я бы рекомендовал поместить в вашу модель метод query-scope , который вызывает его.
Если вы еще этого не сделали, создайте файл app/helpers.php
и добавьте его в свой файл.composer.json
файл и затем запустите composer install
:
"autoload": {
"files": [
"app/helpers.php",
...
],
...
},
...
И, наконец, поместите их в helpers.php
:
if (!function_exists('distance')) {
/**
* Calculate the distance between two sets of coordinates
*
* @param float $latitude1
* @param float $longitude1
* @param float $latitude2
* @param float $longitude2
* @param float $padding
* @return float
*/
function distance($latitude1, $longitude1, $latitude2, $longitude2, $padding = 0.0)
{
$earthRadiusInMiles = 3959;
$latitude1 = deg2rad($latitude1);
$latitude2 = deg2rad($latitude2);
$longitude1 = deg2rad($longitude1);
$longitude2 = deg2rad($longitude2);
$miles = $earthRadiusInMiles * acos(
cos($latitude1) * cos($latitude2)
* cos($longitude2 - $longitude1)
+ sin($latitude1) * sin($latitude2)
);
$miles += $padding * $miles;
return round($miles, 3);
}
}
if (!function_exists('distance_sql')) {
/**
* Generate the SQL needed to calculate the distance between two sets of coordinates
*
* @param float|string $latitude1
* @param float|string $longitude1
* @param float|string $latitude2
* @param float|string $longitude2
* @param float $padding
* @return string
*/
function distance_sql($latitude1, $longitude1, $latitude2, $longitude2, $padding = 0.0)
{
$earthRadiusInMiles = 3959;
$latitude1 = 'RADIANS('.DB::connection()->getPdo()->quote($latitude1).')';
$latitude2 = "RADIANS($latitude2)";
$longitude1 = 'RADIANS('.DB::connection()->getPdo()->quote($longitude1).')';
$longitude2 = "RADIANS($longitude2)";
$sql = "$earthRadiusInMiles * ACOS("
. "COS($latitude1) * COS($latitude2)"
. " * COS($longitude2 - $longitude1)"
. " + SIN($latitude1) * SIN($latitude2))";
$sql .= " + $padding * $sql";
return $sql;
}
}