Geocoding – jak zamienić adres na współrzędne geograficzne?

Geocoding to przeliczenie adresu na współrzędne – długość i szerokość geograficzną. Z pomocą przyjdzie nam google i nie tylko.

Zdarza się, że mamy bazę klientów, sklepów itp, którzy podają adresy. Chcemy pokazać ich na mapie. Możemy oczywiście znajdować każdy z adresów w google maps a potem ręcznie przepisywać współrzędne. Ale nie tędy droga. Skorzystamy z automatu.

Google geocoder

Google API udostępnia nam usługę geocodingu. Jeśli mamy adres, np nazwę miejscowości „Kozia Wólka”, możemy wywołać specjalny adres:

https://maps.googleapis.com/maps/api/geocode/json?address=Kozia+Wólka

W odpowiedzi dostaniemy JSON. Jeśli pole status będzie zawierać „OK” to możemy odczytać współrzędne w results[0].geometry.location.lat i results[0].geometry.location.lon. Pełny JSON jest dość spory i wygląda tak:

{
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "Kozia Wólka",
               "short_name" : "Kozia Wólka",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Gmina Małdyty",
               "short_name" : "Gmina Małdyty",
               "types" : [ "administrative_area_level_3", "political" ]
            },
            {
               "long_name" : "Ostróda County",
               "short_name" : "Ostróda County",
               "types" : [ "administrative_area_level_2", "political" ]
            },
            {
               "long_name" : "Warmian-Masurian Voivodeship",
               "short_name" : "Warmian-Masurian Voivodeship",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "Poland",
               "short_name" : "PL",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "Kozia Wólka, Poland",
         "geometry" : {
            "location" : {
               "lat" : 53.9205064,
               "lng" : 19.8601681
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : 53.9336464,
                  "lng" : 19.8921829
               },
               "southwest" : {
                  "lat" : 53.9073623,
                  "lng" : 19.8281533
               }
            }
         },
         "place_id" : "ChIJzdU8wvmh4kYRF5i4KWQ7I5E",
         "types" : [ "locality", "political" ]
      }
   ],
   "status" : "OK"
}

Zamiast OK możemy dostać inne statusy. Np „ZERO_RESULTS„, „OVER_QUERY_LIMIT„, „REQUEST_DENIED” itp.

Właśnie status OVER_QUERY_LIMIT jest interesujący. Google nie pozwala na wysyłanie więcej niż 2500 zapytań dziennie i więcej niż 5 na sekundę.

Lepiej jest zapisać dane do cache. Radzę też nie testować działania na dużych paczkach danych bo szybko wyczerpiemy limit.

Geocoder w PHP

Zamiast pytać google, lepiej użyć gotowca. W sieci dostępna jest świetna biblioteka geocoder-php/Geocoder. Dzięki niej możemy korzystać z wielu różnych serwisów do geocodingu.

Instalujemy bibliotekę composerem:

composer require willdurand/geocoder

A potem w pliku, np. index.php dekodujemy:

require 'vendor/autoload.php';

// potrzebujemy bibliotekę pobierającą http w standardzie PSR-7
$curl = new \Ivory\HttpAdapter\CurlHttpAdapter();

// tworzymy geocoder do google maps
$geocoder = new \Geocoder\Provider\GoogleMaps($curl);

// dekodujemy
$result = $geocoder->geocode("Kozia Wólka");

// zobaczmy co dostaniemy
var_dump($result);

W ten sposób pobraliśmy dane z Google Map. Biblioteka daje nam więcej providerów. Wystarczy napisać:

$geocoder = new \Geocoder\Provider\OpenStreetMap($curl);
$result = $geocoder->geocode("Kozia Wólka");

Jeśli zechcemy korzystać z kilku providerów naraz – nic nie stoi na przeszkodzie. Dostępny jest agregator:

$geocoder = new \Geocoder\ProviderAggregator();
$geocoder->registerProviders([
   new \Geocoder\Provider\OpenStreetMap($curl),
   new \Geocoder\Provider\GoogleMaps($curl)
]);

Możemy teraz pobierać dane wybierając provider:

$result = $geocoder->with('openstreetmap')->geocode('Kozia Wólka');

Co dalej?

Warto poczytać dokumentację biblioteki geocoder. Do dyspozycji mamy kilkanaście providerów. Jeśli jeszcze nam mało, możemy dołączyć Geocoder Extra z kolejnymi. Możemy też skorzystać z gotowego bundla dla Symfony BazingaGeocoderBundle.

Warto poczytać dokumentację bibloteki. Wszystkie providery zwracają dane w tym samym formacie. Możemy definiować limity liczby odpowiedzi itd. Bundle dla symfony pozwala nam też zdefiniować cache.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *