ns/distance-bundle
A Symfony bundle that provides reusable distance calculation services for PHP applications. Compute geographic distances between coordinates through a clean, dependency-injection-friendly API with configurable units and straightforward integration.
The package is distributed as ns/distance-bundle. Install it with Composer:
composer require ns/distance-bundle
Because it is shipped as a Symfony bundle, the first thing to check is whether it exposes a Laravel service provider — almost certainly not. Plan on one of two paths:
config/bundles.php and configure the postal-code data source (often a local dataset, a SQL table, or an external geocoding API).Look here first, in order:
composer.json — for the actual namespace, required PHP version, and any external driver dependencies.DependencyInjection/ folder — this tells you the exact service IDs and config keys you can inject.DistanceCalculator-style service) — this is what you will call day to day.Minimal first use case — distance between two postal codes:
// Symfony
$distance = $this->get(DistanceCalculator::class)->calculate('75001', '13001'); // returns a float (km)
// Laravel (manual wiring)
app()->bind(DistanceCalculator::class, fn () => new DistanceCalculator(/* driver deps */));
$distance = app(DistanceCalculator::class)->calculate('75001', '13001');
If your first call fails with a "cannot resolve driver" error, the config still needs a geo data source — check the bundle's README and Resources/config/services.yaml for the parameter names.
Controller / Action usage. Inject the calculator into your controller and return the value as JSON. Keep the postal codes as validated request parameters, not free-form strings.
public function distance(DistanceRequest $request, DistanceCalculator $calc)
{
return response()->json([
'km' => $calc->calculate($request->from, $request->to),
]);
}
Batch calculation. When comparing one origin against many destinations, loop but reuse the same calculator instance so any internal geo lookup cache is shared:
$origin = $calc->geocode($from); // resolve once
$results = collect($destinations)->mapWithKeys(fn ($to) =>
[$to => $calc->distanceBetween($origin, $calc->geocode($to))]
);
Store geocoded coordinates in your own model. The bundle typically re-resolves a postal code on each call. Add lat/lng (or the resolved coordinates) to your addresses/warehouses table, then use the bundle only for the pure math step (haversine / vincenty) — that step is deterministic and does not need the network.
Wrap in a caching decorator. Postal code → coordinate lookups rarely change; cache them with a long TTL keyed by country + code:
$coords = Cache::remember("pc:{$country}:{$code}", 86400 * 30, fn () =>
$calc->geocode($code, $country)
);
Delivery-zone / store-locator integration. The most common real-world use: given a customer's postal code, return the list of stores whose stored coordinates fall within a radius.
$nearby = Store::query()
->withCoordinates() // your own lat/lng columns
->get()
->filter(fn ($s) => $calc->haversine($customer, $s) <= $radiusKm);
Push the radius filter into SQL (ST_Distance_Sphere on MySQL 5.7+, PostGIS on Postgres) once the dataset grows.
Testing. Bind a fake calculator in your test container that returns fixed distances. This keeps tests fast and avoids geocoding API quota burn.
DistanceServiceProvider, no facade, no publishable config. Expect to hand-wire services. If you need a Laravel-native option, a thin own-wrapper around a well-maintained geocoding client (e.g. a pure haversine helper + a cached geocoder) is usually less work than adapting the bundle.75001 (FR), SW1A 1AA (UK), 100-0001 (JP), 02134-1234 (US ZIP+4). The package will not normalise these for you — trim, uppercase, and strip internal whitespace before calling. A malformed code can silently geocode to null and yield a nonsense distance.* 1.609 conversion on faith.0.0 or null, check (a) that geocoding succeeded, (b) that both coordinates are in the same datum (WGS-84), and (c) that you are not passing the same value for both args due to a variable-shadowing bug.How can I help you explore Laravel packages today?