Laravel Scope to get locations nearest the user location

johndivam

JohnDivam

Posted on June 14, 2024

Laravel Scope to get locations nearest the user location

In many web applications, particularly those that involve mapping or location-based services, it is crucial to retrieve and display locations closest to a user's current position .

When dealing with geographical coordinates, calculating the distance between two points on the Earth's surface can be complex due to the spherical nature of the Earth. The Haversine formula is commonly used for this purpose. It calculates the distance between two points on a sphere given their longitudes and latitudes.

Setting Up the Scope

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Farm extends Model
{

    public function scopeClosest($query, $lat, $long)
    {
        $distanceQuery = "
            ( 6371 * acos( cos( radians(?) ) *
            cos( radians( farms.lat ) )
            * cos( radians( farms.long ) - radians(?) )
            + sin( radians(?) ) *
            sin( radians( farms.lat ) ) ) )
            AS distance
        ";

        return $query->select('farms.*')
            ->selectRaw($distanceQuery, [$lat, $long, $lat])
            ->orderBy('distance', 'asc');
    }
}
Enter fullscreen mode Exit fullscreen mode

Breaking Down the Scope

SQL Query: The Haversine formula is used within a raw SQL query to calculate the distance.
6371 is the Earth's radius in kilometers. If you need the distance in miles, replace it with 3959.
radians(?) converts degrees to radians for the latitude and longitude.
selectRaw: This method allows us to include raw expressions in our query. The placeholders (?) are replaced with the provided latitude and longitude values.
orderBy: Finally, we sort the results by the calculated distance in ascending order, so the closest farms appear first.

Using the Scope

$lat = 37.7749;  // User's latitude or use $request->lat
$long = -122.4194;  // User's longitude or use $request->long

$nearestFarm = Farm::closest($lat, $long)->first();
Enter fullscreen mode Exit fullscreen mode

This query will return a collection of Farm models ordered by their proximity to the user's location.

💖 💪 🙅 🚩
johndivam
JohnDivam

Posted on June 14, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related