terungwa Posted September 2, 2016 Share Posted September 2, 2016 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); Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted September 2, 2016 Share Posted September 2, 2016 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/ Quote Link to comment Share on other sites More sharing options...
terungwa Posted September 2, 2016 Author Share Posted September 2, 2016 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? Quote Link to comment Share on other sites More sharing options...
Solution Jacques1 Posted September 2, 2016 Solution Share Posted September 2, 2016 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. Quote Link to comment Share on other sites More sharing options...
Psycho Posted September 2, 2016 Share Posted September 2, 2016 (edited) 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: PassNumber: 8021234567, Expected: Valid, Actual: Valid, Result: PassNumber: 802123456, Expected: Invalid, Actual: Invalid, Result: PassNumber: 80212345678, Expected: Invalid, Actual: Invalid, Result: PassNumber: +2348161234567, Expected: Valid, Actual: Valid, Result: PassNumber: +234816123456, Expected: Invalid, Actual: Invalid, Result: PassNumber: +23481612345678, Expected: Invalid, Actual: Invalid, Result: Pass Number: 2347048134704, Expected: Valid, Actual: Valid, Result: Pass Edited September 2, 2016 by Psycho 1 Quote Link to comment Share on other sites More sharing options...
terungwa Posted September 2, 2016 Author Share Posted September 2, 2016 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 Quote Link to comment Share on other sites More sharing options...
requinix Posted September 2, 2016 Share Posted September 2, 2016 (edited) 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 September 2, 2016 by requinix Quote Link to comment Share on other sites More sharing options...
terungwa Posted September 3, 2016 Author Share Posted September 3, 2016 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 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.