Home > PHP/MySQL Programming > UK Post Code Distance Calculator using PHP/MySQL

UK Post Code Distance Calculator using PHP/MySQL

March 30th, 2008

Ever wondered how websites can tell you how far it is from one UK post code to another? This tutorial will tell you everything you need to know about adding this cool feature to your website using PHP and MySQL. Warning - although there is complex maths involved, no clever maths knowledge is required.

How it Works

The theory is simple - you need a database of post codes (only the first part of the post code) and their corresponding longitude/latitude values. When calculating the distance we are actually calculating the distance from one long/lat value to another (using rather clever maths).

To see a demo of the UK post code distance calculator in action please visit www.wroes.co.uk/about/stores.php.

Setting up the Database

Firstly, you require a database of post codes with their corresponding longitude/latitude values. Thankfully, this has already been compiled by easypeasy!which can be downloaded in CSV or SQL format. We’ve provided the files here for your convenience.

Download the UK post codes database in CSV/SQL: uk-postcodes.zip (95KB)

Create your database table using these files and your ready to begin. You will see that the database contains the following fields:

  • Post code (first part)
  • Postal town (Uk-Postcodes-Towns.csv file only)
  • X-coordinate (metres)
  • Y-coordinate (metres)
  • Latitude
  • Longitude

Getting the Latitude and Longitude Values

We’re assuming you have 2 full post codes to calculate the distance between. We only need the first part of the post code so we must trim them accordingly. The second part of the post code is always 3 characters (first part can either be 2, 3, or even 4 characters). So, we need to remove all spaces and then trim 3 characters off the end to give us the first part:

<?php

#Convert the post code to upper case and trim the variable
$postcode = strtoupper(trim($postcode));

#Remove any spaces
$postcode = str_replace(" ","",$postcode);

#Trim the last 3 characters off the end
$postcode_first = substr($postcode,0,strlen($postcode)-3);

?>

We have our 2 post codes now ready to compare. We need to query our database to obtain the latitude and longitude values for each post code. Use the following query, replacing with correct field/table names where appropriate:

“SELECT * FROM tblPostCode WHERE fldPostCode = ‘$postcode_first’ LIMIT 1″;

Check to ensure a post code was found and then assign the variables. You may wish to use something like this: (repeating the code for the second post code)

<?php

Does the post code exist?
if ($myrow["fldPostCode"] != ""){

#Assign variables
$code1_lat = $myrow["fldLatitude"];
$code1_long = $myrow["fldLongitude"];

}else{

#post code not found

}

?>

Calculating the Distance

This is where the complex mathematics starts. Don’t worry if you don’t understand this (we certainly don’t)! All you need for this to work is the latitude and longitude values for your 2 post codes (obtained from your database - above).

We’re going to create a function called getDistance() which takes all 4 lat/long values to return the distance in miles. If you’re after kilometres you can either perform the conversion from miles afterwards or modify the function slightly (see first comment below). This function does take into account the curvature of the Earth. Here’s the function:

<?php

function getDistance($lat1, $long1, $lat2, $long2){

#$earth = 6371; #km change accordingly
$earth = 3960; #miles

#Point 1 cords
$lat1 = deg2rad($lat1);
$long1= deg2rad($long1);

#Point 2 cords
$lat2 = deg2rad($lat2);
$long2= deg2rad($long2);

#Haversine Formula
$dlong=$long2-$long1;
$dlat=$lat2-$lat1;

$sinlat=sin($dlat/2);
$sinlong=sin($dlong/2);

$a=($sinlat*$sinlat)+cos($lat1)*cos($lat2)*($sinlong*$sinlong);

$c=2*asin(min(1,sqrt($a)));

$d=round($earth*$c);

return $d;

}

?>

We call the function with the following code:

<?php

#Returns the distance in miles
$distance = getDistance($code1_lat, $code1_long, $code2_lat, $code2_long);

?>

Limitations

The distance calculated is not the real distance if travelling on roads. It calculates a direct route as the crow flies. This is ideal for an approximate calculation, however, if you want more detailed calculations then you may wish to explore available mapping and route calculation software and APIs.

