A mash-up using the Geo-Location API, Google maps V3 and PHP – Part 1

26 Mar

      Wouldn’t it be awesome if your map-apps showed the user’s exact location without taking any input from him? Of course it is possible using  the famous IP address trick… but it is too approximate, and sometimes everything but correct! You might be sitting on one end of the city and the IP address trace would tell you’re on the other end! But now getting the users exact location is possible using the Geo location API. It returns various pieces of information about the person’s physical location such as the geographical co-ordinates i.e. Latitudes and Longitudes, Altitudes, Heading etc. The returned information can then be used for a number of purposes. But, right now it only works on Mozilla Firefox 3.5+.  Read more about the Geo-Location API here : Geo Location API reference and a few cool tips and tricks here. We divide the mash-up in two parts,
  • Plot user’s location using the Geo-location API, google maps and PHP,
  • Update the map based on the users choice.

Following is the part 1: Plotting user’s location on google map using Geo-location API and PHP.

      When the user visits the page, his co-ordinates are extracted and the corresponding location is plotted on Google maps. The first option for getting the user’s co-ordinates is using the Geo-Location API. It works only if the user is using Firefox 3.5. If not, then the fall back option is to use the IP address trick to get the user’s co-ordinates.
Here is our javascript code:
Code for main function
// File name: index.php (you'll know later why we named our file as .php)
function main()
{
  // We initialize the map for further use here.
  var initOptions =
  {
    zoom: 16,
    mapTypeControl: true,
    mapTypeControlOptions:
         { style:  google.maps.MapTypeControlStyle.DROPDOWN_MENU},
	   navigationControl: true,
	   navigationControlOptions:
         { style: google.maps.NavigationControlStyle.SMALL},
	   mapTypeId: google.maps.MapTypeId.ROADMAP
  }

  map = new google.maps.Map(document.getElementById("map"), initOptions);

     // Check for geoLocation Support
      if (navigator.geolocation)
      {
          //Yes. It does!
          navigator.geolocation.watchPosition(renderPosition, renderError);
      }
      else
     {
         //No. It doesn't, use the IP address trick.
         getGeoByIP();
     }
}
      This function does the following:
  1. Initiates the google map for our further use.
  2. Checks if the browser supports the API, and calls the function renderPosition if yes (renderErrors in case of errors)
  3. If it doesn’t then call a function to get the co-ordinates using IP address.

Here are the renderPosition and the renderError functions:
function renderPosition(position)
{
           if (!window.count) window.count = 0;
           count ++;
           lat = position.coords.latitude;
           lng = position.coords.longitude;
          load(lat, lng);
}

function renderError(err)
{
    switch(err.code)
    {
         //error code 0 = Unknown error
         case 0: getGeoByIP();
                    break;

	 //error code 1 = User clicks 'Don't Share Location'
	 case 1: getGeoByIP();
	            break;

	 //error code 1 = Network Down
	 case 2: getGeoByIP();
	            break;

         //error code 3 = Time taken for locating is too long
         case 3: getGeoByIP();
	            break;
    }
}

      The load function plots these co-ordinates on google maps which we had initiated in the main function. There are various options which can be passed to the watchposition function. Read the documentation for these options and what the error codes are. (link is above!)

Code for getGeoByIP:
function getGeoByIP()
{
   var lat = '<?php echo $ip_data['latitude']; ?>';
   var lng = '<?php echo $ip_data['longitude']; ?>';
   load(lat, lng);			 
}

      One thing might confuse many of the readers, how are pieces of PHP code inserted here? Well, this is a way of using PHP variables in javascript code, and so you have to save the file with the .php extension for this to work. The function to get the co-ordinates based on user’s IP address is written in PHP, we use it to return the values and catch those values in these javascript variables. So when the page loads, we already have our IP based co-ordinates with us, so that in case geo location encounters an error, our getGeoByIP function directly uses the returned PHP variables.

Code for getting user’s IP address and user co-ordinates based on the IP address:
<?php
// File name: iptolatlong.php
//Get the IP address:
function getUserIp()
{
    if (getenv('HTTP_X_FORWARDED_FOR')) 
    {
       $pipaddress = getenv('HTTP_X_FORWARDED_FOR');
       $ipaddress = getenv('REMOTE_ADDR');
       echo "Your Proxy IPaddress is : ".$pipaddress. "(via $ipaddress)" ;
     } 
    else 
    {
         $ipaddress = getenv('REMOTE_ADDR');
         //echo "Your IP address is : $ipaddress";
     }
     return $ipaddress;
}

