Haversine distance calculation between two points in Laravel
This was my implementation of it. I've chosen to alias my query out ahead of time, this way I can take advantage of Pagination
. Furthermore, you need to explicitly select the columns that you wish to retrieve from the query. add them at the ->select()
. Such as users.latitude, users.longitude, products.name
, or whatever they may be.
I have created a scope which looks something like this:
public function scopeIsWithinMaxDistance($query, $location, $radius = 25) { $haversine = "(6371 * acos(cos(radians($location->latitude)) * cos(radians(model.latitude)) * cos(radians(model.longitude) - radians($location->longitude)) + sin(radians($location->latitude)) * sin(radians(model.latitude))))"; return $query ->select() //pick the columns you want here. ->selectRaw("{$haversine} AS distance") ->whereRaw("{$haversine} < ?", [$radius]);}
You can apply this scope to any model with a latitude
andlongitude
.
Replace the $location->latitude
with your latitude
that you wish to search against, and replace the $location->longitude
with the longitude that you wish to search against.
Replace the model.latitude
and model.longitude
with the Models you wish to find around the $location
based on the distance defined in the $radius
.
I know you have a functioning Haversine formula, but if you need to Paginate you can't use the code you've supplied.
Hopefully this helps.
Create this function in your Model
public static function getNearBy($lat, $lng, $distance, $distanceIn = 'miles') { if ($distanceIn == 'km') { $results = self::select(['*', DB::raw('( 0.621371 * 3959 * acos( cos( radians('.$lat.') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('.$lng.') ) + sin( radians('.$lat.') ) * sin( radians(lat) ) ) ) AS distance')])->havingRaw('distance < '.$distance)->get(); } else { $results = self::select(['*', DB::raw('( 3959 * acos( cos( radians('.$lat.') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('.$lng.') ) + sin( radians('.$lat.') ) * sin( radians(lat) ) ) ) AS distance')])->havingRaw('distance < '.$distance)->get(); } return $results; }
And you can use orderby
, groupBy
as per your requirement.
Using Haversine method, you can calculate distance between two points using this function. It works but I don't know how to implement this in Laravel. Thought of sharing this anyway.
$lat1 //latitude of first point$lon1 //longitude of first point $lat2 //latitude of second point$lon2 //longitude of second point $unit- unit- km or milefunction point2point_distance($lat1, $lon1, $lat2, $lon2, $unit='K') { $theta = $lon1 - $lon2; $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); $dist = acos($dist); $dist = rad2deg($dist); $miles = $dist * 60 * 1.1515; $unit = strtoupper($unit); if ($unit == "K") { return ($miles * 1.609344); } else if ($unit == "N") { return ($miles * 0.8684); } else { return $miles; } }