Jump to content

My regex validation for mobile phone numbers failing


Go to solution Solved by Jacques1,

Recommended Posts

I have a regex expression that validates a set of mobile numbers: The numbers have optional prefixes (+234 or 234 or 0) and I have used the alternation with the pipe character. Immediately following the international code or zero character is a set of service provider specific identifiers that I have also specified the options using the alternation character.

 

Based on the regex I have, this number should not be valid (12349098766543); but the regex returns it as valid. It appears the there is a match on 909 in the code. But shouldn't the presence of 1 at the beginning of the test string enforce a validation failure? What is wrong with the regex i have here?

function check_number($number) {
if(!preg_match('/[+234|234|0]?(704|702|803|806|703|706|813|816|810|814|903|802|708|808|812|701|902|809|817|818|909|908|805|705|815|807|811|905)\d{7}$/', $number)) {
    return 'Invalid Phone Number';
}else{
    return 'valid Phone Number';}

The execution below should fail, but is is passed as valid.

$str = '12349098766543';
echo check_number($str); 

The regex syntax is all over the place, and you don't have anchors to prevent matches somewhere in the middle of the input.

  • [+234|234|0] makes no sense. The square brackets denote a list of characters, but you want alternatives: (?:\\+?234|0). Read: Either an optional plus sign followed by 234, or the digit 0.
  • The + character is a meta character in regular expressions and must be escaped.
  • Use the \\A and \\z anchors to match the beginning and end of the input.
/\\A(?:\\+?234|0)?(?:704|...)\\d{7}\\z/

 

The regex syntax is all over the place, and you don't have anchors to prevent matches somewhere in the middle of the input.

  • [+234|234|0] makes no sense. The square brackets denote a list of characters, but you want alternatives: (?:\\+?234|0). Read: Either an optional plus sign followed by 234, or the digit 0.
  • The + character is a meta character in regular expressions and must be escaped.
  • Use the \\A and \\z anchors to match the beginning and end of the input.
/\\A(?:\\+?234|0)?(?:704|...)\\d{7}\\z/

Thanks Jacques1,

but Your pattern

/\\A(?:\\+?234|0)?(?:704|803)\\d{7}\\z/

does not match this subject string (2347048134704); when tested here https://www.regex101.com/

 

Or am I missing something?

  • Solution

It does match in PHP:

<?php

const PHONE_REGEX = '/\\A(?:\\+?234|0)?(?:704|803)\\d{7}\\z/';



$input = '2347048134704';
var_dump( preg_match(PHONE_REGEX, $input) );

Every regex engine has its own syntax flavor, and those backslash escapes won't work well outside of a PHP string. So test this with PHP, not some regex site.

I was already working on this when Jacques1 replied. A couple notes:

 

1. The function should simply return the Boolean True/False. The code that calls the function should determine the output.

2. Rather than putting the area codes in the regex patter directly, I would suggest defining them as an array and dynamically creating that part of the RegEx.  It will make it much easier to maintain the code.

3. For something like this,you should create a unit test that allows you to pass a lot of different values so you don't have to manually test individual values.

function check_number($number)
{
    $areaCodes = array('704','702','803','806','703','706','813', '816',
        '810','814','903','802','708','808','812','701', '902','809',
        '817','818','909','908','805','705','815','807','811','905');
    $areaCodeRegEx = implode('|', $areaCodes);
    $pattern = "/\\A(?:\\+?234|0)?(?:{$areaCodeRegEx})\\d{7}\\z/";
    return preg_match($pattern, $number);
}
 
$testNumbers = array(
    '1234567' => false,  //No area code
'8021234567' => true, //Area code + 7 digits
'802123456' => false, //Area code + 6 digits
'80212345678' => false, //Area code + 8 digits
    '+2348161234567' => true, //Optional  +code + area + 7 digits
    '+234816123456' => false, //Optional code + area + 6 digits
    '+23481612345678' => false, //Optional code + area + 8 digits
    '2347048134704' => true //Optional  +code + area + 7 digits
);
 
foreach($testNumbers as $number => $expected)
{
    echo "Number: {$number}";
echo ", Expected: "; echo ($expected) ? "Valid" : "Invalid";
    $actual = check_number($number);
    echo ", Actual: " . (($actual) ? "Valid" : "Invalid");
    echo ", Result: ";
    if ($actual==$expected) {
        echo "<span style='color:green;'>Pass</span><br>\n";
    } else {
        echo "<span style='color:red;'>Fail</span><br>\n";
    }
}

Output

 

 

Number: 1234567, Expected: Invalid, Actual: Invalid, Result: Pass

Number: 8021234567, Expected: Valid, Actual: Valid, Result: Pass
Number: 802123456, Expected: Invalid, Actual: Invalid, Result: Pass
Number: 80212345678, Expected: Invalid, Actual: Invalid, Result: Pass
Number: +2348161234567, Expected: Valid, Actual: Valid, Result: Pass
Number: +234816123456, Expected: Invalid, Actual: Invalid, Result: Pass
Number: +23481612345678, Expected: Invalid, Actual: Invalid, Result: Pass


Number: 2347048134704, Expected: Valid, Actual: Valid, Result: Pass

Edited by Psycho
  • Like 1

I need to create a pattern attribute that specifies a regular expression for an <input> element's value that accepts mobile phone numbers. Jacques1 provided this PHP regex function which works great. I attempted to use this as a value for the pattern attribute but is is failing to check properly.

 

Here is the regex code below:


<!DOCTYPE html>
<html>
<body>

<form action="demo_form.asp">
  Country code: <input type="text" name="country_code"
 pattern="\\A(?:\\+?234|0)?(?:704|702|803|806|703|706|813|816|810|814|903|802|708|808|812|701|902|809|817|818|909|908|805|705|815|807|811|905)\\d{7}\\z" title="Allowed formats are: 09031111111, 2340801111111, or +2340801111111">
  <input type="submit">
</form>
</body>
</html>

 What is the proper format to use as a pattern attribute value. Note a number as this should be valid (2349098766543) but it is failing.

 

Thanks

Threads merged and moved to Regex.

 

terungwa, as Jacques said the regex works in PHP, while you need a pattern that works with Javascript's regular expressions (which is what the "pattern" is). There are big differences between the two.

(?:\+?234|0)?(?:704|702|803|806|703|706|813|816|810|814|903|802|708|808|812|701|902|809|817|818|909|908|805|705|815|807|811|905)\d{7}
- \A and \z anchors are not supported - use ^ and $. However the "pattern" is already implicitly anchored so you don't need them.

- Remove the extra backslashes, which were being used for escaping within PHP strings

 

Be sure to do the same validation in PHP (with the other regex) because this validation in HTML can by easily bypassed.

Edited by requinix

Threads merged and moved to Regex.

 

terungwa, as Jacques said the regex works in PHP, while you need a pattern that works with Javascript's regular expressions (which is what the "pattern" is). There are big differences between the two.

(?:\+?234|0)?(?:704|702|803|806|703|706|813|816|810|814|903|802|708|808|812|701|902|809|817|818|909|908|805|705|815|807|811|905)\d{7}
- \A and \z anchors are not supported - use ^ and $. However the "pattern" is already implicitly anchored so you don't need them.

- Remove the extra backslashes, which were being used for escaping within PHP strings

 

Be sure to do the same validation in PHP (with the other regex) because this validation in HTML can by easily bypassed.

 

 

Threads merged and moved to Regex.

 

terungwa, as Jacques said the regex works in PHP, while you need a pattern that works with Javascript's regular expressions (which is what the "pattern" is). There are big differences between the two.

(?:\+?234|0)?(?:704|702|803|806|703|706|813|816|810|814|903|802|708|808|812|701|902|809|817|818|909|908|805|705|815|807|811|905)\d{7}
- \A and \z anchors are not supported - use ^ and $. However the "pattern" is already implicitly anchored so you don't need them.

- Remove the extra backslashes, which were being used for escaping within PHP strings

 

Be sure to do the same validation in PHP (with the other regex) because this validation in HTML can by easily bypassed.

 

Yea I shall definitely validate server side. The html5 pattern attribute is for user experience improvement on supported browsers

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.