Formateo de números de teléfono en PHP


102

Estoy trabajando en una aplicación de SMS y necesito poder convertir el número de teléfono del remitente de +11234567890 a 123-456-7890 para que pueda compararse con los registros en una base de datos MySQL .

Los números se almacenan en el último formato para su uso en cualquier otro lugar del sitio y prefiero no cambiar ese formato, ya que requeriría modificar una gran cantidad de código.

¿Cómo haría esto con PHP?

¡Gracias!


13
ahhhhh .... NOOOO .... ¿¡Por qué estás almacenando números de teléfono así !? como una cuerda? ¡Malo malo malo! Debería almacenarlos como entradas grandes ... requiere menos almacenamiento, índice más rápido, clasificación más rápida
sethvargo

7
no es tanto un problema para almacenar números de teléfono como cadenas (no se puede evitar cuando necesita almacenar +61 (0) 812345678) - pero almacenar un formato específico es un poco complicado (es decir, los separadores) - es mejor formatear en la capa de presentación en lugar de la capa de datos.
HorusKol

3
@NightMICU: esa es 100% la forma incorrecta de hacerlo ... Debería almacenar como un número entero y tener una función reutilizable que
formatee

228
Almacenar números de teléfono como números enteros para ahorrar espacio de almacenamiento es una idea horrible. Los números de teléfono no son números en el sentido general en el que harás cálculos matemáticos con ellos. En el momento en que tenga que almacenar números fuera de un formato específico de EE. UU. Donde el número puede comenzar con un 0, encontrará problemas. Es mejor almacenar esta información como una cadena.
Charles Sprayberry

2
@NightMICU Si te hace sentir mejor almacenar como cadena, incluso el gran Jon Skeet dice que no almacenes como números enteros para el problema del cero a la izquierda. stackoverflow.com/a/3483166/746010
Charles Sprayberry

Respuestas:


109
$data = '+11234567890';

if(  preg_match( '/^\+\d(\d{3})(\d{3})(\d{4})$/', $data,  $matches ) )
{
    $result = $matches[1] . '-' .$matches[2] . '-' . $matches[3];
    return $result;
}

Para capturar posibles espacios y otros formatos de números internacionales: / ^ (\ +? \ D {1,2}?) [.-]? (? (\ D {3}))? [.-]? (\ D {3}) [.-]? (\ D {4}) $ /
TeckniX

3
@stoutie estás equivocado, $ coincide con [0] es el texto completo del patrón coincidente, entonces necesitas array_shift ($ coincide con) antes de usarlo de esa manera.
Alexandre Reis Ribeiro

¿Sería más rápido formatear esto en la salida? ¿Usando sprintfo `` printf ''? Alguien, por favor, explícamelo. Estoy trabajando con números de teléfono exclusivos de EE. UU. Y no creo que ejecutarlos a través de una función de salida usando una subcadena sea el mejor método.
Rafael

Creo que SO debería incluir votos negativos en los comentarios. El comentario de @Stoutie es engañoso.
peterchaula

1
Pido disculpas por mis comentarios erróneos antes del día anterior a tdd que publiqué hace tantos años. Prometo hacerlo mejor en el futuro. El comentario al que hace referencia parece haber sido eliminado. Todo está bien. Felices vacaciones.
Stoutie

164

Este es un formateador de teléfonos de EE. UU. Que funciona con más versiones de números que cualquiera de las respuestas actuales.

$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";
}

Y aquí hay un desglose de la expresión regular:

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 ")"

Actualizado: 11 de marzo de 2015 para usar en {0,7}lugar de{,7}


¿Qué pasa si el número de teléfono tiene una extensión?
SpYk3HH

1
Buen punto: ¿tenemos algunos ejemplos de cómo se ven las extensiones en todo el mundo? Proabaly algo así ~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})(?:[ \D#\-]*(\d{3,6}))?.*~.
Xeoncross

1
¿Qué pasa si los usuarios de mi sitio web han omitido el código de área?
skibulk

¿Podemos obtener un desglose de lo que están haciendo las diversas partes de la expresión regular (como se muestra a continuación en otra respuesta)? ie: (\d{3}) // 3 digits [\d]// carácter que no es un dígito
roberthuttinger

1
@WesleyMurch Parece haber un cambio en la coincidencia de expresiones regulares que ahora {,7}debe actualizarse {0,7}. Actualicé el código.
Xeoncross

55

Esta función formateará números de teléfono internacionales (más de 10 dígitos), no internacionales (10 dígitos) o de la vieja escuela (7 dígitos). Cualquier número que no sea 10+, 10 o 7 dígitos permanecerá sin formato.

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;
}

Esto es genial, pero me gustaría señalar que los paréntesis alrededor del código de área implican números opcionales. La mayoría de las jurisdicciones ya no consideran que el código de área sea opcional, por lo que separar con un guion simple es más preciso.
Vincent

30

Suponiendo que sus números de teléfono siempre tengan este formato exacto, puede usar este fragmento:

$from = "+11234567890";
$to = sprintf("%s-%s-%s",
              substr($from, 2, 3),
              substr($from, 5, 3),
              substr($from, 8));

Simplemente repita el $ to var ... Me encanta, funcionó para mí solo prefecto.
Samuel Ramzan

22

Los números de teléfono son difíciles. Para una solución internacional más sólida, recomendaría este puerto PHP bien mantenido de la biblioteca libphonenumber de Google .

Usándolo así,

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
}

obtendrá el siguiente resultado:

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

Recomendaría usar el E164formato para cheques duplicados. También puede verificar si el número es realmente un número de móvil o no (usando PhoneNumberUtil::getNumberType()), o si es incluso un número de EE.UU. (usando PhoneNumberUtil::getRegionCodeForNumber()).

Como beneficio adicional, la biblioteca puede manejar prácticamente cualquier entrada. Si, por ejemplo, elige ejecutar 1-800-JETBLUEel código anterior, obtendrá

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

Neato.

Funciona igual de bien para países que no sean EE. UU. Simplemente use otro código de país ISO en el parse()argumento.


2
Gran biblioteca, pero tenga en cuenta que tiene 37 MB y 1500 archivos. En mi caso, tengo un número limitado de números de teléfono para formatear, así que decidí agregar una number_formattedcolumna en mi base de datos e ingresar manualmente los números formateados. Sin embargo, todavía lo uso libphonenumberlocalmente para generar los números formateados, pero incluir una biblioteca tan grande para mi pequeño proyecto es simplemente excesivo.
Magnus W

9

Aquí está mi solución exclusiva para EE. UU., Con el código de área como componente opcional, el delimitador requerido para la extensión y comentarios de expresiones regulares:

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;
}

Y aquí está el script para probarlo:

$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");
}

5

Aquí hay una función simple para formatear números de teléfono con 7 a 10 dígitos de una manera más europea (¿o 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;
}

5

¡No reinventes la rueda! Importe esta increíble biblioteca:
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);

Se basa en la biblioteca de Google para analizar, formatear y validar números de teléfono internacionales: https://github.com/google/libphonenumber


3
Creo que esta es una respuesta válida, pero si desea que sea útil según los estándares de Stack Overflow, entonces debe editar para incluir un ejemplo que resuelva el problema de OP usando la biblioteca en lugar de simplemente compartir un enlace.
Alecg_O

1
¡Gracias @Alecg_O! He añadido un ejemplo.
Viktor Jarnheimer

4

Veo que esto es posible usando algunas expresiones regulares o algunas llamadas a substr (asumiendo que la entrada es siempre de ese formato y no cambia la longitud, etc.)

algo como

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

Deberías hacerlo.


4

Es más rápido que RegEx.

$input = "0987654321"; 

$output = substr($input, -10, -7) . "-" . substr($input, -7, -4) . "-" . substr($input, -4); 
echo $output;

1
Corto y dulce (y).
rahim.nagori

2

Prueba algo como:

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

esto tomaría $ number de 8881112222y se convertiría en 888-111-2222. Espero que esto ayude.


1
Fuente de su sugerencia: hotscripts.com/forums/php/36805-php-format-phone-numbers.html . El str_replace de '.'también debe actualizarse '-'o eliminarse. Se incluyó debido al caso de uso particular al que se enfrentó: con muy poco esfuerzo podría haberlo convertido preg_replace('/\d{3}/', '$0-', substr($number, 2))y responder la pregunta directamente.
Iiridayn

2

Otra opción: actualizar fácilmente para recibir un formato de la configuración.

$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;
}

1

Todas,

Creo que lo arreglé. ¡Trabaja para archivos de entrada actuales y tiene las siguientes 2 funciones para hacer esto!

función 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

función 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 tengo esto en una clase lib, por lo que la llamada "self :: validate_phone_number" de la primera función / método.

Observe la línea # 32 de la función "validate_phone_number" donde agregué:

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

para obtener la devolución falsa necesaria si no es un número de teléfono válido.

Todavía necesito probar esto con más datos, pero trabajando con datos actuales, con el formato actual y estoy usando el estilo '8' para este lote de datos en particular.

También comenté la lógica de la "extensión", ya que constantemente recibía errores, ya que no tengo ninguna de esa información en mis datos.


1

esto toma 7, 10 y 11 dígitos, elimina caracteres adicionales y agrega guiones yendo de derecha a izquierda a través de la cadena. cambie el guión a un espacio o un punto.

$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;

1

Sé que el OP está solicitando un formato 123-456-7890, pero, según la respuesta de John Dul , lo modifiqué para devolver el número de teléfono entre paréntesis, por ejemplo, (123) 456-7890. Este solo maneja números de 7 y 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;
}

1

Aquí está mi opinión:

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

//  123-456-7890

La sscanffunción toma como segundo parámetro una cadena de formato que le indica cómo interpretar los caracteres de la primera cadena. En este caso, significa 2 caracteres (%2c ), 3 caracteres, 3 caracteres, 4 caracteres.

Normalmente, la sscanffunción también incluiría variables para capturar los datos extraídos. Si no, los datos se devuelven en una matriz que he llamado$parts .

La printdeclaración genera la cadena interpolada.$part[0]se ignora.

He utilizado una función similar para formatear números de teléfono australianos.

Tenga en cuenta que desde la perspectiva de almacenar el número de teléfono:

  • los números de teléfono son cadenas
  • Los datos almacenados no deben incluir formato, como espacios o guiones.

Esta es la solución más elegante y legible. BESO. No te desplaces más si tus cadenas de entrada siempre siguen exactamente el mismo patrón. Gracias por esta adición.
Musa

1

Formatos de teléfono del Reino Unido

Para la aplicación que desarrollé, descubrí que las personas ingresaban su número de teléfono "correctamente" desde un formulario legible por humanos, pero insertaban varios caracteres aleatorios como "-" / "+44", etc. El problema era que la aplicación en la nube que necesitaba hablar con un formato bastante específico. En lugar de usar una expresión regular (puede ser frustrante para el usuario), creé una clase de objeto que procesa el número ingresado en el formato correcto antes de ser procesado por el módulo de persistencia.

El formato de la salida asegura que cualquier software receptor interprete la salida como texto en lugar de un entero (que luego perdería inmediatamente el cero inicial) y el formato es consistente con British Telecoms. directrices sobre el formato de números, que también ayuda a la memorización humana al dividir un número largo en grupos pequeños y fáciles de memorizar.


+441234567890 produce (01234) 567 890
02012345678 produce (020) 1234 5678
1923123456 produce (01923) 123456
01923123456 produce (01923) 123456
01923 hola este es texto123456 produce (01923) 123456

La importancia del segmento de intercambio del número, entre paréntesis, es que en el Reino Unido y la mayoría de los demás países, las llamadas entre números del mismo intercambio se pueden realizar omitiendo el segmento de intercambio. Sin embargo, esto no se aplica a los números de teléfono de las series 07, 08 y 09.

Estoy seguro de que existen soluciones más eficientes, pero esta ha demostrado ser extremadamente confiable. Se pueden acomodar más formatos fácilmente agregando a la función teleNum al final.

El procedimiento se invoca desde el script de llamada, por lo que

$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;
    }
}

0

Esto es para teléfonos fijos del Reino Unido sin el código de 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

0

Por favor, eche un vistazo a la función basada en substr que puede cambiar 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);
}

0

Verifique el número de teléfono

$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;
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.