动态邮政编码验证

I need to validate postcode in a specific format that was given to me, per country basis.

For example:

$postcode_validation = array
(
    'Australia'     => array('NNNN'),
    'Bahrain'       => array('NNN', 'NNNN'),
    'Netherlands'   => array('NNNN AA'),
    'United States' => array('NNNNN', 'NNNNN-NNNN', 'NNNNN-NNNNNN')
);

Each country can have as many variation of postcode format as they want; where:

  • N = Number [0-9]
  • A = Letters [a-zA-Z]
  • and it sometime allows/contains hypens

So, if we take Australia for example, it should validate to true for:

  • 1245
  • 4791
  • 7415

etc...

and should fail on:

  • a113
  • 18q5
  • 1s-s7

etc...

Given that, I am trying to create a single function I can use to validate a postcode for a given country against all the variation of the postcode. function should return true if the postcode matches against at least 1 of the rule and return false if no match is made.

So, this is how I tried to do it (starting with the simple one):

<?php

// mapping
$postcode_validation = array
(
    'Australia'     => array('NNNN'),
    'Bahrain'       => array('NNN', 'NNNN'),
    'Netherlands'   => array('NNNN AA'),
    'United States' => array('NNNNN', 'NNNNN-NNNN', 'NNNNN-NNNNNN')
);

// helper function
function isPostcodeValid($country, $postcode)
{
    // Load Mapping
    global $postcode_validation;

    // Init
    $is_valid = false;

    // Check If Country Exists
    if (!array_key_exists($country, $postcode_validation))
        return false;

    // Load Postcode Validation Rules
    $validation_rules = $postcode_validation[$country];

    // Iterate Through Rules And Check
    foreach ($validation_rules as $validation_rule)
    {
        // Replace N with \d for regex
        $validation_rule = str_replace('N', '\\d', $validation_rule);

        // Check If Postcode Matches Pattern
        if (preg_match("/$validation_rule/", $postcode)) {
            $is_valid = true;
            break;
        }
    }

    // Finished
    return $is_valid;
}

// Test
$myCountry = 'Australia';
$myPostcode = '1468';
var_dump(isPostcodeValid($myCountry, $myPostcode));

?>

This appears to work by returning true. But it also returns true for $myPostcode = '1468a';

Does anyone have a way to do this dynamic postcode validation by fixed rules?


Update

This is how it was solved; by using the regex from Zend library: http://pastebin.com/DBKhpkur

OP's regex was not working correctly because it was not considering the start and end of the line.

As commented by @cOle2, line

if (preg_match("/$validation_rule/", $postcode)) {

should be changed to

if (preg_match("/^$validation_rule$/", $postcode)) {

Also, as noted in the edit by the OP, another good solution is to use the regex from Zend library: http://pastebin.com/DBKhpkur