Distance & matrix
distance() walks the pipeline for a DistanceProvider — Google’s Routes API, out of the box — and returns a Distance, or null when no provider can resolve the query (an unreachable or refusing provider is skipped, and DistanceResolutionFailed says why):
use RoundlyConsulting\Geolocation\DataTransferObjects\Coordinates;
use RoundlyConsulting\Geolocation\DataTransferObjects\DistanceQuery;
use RoundlyConsulting\Geolocation\Enum\DistanceType;
use RoundlyConsulting\Geolocation\Facades\Geolocation;
$distance = Geolocation::distance(
DistanceQuery::between(
from: new Coordinates(48.1482, 17.1067),
to: new Coordinates(49.2000, 16.6068),
type: DistanceType::Driving,
),
);
$distance?->humanReadableDistance; // "133 km"
$distance?->distanceInMeters; // 133000
$distance?->durationInSeconds; // 5400// Skip the query object — distanceBetween() builds it for you (driving by default)
$distance = Geolocation::distanceBetween(
new Coordinates(48.1482, 17.1067),
new Coordinates(49.2000, 16.6068),
DistanceType::Walking,
);The Distance object
| Property | Type | Contents |
|---|---|---|
humanReadableDistance | string | Provider-formatted distance, e.g. “133 km”. |
distanceInMeters | int | Distance in metres. |
humanReadableDuration | string | Provider-formatted travel time. |
durationInSeconds | int | Travel time in seconds. |
type | DistanceType | Walking or Driving. |
Travel mode from user input
DistanceType’s validationRule() makes the travel mode safe to accept from a form:
$data = $request->validate([
'mode' => ['required', DistanceType::validationRule()], // 'in:Walking,Driving'
]);
$distance = Geolocation::distance(DistanceQuery::between(
from: new Coordinates(48.1482, 17.1067),
to: new Coordinates(48.1486, 17.1077),
type: DistanceType::from($data['mode']),
));
$distance?->humanReadableDuration; // e.g. "6 mins"Distance matrix
Resolve a grid of distances between several origins and destinations in one call, through the Routes API’s computeRouteMatrix. A leg without a route degrades to null, and so does every cell of a request Google can’t serve (unreachable or refused):
use RoundlyConsulting\Geolocation\DataTransferObjects\Coordinates;
use RoundlyConsulting\Geolocation\Enum\DistanceType;
$matrix = Geolocation::distanceMatrix(
origins: [new Coordinates(48.14, 17.10)],
destinations: [new Coordinates(49.20, 16.60), new Coordinates(50.07, 14.43)],
type: DistanceType::Driving, // optional — Driving is the default
);
$matrix->get(0, 1)?->distanceInMeters; // origin 0 → destination 1, null when that leg is unavailable
$matrix->origins; // list<Coordinates>
$matrix->rows; // array<int, array<int, Distance|null>>The matrix comes from the bundled Google provider. A grid over the Routes API’s cap of 625 elements (origins × destinations) is split into requests that fit and merged back in order; a request that fails leaves only its own cells null. If Google isn’t in the (scoped) pipeline, or every request fails, you get an empty grid where every get() returns null. Matrices are not cached and dispatch no events.
For a straight-line distance without any API call, use Coordinates::distanceTo().
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.