GuidesBuilding a Geocoding Web Service

Building a Geocoding Web Service

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

In the previous installment of this four-part series regarding creating spatially enabled Web applications, you learned how to create a local datasource mapping mailing addresses to latitudinal and longitudinal coordinates using the Geo::Coder::US Perl package and the U.S Census Bureau’s TIGER/Line data. In this final installment, you’ll learn how to make this data available to the world through a Perl-based Web service. To demonstrate the service’s capabilities, a PHP-driven client will pass a mailing address to the Web service, retrieve the spatial data made available through this Web service, and finally feed it to the Google Maps API to produce a map marking the location of the mailing address.

Building the Perl Web Service

Before you can create a TIGER/Line-based Web service, you need to install the Geo::Coder::US package, and import the appropriate sections of the spatial data. This process was explained in the previous installment; therefore, if you haven’t had the opportunity, be sure to take care of these tasks before proceeding. You’ll also need to configure your Web server to handle Perl-driven scripts, commonly done via the mod_cgi or mod_perl modules. Although this process isn’t discussed in this article, there are countless tutorials available on the Web that explain how to do so.

To create the Perl-driven Web service, you’ll take advantage of the CPAN package Soap::Lite. Use the following command to install this package on the server:

%>cpan -MCPAN -e shell "install 'Soap::Lite'"

Next, create the module that will provide the functionality made available by the Perl web service (geocode.pm):

package geocode;

sub geocode {

   # Designate the location of the geocoding database
   $geocodes = "C:/Perl/site/lib/Geo/Coder/geocoder.db";

   # Retrieve the address value passed into the function
   my ($class,$address) = @_;

   # Point to the geocoding database
   Geo::Coder::US->set_db($geocodes);

   # Retrieve coordinates from geocoding database
   my ($coords) = Geo::Coder::US->geocode($address);

   # Return the latitudinal and longitudinal coordinates
   return $coords->{lat},$coords->{long};

   }

return 1;

Be sure to place this package within a path found in the @INC array. This array contains a list of directories that Perl will refer to when searching for a module referenced within a script.

Next, you’ll create the (geocodews.pl) script that will make geocode.pm accessible through the Web service:

#!/usr/bin/perl -w

use Geo::Coder::US;

use SOAP::Transport::HTTP;
require("geocode.pm");

SOAP::Transport::HTTP::CGI
   ->dispatch_to('geocode')
   ->handle;

Remember that, for any client to take advantage of a Web service through Apache, the service must be placed within the Web server’s document root. It’s also possible to run an independent SOAP::Lite web service without the aid of a Web service, although this approach isn’t discussed in this article.

You can test out the Web service from the command line (or through a Web browser if by making a few minor script modifications that aren’t covered in this article) using the following Perl-based SOAP client (geocodeclient.pl):

#!/usr/bin/perl -w

use SOAP::Lite;

$soap = SOAP::Lite
   -> uri('http://localhost/geocode')
   -> proxy('http://localhost/perl/geocodews.pl');

$address = "411 Woody Hayes Dr, Columbus, OH";

my $result = $soap->call('geocode', $address);

my $latitude = $result->result;
my $longitude = $result->paramsout;

print "Latitude: ".$latitude."n";
print "Longitude: ".$longitude."n";

Producing:

Latitude: 40.004761
Longitude: -83.019945

However, your ultimate goal is to retrieve these coordinates and use them to produce a Google map. While this could, of course, be done with Perl, it’s more interesting to use another language because it truly illustrates the power of Web services interoperability. That said, you can create a PHP-based client to access the Web service. Of course, you can use any Web services-capable language: Java, C#, or Python, for instance.

The PHP Web Services Client

One component remains to be completed to finish the communications chain from data source to end user: the Web services client. Remember that a Web service provides a standard interface for communicating with an Internet-enabled application, meaning that any language capable of adhering to the rules involved in the the request-response process can be used.

The following Web services client (geocodeclient.php) uses PHP 5’s native SOAP extension; however, all is not lost for PHP 4 users. This example could be transformed in just a few steps thanks to the NuSOAP extension; therefore, please consult the NuSOAP Web site for more information if you haven’t yet had the occasion to upgrade to PHP 5.

 "http://localhost/perl/geocodews.pl",
      'uri' => "http://localhost/geocode"));

   # What address shall we look up?
   $address = "411 Woody Hayes Dr, Columbus, OH";

   # Execute the remote call
   $result = $client->geocode($address);

   # Remove the latitudinal value from the returned array
   $latitude = array_shift($result);

   # Remove the longitudinal value from the returned array
   $longitude = array_shift($result);

   # Output the coordinates
   echo "latitude: $latitude 
longitude: $longitude"; ?>

Execute this script from a PHP-enabled Web server and you’ll see the following results:

latitude: 40.004761
longitude: -83.019945

Displaying the Google Map

Now that the coordinates have been retrieved, all you need to do is pass them into the appropriate Google Maps API method. To do so, paste the following code into the PHP Web services client (geocodeclient.php), being sure to place it below the closing PHP delimiter (?>). You’ll also need to replace ADD_YOUR_KEY_HERE with your Google Maps API key. If you haven’t yet registered for your key, see the instructions found in the opening installment of this series.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html >
  <head>
    <script src="http://maps.google.com/maps?file=api&v=1
         &key=ADD_YOUR_KEY_HERE" type="text/javascript">
    </script>
  </head>
  <body>
    <div id="map" style="width: 400px; height: 300px"></div>
    <script type="text/javascript">
    //<![CDATA[
    var map = new GMap(document.getElementById("map"));
    map.centerAndZoom(
    new GPoint(<?php echo $longitude;?>, <?php echo $latitude;?>), 3);
    var point = 
    new GPoint(<?php echo $longitude;?>, <?php echo $latitude;?>);
    var marker = new GMarker(point);
    map.addOverlay(marker);
    //]]>
    </script>
  </body>
</html>

Execute the geocodeclient.php script anew and you’ll see the following map:

Conclusion

There you have it! A custom, end-to-end Web mapping solution built entirely from open source and freely available services.

About the Author

W. Jason Gilmore (http://www.wjgilmore.com/) is the open source editor for Apress. He’s the author of the best-selling Beginning PHP 5 and MySQL: Novice to Professional (Apress, 2004. 758pp.). Along with Robert Treat, Jason is the co-author of the forthcoming Beginning PHP 5 and PostgreSQL 8: From Novice to Professional, due out at the conclusion of 2005. Jason loves receiving e-mail, so don’t hesitate to write him at wjATwjgilmore.com.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories