Reputation: 748
how to write this query in laravel controller
SELECT *, ACOS( SIN( RADIANS( lat ) ) * SIN( RADIANS( $lat ) ) +
COS( RADIANS( lat ) ) * COS( RADIANS( $lat )) * COS( RADIANS( lon ) -
RADIANS( $long )) ) * 6380 AS distance
FROM places
WHERE ACOS( SIN( RADIANS( lat ) ) * SIN( RADIANS( $lat ) ) +
COS( RADIANS( lat ) ) * COS( RADIANS( $lat )) * COS( RADIANS( lon ) -
RADIANS( $long )) ) * 6380 < 10
ORDER BY distance
10 is radius in km $lat and $long is the center or the cirlce lat and lon are attributes if your table
Upvotes: 1
Views: 4244
Reputation: 50787
You're just implementing the haversine formula here. He's a quick scope you can attach to Models.
public function scopeCloseTo($query, $location, $radius = 25)
{
/**
* In order for this to work correctly, you need a $location object
* with a ->latitude and ->longitude.
*/
$haversine = "(6371 * acos(cos(radians($location->latitude)) * cos(radians(latitude)) * cos(radians(longitude) - radians($location->longitude)) + sin(radians($location->latitude)) * sin(radians(latitude))))";
return $query
->select(['comma','separated','list','of','your','columns'])
->selectRaw("{$haversine} AS distance")
->whereRaw("{$haversine} < ?", [$radius]);
}
In the above function, you can set the $radius
as the 3rd argument, so in your case 10
.
The 2nd argument is a location
from which you wish to find places within a radius of
. Think of this as your starting point.
E.G.; if you want to get all places near your house. your house
would then be passed as a location
object as the 3rd argument, with a longitude
and latitude
property.
You can adjust the radians(longitude)
to match your models table. Or you can use this
to reference the current model, and make this reusable (which is what we opted for.
Then you can invoke it like this:
App\Models;
class Hairdresser extends Eloquent {
//scopeCloseTo function in here
}
Finally, invoke it:
$hairdressers = Hairdresser::closeTo($location, 10);
Which will find all Hairdressers
within 10
km of your $location
.
Upvotes: 3