Formatage des numéros de téléphone en PHP

102

Je travaille sur une application SMS et je dois pouvoir convertir le numéro de téléphone de l'expéditeur de +11234567890 à 123-456-7890 afin qu'il puisse être comparé aux enregistrements dans une base de données MySQL .

Les numéros sont stockés dans ce dernier format pour une utilisation ailleurs sur le site et je préfère ne pas changer ce format car cela nécessiterait de modifier beaucoup de code.

Comment procéderais-je avec PHP?

Merci!

NuitMICU
la source
13
ahhhhh .... NOOOO .... pourquoi stockez-vous des numéros de téléphone comme ça !? comme une chaîne? Mauvais mauvais mauvais! Vous devriez les stocker en gros entiers ... moins de stockage requis, index plus rapide, tri plus rapide
sethvargo
7
pas tellement un problème de stockage des numéros de téléphone sous forme de chaînes (ne peut pas être évité lorsque vous devez stocker +61 (0) 812345678) - mais stocker un format spécifique est un peu douteux (c'est-à-dire les séparateurs) - mieux vaut faire le formatage au niveau de la couche de présentation plutôt que de la couche de données.
HorusKol
3
@NightMICU - c'est 100% la mauvaise façon de faire cela ... Vous devriez stocker sous forme d'entier et avoir une fonction réutilisable qui formate pour l'affichage
sethvargo
230
Stocker des numéros de téléphone sous forme d'entiers pour économiser de l'espace de stockage est une idée horrible. Les numéros de téléphone ne sont pas des nombres dans le sens général où vous ferez des calculs dessus. Au moment où vous devez stocker des numéros en dehors d'un format spécifique aux États-Unis où le numéro peut commencer par un 0, vous rencontrerez des problèmes. Mieux vaut stocker ces informations sous forme de chaîne.
Charles Sprayberry
2
@NightMICU Si cela vous permet de mieux stocker sous forme de chaîne, même le grand Jon Skeet dit de ne pas stocker en tant qu'entier pour le problème principal du zéro. stackoverflow.com/a/3483166/746010
Charles Sprayberry

Réponses:

109
$data = '+11234567890';

if(  preg_match( '/^\+\d(\d{3})(\d{3})(\d{4})$/', $data,  $matches ) )
{
    $result = $matches[1] . '-' .$matches[2] . '-' . $matches[3];
    return $result;
}
plus mince
la source
Pour capturer les espaces et autres formats possibles de nombres internationaux: / ^ (\ +? \ D {1,2}?) [.-]? (? (\ D {3}))? [.-]? (\ D {3}) [.-]? (\ D {4}) $ /
TeckniX
3
@stoutie vous vous trompez, $ matches [0] est tout le texte du motif correspondant, vous devez alors array_shift ($ matches) avant de l'utiliser de cette façon.
Alexandre Reis Ribeiro
Serait-il plus rapide de le formater à la sortie? En utilisant sprintfou `printf``? Quelqu'un, s'il vous plaît, expliquez-moi. Je travaille uniquement avec des numéros de téléphone américains et je ne pense pas que les exécuter via une fonction de sortie utilisant une sous-chaîne soit la meilleure méthode.
Rafael
Je pense que SO devrait inclure des votes contre les commentaires. Le commentaire de @Stoutie est trompeur.
peterchaula
1
Je m'excuse pour mon plus jeune jour, avant le tdd, postant des commentaires erronés il y a tant d'années. Je promets de faire mieux à l'avenir. Le commentaire auquel vous faites référence semble avoir été supprimé. Tout est bien. Joyeuses fêtes.
Stoutie
164

Il s'agit d'un formateur de téléphone américain qui fonctionne sur plus de versions de nombres que sur toutes les réponses actuelles.

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

Et voici une ventilation de l'expression régulière:

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

Mise à jour: 11 mars 2015 à utiliser à la {0,7}place de{,7}

Xeoncross
la source
Et si le numéro de téléphone a une extension?
SpYk3HH
1
Bon point - avons-nous quelques exemples de l'apparence des extensions dans le monde? Proabaly quelque chose comme ~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})(?:[ \D#\-]*(\d{3,6}))?.*~.
Xeoncross
1
Que faire si les utilisateurs de mon site Web ont omis l'indicatif régional?
skibulk
Pouvons-nous avoir une ventilation de ce que font les différentes parties de l'expression régulière (comme indiqué ci-dessous dans une autre réponse)? ie: (\d{3}) // 3 digits [\d]// caractère qui n'est pas un chiffre
roberthuttinger
1
@WesleyMurch Il semble y avoir un changement dans la correspondance des expressions régulières qui doit maintenant {,7}être mis à jour {0,7}. J'ai mis à jour le code.
Xeoncross
55

Cette fonction formatera les numéros de téléphone internationaux (10+ chiffres), non internationaux (10 chiffres) ou old school (7 chiffres). Tous les nombres autres que 10+, 10 ou 7 chiffres resteront non formatés.

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
la source
C'est génial, mais je voudrais juste souligner que les parenthèses autour de l'indicatif régional impliquent des nombres facultatifs. La plupart des juridictions ne considèrent plus l'indicatif régional comme facultatif, donc la séparation par un simple trait d'union est plus précise.
Vincent le
30

En supposant que vos numéros de téléphone ont toujours ce format exact, vous pouvez utiliser cet extrait de code:

$from = "+11234567890";
$to = sprintf("%s-%s-%s",
              substr($from, 2, 3),
              substr($from, 5, 3),
              substr($from, 8));
Daniel Hepper
la source
Juste echo the $ to var ... J'adore ça, a fonctionné pour moi juste parfait.
Samuel Ramzan
22

Les numéros de téléphone sont difficiles. Pour une solution internationale plus robuste, je recommanderais ce port PHP bien entretenu de la bibliothèque libphonenumber de Google .

En l'utilisant comme ça,

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
}

vous obtiendrez la sortie suivante:

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

Je recommanderais d'utiliser le E164format pour les chèques en double. Vous pouvez également vérifier si le numéro est réellement un numéro mobile ou non (en utilisant PhoneNumberUtil::getNumberType()), ou s'il s'agit même d'un numéro américain (en utilisant PhoneNumberUtil::getRegionCodeForNumber()).

En prime, la bibliothèque peut gérer à peu près n'importe quelle entrée. Si, par exemple, vous choisissez d'exécuter 1-800-JETBLUEle code ci-dessus, vous obtiendrez

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

Neato.

Cela fonctionne aussi bien pour les pays autres que les États-Unis. Utilisez simplement un autre code de pays ISO dans l' parse()argument.

comme ça
la source
2
Grande bibliothèque, mais notez que c'est 37 Mo et 1500 fichiers! Dans mon cas, j'ai un nombre limité de numéros de téléphone à formater, j'ai donc décidé d'ajouter simplement une number_formattedcolonne dans ma base de données et d'entrer manuellement les numéros formatés. Toujours utiliser libphonenumberlocalement pour générer les nombres formatés, mais inclure une bibliothèque aussi énorme pour mon petit projet est juste exagéré.
Magnus W
9

Voici ma solution réservée aux États-Unis, avec l'indicatif régional en tant que composant facultatif, le délimiteur requis pour l'extension et les commentaires 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;
}

Et voici le script pour le tester:

$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
la source
5

Voici une fonction simple pour formater des numéros de téléphone de 7 à 10 chiffres d'une manière plus européenne (ou suédoise?):

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
la source
5

Ne réinventez pas la roue! Importez cette incroyable bibliothèque:
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);

Il est basé sur la bibliothèque de Google pour l'analyse, le formatage et la validation des numéros de téléphone internationaux: https://github.com/google/libphonenumber

Viktor Jarnheimer
la source
3
Je pense que c'est une réponse valide, mais si vous voulez qu'elle soit utile selon les normes de Stack Overflow, vous devez alors modifier pour inclure un exemple de résolution du problème d'OP en utilisant la bibliothèque plutôt que de simplement partager un lien.
Alecg_O
1
Merci @Alecg_O! J'ai ajouté un exemple.
Viktor Jarnheimer
4

Je vois que cela est possible en utilisant soit une expression régulière, soit quelques appels de substr (en supposant que l'entrée est toujours de ce format, et ne change pas de longueur, etc.)

quelque chose comme

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

devrait le faire.

Ali Lown
la source
4

C'est plus rapide que RegEx.

$input = "0987654321"; 

$output = substr($input, -10, -7) . "-" . substr($input, -7, -4) . "-" . substr($input, -4); 
echo $output;
Rishabh
la source
1
Court et doux (y).
rahim.nagori
2

Essayez quelque chose comme:

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

cela prendrait un nombre de $ 8881112222et serait converti en 888-111-2222. J'espère que cela t'aides.

RobertPitt
la source
1
Source de votre suggestion: hotscripts.com/forums/php/36805-php-format-phone-numbers.html . Le str_replace de '.'doit également être mis à jour '-'ou supprimé. Il a été inclus en raison du cas d'utilisation particulier rencontré - avec très peu d'effort, vous auriez pu le convertir preg_replace('/\d{3}/', '$0-', substr($number, 2))et répondre directement à la question.
Iiridayn
2

Une autre option - facilement mise à jour pour recevoir un format de la configuration.

$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.
la source
1

Tout,

Je pense que je l'ai réparé. Travailler pour les fichiers d'entrée actuels et avoir les 2 fonctions suivantes pour y parvenir!

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

fonction 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

Remarquez que j'ai ceci dans une classe lib, donc l'appel "self :: validate_phone_number" de la première fonction / méthode.

Remarquez la ligne n ° 32 de la fonction "validate_phone_number" où j'ai ajouté:

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

pour me procurer le faux retour nécessaire si ce n'est pas un numéro de téléphone valide.

Encore faut-il tester cela avec plus de données, mais en travaillant sur les données actuelles, avec le format actuel et j'utilise le style '8' pour ce lot de données particulier.

J'ai également commenté la logique de "l'extension" car j'en recevais constamment des erreurs, car je n'ai aucune de ces informations dans mes données.

OldManRiver
la source
1

cela prend 7, 10 et 11 chiffres, supprime les caractères supplémentaires et ajoute des tirets en allant de droite à gauche dans la chaîne. changez le tiret en espace ou en point.

$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
la source
1

Je sais que l'OP demande un format 123-456-7890, mais, sur la base de la réponse de John Dul , je l'ai modifié pour renvoyer le numéro de téléphone au format parenthèses, par exemple (123) 456-7890. Celui-ci ne gère que les nombres à 7 et 10 chiffres.

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
la source
1

Voici ma prise:

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

//  123-456-7890

La sscanffonction prend comme second paramètre une chaîne de format lui indiquant comment interpréter les caractères de la première chaîne. Dans ce cas, cela signifie 2 caractères (%2c ), 3 caractères, 3 caractères, 4 caractères.

Normalement, la sscanffonction comprend également des variables pour capturer les données extraites. Sinon, les données sont renvoyées dans un tableau que j'ai appelé $parts.

L' printinstruction génère la chaîne interpolée. $part[0]est ignoré.

J'ai utilisé une fonction similaire pour formater les numéros de téléphone australiens.

Notez que du point de vue du stockage du numéro de téléphone:

  • les numéros de téléphone sont des chaînes
  • les données stockées ne doivent pas inclure de formatage, comme des espaces ou des traits d'union
Manngo
la source
C'est la solution la plus élégante et la plus lisible. BAISER. Ne faites pas défiler plus loin si vos chaînes d'entrée suivent toujours exactement le même modèle. Merci pour cet ajout.
Musa
1

Formats de téléphone au Royaume-Uni

Pour l'application que j'ai développée, j'ai constaté que les gens entraient leur numéro de téléphone `` correctement '' à partir d'une forme lisible par l'homme, mais inséraient divers caractères aléatoires tels que `` - '' / `` +44 '', etc. Le problème était que l'application cloud qui il fallait parler était assez précis sur le format. Plutôt que d'utiliser une expression régulière (cela peut être frustrant pour l'utilisateur), j'ai créé une classe d'objets qui traite le numéro entré dans le format correct avant d'être traité par le module de persistance.

Le format de la sortie garantit que tout logiciel de réception interprète la sortie comme du texte plutôt que comme un entier (qui perdrait alors immédiatement le zéro de début) et le format est cohérent avec British Telecoms des directives sur le formatage des nombres - ce qui facilite également la mémorisation humaine en divisant un long nombre en petits groupes faciles à mémoriser.


+441234567890 produit (01234) 567890
02012345678 produit (020) 1234 5678
1923123456 produit (01923) 123456
01923123456 produit (01923) 123456
01923 bonjour ceci est text123456 produit (01923) 123456

L'importance du segment d'échange du numéro - entre parenthèses - est qu'au Royaume-Uni, et dans la plupart des autres pays, les appels entre les numéros d'un même central peuvent être effectués en omettant le segment d'échange. Cela ne s'applique cependant pas aux numéros de téléphone des séries 07, 08 et 09.

Je suis sûr qu'il existe des solutions plus efficaces, mais celle-ci s'est avérée extrêmement fiable. Plus de formats peuvent facilement être adaptés en ajoutant à la fonction teleNum à la fin.

La procédure est appelée à partir du script appelant ainsi

$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
la source
0

Ceci est pour les lignes fixes du Royaume-Uni sans le code de pays

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

Résultat:

2012345678
becomes
20 1234 5678
typocodeur
la source
0

Veuillez jeter un œil à la fonction basée sur substr qui peut changer de format

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
la source
0

Vérifier le numéro de téléphone

$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;
}
magasin facile
la source