Validate phone number with optional ninth digit

Asked

Viewed 11,013 times

5

How to validate phone number with the optional ninth digit? in the following formats:

DDD + 8 digits = (21) 9876-5432

DDD + 9 digits = (21) 98765-4321

  • Being regex gives to simplify much more and another is not only the ddd that has 9 digits, almost all states of Angola and not only already adopted, I think that few are missing

4 answers

9

Since 2013 cell phones with DDD 21 started to have the ninth digit, I do not see why be optional, if you are saying that the input can be fixed phone as much as mobile I recommend you do not do this, will give a lot of headache

But if that’s what you wish you can do so:

^\(\d{2}\) 9?[6789]\d{3}-\d{4}$

Using the 9? inside the regex the number 9 is optional, but it still identifies if it is a cell phone, if it starts with 99, 98, 97 and 96 or 9, 8, 7 and 6, because inside the regex has this [6789]

Thus remaining:

<?php
$celular = '(21) 98765-4321';

if (preg_match('#^\(\d{2}\) 9?[6789]\d{3}-\d{4}$#', $celular) > 0) {
     echo 'Validou';
} else {
     echo 'Não validou';
}

How to validate cell phones with and without the ninth digit

Note that cell phones start with 96, 97, 98 and 99 (or 6, 7, 8 and 9 if you don’t have the ninth digit) as I mentioned before and according to Anatel these are the Ddds that will have the ninth digit:

To Resolution 553/2010 Anatel determined the implementation of the ninth digit throughout Brazil.

  • Area Code 11 (city of São Paulo and metropolitan region) gained the ninth digit on July 29, 2012.

  • On August 25, 2013, it was the turn of Ddds 12, 13, 14, 15, 16, 17, 18 and 19 (rest of the state of São Paulo).

  • On October 27, 2013, Ddds 21, 22 and 24 (state of Rio de Janeiro), and 27 and 28 (state of Espírito Santo).

  • On November 2, 2014, They will change the numbers of Area Code 91, 93 e 94 (state of Pará), 92 e 97 (state of Amazonas), 95 (state of Roraima), 96 (state of Amapá), 98 e 99 (state of Maranhão).

  • Until 31 December 2015, Ddds 31, 32, 33, 34, 35, 37 and 38 (state of Minas Gerais), 71, 73, 74, 75 and 77 (state of Bahia), 79 (state of Sergipe), 81 and 87 (state of Pernambuco), 82 (state of Alagoas), 83 (state of Paraíba), 84 (state of Rio Grande do Norte), 85 and 88 (state of Ceará), and 86 and 89 (state of Piauí).

  • Until 31 December 2016, Ddds 41, 42, 43, 44, 45 and 46 (state of Paraná), 47, 48 and 49 (state of Santa Catarina), 51, 53, 54 and 55 (state of Rio Grande do Sul), 61 (Federal District), 62 and 64 (state of Goiás), 63 (state of Tocantins), 65 and 66 will be amended (state of Mato Grosso), 67 (state of Mato Grosso do Sul), 68 (state of Acre) and 69 (state of Rondônia).

That is to be more accurate validation we need a more "lean" Regex, in case I suggest something like:

^(\((11|12|13|14|15|16|17|18|19|21|22|24|27|28|91|92|93|94|95|81|82|83|84|85|86|87|31|32|33|34|35|37|38|71|73|74|75|77|79|61|62|63|64|65|66|67|68|69|49|51|53|54|55)\) 9|\((?!11|12|13|14|15|16|17|18|19|21|22|24|27|28|91|92|93|94|95|81|82|83|84|85|86|87|31|32|33|34|35|37|38|71|73|74|75|77|79|61|62|63|64|65|66|67|68|69|49|51|53|54|55)\d{2}\) )[6789]\d{3}\-\d{4}$

It got a little long, simplified to explain how it works, it would be something like this:

^(\((11|21)\) 9|\((?!11|21)\d{2}\) )[6789]\d{3}\-\d{4}$
     ^        ^    ^                 ^     ^
     1        2    3                 4     5
  1. Checks if it starts with Ddds from the ninth-digit list
  2. Checks if the number starts with the ninth digit if it happens to be one of the Ddds in the list
  3. Checks if the number does not start with the Ddds in the list and also should not have the ninth digit
  4. Check if the phone number starts with 6, 7, 8, 9, 96, 97, 98 or 99
  5. Checks if the rest that comes after the prefix is number

In this second example only accepts Ddds 11 and 21 for phone with the ninth digit and if you do not have the ninth digit it only accepts those has not DDD 21 and 11.

A check function would be something like:

<?php
function validarCelular($celular)
{
    static $regex;

    if ($regex === null) {
        //Coloquei em um array para identificar melhor
        $ddds = implode('|', array(
            11, 12, 13, 14, 15, 16, 17, 18, 19,
            21, 22, 24, 27, 28,
            91, 92, 93, 94, 95,
            81, 82, 83, 84, 85, 86, 87,
            31, 32, 33, 34, 35, 37, 38,
            71, 73, 74, 75, 77, 79,
            61, 62, 63, 64, 65, 66, 67, 68, 69,
            49, 51, 53, 54, 55
        ));

        //Gera a regex
        $regex = '#^(\((' . $ddds . ')\) 9|\((?!' . $ddds . ')\d{2}\) )[6789]\d{3}-\d{4}$#';
    }

    return preg_match($regex, $celular) > 0;
}

$celular = '(21) 98765-4321';

if (validarCelular($celular)) {
     echo 'Validou';
} else {
     echo 'Não validou';
}
  • 1

    What is this @Guilhermenascimento? 11|12|13|14|15|16|17|18|19|21|22|24|27|28|91|92|93|94|95|81|82|83|84|85|86|87|31|32|33|34|35|37|38|71|73|74|75|77|79|61|62|63|64|65|66|67|68|69|49|51|53|54|55, uses like this ([1356789][1345])|([123689]2)|([167][79])|([16][68])|([23][78])|(8[67])|(2[14])|49

  • 1

    @Guilhermelautert I thought about it, the problem is the question Anatel add something new, so I isolated it in an array. But it’s still a great tip :)

  • Ah understood good idea :D

  • I did some tests your regex didn’t work

  • Caro @Brunor didn’t work as? Agree that it didn’t work is quite ambiguous? Did you give any error? Tested with PHP? What value did you pass? Do you have spaces at the end and start of the string passed in value? GIVE details, if it is not impossible to help, and I really want to help you.

  • @Guilhermenascimento calm young, I tested ta equal in the example, of 2 ways, that would be only for cell phones. 1 = (82) 6 9926-5288 & 2 = (88) 8 8888-8888.

  • @Guilhermenascimento I’m out of time now, I’m implementing an API, finally will be the space ? that gave problem ? I will leave this page open and when I have time I will make a post with a phone validation function more transante than its _(ツ)_/

  • @Guilhermenascimento you’re right my dear, is not the function I needed, you just met the need of the guy who asked the question, finally my mistake and by this error of +1 in your answer.

  • 1

    Dear @Brunor Now that I looked more calmly, your phones have nothing to do with ANATEL, so you tried to use something for a specific purpose, type nine, there’s no way something specific works everywhere, regex is amazing, but it’s not magic, ask a question I’ll suggest an example of specific answer for your need ;)

Show 4 more comments

6

Friend, some time ago I used the following regex to make its validation:

(\(?\d{2}\)?) ?9?\d{4}-?\d{4}

I added the same to the regexr community: http://regexr.com/3emuj

I hope I’ve helped.

P.S.: You can insert this regex into the Pattern attribute of the phone input to perform a client-side validation.

Edit:

Example of using regex with the function preg_match():

<?php
$telefone = '(21) 98765-4321';
if (preg_match('/(\(?\d{2}\)?) ?9?\d{4}-?\d{4}/', $telefone)) {
    echo "O telefone passou na validação";
} else {
    echo "O telefone não passou na validação";
}
?>

You can find more examples in the preg_match() function page in the official PHP documentation:

http://php.net/manual/en/function.preg-match.php

  • Sorry, I don’t have much experience with regex, I played a preg_match and returned: preg_match(): Unknown Modifier '?' in

  • Opa amigo: try using /[EXPRESSION]/g, I will add a line in the answer to better illustrate.

  • Gave it now: preg_match(): Unknown Modifier 'g' I used the example you updated the reply.

  • @NGTHM4R3, guy fixed the answer code. This time I tested locally. Sorry about /g, I switched the balls with the Javascript string.replace().

  • Thanks, I tested, but he’s accepting more numbers than the maximum.

  • What do you mean more numbers than the maximum? @NGTHM4R3

  • 2

    Renoir is missing the ^...$, so it’s accepting "more numbers than the maximum", as @NGTHM4R3 said, this should solve preg_match('/^(\(?\d{2}\)?) ?9?\d{4}-?\d{4}$/', $telefone)

  • William, I tried to use the preg_match_all to get all the numbers of a text with this regex and did not return anything, why?

Show 3 more comments

2

Renoir Dos Reis' answer is a little off, I made a few minor changes

^((\(\d{2}\))|\d{2}) ?9?\d{4}-?\d{4}$

the ^ at the beginning means that the expression must begin there and the $ means you have to end up there. The way you were would accept any string that contained a phone in the middle, sfsjkahfsjka2199999999vsjkv would pass for correct.

Includes the |\d{2} and removed the ? of parents. The | means or so you accept so much (21)9999-9999 how much 21 9999-9999, but does not accept (219999-9999 nor 21)9999-9999. As it was before the parentheses were individually optional, now if one of the parentheses must have the other.

0

You can use the following rule:

$exp_regular = '^(\(11\) [9][0-9]{4}-[0-9]{4})|(\(1[2-9]\) [5-9][0-9]{3}-[0-9]{4})|(\([2-9][1-9]\) [5-9][0-9]{3}-[0-9]{4})$';
$ret = preg_match($exp_regular, $phone);

preg_match($exp_regular, '(11) 92222-2222');
preg_match($exp_regular, '(43) 8222-2222');
  • The ninth digit is already national since the beginning of the month, all states already use: http://www.tim.com.br/mg/nonodigito

  • I didn’t know, I’m even from Paraná and here there hasn’t been much talk about it......

  • Returned to me: preg_match(): No ending delimiter ' ' found in, I put it at the end, it only worked for 9 digits.

  • Being regex gives to simplify much more and other is not only the ddd that has 9 digits, almost all states of Brazil have adopted, I think that lack few

Browser other questions tagged

You are not signed in. Login or sign up in order to post.