Geocoding with Google maps and PHP

Geocode addresses to lat/long with Google Geocode APIThere are several high quality map services available on the web. However if you want to use some of these services for your website, you’ll need lat/long coordinates on the geographical data that you wish to display.

I you only have a few addresses to display, you can look the coordinates up on services like Google Maps or Bing maps, but if you have to get lat/long coordinates for several addresses, you need a geocoder to convert the addresses to lat/long coordinates.

In this post you’ll learn to build a php script that can geocode addresses with Google Maps API

See example here

Background

The purpose of this post is to develop a PHP script that can be used to take addresses in a database or list, and send the addresses to a geocoding service, and get geographical information back (lat/long coordinates) that can be used to display the addresses on maps.

In this post we’ll use the Google Geocoding Web Service. Please notice that you’re only allowed to use the Google Geocoding Web Service if you’re using the coordinates for a project that uses Google maps. You’re not allowed to geocode the addresses through the Google Geocoding Web Serice, and afterwards use the coordinates for the map API’s from Yahoo or Bing.

Before you can use the Google Geocoding Web Service you’ll need a Google Maps API key, which can be acquired for free here.

Building the script

In the first part of the script, we’ll build the url with the parameters for the Google Geocoding Web Service. The URL needs the following parameters: address, output format and Google Maps API key. Please notice that it might be worth a few experiments to see which address format gives the best results in the geocoding process. In this example we’ll try to geocode the addess of The White House: 1600 Pennsylvania Ave NW Washington, DC 20500, USA.

$google_maps_key='your google maps api key';
$adr = urlencode("1600 Pennsylvania Ave NW Washington, DC 20500, USA");
$url = "http://maps.google.com/maps/geo?q=".$adr."&output=xml&key=$google_maps_key";

To ensure that the address don’t break the URL format, the address is URL encoded before it’s sent to Goggle. The output parameter specifies which format the Google Geocoding Web Service should respond with. The following parameters and values are supported:

  • xml
  • json

This request in this example, provides the following xml response from the geocoding service:

<blockquote>
<pre id="line1"><?xml version="1.0" encoding="UTF-8" ?>
<kml xmlns="http://earth.google.com/kml/2.0"><Response>
  <name>1600 Pennsylvania Ave NW Washington, DC 20500, USA</name>
  <Status>
    <code>200</code>
    <request>geocode</request>
  </Status>
  <Placemark id="p1">
</pre>
<pre id="line9">    <address>1600 Pennsylvania Ave NW, Washington D.C., DC 20500, USA</address>
    <AddressDetails Accuracy="8" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><CountryName>USA</CountryName><AdministrativeArea><AdministrativeAreaName>DC</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>District of Columbia</SubAdministrativeAreaName><Locality><LocalityName>Washington D.C.</LocalityName><Thoroughfare><ThoroughfareName>1600 Pennsylvania Ave NW</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>20500</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails>
    <ExtendedData>
      <LatLonBox north="38.9002436" south="38.8939484" east="-77.0333974" west="-77.0396926" />
    </ExtendedData>
</pre>
<pre id="line14">    <Point><coordinates>-77.0364550,38.8975960,0</coordinates></Point>
  </Placemark>
  <Placemark id="p2">
    <address>Det Hvide Hus, Washington D.C., DC 20500, USA</address>
    <AddressDetails Accuracy="9" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><CountryName>USA</CountryName><AdministrativeArea><AdministrativeAreaName>DC</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>District of Columbia</SubAdministrativeAreaName><Locality><LocalityName>Washington D.C.</LocalityName><PostalCode><PostalCodeNumber>20500</PostalCodeNumber></PostalCode><AddressLine>Det Hvide Hus</AddressLine></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails>
</pre>
<pre id="line19">    <ExtendedData>
      <LatLonBox north="38.9007568" south="38.8944615" east="-77.0335696" west="-77.0398648" />
    </ExtendedData>
    <Point><coordinates>-77.0356669,38.8976500,0</coordinates></Point>
  </Placemark>
</Response></kml>

First it’s important to notice the <Status> code in the response. If the value is “200” the request is a success and a location has been found. The next interesting thing is that 2 placemarks exists in the Geo database. However the two placemarks have different <AddressDetails Accuracy>. The first result has “8” and the second result has “9”. The highest possible match quality is 9 and the lowest quality is 0. Now we just need to build a little piece of php that parses the Geocoder XML response, using Simple XML, and takesthe following into account:

  • If the address could be geocoded (the status code)
  • That there can be more than one results from the geocoding service
  • That the results can have different qualities.

The following PHP code parses the XML response, and displays if the request was successful or not. If the geocoding was successful, the script outputs all the results, and the quality for each result. With the quality score it’s easy to either manually select which address to use, or to ad additional functionality to the cod,e that automatically selects the result with the highest quality.

$xml = simplexml_load_file($url);
$status = $xml->Response->Status->code;
if ($status=='200') { //address geocoded correct, show results
echo ("The address can be geocoded, we found the following results:<br/>");
foreach ($xml->Response->Placemark as $node) { // loop through the responses
$address = $node->address;
$quality = $node->AddressDetails['Accuracy'];
$coordinates = $node->Point->coordinates;
echo ("Quality: $quality. $address. $coordinates<br/>");
}
} else { // address couldn't be geocoded show error message
echo ("The address $adr could not be geocoded<br/>");
}

In the test example with The White House, the following information is returned by the script:

  • The address can be geocoded, we found the following results:
  • Quality: 8. 1600 Pennsylvania Ave NW, Washington, DC 20500, USA. -77.0364550,38.8975960,0
  • Quality: 9. The White House, Washington, DC 20500, USA. -77.0356669,38.8976500,0

So now you have the information that the address: 1600 Pennsylvania Ave NW Washington, DC 20500, USA, has the coordinates: -77.0356669,38.8976500.

The complete PHP script looks like this:

<?
<?
$google_maps_key='ABQIAAAA48bxgwVsk73Nge4MinJU9RTDHawV2ozIN8S3K3Yx7psoDZubHhQ0dwxvbmiVQlU9jFhzL56SqKevAQ';
$adr = urlencode("1600 Pennsylvania Ave NW Washington, DC 20500, USA");
$url = "http://maps.google.com/maps/geo?q=".$adr."&output=xml&key=$google_maps_key";
$xml = simplexml_load_file($url);
$status = $xml->Response->Status->code;
if ($status='200') { //address geocoded correct, show results
echo ("The address can be geocoded, we found the following results:<br/>");
foreach ($xml->Response->Placemark as $node) { // loop through the responses
$address = $node->address;
$quality = $node->AddressDetails['Accuracy'];
$coordinates = $node->Point->coordinates;
echo ("Quality: $quality. $address. $coordinates<br/>");
}
} else { // address couldn't be geocoded show error message
echo ("The address $adr could not be geocoded<br/>");
}
?>

See example here

Share and Enjoy

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS
fold-left fold-right
About the author
Jørgen Nicolaisen has been passionately interested in everything online since 1995. His experience is based on working with small hobby projects as well as high volume websites. Jørgen is currently focused on the PHP based programming framework - Codeigniter, and WordPress naturally

10 Replies to Geocoding with Google maps and PHP

  1. Thanks for sharing this.. this was exactly what I was looking for, a solution to use GAPI to encode addresses dynamically using PHP. :-)

  2. Wow this is a great resource.. I’m enjoying it.. good article

  3. armenfrast says:

    Grat, but why does the url mention “output=csv” ? where do you describe that the feedback is XML and not JSON ?

    Regards

  4. jhnidk says:

    Hi, that’s a typo – it’s corrected now.
    Thank you for noticing :-)

  5. This is exactly what I am looking for, but I hit a few problems.
    1. When I copy the code as is, each instance of ” > ” produces a parse error until I replace it with ” > ”
    2. Once I make that change I am given the error found on http://lankansas.com/test/ (I have removed the key for the example, but the error is the same. Line 6 is “$xml = simplexml_load_file($url);”

    What I am trying to do is to take a list of customer addresses in our database, and call that list from this script to produce a live map of these addresses on a map. Any help is GREATLY appreciated. This is VERY new territory.

  6. jhnidk says:

    Thank you for the comment. The script has now been adjusted, and I added a real live example as well.

  7. vertoo says:

    Good article, you have small typo in line 8, correct: if ($status==’200′) {

  8. Greg says:

    Very nice but does this violate Google’s Terms of Service? They say their geocode results have to be associated with a map. Do you have a similar example that achieves this?

  9. tenorman says:

    can you update this for google v3? if there’s no changes, that’s fine, i’m a beginner programmer… for instance, it doesn’t seem to require a key anymore?

  10. alex Kouroutsalidis says:

    Excellent work there!
    Thanks a lot!
    On Api v3 a key is not required.
    Is there any change that should be done in the code for v3 or removing the $google_maps_key will do the work?(Removing it doesnt produce any errors).
    Apologies for the newbie question, i m just 1 more starting dev.

Comments are now closed for this article.