Google Geocoder

By Sohaib Muneer (SayB)
This is a wonderful component that will retrieve the latitude and longitude of any given address.
This component is particularly helpful when you want to put more than one address on your google map. People who have implemented google maps know that some times it can get messy as Javascript itself is really messy. I had a real hard time parsing multiple addresses via javascript, although I did succeed but I realized it's far more convenient to use PHP cURL object. First you have to retrieve the longitudes and latitudes of your addresses and then you're able to parse these to the GMap. Using this component all you have to do is parse your addresses and get the longitudes and latitudes. Here it is:

Component Class:

Download code <?php 
class GeocoderComponent extends Object
{
    
// URL Variable Seperator
    
var $uvs        ', ';

    
// You Google Map API Key here -- This is the default API Key registered for www.webmechano.com
    
var $apiKey        "ABQIAAAARwby5rOk_WuL_hld8cb1xBSWIj-Xv5w3UKePKfkno7uIC3OfyRSBOef-mB2swSBAuiIaF_hQsPv68w";
    
    var 
$controller    true;

    function 
startup(&$controller)
    {
        
$this->controller = &$controller;
    }

    function 
getLatLng($addy$api_key null){
        
        if(
is_array($addy)){
            
// First of all make the address
            
if(!empty($addressArr['zip'])){
                
$address    $addy['street'].$uvs.$addy['loc'].$uvs.$addy['zip'];
            }
            else{
                
$address    $addy['street'].$uvs.$addy['loc'];
            }
        }else{
            
$address    $addy;
        }
        
// Default Api Key registered for webmechano. It's highly recommended that you use the one for stylished
        
if($api_key == null){
            
$api_key        $this->apiKey;
        }
        
$url        "http://maps.google.com/maps/geo?output=xml&key=$api_key&q=";

        
// Here make the result array to return
        // If the address is correct, it will return 200 in the CODE field so $result['code'] should be equal to 200
        
$result        = array('lat'=>'''lng'=>'''code'=>'');

        
// Make the Temporary URL for CURL to execute
        
$tempURL    $url.urlencode($address);

        
// Create the cURL Object here
        
$crl    curl_init();
        
curl_setopt($crlCURLOPT_HEADER0);
        
curl_setopt($crlCURLOPT_RETURNTRANSFER1);
        
        
// Here we ask google to give us the lats n longs in XML format
        
curl_setopt($crlCURLOPT_URL$tempURL);
        
$gXML        curl_exec($crl);    // Here we get the google result in XML

        // Using SimpleXML (Built-in XML parser in PHP5) to parse google result
        
$goo        simplexml_load_string(utf8_encode($gXML)); // VERY IMPORTANT ! - ACHTUNG ! - this line is for documents that are UTF-8 encoded
        // If the layout and views are not UTF-8 encoded you can use the line below - 
        // comment the above line and un-comment the line below
        // $goo        = simplexml_load_string($gXML);

        
$result['code']    = $goo->Response->Status->code;
        if(
$result['code'] != 200){
            
$result['lat']        = 'error';
            
$result['lng']        = 'error';
            
$result['address']    ='error';
            return 
$result;
        }
        else{
            
$coords                $goo->Response->Placemark->Point->coordinates;
            list(
$lat$lng)    = split(','$coords);
            
$result['lat']        = $lat;
            
$result['lng']        = $lng;
            
$result['address']    = $gooAddress;
            return 
$result;
        }
    }
// end function / action : getLatLng    
}
?>

The beauty of this component is that it will accept the address as a string for example:
Download code
$address = "560 Panama St, Stanford, CA 94305";

and also as an array of this format:

Download code
$address['street'] = "560 Panama St"; // The street
$address['loc'] = "Stanford, CA"; // The location (city)
$address['zip'] = "94305"; // The zip code

And it will return an array of this format:

Download code
$result['code'] // Google code: will return 200 on success
$result['lat'] // Latitude of the given address
$result['lng'] // Longitude of the given address

All you have to do is paste the code to your /app/controllers/components directory as geocoder.php and viola !

Add this component in any controller and start retrieving the longitudes and latitudes of your addresses.

Download code
$this->Geocoder->getLatLng($address, $api_key);
/*
** IMPORTANT NOTE ! Although $api_key is optional BUT Be sure to give ** it your own API KEY
** currently it uses the API key to my test site www.webmechano.com
*/

 

Comments 276

CakePHP Team Comments Author Comments
 

Bug

1 Latitude and longitude reversed in parsing response

This component works well, except that the parsing of latitude and longitude in the response from Google is reversed, assigning the latitude value to longitude and vice versa.

The Google response specifies longitude before latitude in the response coordinates, so that's the main fix.

I also noticed a couple unset variables and other notices that are fixed, too.

Here's the version I've been using:


class GeocoderComponent extends Object
{
    // URL Variable Seperator
    var $uvs        = ', ';

