Formatando números de telefone em PHP

101

Estou trabalhando em um aplicativo de SMS e preciso converter o número de telefone do remetente de +11234567890 para 123-456-7890 para que possa ser comparado aos registros em um banco de dados MySQL .

Os números são armazenados no último formato para uso em outro lugar no site e eu prefiro não alterar esse formato, pois isso exigiria a modificação de muito código.

Como eu faria isso com o PHP?

Obrigado!

NightMICU
fonte
13
ahhhhh .... NÃOOOO .... por que você está armazenando números de telefone assim !? como uma string? Mau Mau Mau! Você deve armazená-los como grandes ints ... menos armazenamento necessário, índice mais rápido, classificação mais rápida
sethvargo
7
não é tanto um problema em armazenar números de telefone como strings (não pode ser evitado quando você precisa armazenar +61 (0) 812345678) - mas armazenar um formato específico é um pouco duvidoso (ou seja, os separadores) - melhor fazer a formatação na camada de apresentação, e não na camada de dados.
HorusKol
3
@NightMICU - essa é 100% a maneira errada de fazer isso ... Você deve armazenar como um número inteiro e ter uma função reutilizável que formata para exibição
sethvargo
227
Armazenar números de telefone como inteiros para economizar espaço de armazenamento é uma ideia horrível. Os números de telefone não são números no sentido geral de que você fará contas com eles. No momento em que você tiver que armazenar números fora de um formato específico dos EUA, onde o número pode começar com 0, você encontrará problemas. Melhor armazenar essas informações como uma string.
Charles Sprayberry
2
@NightMICU Se isso faz você se sentir melhor em armazenar como string, mesmo o grande Jon Skeet diz para não armazenar como inteiro para o problema do zero à esquerda. stackoverflow.com/a/3483166/746010
Charles Sprayberry

Respostas:

108
$data = '+11234567890';

if(  preg_match( '/^\+\d(\d{3})(\d{3})(\d{4})$/', $data,  $matches ) )
{
    $result = $matches[1] . '-' .$matches[2] . '-' . $matches[3];
    return $result;
}
slier
fonte
Para capturar espaços possíveis e outros formatos de números internacionais: / ^ (\ +? \ D {1,2}?) [.-]? (? (\ D {3}))? [.-]? (\ D {3}) [.-]? (\ D {4}) $ /
TeckniX
3
@stoutie você está errado, $ coincide com [0] é todo o texto do padrão combinado, então você precisa array_shift ($ coincide) antes de usá-lo dessa forma.
Alexandre Reis Ribeiro
Seria mais rápido formatar isso na saída? Usando sprintfou `printf``? Alguém, por favor, me explique. Estou trabalhando apenas com números de telefone dos EUA e não acho que executá-los por meio de uma função de saída usando substring seja o melhor método.
Rafael
Eu acho que o SO deve incluir downvotes nos comentários. O comentário de @Stoutie é enganoso.
peterchaula
1
Peço desculpas por ter postado comentários errôneos antes do dia do tdd, há tantos anos. Eu prometo fazer melhor no futuro. O comentário ao qual você faz referência parece ter sido excluído. Tudo está bem. Boas festas.
Stoutie
163

Este é um formatador de telefone dos EUA que funciona em mais versões de números do que qualquer uma das respostas atuais.

$numbers = explode("\n", '(111) 222-3333
((111) 222-3333
1112223333
111 222-3333
111-222-3333
(111)2223333
+11234567890
    1-8002353551
    123-456-7890   -Hello!
+1 - 1234567890 
');


foreach($numbers as $number)
{
    print preg_replace('~.*(\d{3})[^\d]{0,7}(\d{3})[^\d]{0,7}(\d{4}).*~', '($1) $2-$3', $number). "\n";
}

E aqui está uma análise da regex:

Cell: +1 999-(555 0001)

.*          zero or more of anything "Cell: +1 "
(\d{3})     three digits "999"
[^\d]{0,7}  zero or up to 7 of something not a digit "-("
(\d{3})     three digits "555"
[^\d]{0,7}  zero or up to 7 of something not a digit " "
(\d{4})     four digits "0001"
.*          zero or more of anything ")"

Atualizado: 11 de março de 2015 para usar em {0,7}vez de{,7}

Xeoncross
fonte
E se o número de telefone tiver um ramal?
SpYk3HH
1
Bom ponto - temos alguns exemplos de como as extensões parecem ao redor do mundo? Proabaly algo parecido ~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})(?:[ \D#\-]*(\d{3,6}))?.*~.
Xeoncross
1
E se os usuários do meu site não tiverem o código de área?
skibulk
Podemos obter uma análise do que as várias partes da regex estão fazendo (conforme mostrado abaixo em outra resposta)? ie: (\d{3}) // 3 digits [\d]// caractere que não é um dígito
roberthuttinger
1
@WesleyMurch Parece haver uma mudança na correspondência de expressão regular que agora requer {,7}atualização {0,7}. Eu atualizei o código.
Xeoncross
55

Esta função formatará números de telefone internacionais (10+ dígitos), não internacionais (10 dígitos) ou da velha escola (7 dígitos). Qualquer número diferente de 10+, 10 ou 7 dígitos permanecerá sem formatação.

function formatPhoneNumber($phoneNumber) {
    $phoneNumber = preg_replace('/[^0-9]/','',$phoneNumber);

    if(strlen($phoneNumber) > 10) {
        $countryCode = substr($phoneNumber, 0, strlen($phoneNumber)-10);
        $areaCode = substr($phoneNumber, -10, 3);
        $nextThree = substr($phoneNumber, -7, 3);
        $lastFour = substr($phoneNumber, -4, 4);

        $phoneNumber = '+'.$countryCode.' ('.$areaCode.') '.$nextThree.'-'.$lastFour;
    }
    else if(strlen($phoneNumber) == 10) {
        $areaCode = substr($phoneNumber, 0, 3);
        $nextThree = substr($phoneNumber, 3, 3);
        $lastFour = substr($phoneNumber, 6, 4);

        $phoneNumber = '('.$areaCode.') '.$nextThree.'-'.$lastFour;
    }
    else if(strlen($phoneNumber) == 7) {
        $nextThree = substr($phoneNumber, 0, 3);
        $lastFour = substr($phoneNumber, 3, 4);

        $phoneNumber = $nextThree.'-'.$lastFour;
    }

    return $phoneNumber;
}
Bryan Schoen
fonte
Isso é ótimo, mas gostaria apenas de salientar que os parênteses ao redor do código de área implicam em números opcionais. A maioria das jurisdições não considera mais o código de área opcional, portanto, separar com um hífen simples é mais preciso.
Vincent
30

Supondo que seus números de telefone sempre tenham este formato exato, você pode usar este snippet:

$from = "+11234567890";
$to = sprintf("%s-%s-%s",
              substr($from, 2, 3),
              substr($from, 5, 3),
              substr($from, 8));
Daniel Hepper
fonte
Basta ecoar o $ to var ... Adorei, funcionou para mim apenas prefeito.
Samuel Ramzan
22

Os números de telefone são difíceis. Para uma solução internacional mais robusta, eu recomendaria esta porta PHP bem mantida da biblioteca libphonenumber do Google .

Usando assim,

use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;

$phoneUtil = PhoneNumberUtil::getInstance();

$numberString = "+12123456789";

try {
    $numberPrototype = $phoneUtil->parse($numberString, "US");

    echo "Input: " .          $numberString . "\n";
    echo "isValid: " .       ($phoneUtil->isValidNumber($numberPrototype) ? "true" : "false") . "\n";
    echo "E164: " .           $phoneUtil->format($numberPrototype, PhoneNumberFormat::E164) . "\n";
    echo "National: " .       $phoneUtil->format($numberPrototype, PhoneNumberFormat::NATIONAL) . "\n";
    echo "International: " .  $phoneUtil->format($numberPrototype, PhoneNumberFormat::INTERNATIONAL) . "\n";
} catch (NumberParseException $e) {
    // handle any errors
}

você obterá a seguinte saída:

Input: +12123456789
isValid: true
E164: +12123456789
National: (212) 345-6789
International: +1 212-345-6789

Eu recomendo usar o E164formato para cheques duplicados. Você também pode verificar se o número é realmente um número de celular ou não (usando PhoneNumberUtil::getNumberType()), ou se é mesmo um número dos EUA (usando PhoneNumberUtil::getRegionCodeForNumber()).

Como um bônus, a biblioteca pode lidar com praticamente qualquer entrada. Se você, por exemplo, escolher executar 1-800-JETBLUEo código acima, obterá

Input: 1-800-JETBLUE
isValid: true
E164: +18005382583
National: (800) 538-2583
International: +1 800-538-2583

Neato.

Funciona tão bem para outros países além dos EUA. Basta usar outro código de país ISO no parse()argumento.

likeitlikeit
fonte
2
Ótima biblioteca, mas note que ela tem 37 MB e 1500 arquivos! No meu caso, tenho um número limitado de números de telefone para formatar, então decidi apenas adicionar uma number_formattedcoluna em meu banco de dados e inserir manualmente os números formatados. Ainda uso libphonenumberlocalmente para gerar os números formatados, mas incluir uma biblioteca tão grande para meu pequeno projeto é um exagero.
Magnus W
9

Esta é minha solução apenas para os EUA, com o código de área como um componente opcional, delimitador obrigatório para a extensão e comentários de regex:

function formatPhoneNumber($s) {
$rx = "/
    (1)?\D*     # optional country code
    (\d{3})?\D* # optional area code
    (\d{3})\D*  # first three
    (\d{4})     # last four
    (?:\D+|$)   # extension delimiter or EOL
    (\d*)       # optional extension
/x";
preg_match($rx, $s, $matches);
if(!isset($matches[0])) return false;

$country = $matches[1];
$area = $matches[2];
$three = $matches[3];
$four = $matches[4];
$ext = $matches[5];

$out = "$three-$four";
if(!empty($area)) $out = "$area-$out";
if(!empty($country)) $out = "+$country-$out";
if(!empty($ext)) $out .= "x$ext";

// check that no digits were truncated
// if (preg_replace('/\D/', '', $s) != preg_replace('/\D/', '', $out)) return false;
return $out;
}

E aqui está o script para testá-lo:

$numbers = [
'3334444',
'2223334444',
'12223334444',
'12223334444x5555',
'333-4444',
'(222)333-4444',
'+1 222-333-4444',
'1-222-333-4444ext555',
'cell: (222) 333-4444',
'(222) 333-4444 (cell)',
];

foreach($numbers as $number) {
    print(formatPhoneNumber($number)."<br>\r\n");
}
skibulk
fonte
5

Esta é uma função simples para formatar números de telefone com 7 a 10 dígitos de uma maneira mais europeia (ou sueca?):

function formatPhone($num) {
    $num = preg_replace('/[^0-9]/', '', $num);
    $len = strlen($num);

    if($len == 7) $num = preg_replace('/([0-9]{2})([0-9]{2})([0-9]{3})/', '$1 $2 $3', $num);
    elseif($len == 8) $num = preg_replace('/([0-9]{3})([0-9]{2})([0-9]{3})/', '$1 - $2 $3', $num);
    elseif($len == 9) $num = preg_replace('/([0-9]{3})([0-9]{2})([0-9]{2})([0-9]{2})/', '$1 - $2 $3 $4', $num);
    elseif($len == 10) $num = preg_replace('/([0-9]{3})([0-9]{2})([0-9]{2})([0-9]{3})/', '$1 - $2 $3 $4', $num);

    return $num;
}
Zeromatik
fonte
5

Não reinvente a roda! Importe esta biblioteca incrível:
https://github.com/giggsey/libphonenumber-for-php

$defaultCountry = 'SE'; // Based on the country of the user
$phoneUtil = PhoneNumberUtil::getInstance();
$swissNumberProto = $phoneUtil->parse($phoneNumber, $defaultCountry);

return $phoneUtil->format($swissNumberProto, PhoneNumberFormat::INTERNATIONAL);

É baseado na biblioteca do Google para análise, formatação e validação de números de telefone internacionais: https://github.com/google/libphonenumber

Viktor Jarnheimer
fonte
3
Acho que esta é uma resposta válida, mas se você quiser que seja útil de acordo com os padrões do Stack Overflow, você deve editar para incluir um exemplo resolvendo o problema do OP usando a biblioteca em vez de apenas compartilhar um link.
Alecg_O
1
Obrigado @Alecg_O! Eu adicionei um exemplo.
Viktor Jarnheimer
4

Vejo que isso é possível usando algum regex ou algumas chamadas de substr (assumindo que a entrada é sempre desse formato e não muda o comprimento etc.)

algo como

$in = "+11234567890"; $output = substr($in,2,3)."-".substr($in,6,3)."-".substr($in,10,4);

deve fazer isso.

Ali Lown
fonte
4

É mais rápido do que RegEx.

$input = "0987654321"; 

$output = substr($input, -10, -7) . "-" . substr($input, -7, -4) . "-" . substr($input, -4); 
echo $output;
Rishabh
fonte
1
Curto e doce (y).
rahim.nagori
2

Experimente algo como:

preg_replace('/\d{3}/', '$0-', str_replace('.', null, trim($number)), 2);

isso levaria um $ número de 8881112222e converter para 888-111-2222. Espero que isto ajude.

RobertPitt
fonte
1
Fonte de sua sugestão: hotscripts.com/forums/php/36805-php-format-phone-numbers.html . O str_replace de '.'também deve ser atualizado '-'ou removido. Ele foi incluído devido ao caso de uso específico enfrentado - com muito pouco esforço, você poderia convertê-lo preg_replace('/\d{3}/', '$0-', substr($number, 2))e responder à pergunta diretamente.
Iiridayn
2

Outra opção - facilmente atualizado para receber um formato da configuração.

$numbers = explode("\n", '(111) 222-3333
((111) 222-3333
1112223333
111 222-3333
111-222-3333
(111)2223333
+11234567890
    1-8002353551
    123-456-7890   -Hello!
+1 - 1234567890
');
foreach( $numbers AS $number ){
  echo comMember_format::phoneNumber($number) . '<br>';
}

// ************************************************************************
// Format Phone Number
public function phoneNumber( $number ){
  $txt = preg_replace('/[\s\-|\.|\(|\)]/','',$number);
  $format = '[$1?$1 :][$2?($2):x][$3: ]$4[$5: ]$6[$7? $7:]';
  if( preg_match('/^(.*)(\d{3})([^\d]*)(\d{3})([^\d]*)(\d{4})([^\d]{0,1}.*)$/', $txt, $matches) ){
    $result = $format;
    foreach( $matches AS $k => $v ){
      $str = preg_match('/\[\$'.$k.'\?(.*?)\:(.*?)\]|\[\$'.$k.'\:(.*?)\]|(\$'.$k.'){1}/', $format, $filterMatch);
      if( $filterMatch ){
        $result = str_replace( $filterMatch[0], (!isset($filterMatch[3]) ? (strlen($v) ? str_replace( '$'.$k, $v, $filterMatch[1] ) : $filterMatch[2]) : (strlen($v) ? $v : (isset($filterMatch[4]) ? '' : (isset($filterMatch[3]) ? $filterMatch[3] : '')))), $result );
      }
    }
    return $result;
  }
  return $number;
}
David H.
fonte
1

Tudo,

Eu acho que consertei. Trabalhando para arquivos de entrada atuais e tem as 2 funções a seguir para fazer isso!

function format_phone_number:

        function format_phone_number ( $mynum, $mask ) {
        /*********************************************************************/
        /*   Purpose: Return either masked phone number or false             */
        /*     Masks: Val=1 or xxx xxx xxxx                                             */
        /*            Val=2 or xxx xxx.xxxx                                             */
        /*            Val=3 or xxx.xxx.xxxx                                             */
        /*            Val=4 or (xxx) xxx xxxx                                           */
        /*            Val=5 or (xxx) xxx.xxxx                                           */
        /*            Val=6 or (xxx).xxx.xxxx                                           */
        /*            Val=7 or (xxx) xxx-xxxx                                           */
        /*            Val=8 or (xxx)-xxx-xxxx                                           */
        /*********************************************************************/         
        $val_num        = self::validate_phone_number ( $mynum );
        if ( !$val_num && !is_string ( $mynum ) ) { 
            echo "Number $mynum is not a valid phone number! \n";
            return false;
        }   // end if !$val_num
        if ( ( $mask == 1 ) || ( $mask == 'xxx xxx xxxx' ) ) { 
            $phone = preg_replace('~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4}).*~', 
                    '$1 $2 $3'." \n", $mynum);
            return $phone;
        }   // end if $mask == 1
        if ( ( $mask == 2 ) || ( $mask == 'xxx xxx.xxxx' ) ) { 
            $phone = preg_replace('~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4}).*~', 
                    '$1 $2.$3'." \n", $mynum);
            return $phone;
        }   // end if $mask == 2
        if ( ( $mask == 3 ) || ( $mask == 'xxx.xxx.xxxx' ) ) { 
            $phone = preg_replace('~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4}).*~', 
                    '$1.$2.$3'." \n", $mynum);
            return $phone;
        }   // end if $mask == 3
        if ( ( $mask == 4 ) || ( $mask == '(xxx) xxx xxxx' ) ) { 
            $phone = preg_replace('~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4}).*~', 
                    '($1) $2 $3'." \n", $mynum);
            return $phone;
        }   // end if $mask == 4
        if ( ( $mask == 5 ) || ( $mask == '(xxx) xxx.xxxx' ) ) { 
            $phone = preg_replace('~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4}).*~', 
                    '($1) $2.$3'." \n", $mynum);
            return $phone;
        }   // end if $mask == 5
        if ( ( $mask == 6 ) || ( $mask == '(xxx).xxx.xxxx' ) ) { 
            $phone = preg_replace('~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4}).*~', 
                    '($1).$2.$3'." \n", $mynum);
            return $phone;
        }   // end if $mask == 6
        if ( ( $mask == 7 ) || ( $mask == '(xxx) xxx-xxxx' ) ) { 
            $phone = preg_replace('~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4}).*~', 
                    '($1) $2-$3'." \n", $mynum);
            return $phone;
        }   // end if $mask == 7
        if ( ( $mask == 8 ) || ( $mask == '(xxx)-xxx-xxxx' ) ) { 
            $phone = preg_replace('~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4}).*~', 
                    '($1)-$2-$3'." \n", $mynum);
            return $phone;
        }   // end if $mask == 8
        return false;       // Returns false if no conditions meet or input
    }  // end function format_phone_number

function validate_phone_number:

        function validate_phone_number ( $phone ) {
        /*********************************************************************/
        /*   Purpose:   To determine if the passed string is a valid phone  */
        /*              number following one of the establish formatting        */
        /*                  styles for phone numbers.  This function also breaks    */
        /*                  a valid number into it's respective components of:      */
        /*                          3-digit area code,                                      */
        /*                          3-digit exchange code,                                  */
        /*                          4-digit subscriber number                               */
        /*                  and validates the number against 10 digit US NANPA  */
        /*                  guidelines.                                                         */
        /*********************************************************************/         
        $format_pattern =   '/^(?:(?:\((?=\d{3}\)))?(\d{3})(?:(?<=\(\d{3})\))'.
                                    '?[\s.\/-]?)?(\d{3})[\s\.\/-]?(\d{4})\s?(?:(?:(?:'.
                                    '(?:e|x|ex|ext)\.?\:?|extension\:?)\s?)(?=\d+)'.
                                    '(\d+))?$/';
        $nanpa_pattern      =   '/^(?:1)?(?(?!(37|96))[2-9][0-8][0-9](?<!(11)))?'.
                                    '[2-9][0-9]{2}(?<!(11))[0-9]{4}(?<!(555(01([0-9]'.
                                    '[0-9])|1212)))$/';

        // Init array of variables to false
        $valid = array('format' =>  false,
                            'nanpa' => false,
                            'ext'       => false,
                            'all'       => false);

        //Check data against the format analyzer
        if ( preg_match ( $format_pattern, $phone, $matchset ) ) {
            $valid['format'] = true;    
        }

        //If formatted properly, continue
        //if($valid['format']) {
        if ( !$valid['format'] ) {
            return false;
        } else {
            //Set array of new components
            $components =   array ( 'ac' => $matchset[1], //area code
                                                            'xc' => $matchset[2], //exchange code
                                                            'sn' => $matchset[3] //subscriber number
                                                            );
            //              $components =   array ( 'ac' => $matchset[1], //area code
            //                                              'xc' => $matchset[2], //exchange code
            //                                              'sn' => $matchset[3], //subscriber number
            //                                              'xn' => $matchset[4] //extension number             
            //                                              );

            //Set array of number variants
            $numbers    =   array ( 'original' => $matchset[0],
                                        'stripped' => substr(preg_replace('[\D]', '', $matchset[0]), 0, 10)
                                        );

            //Now let's check the first ten digits against NANPA standards
            if(preg_match($nanpa_pattern, $numbers['stripped'])) {
                $valid['nanpa'] = true;
            }

            //If the NANPA guidelines have been met, continue
            if ( $valid['nanpa'] ) {
                if ( !empty ( $components['xn'] ) ) {
                    if ( preg_match ( '/^[\d]{1,6}$/', $components['xn'] ) ) {
                        $valid['ext'] = true;
                    }   // end if if preg_match 
                } else {
                    $valid['ext'] = true;
                }   // end if if  !empty
            }   // end if $valid nanpa

            //If the extension number is valid or non-existent, continue
            if ( $valid['ext'] ) {
                $valid['all'] = true;
            }   // end if $valid ext
        }   // end if $valid
        return $valid['all'];
    }   // end functon validate_phone_number

Observe que tenho isso em uma classe lib, portanto, a chamada "self :: validate_phone_number" da primeira função / método.

Observe a linha nº 32 da função "validate_phone_number" onde eu adicionei:

            if ( !$valid['format'] ) {
            return false;
        } else {

para obter o falso retorno necessário, se não for um número de telefone válido.

Ainda preciso testar isso com mais dados, mas trabalhando nos dados atuais, com o formato atual e estou usando o estilo '8' para este lote de dados específico.

Também comentei a lógica da "extensão", pois estava constantemente recebendo erros dela, visto que não tenho nenhuma dessas informações em meus dados.

OldManRiver
fonte
1

isto leva 7, 10 e 11 dígitos, remove caracteres adicionais e adiciona travessões indo da direita para a esquerda através da string. mude o traço para um espaço ou ponto.

$raw_phone = preg_replace('/\D/', '', $raw_phone);
$temp = str_split($raw_phone);
$phone_number = "";
for ($x=count($temp)-1;$x>=0;$x--) {
    if ($x === count($temp) - 5 || $x === count($temp) - 8 || $x === count($temp) - 11) {
        $phone_number = "-" . $phone_number;
    }
    $phone_number = $temp[$x] . $phone_number;
}
echo $phone_number;
John Dul
fonte
1

Sei que o OP está solicitando um formato 123-456-7890, mas, com base na resposta de John Dul , modifiquei-o para retornar o número de telefone no formato de parênteses, por exemplo, (123) 456-7890. Este só lida com números de 7 e 10 dígitos.

function format_phone_string( $raw_number ) {

    // remove everything but numbers
    $raw_number = preg_replace( '/\D/', '', $raw_number );

    // split each number into an array
    $arr_number = str_split($raw_number);

    // add a dummy value to the beginning of the array
    array_unshift( $arr_number, 'dummy' );

    // remove the dummy value so now the array keys start at 1
    unset($arr_number[0]);

    // get the number of numbers in the number
    $num_number = count($arr_number);

    // loop through each number backward starting at the end
    for ( $x = $num_number; $x >= 0; $x-- ) {

        if ( $x === $num_number - 4 ) {
            // before the fourth to last number

            $phone_number = "-" . $phone_number;
        }
        else if ( $x === $num_number - 7 && $num_number > 7 ) {
            // before the seventh to last number
            // and only if the number is more than 7 digits

            $phone_number = ") " . $phone_number;
        }
        else if ( $x === $num_number - 10 ) {
            // before the tenth to last number

            $phone_number = "(" . $phone_number;
        }

        // concatenate each number (possibly with modifications) back on
        $phone_number = $arr_number[$x] . $phone_number;
    }

    return $phone_number;
}
Andrew Tibbetts
fonte
1

Aqui está minha opinião:

$phone='+11234567890';
$parts=sscanf($phone,'%2c%3c%3c%4c');
print "$parts[1]-$parts[2]-$parts[3]";

//  123-456-7890

A sscanffunção recebe como um segundo parâmetro uma string de formato informando como interpretar os caracteres da primeira string. Neste caso, significa 2 caracteres ( %2c), 3 caracteres, 3 caracteres, 4 caracteres.

Normalmente, a sscanffunção também incluiria variáveis ​​para capturar os dados extraídos. Caso contrário, os dados são retornados em uma matriz que chamei $parts.

A printinstrução produz a string interpolada. $part[0]é ignorado.

Usei uma função semelhante para formatar números de telefone australianos.

Observe que, da perspectiva de armazenamento do número de telefone:

  • números de telefone são strings
  • os dados armazenados não devem incluir formatação, como espaços ou hifens
Manngo
fonte
Esta é a solução mais elegante e legível. BEIJO. Não role mais se suas strings de entrada sempre seguem exatamente o mesmo padrão. Obrigado por esta adição.
Musa
1

Formatos de telefone do Reino Unido

Para o aplicativo que desenvolvi, descobri que as pessoas inseriram seus números de telefone "corretamente" de uma forma legível por humanos, mas inseriram vários caracteres aleatórios, como "-" / "+44" etc. O problema era que o aplicativo em nuvem que ele precisava conversar era bastante específico sobre o formato. Em vez de usar uma expressão regular (pode ser frustrante para o usuário), criei uma classe de objeto que processa o número inserido no formato correto antes de ser processada pelo módulo de persistência.

O formato da saída garante que qualquer software receptor interprete a saída como texto em vez de um inteiro (que então perderia imediatamente o zero à esquerda) e o formato é consistente com a British Telecoms diretrizes sobre a formatação de números - que também ajuda na memorização humana, dividindo um número longo em grupos pequenos e facilmente memorizáveis.


+441234567890 produz (01234) 567 890
02012345678 produz (020) 1234 5678
1923123456 produz (01923) 123 456
01923123456 produz (01923) 123 456 01923
olá, este é text123456 produz (01923) 123 456

A importância do segmento de troca do número - entre parênteses - é que no Reino Unido, e na maioria dos outros países, as chamadas entre números na mesma central podem ser feitas omitindo o segmento de troca. No entanto, isso não se aplica aos números de telefone das séries 07, 08 e 09.

Tenho certeza de que existem soluções mais eficientes, mas esta se mostrou extremamente confiável. Mais formatos podem ser facilmente acomodados adicionando à função teleNum no final.

O procedimento é invocado a partir do script de chamada, portanto

$telephone = New Telephone;
$formattedPhoneNumber = $telephone->toIntegerForm($num)

`

<?php
class   Telephone 
{   
    public function toIntegerForm($num) {
        /*
         * This section takes the number, whatever its format, and purifies it to just digits without any space or other characters
         * This ensures that the formatter only has one type of input to deal with
         */
        $number = str_replace('+44', '0', $num);
        $length = strlen($number);
        $digits = '';
        $i=0;
        while ($i<$length){
            $digits .= $this->first( substr($number,$i,1) , $i);
            $i++;
        }
        if (strlen($number)<10) {return '';}
        return $this->toTextForm($digits);
    }
    public function toTextForm($number) {

        /*
         * This works on the purified number to then format it according to the group code
         * Numbers starting 01 and 07 are grouped 5 3 3
         * Other numbers are grouped 3 4 4 
         * 
         */
        if (substr($number,0,1) == '+') { return $number; }
        $group = substr($number,0,2);
        switch ($group){
            case "02" :
                $formattedNumber = $this->teleNum($number, 3, 4); // If number commences '02N' then output will be (02N) NNNN NNNN
                break;
            default :
                $formattedNumber = $this->teleNum($number, 5, 3); // Otherwise the ooutput will be (0NNNN) NNN NNN
        }
        return $formattedNumber;

    }
    private function first($digit,$position){
        if ($digit == '+' && $position == 0) {return $digit;};
        if (!is_numeric($digit)){
            return '';
        }
        if ($position == 0) {
            return ($digit == '0' ) ? $digit :  '0'.$digit;
        } else {
            return $digit;
        } 
    }
    private function teleNum($number,$a,$b){
        /*
         * Formats the required output 
         */
        $c=strlen($number)-($a+$b);
        $bit1 = substr($number,0,$a);
        $bit2 = substr($number,$a,$b);
        $bit3 = substr($number,$a+$b,$c);
        return '('.$bit1.') '.$bit2." ".$bit3;
    }
}
Mike M0ITI
fonte
0

Isso é para telefones fixos no Reino Unido sem o código do país

function format_phone_number($number) {
    $result = preg_replace('~.*(\d{2})[^\d]{0,7}(\d{4})[^\d]{0,7}(\d{4}).*~', '$1 $2 $3', $number);
    return $result;
}

Resultado:

2012345678
becomes
20 1234 5678
tipocoder
fonte
0

Por favor, dê uma olhada na função baseada em substr que pode mudar formatos

function phone(string $in): string
{
    $FORMAT_PHONE = [1,3,3,4];
    $result =[];
    $position = 0;
    foreach ($FORMAT_PHONE as $key => $item){
        $result[] = substr($in, $position, $item);
        $position += $item;
    }
    return '+'.implode('-',$result);
}
Yevgeniy Afanasyev
fonte
0

Verifique o número do telefone

$phone = '+385 99 1234 1234'

$str = preg_match('/^\+?\d{1,3}[\s-]?\d{1,3}[\s-]?\d{1,4}[\s-]?\d{1,4}$/', $phone);

if($str){
return true;
}else{
return false;
}
loja fácil
fonte