Displaying the user's location using a KML feed (Intermediate)
The Keyhole Markup Language (KML) is an XML-based markup language suitable for defining geographic data. Alongside GeoRSS, it's one of two main XML-based standards that Google Maps supports. It was originally developed for using with Google Earth, which was known as Keyhole Earth Viewer until Google acquired it. Because multiple applications support KML files, it's a good way to easily export your geographic data.
Getting ready
Perform the following steps:
Ensure that you have a recent version of PHP installed.
Check that DOM extension of PHP 5 is installed. Specifically, this will use the XML
DOMDocument
class. For most installations of PHP 5, this will be installed by default, but it's worth checking, as not all installations are the same. You can read information about the DOM extension at http://php.net/manual/en/book.dom.php.You may also wish to install Google Earth in order to test your KML feed. The website for Google Earth is listed at the end of this section.
How to do it…
Perform the following steps to display the user's location using a KML feed:
Set up
feed.php
as follows. This will retrieve the location items using thegetPreviousLocations($user_id)
function that we created in the Displaying the user's location using the Google Maps API (Intermidiate) recipe. Using the PHP DOM extension, it will create an XML feed in Keyhole Markup Language, which will encode the locations and timestamps of each saved point.<?php // Load our common library file, and fail if it isn't present require_once('lib.php'); // PHP's date function requires that the timezone is set. As I'm located on // America's west coast, I'm setting this to America/Los_Angeles. You can // also set this in your php.ini. date_default_timezone_set('America/Los_Angeles'); // Create a new XML file using PHP's DOM extension. $feed = new DOMDocument('1.0','UTF-8'); $feed->formatOutput = true; // Create a root node for the XML document. $rootNode = $feed->appendChild($feed->createElementNS('http://earth.google.com/kml/2.2', 'kml')); // Create a document node inside the root node. $documentNode = $rootNode->appendChild($feed->createElement('Document')); $documentNameNode = $documentNode->appendChild($feed->createElement('name','Location detector feed')); // Attempt to retrieve previous map points - and if they exist, iterate // through them. Note that we're hardcoding $user_id to 1; in more complex // implementations with user management, we might get $user_id from the // current user session. if ($points = getPreviousLocations(1)) { foreach($points as $point) { // Each place is stored inside a Placemark tag $placeNode = $documentNode->appendChild ($feed->createElement('Placemark')); // We're going to use the timestamp of the saved // location as its title $nameNode = $placeNode->appendChild ($feed->createElement('name',date('r',$point->time))); // The actual coordinates are stored inside a Point tag $pointNode = $placeNode->appendChild ($feed->createElement('Point')); // Note that KML coordinates are longitude // then latitude! $coordinatesNode = $pointNode->appendChild ($feed->createElement('coordinates', $point->longitude . ',' . $point->latitude)); // Each place also has an actual TimeStamp tag $timeNode = $placeNode->appendChild ($feed->createElement('TimeStamp', date('c',$point->time))); } } // Make sure browsers know to render the feed as XML header('Content-type: text/xml'); // Write the feed content to the page echo $feed->saveXML();
Ensure that the resulting feed looks something like this in your browser:
If your feed is accessible to the public Internet, test it by entering its URL into the Google Maps search bar:
Select File | Save in your web browser while viewing the feed, and save it with a filename ending in
.kml
.You will be able to open the resulting KML file in Google Earth. If you have Google Earth installed, test the feed by double-clicking on the file.
How it works...
It's not a good idea to hand-code an XML-based file, or to use a static template to do so. Various tools and libraries are available, and the DOM extension that was introduced with PHP 5 is an easy way to get started.
Our KML file consists of a Document node, which in turn contains a series of Placemark nodes. We could include a large amount of data here, but our minimum viable KML file will list name, timestamp, and geographic point information inside each Placemark. These are contained within name, TimeStamp, and Point nodes respectively. The Point node in turn contains a coordinates node, which lists the geographic coordinates of the point. Note that KML coordinates list the latitude first, followed by a comma, followed by the longitude. Spaces should not be used.
Placemarks can include more than one Point, as well as a selection of other geographic elements, but for the purposes of this example, we'll stick to one Point per Placemark.
TimeStamps are listed in ISO 8601 format. The TimeStamp for 7:30 p.m. Pacific Time on March 11, 2013 would appear as follows:
Mon, 11 Mar 2013 19:30:00 -0700
Create a new XML file in PHP by instantiating a DOMDocument object, specifying XML Version 1.0 and the UTF-8 character set:
$feed = new DOMDocument('1.0','UTF-8');
Define it as being a KML file by including the KML namespace, and establishing a root node:
$rootNode = $feed->appendChild($feed->createElementNS('http://earth.google.com/kml/2.2', 'kml'));
New child nodes are added to a DOMDocument through use of the appendChild
method; elements are created inside them using createElement
. Now you have your root node, you can add the Document node:
$documentNode = $rootNode->appendChild($feed->createElement('Document'));
Using the getPreviousLocations
function we created earlier, we can nest a series of Placemark nodes with the features as described in the preceding code line, using more calls to appendChild
and createElement
. The complete code is available in feed.php
for you to peruse.
All of your data is now loaded into the feed. All that's left is to write it to the browser. First, you must tell it that this is an XML file, by setting the HTTP header appropriately:
header('Content-type: text/xml');
Finally, then, you can write it to the browser:
echo $feed->saveXML();
This is all you need to create a fully functional KML feed. There's much more available in the KML specification, including details about how to style map points, and other information that can be included inside the feed as a whole, as well as each individual Placemark. A link to the KML specification is included at the end of this section.
Because Google Maps natively supports KML, once you've made your system live on the web, you can simply paste the URL to your feed.php
file into the Google Maps search box, and your geographic points will be displayed.
Additionally, you can choose to load your KML file into the map you created in index.php
. This has the same effect as entering the address of your KML file into the Google Maps search bar, but on the map embedded in your own application.
You may remember that we created a global variable referencing the map called window.googleMap
. Directly underneath, you can create a KmlLayer
object as follows:
window.kmlLayer = new google.maps.KmlLayer('http://your/kml/feed.php'); window.kmlLayer.setMap(window.googleMap);
Of course, http://your/kml/feed.php
must be replaced with the URL of your feed.
See also
Keyhole Markup Language specification: https://developers.google.com/kml/