    // You Google Map API Key here -- This is the default API Key registered for www.webmechano.com
    var $apiKey        = "ABQIAAAARwby5rOk_WuL_hld8cb1xBSWIj-Xv5w3UKePKfkno7uIC3OfyRSBOef-mB2swSBAuiIaF_hQsPv68w";

    var $controller    = true;

    function startup(&$controller)
    {
        $this->controller = &$controller;
    }

    function getLatLng($addy, $api_key = null){

        if(is_array($addy)){
            // First of all make the address
            if(!empty($addressArr['zip'])){
                $address    = $addy['street'].$this->uvs.$addy['loc'].$this->uvs.$addy['zip'];
            }
            else{
                $address    = $addy['street'].$this->uvs.$addy['loc'];
            }
        }else{
            $address    = $addy;
        }
        // Default Api Key registered for webmechano. It's highly recommended that you use the one for stylished
        if($api_key == null){
            $api_key        = $this->apiKey;
        }
        $url        = "http://maps.google.com/maps/geo?output=xml&key=$api_key&q=";

        // Here make the result array to return
        // If the address is correct, it will return 200 in the CODE field so $result['code'] should be equal to 200
        $result        = array('lat'=>'', 'lng'=>'', 'code'=>'');

        // Make the Temporary URL for CURL to execute
        $tempURL    = $url.urlencode($address);

        // Create the cURL Object here
        $crl    = curl_init();
        curl_setopt($crl, CURLOPT_HEADER, 0);
        curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1);

        // Here we ask google to give us the lats n longs in XML format
        curl_setopt($crl, CURLOPT_URL, $tempURL);
        $gXML        = curl_exec($crl);    // Here we get the google result in XML

        // Using SimpleXML (Built-in XML parser in PHP5) to parse google result
        $goo        = simplexml_load_string(utf8_encode($gXML)); // VERY IMPORTANT ! - ACHTUNG ! - this line is for documents that are UTF-8 encoded
        // If the layout and views are not UTF-8 encoded you can use the line below -
        // comment the above line and un-comment the line below
        // $goo        = simplexml_load_string($gXML);

        $result['code']    = $goo->Response->Status->code;
        if($result['code'] != 200){
            $result['lat']        = 'error';
            $result['lng']        = 'error';
            $result['address']    ='error';
            return $result;
        }
        else{
            $coords                = $goo->Response->Placemark->Point->coordinates;
            list($lng, $lat)    = split(',', $coords);
            $result['lat']        = $lat;
            $result['lng']        = $lng;
            $result['address']    = $gooAddress;
            return $result;
        }
    }// end function / action : getLatLng
}
Posted Apr 17, 2008 by Michael Lehmkuhl
 

Comment

2 Thanks for the fixes

Thanks Michael, fixes appreciated very much. May be I understood these lats and longs in reverse at that time :)
Posted Jun 21, 2008 by Sohaib Muneer
 

Question

3 But when I try this I get the 620 error

What's odd about this is that when I hit the link manually, I get the correct lat and long, but when cURL or any other method I tried (like fopen/fread), I get the 620 (You've tried this too many times with your IP address, when there's no way in heck that's true.) error.

Do you know a way around this?
Posted Aug 18, 2008 by Robbie Smith
 

Comment

4 great simple geocoder 1 problem

$result['address'] = $gooAddress;

this line doesn't make sense to me and throws an error in my view:

Notice (8): Undefined variable: gooAddress [APP/controllers/components/geocoder.php, line 70]
i just got rid of:

$result['address'] = $gooAddress; //line 70
and $result['address'] ='error'; //line 62

and everything worked fine!
Posted Mar 28, 2009 by james f