How to validate phone in php

Asked

Viewed 11,400 times

5

I’m trying to validate the phone number, both landline and mobile, and I’m trying to do so no matter how the user writes:

11965453789

(11)965453789

(11) 965453789

(11) 96545-3789

It will always save in the database and show back to the user in this format: (11)965453789.

How do I do this in php?

  • Normally I put only one mask, so the user is forced to type only numbers and in the format I need... http://digitalbush.com/projects/masked-input-plugin/

7 answers

8

I think you need a regex like this: /\(?\d{2}\)?\s?\d{5}\-?\d{4}/

Example: https://regex101.com/r/hB8dH7/1

Nessa regex:

  • \ is to escape some special characters that without this \ have another feature. Escapes with \ are the very character.
  • ? I mean optional, there may or may not be.
  • {n} means "the previous character" exactly n times.

You can still use ^ at the beginning and $ at the end to ensure that there is nothing Resp. before or after. In that case the regex would be /^\(?\d{2}\)?\s?\d{5}\-?\d{4}$/.

To apply this regex in PHP you can do so:

if(preg_match("/\(?\d{2}\)?\s?\d{5}\-?\d{4}/", $phone)) {
  // o telefone é válido
}

8


I use this function to validate phone:

function celular($telefone){
    $telefone= trim(str_replace('/', '', str_replace(' ', '', str_replace('-', '', str_replace(')', '', str_replace('(', '', $telefone))))));

    $regexTelefone = "^[0-9]{11}$";

    //$regexCel = '/[0-9]{2}[6789][0-9]{3,4}[0-9]{4}/'; // Regex para validar somente celular
    if (preg_match($regexCel, $telefone)) {
        return true;
    }else{
        return false;
    }
}
  • 2

    Good approach ignore the ()-. You could have at the end return !!preg_match($regexCel, $telefone); and avoid if/Else. However +1.

  • Thank you I’ll test here

  • 1

    It’s really @Sergio is because before I had some codes inside the if, but I could have just returned the preg_match.

2

If you want to let the user enter the number freely and apply sanitization:

// número que o usuário digitou
$n = '(11) 456-456-4567';

// faz um cast para o tipo numérico inteiro.
// isso quer dizer que tudo que não for numérico, incluindo pontos, será removido.
$n = (int)$n;

//mostra resultado da sanitização
echo $n;
//output 114564564567

Once done, just save to the database or any other location you wish.

When displaying you can apply some mask, preferably, using Javascript.

Validation

For validation, you can check by string size.

This will also depend on how you receive the data. For example, if you receive the number’s separate area code, it already makes validation a little easier.

Cell phones have 11 digits, normally. So a validation could be done like this

if (strlen($n) == 11) {
    // provavelmente é número mobile
}

Mask

Example of geńerica mask in PHP /a/82687/4793

Javascript generic mask example /a/55235/4793

I particularly prefer this way more free because the user gets angry with masks and validations that do not tolerate data entry with sanitization.

Auto format while typing

The masks, especially when applied in Runtime, auto formatting at the time you type, often ends up disrupting the experience of using the site by the user. Even worse when the mask presents some bug that prevents the user from completing a form and this is very common. on many websites.

Upside

The solution proposed above aims at the reuse of codes.

The subject here is specific about phone numbers, however, can apply this same routine for several other types like ZIP code, CPF, CNPJ, serial numbers, anyway, any type of number with any type of formatting.

1

I made this implementation simple in a single line function:

Here for phone of any kind:

function validaTelefone($t){
     return (bool) preg_match('/[0-9]{10,11}/', preg_replace('/\D/', '', $t));
}

Here only for cell phones who have the 9th (ninth) digit filled in:

function validaCelular($c){
     return (bool) preg_match('/[0-9]{2}[9][6789][0-9]{3}[0-9]{4}/', preg_replace('/\D/', '', $c));
}

1

After having consulted this page and started to draft a gambiarra, I noticed that I had in the "trunk" a function ready... And looking above I notice that the foundation has already been given here by @Danielomine, remembering that cell phone with DDD has 11 digits and fixed 10 digits. PS: no DDD are 9 and 8 respectively.

It was more or less in the year 2000 that Brazilian telephones started to have 8 digits, and between 2010 and 2013 that all cellulars started to have 9 digits. See anatel standards.

The generic algorithm of interpretation of a supposed telephone string expressed in free text is based on the Anatel standard... It’s just a little more complicated because it needs to give context and know how to differentiate cases with and without IDD and IDD.


To whom it may interest... Algorithm that "sanitizes" telephone data typed, written (in PL/SQL) and validated years ago... I’ll update if I find something better later (leaving now in Wiki for you to edit).

CREATE or replace FUNCTION lib.get_string_tel(text) RETURNS text AS $f$
  SELECT regexp_replace(
      $1
      ,'^.*?((\+?55[\s-]|\+\d\d[\s-])?\s*\(?\d\d\)?[\s\-\.]*\d[\.\s]?\d\d[\d\s\.\-]+).*?$'
      ,'\1'
    )
$f$ LANGUAGE SQL IMMUTABLE;
CREATE or replace FUNCTION lib.telbr_split(
  p_tel text  -- a string contendo o telefone 
  ,p_pode_ddi boolean DEFAULT true -- deixa preceder 55?
  ,p_ddd_default text DEFAULT '11' -- contexto Sampa
  ,p_max int DEFAULT 21  -- tamaho  máximo da string para remover outros dígitos
) RETURNS text[] AS $f$
DECLARE
  basenum text;
  digits text;
  len int;
  ret text[];
BEGIN
  basenum := trim(p_tel);
  IF length(basenum)>p_max THEN
    basenum := lib.get_string_tel(basenum);
  END IF;
  digits := lib.digits(basenum);
  IF p_pode_ddi THEN
    IF length(digits)>=14 THEN
      basenum := regexp_replace(basenum,'^[^\d]*\d\d','');
      digits := lib.digits(basenum);
    ELSEIF length(digits)>=12 AND substr(digits,1,2)='55' THEN
      basenum := regexp_replace(basenum,'^[^\d]*55','');
      digits := lib.digits(basenum);
    END IF;
  END IF;
  digits := regexp_replace(digits,'^0+','');
  len := length(digits);
  IF len<=9 THEN
    digits := p_ddd_default||digits;
  END IF;
  RETURN array[substr(digits,1,2), substr(digits,3)];
END
$f$ LANGUAGE PLpgSQL IMMUTABLE;

The first function does extraction of the string apparently containing a phone number in the free text medium.
For example the other day registered Iphone 6s plus (11) 9 1234-5678 as phone number one of those Google forms.

The second is that it actually normalizes and explodes the number two parts, DDD and number.

The PL/SQL language (Postgresql or Oracle bases) is almost a Pascal, very easy to convert to PHP, Javascript, etc. Just have patience.

0

Use this code that uses preg_match to validate and preg_replace to fix.

$validacao = "^\(?(\d{2})\)?\b+(\d{5})\-?(\d{4})$";
if (preg_match($validacao, $telefone)){
    $telefone = preg_replace($validacao, "($1)$2$3", $telefone);
} else {
    //Acao para erro de validacao
}

0

Hello! Here’s a PHP function that solves the problem of cell phone and landline validation, no matter what format the user writes, including checking that DD and phone number can start with zero..

function validarTelefoneCelularEFixo(string $valor): bool {
    
    //processa a string mantendo apenas números no valor de entrada.
    $valor = preg_replace("/[^0-9]/", "", $valor); 
        
    $lenValor = strlen($valor);
    
    //validando a quantidade de caracteres de telefone fixo ou celular.
    if($lenValor != 10 && $lenValor != 11)
        return false;
    
    //DD e número de telefone não podem começar com zero.
    if($valor[0] == "0" || $valor[2] == "0")
        return false;
    
    return true;
}

# Testes ------------------------------
    
validarTelefoneCelularEFixo("(11) 99110-0000"); //true
validarTelefoneCelularEFixo("11991100000"); //true
validarTelefoneCelularEFixo("(11)3311-0000"); //true
validarTelefoneCelularEFixo("1133110000"); //true
validarTelefoneCelularEFixo("(00) 99000-0000"); //false

Browser other questions tagged

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