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 email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *