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

16 Jun

Hey friends, we’re back to the mash-up tutorial. I had divided the tutorial in two parts, which were:

  • Plot user’s location using the Geo-location API, google maps and PHP
  • Update the map based on the users choice

I explained the first part in the previous blog, you can check it out here. This is the second part. In this I’ll explain how to plot the points from a list provided along, which will update the map accordingly. The first question is how to get the points? We are not using the addresses for plotting, but we’re using the co-ordinates.There are many ways to get the co-ordinates. What we’re doing is, we’re storing the locations we want to show on google maps in a database table. Then we’ll loop through them and fetch corresponding co-ordinates using a very simple PHP script, and store these co-ordinates in the same table.

The table structure would be as follows:
id name add lat lang
1 Shaniwarwada Pune lat lang
2 Sinhagad Pune lat lang
3 Khadakwasla Pune lat lang
4 NDA Pune lat lang
SQL for creating this table:
CREATE TABLE  `mashup`.`locations` (
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR( 40 ) NOT NULL ,
`add` VARCHAR( 40 ) NOT NULL ,
`lat` VARCHAR( 20 ) NOT NULL ,
`long` VARCHAR( 20 ) NOT NULL ,
PRIMARY KEY (  `id` )
) ENGINE = MYISAM ;


INSERT INTO  `mashup`.`locations` (
`id` ,
`name` ,
`add` ,
`lat` ,
`long`
)
VALUES (
'1',  'Shaniwarwada',  'Pune', NULL , NULL
), (
'2',  'Khadakwasla',  'Pune', NULL , NULL
);
'3',  'Sinhagad',  'Pune', NULL , NULL
), (
'4',  'NDA',  'Pune', NULL , NULL
);

The code to take the locations from the database table and get the co-ordinates for them is here:

Code for latlongupdate.php
<?php

$conn = mysql_connect('localhost', 'root', ' '); //assuming that you are working without a username and password
if(!$conn)
 {
   echo "Database Error.";
 }
 else
 {
   echo "Connected.";
   mysql_select_db('mashup', $conn);
   $query = "SELECT * from locations";
   $result = mysql_query($query, $conn);
    while($row = mysql_fetch_array( $result ))
    {
	  $name = $row['name'];
	  $add = $row['add'];
	  $id = $row['id'];

	  $loc_name = str_replace(" ", "+", $name); //to replace spaces by '+' signs
          $location = $loc_name."+".$add;
	  echo $location."<br>";

      $url = "http://maps.google.com/maps/api/geocode/json?address=".$location."&sensor=false";
      echo $url;
            $output=file_get_contents($url);
            $out= json_decode($output);
            $lat = $out->results[0]->geometry->location->lat;
			$long = $out->results[0]->geometry->location->lng;
			echo '<br>Lat is '. $lat;
            echo '<br>Long is '. $long;

      $query = "UPDATE locations SET lat = '".$lat."',";
      $query .= " `long` = '".$long."' WHERE id =".$id."";
      mysql_query($query)
      echo "Successfully inserted.";
    }
}

mysql_close($conn);
?>
After updating the table:
id name add lat lang
1 Shaniwarwada Pune 18.5192953 73.855506
2 Sinhagad Pune 18.4674145 73.7683784
3 Khadakwasla Pune 18.3663038 73.7558759
4 NDA Pune 18.4906528 73.779642

Next thing to do after we have our latitudes and longitudes is, to take these details and put them in an XML document so that it could be understood by the Javascript function that will plot them on google maps. This is again done using a very simple PHP script. If you take a look at the index.php file, we just have a div that displays the map on our page. We need to the index.php file and add a few more lines of code. First would be to add a list of locations to select from for viewing on the map. I’m using a dropdown for this purpose. When a location is selected from the dropdown, a key related to that location is passed to a Javascript function which sends it to the PHP script that will make the XML document populated with the co-ordinates corresponding to that location.

Here is the code to be added to the index.php file:
<p id="location">
	Select a location:
	    <select name="locname" id="locname" onchange = "setmarkers()">
                <option value = 0 selected = "selected">Select a location</option>
	        <option value = 1>Shaniwarwada</option>
               	<option value = 2>Sinhagad</option>
      	        <option value = 3>Khadakwasla</option>
	        <option value = 4>NDA</option>
            </select>
</p>

And here’s the Javascript function. It uses JQuery to do what GDownloadURL does in google maps V2. So make sure to include JQuery in your script tag (I have already done it in index.php). You can get JQuery from JQuery.com. Also in this function, we’re passing an ‘iconGreen’ to the createMarker function, you have to initialize it at first.
Code:


//initialize the icon
var iconGreen = "http://maps.google.com/mapfiles/ms/micons/green-dot.png";

function setmarkers()
       {
	        var id = $("#locname").val();
	        var url = "datatoXML.php?key="+id;

		$.get(url, function(data){
		        $.each($(data).find("marker"), function(key, value) {
	        		var lat = $(value).attr("lat");
			        var lng = $(value).attr("lng");

			        content = "<h2>"+$(value).attr("name")+'</h2><p>'+$(value).attr("address")+"</p>";
			        mpoint = new google.maps.LatLng(parseFloat(lat),
										parseFloat(lng));
			        createMarker(mpoint, iconGreen, content);
		           });
                });
       }

And here’s the datatoXML.php file that prepares the XML document:

Code for datatoXML.php
<?php
      $key = $_GET['key'];

      // Start XML file, create parent node
      $dom = new DOMDocument("1.0");
      $node = $dom->createElement("markers");
      $parent = $dom->appendChild($node);
      //$dom->formatOutput = true;

       // Opens a connection to a MySQL server
       $connection=mysql_connect ('localhost', 'root', ' ');
       if (!$connection)
       {
	   die('Not connected : ' . mysql_error());
        }
        else
	{
	   $db_selected = mysql_select_db($dbname, $connection);
           $query = "SELECT locations.name, locations.add, locations.lat, locations.long FROM locations where id=".$key.";";
           $result = mysql_query($query);

           header("Content-type: text/xml");

	   while ($row = mysql_fetch_array($result))
          {
             // ADD TO XML DOCUMENT NODE
              $node = $dom->createElement("marker");
              $newnode = $parent->tappendChild($node);
              $newnode->setAttribute("name", $row['name']);
              $newnode->setAttribute("address", $row['add']);
              $newnode->setAttribute("lat", $row['lat']);
              $newnode->setAttribute("lng", $row['long']);
	   }
          echo $dom->saveXML();
     }
?>

The XML document is returned to the function which plots them on google maps.

Finally here are the files you should have:

index.php

// index.php file, copy paste if you want to use it.
<?php

  include('iptolatlong.php');
  include('datatoXML.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 iconGreen = "http://maps.google.com/mapfiles/ms/micons/green-dot.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);
}

function setmarkers()
{
	 var id = $("#locname").val();
	 var url = "datatoXML.php?key="+id;

	 $.get(url, function(data){
	 $.each($(data).find("marker"), function(key, value) {
	      		var lat = $(value).attr("lat");
		        var lng = $(value).attr("lng");

        	        content = "<h2>"+$(value).attr("name")+'</h2><p>'+$(value).attr("address")+"</p>";
		        mpoint = new google.maps.LatLng(parseFloat(lat),
										parseFloat(lng));
			        createMarker(mpoint, iconGreen, content);
		           });
                });
       }

</script>
<style>
#map
       {
	     height: 445px;
             border: 2px solid black;
       }

#location
       {
	      border:1px solid red;
	      float:right;
	      width:250px;
        }
</style>
</head>
<body onload="main()" >
<p id="location">
	Select a location:
	    <select name="locname" id="locname" onchange = "setmarkers()">
                <option value = 0 selected = "selected">Select a location</option>
	        <option value = 1>Shaniwarwada</option>
               	<option value = 2>Sinhagad</option>
      	        <option value = 3>Khadakwasla</option>
	        <option value = 4>NDA</option>
            </select>
</p>

<div id="map"></div>
</body>
</html>

latlongupdate.php
<?php

$conn = mysql_connect('localhost', 'root', ' '); //assuming that you are working without a username and password
if(!$conn)
 {
   echo "Database Error.";
 }
 else
 {
   echo "Connected.";
   mysql_select_db('mashup', $conn);
   $query = "SELECT * from locations";
   $result = mysql_query($query, $conn);
    while($row = mysql_fetch_array( $result ))
    {
	  $name = $row['name'];
	  $add = $row['add'];
	  $id = $row['id'];

	  $loc_name = str_replace(" ", "+", $name); //to replace spaces by '+' signs
          $location = $loc_name."+".$add;
	  echo $location."<br>";

      $url = "http://maps.google.com/maps/api/geocode/json?address=".$location."&sensor=false";
      echo $url;
            $output=file_get_contents($url);
            $out= json_decode($output);
            $lat = $out->results[0]->geometry->location->lat;
			$long = $out->results[0]->geometry->location->lng;
			echo '<br>Lat is '. $lat;
            echo '<br>Long is '. $long;

      $query = "UPDATE locations SET lat = '".$lat."',";
      $query .= " `long` = '".$long."' WHERE id =".$id."";
      mysql_query($query)
      echo "Successfully inserted.";
    }
}

mysql_close($conn);
?>
datatoXML.php
<?php
      $key = $_GET['key'];

      // Start XML file, create parent node
      $dom = new DOMDocument("1.0");
      $node = $dom->createElement("markers");
      $parent = $dom->appendChild($node);
      //$dom->formatOutput = true;

       // Opens a connection to a MySQL server
       $connection=mysql_connect ('localhost', 'root', ' ');
       if (!$connection)
       {
	   die('Not connected : ' . mysql_error());
        }
        else
	{
	   $db_selected = mysql_select_db($dbname, $connection);
           $query = "SELECT locations.name, locations.add, locations.lat, locations.long FROM locations where id=".$key.";";
           $result = mysql_query($query);

           header("Content-type: text/xml");

	   while ($row = mysql_fetch_array($result))
          {
             // ADD TO XML DOCUMENT NODE
              $node = $dom->createElement("marker");
              $newnode = $parent->tappendChild($node);
              $newnode->setAttribute("name", $row['name']);
              $newnode->setAttribute("address", $row['add']);
              $newnode->setAttribute("lat", $row['lat']);
              $newnode->setAttribute("lng", $row['long']);
	   }
          echo $dom->saveXML();
     }
?>

These are all the files you need to get going. That completes the mash-up tutorial. Sorry for the extremely long delay. Please feel free to contact me in case of any doubts/errors.

Thank You. Happy Mapping! :)

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

  1. Zeb October 22, 2010 at 10:04 pm #

    Hello,

    Thank you for this tutorial. I really appreciate it!

    I am getting the following error and am not sure how to fix it:

    XML Parsing Error: junk after document element
    Location: http://localhost/yapa/mashup/index.php
    Line Number 2, Column 1:Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\…\mashup\datatoXML.php on line 24
    ^

    Do you have any ideas what I can do to fix it?

    Thanks!

    -Zeb

  2. Glynn Phillips December 27, 2010 at 3:49 pm #

    Hi, When will part 3 be coming? I have done what you have said you are going to do but using maps V2 and wanted to see how you go about doing it with V3.

    Thanks
    Glynn

  3. Bille Brahe January 18, 2011 at 7:48 pm #

    #Zeb

    > $db_selected = mysql_select_db($dbname, $connection);

    $dbname is not defined in the supplied code. Substitute it with the name of your database.

    > $newnode = $parent->tappendChild($node);

    Should be altered to: (removed a “t”).

    $newnode = $parent->appendChild($node);

  4. Bille Brahe January 18, 2011 at 8:08 pm #

    And omit the line:

    include(‘datatoXML.php’);

    Since it requires a paramter – it is called when it is needed.

    Be aware, that the datatoXML.php is recieving a $_GET value which is NOT secured, and can potentially course a SQL-injection.

    A fast solution is to substitute:

    $key = $_GET['key'];

    with something like:

    $key = preg_replace(“/^[0-9]$/,”",$_GET['key']);

    One should maybe remember, that this is a tutorial, and not a script ready for production.

    Anyway – thank you for a great script :-)

    • Rutwick Gangurde January 20, 2011 at 5:15 am #

      Hi Bille,

      You’re welcome :)
      I’ll make the changes you suggested… I wasn’t aware of the SQL injection attack.

      Thanks,
      Rutwick

  5. Current Weather January 25, 2011 at 3:15 am #

    Nice article and tutorial. Glad you took the time to write it. Came across it while doing some research for an ongoing project in the geolocation space. http://www.currentweather.ca — although it’s still an infant I’d be happy to hear some feedback.

  6. Ruben August 14, 2013 at 4:37 pm #

    hi there. These code initializes with geolocation and after the people choose goes to the lat and long references to what people want?

    • rutwick August 15, 2013 at 4:31 pm #

      Hi,

      If I’m getting you right… no it doesn’t. It only get’s the user’s current location and digs through the nearby locations which are already stored in the database. You’ll have to store them!

  7. Maha October 19, 2014 at 10:16 am #

    i’m a beginner, please reply me, how to get the map location by using address .
    can you please send me the code.

    • rutwick October 20, 2014 at 12:37 pm #

      Hi,

      What you’re trying is called as reverse geo coding. You’ll need to look for a service that takes in the address and returns the co-ordinates which you can then use on the map.

Leave a Reply