-2

I am trying to match a full UK postcode against a partial postcode. Take a users postcode, i.e g22 1pf, and see if there's a match / partial match in the array / database.

//Sample data
$postcode_to_check= 'g401pf';
//$postcode_to_check= 'g651qr';
//$postcode_to_check= 'g51rq';
//$postcode_to_check= 'g659rs';
//$postcode_to_check= 'g40';

$postcodes = array('g657','g658','g659','g659pf','g40','g5');
$counter=0;

foreach($postcodes as $postcode){
    $postcode_data[] = array('id' =>$counter++ , 'postcode' => $postcode, 'charge' => '20.00');
}

I do have some code but that was just comparing the strings with fixed lengths from the database. I need the strings in the array / database to be dynamic in length.

The database may contain "g22" this would be a match, it could also contain more or less of the postcode, i.e "g221" or "g221p" which would also be a match. It could contain "g221q" or "g221qr" these would not match.

Help Appreciated, Thank you

edit.

I was possibly overthinking this. the following pseudo code seems to function as expected.

check_delivery('g401pf');
//this would match because g40 is in the database.

check_delivery('g651dt');
// g651dt this would NOT match because g651dt is not in the database.

check_delivery('g524pq');
//g524pq this would match because g5 is in the database.

check_delivery('g659pf');
//g659pf this would match because g659 is in the database.

check_delivery('g655pf');
//g655pf this would not match, g665 is not in the database

//expected output, 3 matches

function check_delivery($postcode_to_check){

    $postcodes = array('g657','g658','g659','g659pf','g40','g5');       
    $counter=0;

    foreach($postcodes as $postcode){

        $stripped_postcode = substr($postcode_to_check,0, strlen($postcode));

        if($postcode==$stripped_postcode){
            echo "Matched<br><br>";
          break;
        } 
    }
}
Raymie
  • 109
  • 1
  • 9
  • Please define the parameters of a match (e.g. why is `g221p` a match while . the `q` and `r` variations are not). Also why not do this at the DB level? – chris85 Dec 02 '17 at 23:06
  • If I understand you correctly, it should be easy to create an array of potential matches: `for ($i = 1; $i <= strlen($postcode); $i++) $matches[]=substr($postcode,0,$i);` Then you can use it to compare against another array with `array_intersect` or sth. similar. For the database you can use sth. like `"WHERE postcode in ('". implode("','",$matches)."'"` **the DB part is not safe for SQLi**, I just want to make sure I understand your intended search correctly. – jh1711 Dec 02 '17 at 23:23
  • I added some pseudo code above that appears to work. I'm going to try it more before delving into any of the provided solutions as it seems more simple. – Raymie Dec 02 '17 at 23:52
  • Looks like you are trying to calculate delivery costs or coverage areas or something. I found it much easier and much more accurate to just use Googles free Distance Matrix api when I did this. Then all postcodes match and it returns accurate driving distances and journey times based on historic traffic data. – miknik Dec 03 '17 at 00:04
  • loading separate api's etc is a bit much for the project, basically each shop front will have around 5 areas they delivery to. They get to input the postcodes as they see fit, i.e they might decide to delivery to the whole G22 Area, or only certain parts of it, i.e G22 1AA, G22 1AB. – Raymie Dec 03 '17 at 01:13

2 Answers2

0
       <?php
    $postcode_to_check= 'g401pf';

    $arr = preg_split("/\d+/",$postcode_to_check,-1, PREG_SPLIT_NO_EMPTY);
    preg_match_all('/\d+/', $postcode_to_check, $postcode);
    $out = implode("",array_map(function($postcode) {return implode("",$postcode);},$postcode));
    $first_char = mb_substr($arr[1], 0, 1);

    $MatchingPostcode=$arr[0].''.$out.''.$first_char;
    echo $MatchingPostcode;



 SELECT * FROM my_table WHERE column_name LIKE '%$MatchingPostcode%';

It's a dirty solution but it will solve your problem. Things like this should be handled in front-end or in the DB but if you must do it in php then this is a solution.

So this code will match you anything that includes g401p. If you don't want to match in the start of the end just remove % from which part you don't want to match. In my the case i provide you it will search for every column record that has g401p

pr1nc3
  • 8,108
  • 3
  • 23
  • 36
  • Thanks for pointing out. Updated my answer. It was more weird that i thought. – pr1nc3 Dec 02 '17 at 23:48
  • I added some pseudo code above that appears to work. I'm going to try it more before delving into any of the provided solutions as it seems more simple. – Raymie Dec 02 '17 at 23:52
  • I thought that the length of the string is not always the same so i tried to get everything before and the first char after the last number appearance. If it's always 1 letter +3 digits + the rest then you can go for string length. – pr1nc3 Dec 02 '17 at 23:56
  • The postcode_to check will always be greater or equal to the postcode in the database, the postcodes in the database will always be less than or equal to the postcode_to_check. think that makes sense! so stripping it to the same length and checking for the first match should be sufficient i guess. Thanks for your input, i'll probably be back for your answer when i discover a flaw in mine lol. – Raymie Dec 03 '17 at 00:06
0

Check the length and strip the one you want to compare it with to the same length.

function check_delivery($postcode_to_check){

$postcodes = array('g657','g658','g659','g659pf','g40','g5');       
$counter=0;

foreach($postcodes as $postcode){

    $stripped_postcode = substr($postcode_to_check,0, strlen($postcode));

    if($postcode==$stripped_postcode){
        echo "Matched<br><br>";
      break;
    } 
}

}

Raymie
  • 109
  • 1
  • 9