Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Find first part of UK postcode when full or part can be entered

Tags:

php

Someone please put me out of my misery and help me solve this one.

I have a postcode lookup box that allows people to put in full postcodes (e.g. BS34 5GF) or part post codes (e.g. BS34).

My postcode lookup only requires the first part of the postcode and I am trying to find the most effective way of trimming the string to only have the first section, without explicitly knowing the format it is entered in.

Here are some example codes: B2 5GG, B22 5GG, BS22 5GG, B25GG, BS25GG, BS225GG, B2, BS2, BS22

This shows how many possible variations there could be.. What is the best way to ensure I always get the first part of the postcode?

like image 345
David Shaw Avatar asked Dec 20 '22 06:12

David Shaw


2 Answers

IMHO regexes are exactly the right solution to the problem.

Ignoring for now BFPO address, try:

if (preg_match("(([A-Z]{1,2}[0-9]{1,2})($|[ 0-9]))", trim($postcode), $match)) {
   $region=$match[1];
}
like image 101
symcbean Avatar answered May 21 '23 13:05

symcbean


If you use regular expressions to match British postcodes (part or whole), you're doing it wrong. Also, please note before going any further that, no matter how you write your code, there is one case where the format will be ambiguous: BS22 could very well belong to BS2 2AB or BS22 5GS. There is absolutely no way to tell, and you'll need to make a decision based on that.

The algorithm I am suggesting considers the case of BS22 to count as BS22. It is as follows:

<?php
function testPostcode($mypostcode) {
if (($posOfSpace = stripos($mypostcode," ")) !== false) return substr($mypostcode,0,$posOfSpace);
    // Deal with the format BS000
    if (strlen($mypostcode) < 5) return $mypostcode;

    $shortened = substr($mypostcode,0,5);
    if ((string)(int)substr($shortened,4,1) === (string)substr($shortened,4,1)) {
       // BS000. Strip one and return
       return substr($shortened,0,4);
    }
    else {
      if ((string)(int)substr($shortened,3,1) === (string)substr($shortened,3,1)) {
         return substr($shortened,0,3);
      }
      else return substr($shortened,0,2);
    }
}

// Test cases
$postcodes = array("BS3 3PL", "BS28BS","BS34","BS345","BS32EQ");
foreach ($postcodes as $k => $v) {
   echo "<p>".$v." => ".testPostcode($v)."</p>";
}

This is both faster and simpler to maintain than a regular expression.

like image 31
Sébastien Renauld Avatar answered May 21 '23 13:05

Sébastien Renauld