Updated June 2026. Tested on Laravel 13, PHP 8.4 and MySQL 8.

I built this for a food delivery app. A user opens the app and wants restaurants within, say, one kilometre of where they are standing. The phone sends their latitude and longitude to a Laravel API, and the API returns the nearby restaurants sorted by distance. The trick is calculating distance from coordinates, which the haversine formula does, right inside a single SQL query.

The data lives in a table with latitude and longitude columns for each place.

The query

You compute the distance as a derived column with the haversine formula, then filter and sort by it. Here it is with the Eloquent query builder. Bind the user's coordinates as parameters so it is safe.

use App\Models\Restaurant;

public function nearby(float $lat, float $lng, int $radiusMeters = 1000)
{
    return Restaurant::query()
        ->selectRaw(
            'id, name, address, latitude, longitude,
             ( 6371000 * acos(
                cos(radians(?)) * cos(radians(latitude))
                * cos(radians(longitude) - radians(?))
                + sin(radians(?)) * sin(radians(latitude))
             ) ) AS distance',
            [$lat, $lng, $lat]
        )
        ->where('is_active', true)
        ->having('distance', '<', $radiusMeters)
        ->orderBy('distance')
        ->limit(20)
        ->get();
}

Reading the formula

The big expression is the haversine formula, which gives the great circle distance between two points on a sphere. The 6371000 is the Earth's radius in metres, so the result comes back in metres. Swap it to get other units:

  • 6371 for kilometres
  • 3956 for miles

The three ? placeholders are the user's latitude, longitude and latitude again, in that order, matching how the formula uses them.

Why having, not where

Notice the filter is having, not where. That is because distance is a computed column built in the SELECT, and SQL does not let you use a SELECT alias in a WHERE. having runs after the columns are computed, so it can see distance. The orderBy('distance') then gives you the closest places first.

Using it in an API endpoint

public function search(Request $request)
{
    return $this->nearby(
        $request->float('lat'),
        $request->float('lng'),
        $request->integer('radius', 1000),
    );
}

Laravel serialises the result to JSON, and the app gets a list of nearby restaurants with each one's distance, ready to show on a map or a list. The same query works for any "find nearby" feature, shops, drivers, events, just point it at a table with latitude and longitude. Questions welcome in the comments.