Using Google to Calculate Driving Distance / Time in PHP

A common problem for programmers is to calculate the straight line distance between two points given coordinates (lon / lat or easting / northing) and is trivial to solve. A less simple task is calculating the road distance between two addresses / postcodes / sets of coordinates.

But, as usual, Google can do this with ease and while it does not allow this functionality for every country in it's API it is very simple to scrape the required information from their http service that they provide to everyone.

So the function: (I didn't use cURL because many don't have it, but you should if you do!)

function get_driving_information($start, $finish, $raw = false)
{
	if(strcmp($start, $finish) == 0)
	{
		$time = 0;
		if($raw)
		{
			$time .= ' seconds';
		}
 
		return array('distance' => 0, 'time' => $time);
	}
 
	$start  = urlencode($start);
	$finish = urlencode($finish);
 
	$distance   = 'unknown';
	$time		= 'unknown';
 
	$url = 'http://maps.googleapis.com/maps/api/directions/xml?origin='.$start.'&destination='.$finish.'&sensor=false';
	if($data = file_get_contents($url))
	{
		$xml = new SimpleXMLElement($data);
 
		if(isset($xml->route->leg->duration->value) AND (int)$xml->route->leg->duration->value > 0)
		{
			if($raw)
			{
				$distance = (string)$xml->route->leg->distance->text;
				$time	  = (string)$xml->route->leg->duration->text;
			}
			else
			{
				$distance = (int)$xml->route->leg->distance->value / 1000 / 1.609344; 
				$time	  = (int)$xml->route->leg->duration->value;
			}
		}
		else
		{
			throw new Exception('Could not find that route');
		}
 
		return array('distance' => $distance, 'time' => $time);
	}
	else
	{
		throw new Exception('Could not resolve URL');
	}
}

And the usage (with postcodes):

try
{
	$info = get_driving_information('ec1m 4df', 'pr4 0up');
	echo $info['distance'].' miles '.$info['time'].' seconds';
}
catch(Exception $e)
{
    echo 'Caught exception: '.$e->getMessage()."\n";
}
 
# Outputs 229.00 miles 14640 seconds

Or with addresses:

try
{
	$info = get_driving_information('44-46 St. John Street London', '15 Manor Road, Inskip, Preston');
	echo $info['distance'].' miles '.$info['time'].' seconds';
}
catch(Exception $e)
{
    echo 'Caught exception: '.$e->getMessage()."\n";
}
 
# Outputs 229.00 miles 14640 seconds

You can also choose to keep Google's raw output:

try
{
	$info = get_driving_information('ec1m 4df', 'pr4 0up', true);
	echo $info['distance'].' '.$info['time'];
}
catch(Exception $e)
{
    echo 'Caught exception: '.$e->getMessage()."\n";
}
 
# Outputs 229 mi 4 hours 4 mins

Hopefully this will be of use to someone! Enjoy.

Update 1

It was brought to my attention that this function did not work with two sets of lon/lat coordinates. For some reason Google no longer supports this in the non-JavaScript version? Not to worry though, they allow you to use their individual location tool to convert one of them into an address first. Sloppy, but effective.

Update 2 - May 2012

Google has once again changed the way they work, so there is a new version available...