The exact same theory and code can be used when calculating distances from US Zip codes.

For more information on web development please contact us on +44(0)1202 315285 or info@acmultimedia.co.uk. Learn more about AC Multimedia.
Bookmark and Share

PHP/MySQL Programming

  1. Archive
    March 25th, 2009 at 15:33 | #1

    Hi
    It is a nice post and really like it .

  2. Archive
    March 25th, 2009 at 15:33 | #2

    As a web designer and developer you never know what each project is going to need, and although I’ve never had to do anything like this up until now, I may have to in the future.

    So this post I’ll be adding to my favourites for when that time comes :)

  3. Archive
    March 25th, 2009 at 15:33 | #3

    Thanks a lot for this tutorial, it was very helpful. Although it doesn’t calculate the real distance traveling on roads, it gives some good evaluation of it.

  4. Archive
    March 25th, 2009 at 15:33 | #4

    Thanks for the script - I know it’s already been said, but you never know what project is coming up next.

  5. Archive
    March 25th, 2009 at 15:33 | #5

    Great function!
    I just changed the round bit. If you want to show distances under 1 mile eg $d=round($earth*$c,2);

  6. Archive
    March 25th, 2009 at 15:34 | #6

    is that the exact code to use in the page?
    it doesnt seem to have the same field names as the downloaded sql file…

  7. Archive
    March 25th, 2009 at 15:34 | #7

    Hi this looks really handy for a university project that I am about to start.

    I have two types of user (consumers and producers) who provide their postcodes when they register to the site and the postcode is added to a table called ‘user’

    The project is based on a directory so consumers can search for their nearest producers by distance. But also consumers can join ‘community projects’ created by other consumers and producers which works the same by listing them in distance order from the user.

    Would I be able to use this code?
    Or how can it be modified to work?

    I’m quite new to php and so don’t have a huge understanding.
    How would I set the tables up in terms of values etc

  8. Archive
    March 25th, 2009 at 15:34 | #8

    PHP works how ever the script is very faulty.

    example NE1 (newcastle in the north of enland) to SW1 (London) is 270 miles ish in a stright line and 300 on the road. script returns 100 miles.

  9. Archive
    March 25th, 2009 at 15:35 | #9

    Thank you for sharing this. Approximate distance calculation is something that can come in really handy for ecommerce shops calculating postage. Great tutorial.

  10. Archive
    March 25th, 2009 at 15:35 | #10

    Thank you for sharing this with us -
    in theory it is a good idea but in practice it is flawed. On the woes page if i pick a postcode in heartland and a postocde in crackington haven they both state 1 mile to bude store - as you are well aware this is totally incorrect - it is not even close!
    It is 10.4 miles from crackington haven to the bude store and from heartland to the bude store is 17.1 miles.

  11. Archive
    March 25th, 2009 at 15:35 | #11

    What a life saver, web design companies will love you for this. I do!

    I started something like this a long time ago, using the postcodes listed on Wikipedia. Just thought it would be worth asking, is there any copyright issues relating to Royal Mail here?

  12. Luke
    July 9th, 2009 at 10:23 | #12

    Hi, thanks for this page explaining what needs to be done; but i am a little confused :) I’m using the joomla cms with the jumi add on (so you can put in your custom scripts) Are all the codes snippets meant to be in one file? I added the postcode data into a table but im getting an error on one of the lines :(

    Parse error: syntax error, unexpected ‘”‘, expecting T_STRING or T_VARIABLE or T_NUM_STRING:

    if ($myrow["postcode"] != “”){

  13. August 3rd, 2009 at 16:11 | #13

    Hi,

    Thanks very much, just want i wanted - very useful ta. Didn’t want ot use the MySQL side so just stuck the POs in an array and its great!

  14. June 15th, 2010 at 10:15 | #14

    This is great, nicely explained :)

    Unfortuantely it is only accurate to the postal area (first part of the postcode). Something like http://postcoder.tenfourzero.net is great for accurate measurements to within 1 metre.

  1. No trackbacks yet.