thinwrap/location
thinwrap/location for PHP — unified facade for 21 connectors across 6 providers, spanning routing, matrix, geocoding, and isochrone. Built-in polyline utilities. Stateless, BYO PSR-18 client.
PHP constraints
- Runtime dependencies
- php-http/discovery, psr/http-client, psr/http-factory
- BYO HTTP client
- consumer-supplied PSR-18 client via php-http/discovery
- Provenance
- cosign-signed GitHub Release artifacts
- Minimum runtime
- PHP 8.2+
- PSR-17/PSR-18 discovery is auto-detected; consumers can also pass clients explicitly
30-second install
composer require thinwrap/location2-minute end-to-end example
Compute a route between two waypoints through any supported provider. The example below uses Mapbox; switching providers means swapping the provider id case and config DTO — input and output shape stay identical.
<?php
use Thinwrap\Location\Routing;
use Thinwrap\Location\Enum\LocationProviderId;
use Thinwrap\Location\Config\MapboxConfig;
use Thinwrap\Location\DTO\LatLng;
use Thinwrap\Location\DTO\Routing\RoutingOptions;
$routing = new Routing(LocationProviderId::Mapbox, new MapboxConfig(accessToken: getenv('MAPBOX_TOKEN')));
$result = $routing->route(new RoutingOptions(
waypoints: [
new LatLng(37.7749, -122.4194),
new LatLng(37.3382, -121.8863),
],
));
echo "Distance: {$result->totalDistanceMeters}m, Duration: {$result->totalDurationSeconds}s\n";
echo $result->polyline; // Google precision-5 encodedSame code works for all supported routing providers — swap to LocationProviderId::Google, ::Here, ::Esri, ::TomTom, or ::Osrm and pass the matching config DTO.
See the universal route snippet for the full copy-paste pattern.
Supported providers
| Provider | Operations | Auth | README |
|---|---|---|---|
google Google Maps Platform | routing, matrix, geocoding | query | docs |
mapbox Mapbox | routing, matrix, geocoding, isochrone | query | docs |
here HERE | routing, matrix, geocoding, isochrone | header | docs |
esri ESRI ArcGIS | routing, matrix, geocoding, isochrone | bearer | docs |
tomtom TomTom | routing, matrix, geocoding, isochrone | query | docs |
osrm OSRM (self-hosted) | routing, matrix | header | docs |
Migration paths
Built-in polyline utilities
Every routing connector emits a Google precision-5 encoded polyline on$result->polyline. Decode, re-encode, or convert HERE's flex-polyline / ESRI's path geometry without a third-party library:
<?php
use Thinwrap\Location\Util\Polyline;
$points = Polyline::decode($result->polyline); // LatLng[]
$reEncoded = Polyline::encode($points); // back to precision-5
$here = Polyline::decodeFlex('BFoz5...'); // HERE flex-polyline
$esri = Polyline::encodeEsriPaths([[[-74, 40], [-73.5, 40.5]]]);Operation coverage
Provider × operation gaps below are architectural, not bugs:
- OSRM ships only
routing+matrix— geocoding and isochrone are out of scope by design for OSRM. - Google does not expose a public isochrone API at v1.0; if Google adds one, it lands in a minor release.
Migration: from a Google Maps PHP SDK
Drop the SDK; the wrapper hits the same HTTP endpoint and normalizes the response. Cross-language parity with/packages/location-ts is tracked as a design goal, not a hard release gate.
Migration: from hand-rolled cURL or Guzzle
Keep your PSR-18 client; replace the per-vendor request shape with one uniform call. The wrapper holds no state — every operation is a single method call from input to output (HERE Matrix v8's submit-poll-retrieve cycle stays hidden behind one matrix(...)).
Migration: from a TS service rewriting in PHP
The TS variant ships the same facade shape and provider set. Method names, result-shape fields, and error semantics are parity-locked. Port input/output payloads as-is.