// Get the co-ordinates:
function locateIp($ip)
{ 
  $d = file_get_contents("http://www.ipinfodb.com/ip_query.php?ip=$ip&output=xml&timezone=false");
 
  //Use backup server if cannot make a connection
  if (!$d)
  {
   $backup = file_get_contents("http://backup.ipinfodb.com/ip_query.php?ip=$ip&output=xml&timezone=false"); 
   $answer = new SimpleXMLElement($backup);
   if (!$backup) return false; // Failed to open connection
  }
 else
 {
    $answer = new SimpleXMLElement($d);
 }
 
  // Uncomment to get all details:
  /*
    $country_code = $answer->CountryCode;
    $country_name = $answer->CountryName;
    $region_name = $answer->RegionName;
    $city = $answer->City;
    $zippostalcode = $answer->ZipPostalCode;
  */
   $latitude = $answer->Latitude;
   $longitude = $answer->Longitude;
 
   //Return the data as an array
   return array('latitude' => $latitude, 'longitude' => $longitude);
}
?>

Put the following at the top of the main file, (That is why you should name the file as index.php!) even above the DOCTYPE declaration, so that it will be called when the execution starts.

<?php
include('iptolatlong.php'); // the file that contains the functions.
   
$ip = getUserIp();
 
//If you're testing on a local server, then hardcode your IP, we've used Pune's IP for testing.
  if($ip == '127.0.0.1')
  {
    $ip = "115.109.9.20"; 
    $ip_data = locateIp($ip);
  }
  else
  {  
     $ip_data = locateIp($ip);
  }
?>

Code for load(lat, lng) function:
function load(lat, lng)
{
     var userpoint = new google.maps.LatLng(parseFloat(lat),
                                              parseFloat(lng));
     var myOptions = {
                             zoom: 15,
                             center: userpoint,
                             mapTypeId: google.maps.MapTypeId.ROADMAP
                            };
    map.setCenter(new google.maps.LatLng(lat, lng), myOptions);
    createMarker(userpoint, manIcon, "You're here!");
}
      The createMarker function has 3 parameters, first is the google point in the map which is formed using the lat/long passed to the load function. Second is the icon. The manIcon is a link to the image that’ll be displayed at the user’s location. You can also use an image stored in your local drive and put the path here. The third is the message that will be displayed when clicked on the marker, you can use html here.

Code for createMarker function:
function createMarker(point, icon, contentString)
{
  var marker = new google.maps.Marker({
                                                       position: point,
                                                       icon: icon
                                                      });
google.maps.event.addListener(marker, 'click', function() {
 infoWindow = new google.maps.InfoWindow({ content: contentString,});
 infoWindow.open(map, marker);
});

marker.setMap(map);
}
Finally, index.php should look like this:

// index.php file, copy paste if you want to use it.
<?php
    	
  include('iptolatlong.php'); 
  include('bank_list.php');
  
  $ip = getUserIp();
  if($ip == '127.0.0.1')
  {
    $ip = "115.109.9.20"; //Pune's IP for testing.
    $ip_data = locateIp($ip);
  }
  else
  {  
     $ip_data = locateIp($ip);
  }

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
    <script type="text/javascript">
        var lat;
	var lng ;
	var map;
	var marker;
        var manIcon = "http://maps.google.com/mapfiles/ms/micons/man.png";    
	var contentString;
	var infoWindow;
function main()
{
  // We initialize the map for further use here.
  var initOptions =
  {
    zoom: 16,
    mapTypeControl: true,
    mapTypeControlOptions:
         { style:  google.maps.MapTypeControlStyle.DROPDOWN_MENU},
	   navigationControl: true,
	   navigationControlOptions:
         { style: google.maps.NavigationControlStyle.SMALL},
	   mapTypeId: google.maps.MapTypeId.ROADMAP
  }

  map = new google.maps.Map(document.getElementById("map"), initOptions);

     // Check for geoLocation Support
      if (navigator.geolocation)
      {
          //Yes. It does!
          navigator.geolocation.watchPosition(renderPosition, renderError);
      }
      else
     {
         //No. It doesn't, use the IP address trick.
         getGeoByIP();
     }
}	
function renderPosition(position)
{
           if (!window.count) window.count = 0;
           count ++;
           lat = position.coords.latitude;
           lng = position.coords.longitude;
          load(lat, lng);
}

function renderError(err)
{
    switch(err.code)
    {
         //error code 0 = Unknown error
         case 0: getGeoByIP();
                    break;

	 //error code 1 = User clicks 'Don't Share Location'
	 case 1: getGeoByIP();
	            break;

	 //error code 1 = Network Down
	 case 2: getGeoByIP();
	            break;

         //error code 3 = Time taken for locating is too long
         case 3: getGeoByIP();
	            break;
    }
} 
    
function getGeoByIP()
{
   var lat = '<?php echo $ip_data['latitude']; ?>';
   var lng = '<?php echo $ip_data['longitude']; ?>';
   load(lat, lng);			 
}
		
function load(lat, lng)
{
     var userpoint = new google.maps.LatLng(parseFloat(lat),
                                              parseFloat(lng));
     var myOptions = {
                             zoom: 14,
                             center: userpoint,
                             mapTypeId: google.maps.MapTypeId.ROADMAP
                            };
    map.setCenter(new google.maps.LatLng(lat, lng), myOptions);
    createMarker(userpoint, manIcon, "You're here!");
}    

function createMarker(point, icon, contentString)
{
  var marker = new google.maps.Marker({
                                                       position: point,
                                                       icon: icon
                                                      });
google.maps.event.addListener(marker, 'click', function() {
 infoWindow = new google.maps.InfoWindow({ content: contentString,});
 infoWindow.open(map, marker);
});

marker.setMap(map);
}
</script>
<style>
#map
       {
	     height: 445px;
             border: 2px solid black;
       }
</style>
</head>
<body onload="main()" >
<div id="map"></div>
</body>
</html>

And your iptolatlong.php file should look like this:
<?php
// File name: iptolatlong.php
//Get the IP address:
function getUserIp()
{
    if (getenv('HTTP_X_FORWARDED_FOR')) 
    {
       $pipaddress = getenv('HTTP_X_FORWARDED_FOR');
       $ipaddress = getenv('REMOTE_ADDR');
       echo "Your Proxy IPaddress is : ".$pipaddress. "(via $ipaddress)" ;
     } 
    else 
    {
         $ipaddress = getenv('REMOTE_ADDR');
         //echo "Your IP address is : $ipaddress";
     }
     return $ipaddress;
}

// Get the co-ordinates:
function locateIp($ip)
{ 
  $d = file_get_contents("http://www.ipinfodb.com/ip_query.php?ip=$ip&output=xml&timezone=false");
 
  //Use backup server if cannot make a connection
  if (!$d)
  {
   $backup = file_get_contents("http://backup.ipinfodb.com/ip_query.php?ip=$ip&output=xml&timezone=false"); 
   $answer = new SimpleXMLElement($backup);
   if (!$backup) return false; // Failed to open connection
  }
 else
 {
    $answer = new SimpleXMLElement($d);
 }
 
  // Uncomment to get all details:
  /*
    $country_code = $answer->CountryCode;
    $country_name = $answer->CountryName;
    $region_name = $answer->RegionName;
    $city = $answer->City;
    $zippostalcode = $answer->ZipPostalCode;
  */
   $latitude = $answer->Latitude;
   $longitude = $answer->Longitude;
 
   //Return the data as an array
   return array('latitude' => $latitude, 'longitude' => $longitude);
}
?>
If you’ve followed the tutorial by now and done everything right, then you should now have a map that plots your location without taking any input from you! In the next part, you’ll see how to store the co-ordinates in a database and then plot them on the maps based on your choice.

Thank You!
Please leave comments and suggestions!
About these ads

6 Responses to “A mash-up using the Geo-Location API, Google maps V3 and PHP – Part 1”

  1. rushi December 5, 2010 at 12:30 pm #

    Thanx … its really helpful for me

    • Rutwick Gangurde December 5, 2010 at 3:59 pm #

      You’re welcome Rushi ! B-)
      You’re from Pune right? Were you at doctypehtml5? I was there too…

  2. raw Hasan February 10, 2011 at 7:37 am #

    This is very much useful tutorial which is rare to find in the web. Thnx for sharing! :)

    • Rutwick Gangurde February 11, 2011 at 4:21 am #

      Hi,

      Glad you found it useful! Feel free to contact me for any help you need!

      Rutwick

  3. mcliquid February 14, 2011 at 8:06 pm #

    Anywere some Demonstration? Would be really nice. Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.