Coordinates, queries & enums
Coordinates is an immutable value object that validates its range on construction and computes great-circle distance:
use RoundlyConsulting\Geolocation\DataTransferObjects\Coordinates;
$here = new Coordinates(48.1486, 17.1077); // validates lat ∈ [-90,90], lng ∈ [-180,180]
$same = Coordinates::make(48.1486, 17.1077); // static constructor, same validation
$metres = $here->distanceTo(new Coordinates(50.0755, 14.4378)); // Haversine, ≈ 290 km
$here->latitude; // 48.1486
$here->toArray(); // ['latitude' => 48.1486, 'longitude' => 17.1077]
new Coordinates(91.0, 17.1077); // throws InvalidCoordinatesExceptionQueries
GeolocationQuery has forIp(), forAddress() and forCoordinates(); DistanceQuery has between(), with Driving as the default travel mode:
use RoundlyConsulting\Geolocation\DataTransferObjects\DistanceQuery;
use RoundlyConsulting\Geolocation\DataTransferObjects\GeolocationQuery;
use RoundlyConsulting\Geolocation\Enum\DistanceType;
$query = GeolocationQuery::forCoordinates($here);
$query->coordinates(); // ?Coordinates — null for IP and address queries
$query->ipAddress; // ?string
$query->address; // ?string
$trip = DistanceQuery::between(from: $here, to: $there, type: DistanceType::Walking);
$trip->from(); // Coordinates
$trip->to(); // Coordinates
// Positional constructors work too:
new GeolocationQuery('203.0.113.7');
new DistanceQuery(48.1, 17.1, 50.0, 14.4, DistanceType::Driving);Enums
DistanceType (Walking, Driving) and GeolocationType (Default, IP, Geolocation) are string-backed and use the Helpers trait from enums-for-laravel, so values(), labels(), options() / toOptions(), validationRule(), tryFromName(), is() / isIn() and the when* guards come for free:
use RoundlyConsulting\Geolocation\Enum\DistanceType;
use RoundlyConsulting\Geolocation\Enum\GeolocationType;
DistanceType::values()->all(); // ['Walking', 'Driving']
DistanceType::validationRule(); // 'in:Walking,Driving'
DistanceType::toOptions()->all(); // ['Walking' => 'Walking', 'Driving' => 'Driving'] — ready for <select>
DistanceType::tryFromName('Driving'); // DistanceType::Driving
GeolocationType::values()->all(); // ['Default', 'IP', 'Geolocation']
GeolocationType::Ip->value; // 'IP' (wire value is preserved)
GeolocationType::Ip->readable(); // 'IP'Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.