http://www.developer.com/

Back to article

Performing HTTP Geocoding with the Google Maps API


July 24, 2006

The previous installment of this ongoing series covering the Google Maps API (Part 1, Part 2, Part 3, Part 4, Part 5), I introduced the API's new geocoding feature, released this past June 11. In this tutorial I showed you how to submit geocoding requests via JavaScript, which is convenient because it's easy to subsequently build a map using the retrieved coordinates. However, if you're interested in performing bulk geocoding for reason of storing a series of coordinates in a database, you might be interested in taking advantage of a second means for geocoding, accomplished by way of HTTP request. Storing the coordinates locally will not only decrease the number of required daily geocoding requests (limited to 50,000 daily), but it will speed your application by cutting down on the total requests required to ultimately build a map.

In this article I'll show you how to use the HTTP request method in conjunction with PHP, culminating with an example involving the geocoding of numerous addresses for storage in a MySQL database.

A Simple Example

Let's begin with using the HTTP method to retrieve the coordinates of the greatest college football stadium in the United States: The Horseshoe. Because this request (easily done using PHP's file_get_contents() function) returns an XML document, I'll filter the output through htmlspecialchars() so the document can be properly output to the screen. The code is found below, followed by the output:

<?php

   // Your Google Maps API key
   $key = "YOUR_KEY_HERE";

   // Desired address
   $address = "http://maps.google.com/maps/geo?q=411+Woody+Hayes+Drive,+Columbus,+OH&output=xml&key=$key";

   // Retrieve the URL contents
   echo htmlspecialchars(file_get_contents($address));

?>

Executing this script produces the following output (formatted for this article):

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
  <Response>
     <name>411 Woody Hayes Drive, Columbus, OH</name>
     <Status>
        <code>200</code>
        <request>geocode</request>
     </Status>
     <Placemark>
        <address>411 Woody Hayes Dr, Columbus, OH 43210, USA</address>
        <AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">
           <Country>
              <CountryNameCode>US</CountryNameCode>
              <AdministrativeArea>
                 <AdministrativeAreaName>OH</AdministrativeAreaName>
                 <SubAdministrativeArea>
                    <SubAdministrativeAreaName>Franklin</SubAdministrativeAreaName>
                    <Locality>
                       <LocalityName>Columbus</LocalityName>
                       <Thoroughfare>
                          <ThoroughfareName>411 Woody Hayes Dr</ThoroughfareName>
                       </Thoroughfare>
                       <PostalCode>
                          <PostalCodeNumber>43210</PostalCodeNumber>
                       </PostalCode>
                    </Locality>
                 </SubAdministrativeArea>
              </AdministrativeArea>
           </Country>
        </AddressDetails>
        <Point><coordinates>-83.019739,40.004098,0</coordinates></Point>
     </Placemark>
  </Response>
</kml>

Note the coordinates are embedded towards the bottom of the document. All we need to do is parse the document to retrieve this information. This is much easier than it seems, as you'll soon learn.

You might be wondering why the document's root element is <kml> rather than <xml>. KML is an XML grammer called Keyhole Markup Language, which is used to describe the geographic data found in Google Earth. If you save this as a file (with a .kml extension) you can drag it onto the Google Earth 3D viewer to see the visual representation. While KML is the default, you also have the option of receiving this data in XML markup, or a JSON object, done by appending &output=[xml|json] to the URL. If your interest lies solely in retrieving the coordinates, KML will work just fine as you'll soon see. However if you have reason to use one of the other formats, by all means adjust the output parameter accordingly. Keep in mind that the returned XML and KML documents are identical except for the MIME type.

Of course, it's likely the only bit of information you're interested in is the coordinates. You'll find this information in the Response » Placemark » Point » coordinates node, which includes the appropriate longitude, latitude and altitude values (at present altitude is always set to zero). Thankfully, PHP's SimpleXML extension makes retrieving these coordinates from the returned XML string a trivial affair. Revising the previous example, the returned data is parsed with SimpleXML, and the coordinates output:

<?php

   // Your Google Maps API key
   $key = "YOUR_KEY_HERE";

   // Desired address
   $address = "http://maps.google.com/maps/geo?q=411+Woody+Hayes+Drive,+Columbus,+OH&output=xml&key=$key";

   // Retrieve the URL contents
   $page = file_get_contents($address);

   // Parse the returned XML file
   $xml = new SimpleXMLElement($page);

   // Retrieve the desired XML node
   echo $xml->Response->Placemark->Point->coordinates;

?>

Executing this script returns the following output: -83.019739,40.004098,0. Therefore we'll need to the previous script to parse this data, replacing the echo statement with the following:

// Parse the coordinate string
list($longitude, $latitude, $altitude) = explode(",", 
     $xml->Response->Placemark->Point->coordinates);

// Output the coordinates
echo "Longitude: $longitude, Latitude: $latitude";

Executing the revised script produces:

Longitude: -83.019739, Latitude: 40.004098

Performing Bulk Geocoding

As mentioned this methodology's greatest advantage is the ease in which it can help geocode large numbers of addresses. For example, suppose you wanted to create a map which charted the locations of area hospitals. For the purposes of this exercise I'll choose from five Columbus, OH-based hospitals, including The Ohio State University Medical Center, Children's Hospital, Grant Medical Center, Riverside Methodist Hospital, and Mount Carmel East. The hospital names and their corresponding addresses are stored in a MySQL table which might look like this:

CREATE TABLE hospitals (
   id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
   name VARCHAR(75) NOT NULL,
   address VARCHAR(100) NOT NULL,
   city VARCHAR(50) NOT NULL,
   state CHAR(2) NOT NULL,
   zip CHAR(5) NOT NULL,
   latitude FLOAT(8,6),
   longitude FLOAT(8,6)
)

The following script will retrieve the address information found in this table, encoding it for transmission via HTTP, and output the appropriate latitudinal and longitudinal coordinates:

<?php

   // Your Google Maps API key
   $key = "YOUR_KEY_HERE";

   // Connect to the MySQL database
   $conn = mysql_connect("localhost", "jason", "secretpswd");

   // Select the database
   $db = mysql_select_db("googlemaps");

   // Query the table
   $query = "SELECT id, address, city, state FROM hospitals";
   $result = mysql_query($query) or die(mysql_error());

   // Loop through each row, submit HTTP request, output coordinates
   while (list($id, $address, $city, $state) = mysql_fetch_row($result))
   {
      $mapaddress = urlencode("$address $city $state");

      // Desired address
      $url = "http://maps.google.com/maps/geo?q=$mapaddress&output=xml&key=$key";

      // Retrieve the URL contents
      $page = file_get_contents($url);

      // Parse the returned XML file
      $xml = new SimpleXMLElement($page);

      // Parse the coordinate string
      list($longitude, $latitude, $altitude) = explode(",", $xml->Response->Placemark->Point->coordinates);

      // Output the coordinates
      echo "latitude: $latitude, longitude: $longitude <br />";

   }

?>
Executing this script produces the following output:
latitude: 39.993932, longitude: -83.018649
latitude: 39.952297, longitude: -82.978954
latitude: 39.960770, longitude: -82.990525
latitude: 40.031565, longitude: -83.031058
latitude: 39.957899, longitude: -83.019699

Of course, this script can be easily modified to insert the data into the appropriate row.

Conclusion

I'll continue expanding this series as Google evolves it's mapping API. In the meantime, I invite you to email me with URLs to your Google Maps mashups. Also, please feel free to email me with specific API features you'd like me to cover in future articles!

About the Author

W. Jason Gilmore has developed countless Web applications over the past seven years and has dozens of articles to his credit on Internet application development topics. He is the author of three books, including most recently "Beginning PHP 5 and MySQL 5: From Novice to Professional", (Apress), now in its second edition, and with co-author Robert Treat, "Beginning PHP and PostgreSQL 8: From Novice to Professional" (Apress). Jason is Apress' Open Source Editorial Director, and is the co-founder of IT Enlightenment, a technical training company. Check out his blog at http://www.wjgilmore.com/.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date