automapa/map-services
Composer 安装命令:
composer require automapa/map-services
包简介
PHP SDK for Automapa Map Services REST API — Geocoding, Routing & Address Autocomplete
README 文档
README
European Geocoding, Routing & Address Autocomplete
PHP SDK for the Automapa Map Services REST API. Simplifies integration with geocoding, routing, and address autocomplete services for Europe.
Getting started with your .env file
You will receive a .env file from us containing your API credentials. Place it in the root directory of this repository:
AUTOMAPA_API_KEY=your-key
AUTOMAPA_API_PASSWORD=your-password
Once the .env file is in place, you can test all endpoints against the live API using Docker — no local PHP installation required:
# Run the full test suite (unit + integration) inside Docker make docker-test # Run only integration tests (live API calls) make docker-test-integration # Run only unit tests (no API calls) make docker-test-unit # Run all (phpstan + unit + integration) tests inside Docker make docker-check
Zero dependencies. The SDK has no runtime Composer dependencies — only
ext-curlandext-json, which are bundled with every standard PHP installation. It is compatible with PHP 8.0 and above.
1. Overview
The SDK covers:
- Geocoding — convert an address to coordinates and back
- Routing — calculate routes, distance matrices, and point-order optimization
- Address autocomplete — suggestions as the user types
- Google Geocoding API compatibility — optional
googleresponse format
For the full list of endpoints and parameters, see the Automapa REST API documentation.
2. Installation
composer require automapa/map-services
Requirements: PHP 8.0+, ext-curl, ext-json.
3. Client configuration
use Automapa\MapServices\ApiClient; use Automapa\MapServices\Config; $client = new ApiClient(new Config( key: 'YOUR_API_KEY', pass: 'YOUR_PASSWORD', ));
4. Session handling
A session is opened automatically (lazy) on the first call that requires authorisation. To open it manually:
$client->session()->generateSession();
5. Available services
| Class | Methods |
|---|---|
PingPong |
ping() |
Session |
getSalt(), generateSession() |
Geocoder |
geocode(), geocodemulti(), revgeocode(), revgeocodemulti() |
Autocomplete |
search(), searchAddress() |
Road |
getSegmentInfo(), speedCheck(), speedCheckMulti() |
RoadPermit |
add(), overwrite(), remove(), list() |
Routes |
matrix(), optimize(), optimizeQueue(), optimizeQueueResult(), route() |
Speed |
speedReport(), speedReportResult() |
Geocoder
geocode() — address to coordinates
$response = $client->geocoder()->geocode( city: 'Warsaw', street: 'Domaniewska', house: '37', maxResults: 1, ); $results = $response->data(); // array of results, each with x, y, city, street, ...
geocodemulti() — batch geocoding (up to 100 addresses)
$response = $client->geocoder()->geocodemulti( addresses: [ ['city' => 'Warsaw', 'street' => 'Domaniewska', 'house' => '37'], ['city' => 'Kraków', 'street' => 'Floriańska', 'house' => '1'], ], ); $results = $response->data(); // array of result arrays, one per input address
revgeocode() — coordinates to address
$response = $client->geocoder()->revgeocode( point: [21.0073642, 52.18288], snapToBld: true, ); $address = $response->data(); // city, street, house, pcode, ...
revgeocodemulti() — batch reverse geocoding
$response = $client->geocoder()->revgeocodemulti( points: [ [21.0073642, 52.18288], [19.9449799, 50.0646501], ], snapToBld: true, ); $addresses = $response->data(); // array of address arrays, one per input point
Autocomplete
Address and POI autocomplete — returns suggestions as the user types.
search() — search by phrase
$response = $client->autocomplete()->search( query: 'Warsaw Domaniewska 37', // types: ['place'], // optional: 'place', 'poi', or both (null = both) ); $items = $response->data()['items']; foreach ($items as $item) { echo $item['name']; // "Domaniewska 37, 02-672 Warsaw" echo $item['type']; // "place" echo $item['subtype']; // "building" echo $item['coords']['x']; // longitude (lng) echo $item['coords']['y']; // latitude (lat) }
Each items entry contains: type, subtype, name, province, district, community,
place, quarter, street, number, postal_code, coords.{x,y}.
searchAddress() — step-by-step address search
Useful for multi-field address forms (city → street → number → postcode).
$response = $client->autocomplete()->searchAddress( query: [ 'city' => 'Warsaw', 'street' => 'Dom', // partial street name 'number' => '', 'zipcode' => '02-672', ], source: 'street', // field being searched: 'place', 'street', 'number', 'zipcode' selected: ['city', 'zipcode'], // optional: fields already confirmed by the user // limit: 10, // optional: max results (default 10) ); $items = $response->data()['items']; // [['city' => 'Warsaw', 'street' => 'Domaniewska', 'zipcode' => '02-672', 'count' => 1]]
Each entry may contain: city, street, number, zipcode, count, and optionally coords.{x,y}.
Note on Autocomplete coordinates: Unlike
Geocoder, coordinates are nested:coords.x= longitude,coords.y= latitude.
Routes
Route calculation, distance matrix, and point-order optimisation.
route() — calculate a route
$response = $client->routes()->route( points: [ [21.0073642, 52.2297], // Warsaw (x=lng, y=lat) [18.6282, 54.3520], // Gdańsk ], route: [ 'type' => 'short', // 'quick' | 'short' | 'optimal' 'traffic' => true, // true = take live traffic into account ], object: ['type' => 'car'], ); $data = $response->data(); echo round($data['length'] / 1000, 1) . ' km'; echo gmdate('H:i:s', $data['eta']); // estimated travel time echo $data['mapurl']; // link to map // $data['desc'] — turn-by-turn manoeuvre list // $data['tolls'] — toll charges
matrix() — distance / time matrix
$response = $client->routes()->matrix( points: [ [21.0073642, 52.2297], [18.6282, 54.3520], [16.9252, 52.4064], ], type: 1, // 1 = time (minutes), 2 = distance (metres) ); foreach ($response->data() as $row) { echo "Segment {$row['points']}: " . round($row['length'] / 1000) . ' km, ' . $row['duration'] . " min\n"; }
optimize() — synchronous optimisation (max 10 points)
$response = $client->routes()->optimize( points: [[21.0, 52.2], [18.6, 54.4], /* ... */], type: 1, // 1 = time, 2 = distance fixedEnd: false, // true = last point is the destination; false = open end object: ['type' => 'car'], ); $data = $response->data(); $data['order']; // optimal index sequence, e.g. "0,3,2,1" $data['sections']; // segment details: x, y, eta, dist
optimizeQueue() + optimizeQueueResult() — asynchronous optimisation (max 50 points)
// Step 1: submit — each point requires an 'id' field $response = $client->routes()->optimizeQueue( points: [['id' => 'Warsaw', 'x' => 21.0, 'y' => 52.2], /* ... */], optimizeBy: 'time', // 'time' or 'distance' object: ['type' => 'car'], ); $requestId = $response->data()['requestId']; // Step 2: poll for the result do { sleep(2); $result = $client->routes()->optimizeQueueResult(requestId: $requestId); $data = $result->data(); } while ($data['resultReady'] !== true); $data['optimizedSequence']; // array of point IDs in the optimal order
Road
Query road segment metadata and speed limits.
Each method accepts an optional $extra array for any additional API fields; named parameters take priority.
// Road segment information nearest to a point $response = $client->road()->getSegmentInfo( x: 21.00736, y: 52.18288, distLimit: 50, // search radius in metres (optional) useTolls: 1, // 1=accept tolls, 0=reject, -1=ignore (optional) useHighways: -1, // 1=accept, 0=reject, -1=ignore (optional) ); $segment = $response->data()['segment']; // id, streetName, speedLimit, isToll, … // Speed limit for a single point $response = $client->road()->speedCheck( x: 15.2154636, y: 52.3118895, dir: 350, // direction of travel in degrees (optional) ); $speedLimit = $response->data()['speedLimit']; // cars $speedLimitTruck = $response->data()['speedLimitTruck']; // trucks // Speed limits for up to 100 points in one request $response = $client->road()->speedCheckMulti( points: [ ['x' => 15.2154636, 'y' => 52.3118895, 'dir' => 350], ['x' => 13.8412285, 'y' => 52.3111549], ], ); foreach ($response->data() as $result) { echo $result['speedLimit'] . "\n"; }
RoadPermit
Manage road permits (weight/size restrictions) tied to a geographic polygon.
Each method accepts an optional $extra array for any additional API fields not listed in the signature.
use Automapa\MapServices\Endpoints\RoadPermit; $rp = $client->roadPermit(RoadPermit::ROAD_PERMIT_ENVIRONMENT_TEST); // GeoJSON Polygon (ring must be closed — first === last point) $poly = [ 'type' => 'Polygon', 'coordinates' => [[ [21.000, 52.220], [21.020, 52.220], [21.020, 52.240], [21.000, 52.240], [21.000, 52.220], ]], ]; // Create a new permit $response = $rp->add( permissions: ['tr_tonnage' => 12, 'tr_tonn_axis' => 8.5], poly: $poly, date_start: '2026-01-01', date_end: '2026-12-31', description: 'Weight limit — city centre', document_name: 'DOC-001', location: 'Warsaw', is_valid_after_expiry: false, extra: ['myCustomField' => 'value'], // forwarded to the API as-is ); $id = $response->raw()['result']['id']; // Replace an existing permit $rp->overwrite( id: $id, permissions: ['tr_tonnage' => 24], poly: $poly, ); // List all permits (optionally filter) $permits = $rp->list(id: $id); // $permits->data() — array of permit objects // Delete a permit $rp->remove($id);
Available permissions keys: tr_tonnage (total weight, t), tr_tonn_axis (axle load, t),
tr_height (m).
Speed
GPS-trace speed-violation analysis — submit a trace asynchronously and poll for results.
speedReport() — submit a GPS trace
$points = [ ['x' => 21.007, 'y' => 52.230, 't' => 1700000000], ['x' => 21.012, 'y' => 52.234, 't' => 1700000060], // each point: x = longitude, y = latitude, t = Unix timestamp ]; $response = $client->speed()->speedReport( objID: 'VEHICLE-001', objName: 'Van 1', objGroup: 'Fleet', points: $points, ); $requestID = $response->data()['requestID'];
speedReportResult() — poll for the analysis result
do { sleep(5); $result = $client->speed()->speedReportResult(requestID: $requestID); $data = $result->data(); } while ($data['progress'] < 1.0); foreach ($data['overspeedingArray'] as $violation) { echo $violation['startLocation'] . ' → ' . $violation['endLocation'] . "\n"; echo ' speed: ' . $violation['speedMax'] . ' km/h, limit: ' . $violation['speedLimit'] . " km/h\n"; } // $data['reportURL'] — link to the full report
Each overspeedingArray entry contains: duration (s), length (m), type (category 1–6),
speedMax, speedAvg (km/h), speedLimit (km/h), urbanArea, startLocation,
startPoint.{x,y}, endLocation, endPoint.{x,y}, startTime, endTime (Unix timestamps).
The optional limit parameter (default 1) sets the minimum violation category to include (1–6).
6. Examples
# Copy configuration cp .env.example .env # Fill in AUTOMAPA_API_KEY and AUTOMAPA_API_PASSWORD in .env # Routes php examples/routes-route.php # point-to-point route php examples/routes-matrix.php # distance/time matrix php examples/routes-optimize.php # sync optimisation (max 10 points) php examples/routes-optimize-async.php # async optimisation (max 50 points) # Geocoder php examples/geocoder-geocode.php # single address → coordinates php examples/geocoder-geocodemulti.php # batch address geocoding php examples/geocoder-revgeocode.php # coordinates → single address php examples/geocoder-revgeocodemulti.php # coordinates → multiple addresses # Autocomplete php examples/autocomplete-search.php # search places and POI by phrase php examples/autocomplete-search-address.php # search address objects # Road php examples/road-segment-info.php # road segment metadata php examples/road-speed-check.php # speed limit for a single point php examples/road-speed-check-multi.php # speed limits for multiple points # Road permits php examples/road-permit-list.php # list permits php examples/road-permit-add.php # create a new permit php examples/road-permit-overwrite.php <id> # replace an existing permit php examples/road-permit-remove.php <id> # delete a permit # Speed reports php examples/speed-report.php # submit async speed report php examples/speed-report-result.php <id> # poll for report results
or simply run make examples to run all examples.
7. Passing additional parameters
The SDK does not restrict unknown parameters — all fields are forwarded to the API as-is.
Every endpoint accepts an $extra array as its last argument. Named params always take priority over $extra:
// Autocomplete $client->autocomplete()->search( query: 'Warsaw', extra: ['myCustomParam' => 'value'], ); // Speed (named params override $extra when the same key appears in both) $client->speed()->speedReport( objID: 'VEHICLE-001', objName: 'Van 1', objGroup: 'Fleet', points: $points, extra: ['myCustomParam' => 'value'], );
8. Low-level call() and request()
// Via service + method name (preferred) $client->call('Geocoder', 'newMethod', ['param' => 'value']); // Or via full URL path (fallback) $client->request('POST', '/v3/Geocoder/newMethod', ['param' => 'value']);
9. Response formats: native vs google
// Native format (default) $response = $client->geocoder()->geocode(city: 'Kraków'); $data = $response->data(); // API data $raw = $response->raw(); // full raw response (always available) // Google format $response = $client->geocoder()->geocode(city: 'Kraków', extra: ['format' => 'google']);
10. Google format field limitations
| Google field | Value |
|---|---|
geometry.viewport |
always null (not provided by the API) |
place_id |
always null (not provided by the API) |
Note: The Automapa API uses
x= longitude andy= latitude — the opposite of Google's convention.
11. Error handling
| Situation | Exception class |
|---|---|
| Invalid API key / password | AuthenticationException |
| Expired session | SessionException |
| Parameter validation failure | ValidationException |
| Resource not found | NotFoundException |
| Rate limit exceeded | RateLimitException |
| Network / cURL error | NetworkException |
| Server error (5xx) | ServerException |
| Unexpected response | UnknownResponseException |
use Automapa\MapServices\Exception\AuthenticationException; use Automapa\MapServices\Exception\AutomapaException; try { $response = $client->geocoder()->geocode(city: 'Warsaw'); } catch (AuthenticationException $e) { echo 'Authentication error: ' . $e->getMessage(); } catch (AutomapaException $e) { echo 'API error: ' . $e->getMessage(); }
License
MIT © 2026 Automapa sp. z o.o.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-25