SitePoint Sponsor

User Tag List

Results 1 to 20 of 20
  1. #1
    SitePoint Wizard billy_111's Avatar
    Join Date
    Jul 2009
    Posts
    1,683
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    UK Postcode Search

    Hi,

    I don't know how how difficult this is but i need to create a postcode search on the following site:

    http://www.babiesinthecity.co.uk/sea...ton=&search=M1

    What you can see here is a set of "Reviews" which are being pulled out of a database. Each review has a postcode.

    Now what i need to show on this page is the distance the inputted postcode which is "M1" is to each review.

    I know i need an API, and i looked into The Google Directions API

    The site is coded in PHP, but i don't quite know how or where to begin? Can anyone point me in the right direction?

    Thanks
    Software Engineer ASP, ASP.NET, VB, PHP

    Kind regards
    Billy

  2. #2
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Well, first you need to find a longitude and latitude for the given postcode. The starting point is easy, you can manually find that, the second however will need to be 'found' by the code.

    Remember though, you'll only need to do this the once, the long and lat ain't gonna change so just pop 'em in your database once obtained.

    For the reverse GeoCoding you can use a rather funky YQL query such as this. This will find the long and lat for you, now the math begins.

    You now have 2 sets of long and lats. To calculate the distance (as the crow flies) you can apply the Great Circle Distance formula which takes into account the curvature of the earth too.

    Who says math aint cool?
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  3. #3
    SitePoint Wizard billy_111's Avatar
    Join Date
    Jul 2009
    Posts
    1,683
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok it looks quite difficult to do, but i will start from the beginning and work my way forward..

    So first things first, you mentioned i need to get the long and lat values. So i understand why i need to get these values for the given postcode, however what do you mean when you say:

    "The starting point is easy, you can manually find that, the second however will need to be 'found' by the code..."
    Which starting point? And what needs to be found by the code? Once i have these values in my database, i presume i would then need to develop a method where the script calculates how far each Reviews postcode is against the given postcode..
    Software Engineer ASP, ASP.NET, VB, PHP

    Kind regards
    Billy

  4. #4
    SitePoint Wizard billy_111's Avatar
    Join Date
    Jul 2009
    Posts
    1,683
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi Anthony..

    I have been looking at Google's Directions API.. And have managed to put together something.. This is my code:

    PHP Code:
    class PostcodeSearch{

        public function 
    LoadXml($origin$destination){        
            
    $xml simplexml_load_file("http://maps.google.com/maps/api/directions/xml?origin=".$origin."&destination=".$destination."&sensor=false");

            foreach (
    $xml->xpath('//distance') as $distance):
                
    $lastvalue $distance->value;
            endforeach;

            
    $total $lastvalue 0.00062137119;
            
    $total number_format($total2);

            return 
    $total;
        }

    Then in my front end i have this:

    PHP Code:
    <?
    $review 
    Review::searchAllReviewsByTitlePoscodeAndAddress();
                    while(
    $row mysql_fetch_array($review)){ 
                                            
    $pcode PostcodeSearch::LoadXml($_GET['search'], $row['postcode']);
    ?>

    <div style="margin:0 0 10px 0; font-weight: bold">Distance: <span style="color:#990000"><?=$pcode?> miles</span></div>

    <? ?>
    Now i am trying to get this working on this page:

    http://www.babiesinthecity.co.uk/sea...on=&search=M25

    Notice i have already put in a search of "M25"..

    So basically for each review i loop through and check its postcode against the given input which in this case is "M25". The first result is "Heaton Park" which has a postcode of "M25 2SW".. If we put this into the xml link like so:

    http://maps.google.com/maps/api/dire...W&sensor=false

    It gives no results.. Hence why i am getting the error on the display page:

    Notice: Undefined variable: lastvalue in /home/migbabie/public_html/classes/PostcodeSearch.class.php on line 11
    Yet if we look in Google:

    http://maps.google.co.uk/maps?f=q&so...=UTF8&t=h&z=15

    It works fine.

    Any ideas why i am having this problem. This is all i need to do, just show the distance..

    Don't understand why it won't work..

    Thanks
    Software Engineer ASP, ASP.NET, VB, PHP

    Kind regards
    Billy

  5. #5
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    function get_distance($from$to){
      
    $xml = new SimpleXMLElement(
        
    sprintf(
          
    'http://maps.google.com/maps/api/directions/xml?origin=%s&destination=%s&sensor=false',
          
    urlencode($from),
          
    urlencode($to)
        )
      );
      
    $distance 0;
      if(
    'OK' === (string)$xml->status){
        
    $query $xml->xpath("route/leg/distance/value/text()");
        if(
    count($query)){
          
    $distance = (int)$query[0];
        }
      }
      return 
    $distance;

    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  6. #6
    SitePoint Wizard billy_111's Avatar
    Join Date
    Jul 2009
    Posts
    1,683
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Anthony,

    I am getting an error:

    http://www.babiesinthecity.co.uk/sea...on=&search=M25

    In the front end i am calling the method like so:

    PHP Code:
    $pcode PostcodeSearch::get_distance($_GET['search'], $row['postcode']); 
    Any ideas why i get the error?

    Thanks again
    Software Engineer ASP, ASP.NET, VB, PHP

    Kind regards
    Billy

  7. #7
    SitePoint Wizard billy_111's Avatar
    Join Date
    Jul 2009
    Posts
    1,683
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    By the way, this is the error:

    Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: Entity: line 1: parser error : Start tag expected, '<' not found in /home/migbabie/public_html/classes/PostcodeSearch.class.php on line 24

    Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: http://maps.google.com/maps/api/dire...ion=M25+2SW&se in /home/migbabie/public_html/classes/PostcodeSearch.class.php on line 24

    Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: ^ in /home/migbabie/public_html/classes/PostcodeSearch.class.php on line 24

    Fatal error: Uncaught exception 'Exception' with message 'String could not be parsed as XML' in /home/migbabie/public_html/classes/PostcodeSearch.class.php:24 Stack trace: #0 /home/migbabie/public_html/classes/PostcodeSearch.class.php(24): SimpleXMLElement->__construct('http://maps.goo...') #1 /home/migbabie/public_html/search/index.php(36): PostcodeSearch::get_distance('M25', 'M25 2SW') #2 {main} thrown in /home/migbabie/public_html/classes/PostcodeSearch.class.php on line 24
    Software Engineer ASP, ASP.NET, VB, PHP

    Kind regards
    Billy

  8. #8
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Entity: line 1: parser error : Start tag expected, '<' not found in /home/migbabie/public_html/classes/PostcodeSearch.class.php on line 24
    Sorry, I cannot test as my internal dev server has no internet access (I'm at work). The above message states the problem, try a spot of debugging.
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  9. #9
    @php.net Salathe's Avatar
    Join Date
    Dec 2004
    Location
    Edinburgh
    Posts
    1,397
    Mentioned
    65 Post(s)
    Tagged
    0 Thread(s)
    It's not clear from the error message, but are you trying to create the SimpleXMLElement object without telling the class that you are providing a URL (as opposed to an XML string)? See the docs, especially the optional third parameter which defaults to false.

    If you're already doing that, can we see the PHP code?
    Salathe
    Software Developer and PHP Manual Author.

  10. #10
    SitePoint Wizard billy_111's Avatar
    Join Date
    Jul 2009
    Posts
    1,683
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,

    I have this code:

    PHP Code:
    class PostcodeSearch{

        public function 
    get_distance($from$to){
          
    $xml = new SimpleXMLElement(
            
    sprintf(
              
    'http://maps.google.com/maps/api/directions/xml?origin=%s&destination=%s&sensor=false',
              
    urlencode($from),
              
    urlencode($to)
            )
        );
          
    $distance 0;
          if(
    'OK' === (string)$xml->status){
            
    $query $xml->xpath("route/leg/distance/value/text()");
            if(
    count($query)){
              
    $distance = (int)$query[0];
            }
          }
          return 
    $distance;
        }


    And then i call the code like this:

    PHP Code:
    $review Review::searchAllReviewsByTitlePoscodeAndAddress();
                    while(
    $row mysql_fetch_array($review)){ 
                                            
    $text strip_tags($row['body']);
                                            
    $intro substr($text0600);

    $pcode PostcodeSearch::get_distance($_GET['search'], $row['postcode']);

    Thats all i have, any ideas what it might be?

    That error points to this line:

    PHP Code:
        public function get_distance($from$to){
          
    $xml = new SimpleXMLElement(
            
    sprintf(
              
    'http://maps.google.com/maps/api/directions/xml?origin=%s&destination=%s&sensor=false',
              
    urlencode($from),
              
    urlencode($to)
            )
        [
    B]);[/B
    See bold closing bracket..
    Software Engineer ASP, ASP.NET, VB, PHP

    Kind regards
    Billy

  11. #11
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Salathe View Post
    It's not clear from the error message, but are you trying to create the SimpleXMLElement object without telling the class that you are providing a URL (as opposed to an XML string)? See the docs, especially the optional third parameter which defaults to false.

    If you're already doing that, can we see the PHP code?
    Bah! Thanks Salathe.

    As Salathe states, there are some parameters missing from SimpleXMLElement, care to fix it yourself Billy?

    All you need is the manual.
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  12. #12
    SitePoint Wizard billy_111's Avatar
    Join Date
    Jul 2009
    Posts
    1,683
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok i have been doing some more debugging and testing..

    Turns out the code i was using before, which is this:

    PHP Code:
        public function LoadXml($origin$destination){
            
    $xml simplexml_load_file("http://maps.google.com/maps/api/directions/xml?origin=".$origin."&destination=".$destination."&sensor=false");

            foreach (
    $xml->xpath('//distance') as $distance):
                
    $lastvalue $distance->value;
            endforeach;

            
    $total $lastvalue 0.00062137119;
            
    $total number_format($total2);
            
            return 
    $total;
        } 
    The reason i say this is because it was successfully giving me the correct distance between a given postcode but then suddenly stopped working.

    I did a print_r on the XML object and got this:

    OVER_QUERY_LIMIT
    Looked this up on Google and come to know it meant my daily limit has been reached??

    Can anyone shed some light on this?

    What can i do to overcome this?

    Thanks
    Software Engineer ASP, ASP.NET, VB, PHP

    Kind regards
    Billy

  13. #13
    Community Advisor silver trophy

    Join Date
    Nov 2006
    Location
    UK
    Posts
    2,554
    Mentioned
    40 Post(s)
    Tagged
    1 Thread(s)
    You could store returned values in a database so that before repeating a request to google, you check your local store of data first - this should reduce your requests. Alternatively, you can switch to using GClientGeocoder client side which means the limit is now applicable per visitor ip rather than server ip.

  14. #14
    From space with love silver trophy
    SpacePhoenix's Avatar
    Join Date
    May 2007
    Location
    Poole, UK
    Posts
    5,067
    Mentioned
    103 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by AnthonySterling View Post
    Well, first you need to find a longitude and latitude for the given postcode. The starting point is easy, you can manually find that, the second however will need to be 'found' by the code.

    Remember though, you'll only need to do this the once, the long and lat ain't gonna change so just pop 'em in your database once obtained.

    For the reverse GeoCoding you can use a rather funky YQL query such as this. This will find the long and lat for you, now the math begins.

    You now have 2 sets of long and lats. To calculate the distance (as the crow flies) you can apply the Great Circle Distance formula which takes into account the curvature of the earth too.

    Who says math aint cool?
    An option for getting the coordinates for postcodes is a think from Ordinance Survey called Code-Point, which has coordianates for each post code, though before you use it you should contact Ordinance Survey to check on licensing, etc for your intended plans. I don't know how much they will charge for the use of the data.

    Another alternative is the Royal Mail PAF but the costs of it, licensing etc is expensive.

    If you go for either option it may well pay to contact them and go through with them the relevant options for your intended use and licensing, costs, etc.
    Community Team Advisor
    Forum Guidelines: Posting FAQ Signatures FAQ Self Promotion FAQ
    Help the Mods: What's Fluff? Report Fluff/Spam to a Moderator

  15. #15
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    How about making use of a free api for UK Postcodes.
    http://www.uk-postcodes.com/api.php

    It will:
    • Return data for a postcode
    • Return data for the nearest postcode to a point
    • Return data for postcodes within x distance (miles) of a postcode or lat/lng
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  16. #16
    SitePoint Wizard billy_111's Avatar
    Join Date
    Jul 2009
    Posts
    1,683
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks pmw57.

    Well what i essentially need is to check the given postcode (By the user in the search box) against a series of "Reviews".. Each review has it's own postcode so it's quite simple to pull that out.

    I visited that page you have suggested.. So lets say the enters "M5 4WT" and i want to check it against "OL12 0JJ". I would want the results in xml as i can sift through the different nodes to get what i need, such as the distance.

    Would the URL be as such:

    http://www.uk-postcodes.com/distance.php?postcode=OL11%201PH&distance=M1&format=xml

    Can you see where i'm going wrong? I just need to find the distance between the two postcodes?

    Thanks
    Software Engineer ASP, ASP.NET, VB, PHP

    Kind regards
    Billy

  17. #17
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Afternoon Billy,

    You're not listening.

    The lookup of the distance, should only happen once. Not once per page load, day, summer holiday or full moon.

    Once.

    Create a background job to lookup all records in your database that do not have the distance between the x -> y already calculated. The job will look up the distance, if found/available/possible and update the record accordingly.

    Any look ups which fail will automatically be picked back up on the next run.

    If the records postcode changes, clear the distance column too and it auto-magic-tastically will be updated.

    If you cannot create a cron job, cache it locally so the external call only happens *once*.

    Bob requests the page, no distance found, look it up, save it, display page. Now, when Joe visits the page, the distance already exists and no external request is made.

    Thoughts?
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  18. #18
    SitePoint Wizard billy_111's Avatar
    Join Date
    Jul 2009
    Posts
    1,683
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I must say Anthony your method sounds the best!

    I think i was just being stupid looking for an easy way out..

    Anyway just to re-iterate what you've suggested, the logic will be:

    1. Lookup postcodes to see if given postcodes exist in database
    2. If they do, simply show those results
    3. If not, insert them into database and show results


    If you see now, the page works:

    http://babiesinthecity.co.uk/test/?s...ton=&search=M5

    This is because i haven't reached my limit yet. But what you are saying makes sense, if i store the postcodes in a database, it will result in less requests..

    Am i thinking along the right lines now Anthony?
    Software Engineer ASP, ASP.NET, VB, PHP

    Kind regards
    Billy

  19. #19
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Perfecto! Brilliant.
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  20. #20
    SitePoint Wizard billy_111's Avatar
    Join Date
    Jul 2009
    Posts
    1,683
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok cool,

    Well first things first, i want to make this code work better, because on some search results i get this:

    http://babiesinthecity.co.uk/test/?s...ton=&search=m1

    The top results show fine with the distance being shown. But the bottom results show an error saying "lastvalue" is undefined??

    Anyway, this is my code:

    PHP Code:
        public function LoadXml($origin$destination){
     
            
    $xml simplexml_load_file("http://maps.google.com/maps/api/directions/xml?origin=".$origin."&destination=".$destination."&sensor=false");

            foreach (
    $xml->xpath('//distance') as $distance):
                
    $lastvalue $distance->value;
            endforeach;

            
    $total $lastvalue 0.00062137119;
            
    $total number_format($total2);

            return 
    $total;
        } 
    I had a look at code suggested by Anthony, the error i was getting when using that code was because a third parameter was missing? I viewed the link to the documents, and i found this at the very top:

    PHP Code:
    SimpleXMLElement::__construct  string $data  [, int $options  [, bool $data_is_url  [, string $ns  [, bool $is_prefix  ]]]] ) 
    Showing 3 parameters. I just wasn't quite sure how or where to add this to that code
    Software Engineer ASP, ASP.NET, VB, PHP

    Kind regards
    Billy


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •