Skip to content

Instantly share code, notes, and snippets.

@trovster
Created June 9, 2022 07:48
Show Gist options
  • Save trovster/45a57b5448223c77522bc8e26e02aec8 to your computer and use it in GitHub Desktop.
Save trovster/45a57b5448223c77522bc8e26e02aec8 to your computer and use it in GitHub Desktop.
Get properties, ordered by the distance from an existing property. Latitude and longitude are stored in the address relationship.
<?php
// Property::query()->nearest($property)->limit(5)->get();
// $property->nearest()->limit(5)->get();
public function scopeNearest(Builder $query, ?Property $property = null): Builder
{
$property = $property ?? $this;
$earthRadius = 3959;
$latitude = $property->address->lat;
$longitude = $property->address->lng;
$distanceColumn = 'distance';
$addressTable = $property->address->getTable();
$addressKeyColumn = $property->address->getQualifiedKeyName();
$addressRelationColumn = $property->qualifyColumn('address_id');
$latitudeColumn = $property->address->qualifyColumn('lat');
$longitudeColumn = $property->address->qualifyColumn('lng');
$selects = [
$property->qualifyColumn('*'),
"(
{$earthRadius} * Acos(
Cos(Radians({$latitude})) *
Cos(Radians({$latitudeColumn})) *
Cos(Radians({$longitudeColumn}) -
Radians({$longitude})) +
Sin(Radians({$latitude})) *
Sin(Radians({$latitudeColumn}))
)
) AS `{$distanceColumn}`",
];
return $query
->selectRaw(implode(', ', $selects))
->whereNot($property->getQualifiedKeyName(), $property->getKey())
->join($addressTable, $addressKeyColumn, '=', $addressRelationColumn)
->orderby($distanceColumn);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment