Formattazione dei numeri di telefono in PHP


102

Sto lavorando su un'app SMS e devo essere in grado di convertire il numero di telefono del mittente da +11234567890 a 123-456-7890 in modo che possa essere paragonato ai record in un database MySQL .

I numeri sono memorizzati in quest'ultimo formato per essere utilizzati altrove sul sito e preferirei non cambiare quel formato in quanto richiederebbe la modifica di molto codice.

Come potrei farlo con PHP?

Grazie!


13
ahhhhh .... NOOOO .... perché memorizzi numeri di telefono in questo modo !? come una stringa? Male male male! Dovresti memorizzarli come big int ... meno spazio di archiviazione richiesto, indice più veloce, ordinamento più veloce
sethvargo

7
non è tanto un problema con la memorizzazione di numeri di telefono come stringhe (non può essere evitato quando è necessario memorizzare +61 (0) 812345678) - ma memorizzare un formato specifico è un po 'rischioso (ad esempio, i separatori) - è meglio fare la formattazione a livello di presentazione piuttosto che a livello di dati.
HorusKol

3
@NightMICU - questo è il modo sbagliato al 100% per farlo ... Dovresti archiviare come numero intero e avere una funzione riutilizzabile che si formatta per la visualizzazione
sethvargo

228
Memorizzare i numeri di telefono come numeri interi per risparmiare spazio di archiviazione è un'idea orribile. I numeri di telefono non sono numeri nel senso generale in cui farai i calcoli su di essi. Nel momento in cui devi memorizzare numeri al di fuori di un formato specifico degli Stati Uniti in cui il numero può iniziare con uno 0, incontrerai problemi. È meglio memorizzare queste informazioni come una stringa.
Charles Sprayberry

2
@NightMICU Se ti fa sentire meglio a memorizzare come stringa, anche il grande Jon Skeet dice di non memorizzare come numero intero per il problema zero iniziale. stackoverflow.com/a/3483166/746010
Charles Sprayberry

Risposte:


109
$data = '+11234567890';

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

Per acquisire possibili spazi e altri formati di numeri internazionali: / ^ (\ +? \ D {1,2}?) [.-]? (? (\ D {3}))? [.-]? (\ D {3}) [.-]? (\ D {4}) $ /
TeckniX

3
@stoutie hai sbagliato, $ corrisponde a [0] è l'intero testo del modello abbinato, quindi devi eseguire array_shift ($ corrispondenze) prima di usarlo in questo modo.
Alexandre Reis Ribeiro

Sarebbe più veloce formattarlo in uscita? Usando sprintfo `printf``? Qualcuno mi spieghi per favore. Sto lavorando solo con numeri di telefono statunitensi e non credo che eseguirli tramite una funzione di output utilizzando la sottostringa sia il metodo migliore.
Rafael

Penso che SO dovrebbe includere voti negativi sui commenti. Il commento di @Stoutie è fuorviante.
peterchaula

1
Mi scuso per i miei commenti errati che ho postato da me prima del giorno precedente così tanti anni fa. Prometto di fare meglio in futuro. Il commento a cui fai riferimento sembra essere stato cancellato. Tutto bene. Buone vacanze.
Stoutie

164

Questo è un formattatore telefonico statunitense che funziona su più versioni di numeri rispetto a qualsiasi risposta attuale.

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

Ed ecco una ripartizione della 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 ")"

Aggiornato: 11 marzo 2015 da utilizzare al {0,7}posto di{,7}


E se il numero di telefono ha un'estensione?
SpYk3HH

1
Buon punto: abbiamo alcuni esempi di come appaiono le estensioni nel mondo? Proabaly qualcosa di simile ~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})(?:[ \D#\-]*(\d{3,6}))?.*~.
Xeoncross

1
Cosa succede se gli utenti del mio sito web hanno omesso il prefisso?
skibulk

Possiamo ottenere una ripartizione di ciò che stanno facendo le varie parti della regex (come mostrato di seguito in un'altra risposta)? cioè: (\d{3}) // 3 digits [\d]// carattere che non è una cifra
roberthuttinger

1
@WesleyMurch Sembra che ci sia un cambiamento nella corrispondenza delle espressioni regolari che ora richiede {,7}di essere aggiornato {0,7}. Ho aggiornato il codice.
Xeoncross

55

Questa funzione formatterà numeri di telefono internazionali (10+ cifre), non internazionali (10 cifre) o vecchia scuola (7 cifre). Qualsiasi numero diverso da 10+, 10 o 7 cifre rimarrà non formattato.

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

Questo è fantastico, ma vorrei solo sottolineare che le parentesi attorno al prefisso indicano numeri opzionali. La maggior parte delle giurisdizioni non considera più il prefisso opzionale, quindi separare con un semplice trattino è più accurato.
Vincent,

30

Supponendo che i tuoi numeri di telefono abbiano sempre questo formato esatto, puoi utilizzare questo snippet:

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

Basta fare eco al $ per var ... Lo adoro, ha funzionato per me semplicemente perfetto.
Samuel Ramzan

22

I numeri di telefono sono difficili. Per una soluzione internazionale più robusta, consiglierei questo port PHP ben mantenuto della libreria libphonenumber di Google .

Usandolo in questo modo,

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
}

otterrai il seguente output:

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

Suggerirei di utilizzare il E164formato per i controlli duplicati. Puoi anche verificare se il numero è effettivamente un numero di cellulare o meno (utilizzando PhoneNumberUtil::getNumberType()) o se è anche un numero statunitense (utilizzando PhoneNumberUtil::getRegionCodeForNumber()).

Come bonus, la libreria può gestire praticamente qualsiasi input. Se, ad esempio, scegli di eseguire 1-800-JETBLUEil codice sopra, otterrai

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

Neato.

Funziona altrettanto bene per paesi diversi dagli Stati Uniti. Usa semplicemente un altro codice paese ISO parse()nell'argomento.


2
Grande libreria, ma nota che è 37 MB e 1500 file! Nel mio caso, ho un numero limitato di numeri di telefono da formattare, quindi ho deciso di aggiungere semplicemente una number_formattedcolonna nel mio database e inserire manualmente i numeri formattati. Tuttavia, uso ancora libphonenumberlocalmente per generare i numeri formattati, ma includere una libreria così enorme per il mio piccolo progetto è semplicemente eccessivo.
Magnus W

9

Ecco la mia soluzione solo per gli Stati Uniti, con il prefisso come componente opzionale, delimitatore obbligatorio per l'estensione e commenti 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;
}

Ed ecco lo script per provarlo:

$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

Ecco una semplice funzione per formattare numeri di telefono da 7 a 10 cifre in un modo più europeo (o svedese?):

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

Non reinventare la ruota! Importa questa fantastica libreria:
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);

Si basa sulla libreria di Google per l'analisi, la formattazione e la convalida dei numeri di telefono internazionali: https://github.com/google/libphonenumber


3
Penso che questa sia una risposta valida, ma se vuoi che sia utile per gli standard Stack Overflow, allora dovresti modificare per includere un esempio che risolva il problema di OP utilizzando la libreria piuttosto che condividere semplicemente un collegamento.
Alecg_O

1
Grazie @Alecg_O! Ho aggiunto un esempio.
Viktor Jarnheimer

4

Vedo che ciò è possibile utilizzando alcune espressioni regolari o alcune chiamate substr (supponendo che l'input sia sempre di quel formato e non cambi la lunghezza ecc.)

qualcosa di simile a

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

dovrebbe farlo.


4

È più veloce di RegEx.

$input = "0987654321"; 

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

1
Breve e dolce (y).
rahim.nagori

2

Prova qualcosa come:

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

questo richiederebbe un numero di $ 8881112222e la conversione in 888-111-2222. Spero che questo ti aiuti.


1
Fonte del tuo suggerimento: hotscripts.com/forums/php/36805-php-format-phone-numbers.html . Anche str_replace di '.'dovrebbe essere aggiornato '-'o rimosso. È stato incluso a causa del particolare caso d'uso affrontato: con uno sforzo minimo avresti potuto convertirlo preg_replace('/\d{3}/', '$0-', substr($number, 2))e rispondere direttamente alla domanda.
Iiridayn

2

Un'altra opzione: facilmente aggiornabile per ricevere un formato dalla configurazione.

$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

Tutti,

Penso di averlo risolto. Lavorare per i file di input correnti e avere le seguenti 2 funzioni per farlo!

funzione 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

funzione 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

Si noti che ho questo in una classe lib, quindi la chiamata "self :: validate_phone_number" dalla prima funzione / metodo.

Nota la riga # 32 della funzione "validate_phone_number" dove ho aggiunto:

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

per farmi ottenere il falso reso necessario se non valido numero di telefono.

Devo ancora testarlo con più dati, ma sto lavorando sui dati correnti, con il formato corrente e sto usando lo stile "8" per questo particolare batch di dati.

Inoltre ho commentato la logica di "estensione" poiché ricevevo costantemente errori da essa, visto che non ho nessuna di queste informazioni nei miei dati.


1

questo richiede 7, 10 e 11 cifre, rimuove caratteri aggiuntivi e aggiunge trattini andando da destra a sinistra attraverso la stringa. cambia il trattino in uno spazio 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

So che l'OP richiede un formato 123-456-7890, ma, in base alla risposta di John Dul , l'ho modificato per restituire il numero di telefono tra parentesi, ad esempio (123) 456-7890. Questo gestisce solo numeri a 7 e 10 cifre.

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

Ecco la mia opinione:

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

//  123-456-7890

La sscanffunzione prende come secondo parametro una stringa di formato che le dice come interpretare i caratteri dalla prima stringa. In questo caso, significa 2 caratteri ( %2c), 3 caratteri, 3 caratteri, 4 caratteri.

Normalmente la sscanffunzione include anche variabili per catturare i dati estratti. In caso contrario, i dati vengono restituiti in un array che ho chiamato $parts.

L' printistruzione restituisce la stringa interpolata. $part[0]viene ignorato.

Ho utilizzato una funzione simile per formattare i numeri di telefono australiani.

Si noti che dal punto di vista della memorizzazione del numero di telefono:

  • i numeri di telefono sono stringhe
  • i dati memorizzati non devono includere la formattazione, come spazi o trattini

Questa è la soluzione più elegante e leggibile. BACIO. Non scorrere oltre se le stringhe di input seguono sempre lo stesso identico schema. Grazie per questa aggiunta.
Musa

1

Formati telefonici del Regno Unito

Per l'applicazione che ho sviluppato, ho riscontrato che le persone immettevano il loro numero di telefono "correttamente" da un formato leggibile dall'uomo, ma inserivano vari caratteri casuali come "-" / "" +44 "ecc. Il problema era che l'app cloud che aveva bisogno di parlare era abbastanza specifico riguardo al formato. Piuttosto che usare un'espressione regolare (può essere frustrante per l'utente) ho creato una classe di oggetti che elabora il numero inserito nel formato corretto prima di essere elaborato dal modulo di persistenza.

Il formato dell'output garantisce che qualsiasi software ricevente interpreti l'output come testo anziché come numero intero (che quindi perderebbe immediatamente lo zero iniziale) e il formato è coerente con British Telecoms linee guida sulla formattazione dei numeri, che aiutano anche la memorabilità umana dividendo un numero lungo in piccoli gruppi facilmente memorizzabili.


+441234567890 produce (01234)
567890 02012345678 produce (020) 1234 5678
1923123456 produce (01923)
123456 01923123456 produce (01923)
123456 01923 ciao questo è testo123456 produce (01923) 123456

Il significato del segmento di scambio del numero, tra parentesi, è che nel Regno Unito e nella maggior parte degli altri paesi, le chiamate tra numeri nello stesso scambio possono essere effettuate omettendo il segmento di scambio. Tuttavia, ciò non si applica ai numeri di telefono delle serie 07, 08 e 09.

Sono sicuro che ci siano soluzioni più efficienti, ma questa si è dimostrata estremamente affidabile. Più formati possono essere facilmente adattati aggiungendo alla funzione teleNum alla fine.

La procedura viene quindi richiamata dallo script chiamante

$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

Questo è per i telefoni fissi del Regno Unito senza il codice del paese

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

Risultato:

2012345678
becomes
20 1234 5678

0

Dai un'occhiata alla funzione basata su substr che può cambiare formato

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

Controlla il numero di telefono

$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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.