Форматирование телефонных номеров в PHP

102

Я работаю над приложением SMS, и мне нужно иметь возможность преобразовать номер телефона отправителя с +11234567890 в 123-456-7890, чтобы его можно было сравнить с записями в базе данных MySQL .

Числа хранятся в последнем формате для использования в других местах на сайте, и я бы предпочел не менять этот формат, поскольку это потребует изменения большого количества кода.

Как мне это сделать с помощью PHP?

Спасибо!

Ночное отделение интенсивной терапии
источник
13
ааааа .... НЕЕЕТ .... зачем ты так хранишь телефонные номера !? как строку? Плохо, плохо, плохо! Вы должны хранить их как большие целые числа ... требуется меньше памяти, более быстрый индекс, более быстрая сортировка
sethvargo
7
не такая большая проблема с хранением телефонных номеров в виде строк (этого нельзя избежать, когда вам нужно сохранить +61 (0) 812345678), но хранение определенного формата немного изворотливо (например, разделители) - лучше всего выполнить форматирование на уровне представления, а не на уровне данных.
HorusKol
3
@NightMICU - это 100% неправильный способ сделать это ... Вы должны хранить как целое число и иметь многоразовую функцию, которая форматирует для отображения
sethvargo
230
Хранить телефонные номера в виде целых чисел для экономии места - ужасная идея. Номера телефонов не являются числами в том смысле, в котором вы будете их вычислять. В тот момент, когда вам нужно сохранить числа за пределами формата, определенного для США, где число может начинаться с 0, вы столкнетесь с проблемами. Лучше хранить эту информацию в виде строки.
Чарльз Спрейберри
2
@NightMICU Если это заставляет вас чувствовать себя лучше при хранении в виде строки, даже великий Джон Скит говорит, что не следует хранить как целое число для ведущей проблемы с нулем. stackoverflow.com/a/3483166/746010
Чарльз Спрейберри

Ответы:

109
$data = '+11234567890';

if(  preg_match( '/^\+\d(\d{3})(\d{3})(\d{4})$/', $data,  $matches ) )
{
    $result = $matches[1] . '-' .$matches[2] . '-' . $matches[3];
    return $result;
}
хитрее
источник
Для ввода возможных пробелов и других форматов международных номеров: / ^ (\ +? \ D {1,2}?) [.-]? (? (\ D {3}))? [.-]? (\ D {3}) [.-]? (\ D {4}) $ /
TeckniX
3
@stoutie вы ошибаетесь, $ matches [0] - это весь текст сопоставленного шаблона, тогда вам нужно array_shift ($ match) перед его использованием таким образом.
Alexandre Reis Ribeiro
Было бы быстрее отформатировать это на выходе? Используете sprintfили printf? Кто-нибудь, пожалуйста, объясните мне. Я работаю только с телефонными номерами в США и не думаю, что запуск их через функцию вывода с использованием подстроки - лучший метод.
Рафаэль
Я думаю, что ТАК следует включать в комментарии отрицательные голоса. Комментарий @Stoutie вводит в заблуждение.
peterchaula
1
Я приношу свои извинения за то, что так много лет назад я публиковал ошибочные комментарии, когда я был моложе, чем раньше. Я обещаю добиться большего в будущем. Комментарий, на который вы ссылаетесь, похоже, был удален. Все хорошо. Счастливых праздников.
Stoutie
164

Это форматировщик телефонов в США, который работает с большим количеством версий чисел, чем любой из текущих ответов.

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

А вот разбивка регулярного выражения:

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

Обновлено: 11 марта 2015 г. для использования {0,7}вместо{,7}

Xeoncross
источник
Что делать, если у номера телефона есть добавочный номер?
SpYk3HH
1
Хороший момент - у нас есть примеры того, как расширения выглядят во всем мире? Пробалы что-то вроде ~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})(?:[ \D#\-]*(\d{3,6}))?.*~.
Xeoncross
1
Что, если пользователи моего сайта не указали код города?
skibulk
Можем ли мы получить разбивку того, что делают различные части регулярного выражения (как показано ниже в другом ответе)? то есть: (\d{3}) // 3 digits [\d]// символ, который не является цифрой
roberthuttinger
1
@WesleyMurch Кажется, есть изменение в сопоставлении регулярных выражений, которое теперь необходимо {,7}обновить {0,7}. Я обновил код.
Xeoncross
55

Эта функция форматирует международные (10+ цифр), немеждународные (10-значные) или старые (7-значные) телефонные номера. Любые числа, кроме 10+, 10 или 7 цифр, останутся неформатированными.

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;
}
Брайан Шон
источник
Это здорово, но я просто хотел бы отметить, что круглые скобки вокруг кода области подразумевают необязательные числа. Большинство юрисдикций больше не считают код города необязательным, поэтому разделение с помощью простого дефиса будет более точным.
Винсент
30

Предполагая, что ваши номера телефонов всегда имеют именно такой формат, вы можете использовать этот фрагмент:

$from = "+11234567890";
$to = sprintf("%s-%s-%s",
              substr($from, 2, 3),
              substr($from, 5, 3),
              substr($from, 8));
Дэниел Хеппер
источник
Просто повторите $ to var ... Мне понравилось, у меня сработало, просто префект.
Самуэль Рамзан,
22

С телефонными номерами сложно. Для более надежного международного решения я бы порекомендовал этот хорошо поддерживаемый порт PHP библиотеки Google libphonenumber .

Используя это так,

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
}

вы получите следующий результат:

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

Я бы рекомендовал использовать этот E164формат для повторяющихся проверок. Вы также можете проверить, действительно ли это номер мобильного телефона (с использованием PhoneNumberUtil::getNumberType()) или даже номер в США (с использованием PhoneNumberUtil::getRegionCodeForNumber()).

В качестве бонуса библиотека может обрабатывать практически любой ввод. Если вы, например, решите запустить 1-800-JETBLUEприведенный выше код, вы получите

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

Neato.

Это работает так же хорошо для других стран, кроме США. Просто используйте в качестве parse()аргумента другой код страны ISO .

нравится
источник
2
Отличная библиотека, но учтите, что это 37 МБ и 1500 файлов! В моем случае у меня ограниченное количество телефонных номеров для форматирования, поэтому я решил просто добавить number_formattedстолбец в свою базу данных и вручную ввести отформатированные номера. Тем не менее, все еще использовать libphonenumberлокально для генерации форматированных чисел, но включение такой огромной библиотеки для моего небольшого проекта просто излишне.
Magnus W
9

Вот мое решение для США, с кодом области в качестве необязательного компонента, обязательным разделителем для расширения и комментариями к регулярному выражению:

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

А вот сценарий для проверки:

$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

Вот простая функция для форматирования телефонных номеров от 7 до 10 цифр в более европейской (или шведской?) Манере:

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

Не изобретайте велосипед! Импортируйте эту удивительную библиотеку:
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);

Он основан на библиотеке Google для анализа, форматирования и проверки международных телефонных номеров: https://github.com/google/libphonenumber

Виктор Ярнхаймер
источник
3
Я думаю, что это правильный ответ, но если вы хотите, чтобы он был полезен в соответствии со стандартами Stack Overflow, вам следует отредактировать, чтобы включить пример решения проблемы OP с использованием библиотеки, а не просто поделиться ссылкой.
Alecg_O
1
Спасибо @Alecg_O! Я добавил пример.
Виктор
4

Я вижу, что это возможно, используя либо какое-то регулярное выражение, либо несколько вызовов substr (при условии, что ввод всегда имеет этот формат и не меняет длину и т. Д.)

что-то вроде

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

должен это сделать.

Али Лаун
источник
4

Это быстрее, чем RegEx.

$input = "0987654321"; 

$output = substr($input, -10, -7) . "-" . substr($input, -7, -4) . "-" . substr($input, -4); 
echo $output;
Ришаб
источник
1
Коротко и мило (у).
rahim.nagori
2

Попробуйте что-нибудь вроде:

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

для этого потребуется $ number 8881112222и преобразовать в 888-111-2222. Надеюсь это поможет.

Роберт Питт
источник
1
Источник вашего предложения: hotscripts.com/forums/php/36805-php-format-phone-numbers.html . Str_replace of '.'также должен быть обновлен '-'или удален. Он был включен из-за конкретного случая использования - с очень небольшими усилиями вы могли преобразовать его preg_replace('/\d{3}/', '$0-', substr($number, 2))и напрямую ответить на вопрос.
Iiridayn
2

Другой вариант - легко обновить, чтобы получить формат из конфигурации.

$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

Все,

Думаю, я исправил. Работаем с текущими входными файлами и выполняем следующие 2 функции!

функция 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

функция 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

Заметьте, у меня это есть в классе lib, поэтому вызов self :: validate_phone_number из первой функции / метода.

Обратите внимание на строку № 32 функции «validate_phone_number», где я добавил:

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

чтобы получить ложный возврат, если не действительный номер телефона.

Все еще нужно проверить это на большем количестве данных, но работаю с текущими данными, с текущим форматом, и я использую стиль «8» для этого конкретного пакета данных.

Также я прокомментировал логику «расширения», поскольку я постоянно получал от нее ошибки, видя, что у меня нет такой информации в моих данных.

СтарыйЧеловекРека
источник
1

это занимает 7, 10 и 11 цифр, удаляет дополнительные символы и добавляет тире, перемещаясь справа налево по строке. замените тире на пробел или точку.

$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

Я знаю, что OP запрашивает формат 123-456-7890, но, основываясь на ответе Джона Дула , я изменил его, чтобы вернуть номер телефона в формате круглых скобок, например (123) 456-7890. Этот обрабатывает только 7- и 10-значные числа.

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

Вот мой вывод:

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

//  123-456-7890

sscanfФункция принимает в качестве второго параметра в строку формата , говоря ему , как интерпретировать символы из первой строки. В данном случае это означает 2 символа ( %2c), 3 символа, 3 символа, 4 символа.

Обычно sscanfфункция также включает переменные для сбора извлеченных данных. Если нет, данные возвращаются в массиве, который я вызвал $parts.

printОператор выводит интерполированную строку. $part[0]игнорируется.

Я использовал аналогичную функцию для форматирования номеров телефонов в Австралии.

Обратите внимание, что с точки зрения хранения номера телефона:

  • номера телефонов - это строки
  • сохраненные данные не должны включать форматирование, такое как пробелы или дефисы
Manngo
источник
Это наиболее элегантное и удобочитаемое решение. ПОЦЕЛУЙ. Не прокручивайте дальше, если ваши входные строки всегда следуют одному и тому же шаблону. Спасибо за это дополнение.
Муса
1

Телефонные Форматы Соединенного Королевства

Для приложения, которое я разработал, я обнаружил, что люди вводили свой номер телефона «правильно» в удобочитаемой форме, но вставляли различные случайные символы, такие как «-» / «+44» и т. Д. Проблема заключалась в том, что облачное приложение, которое нужно было поговорить с довольно конкретным о формате. Вместо того, чтобы использовать регулярное выражение (что может расстраивать пользователя), я создал класс объекта, который обрабатывает введенное число в правильный формат перед обработкой модулем постоянства.

Формат вывода гарантирует, что любое принимающее программное обеспечение интерпретирует вывод как текст, а не целое число (которое тогда сразу потеряет начальный ноль), а формат соответствует British Telecoms рекомендации по форматированию чисел, которые также помогают запоминать человека, разделяя длинное число на небольшие, легко запоминающиеся группы.


+441234567890 производит (01234) 567 890
02012345678 производит (020) 1234 5678
1923123456 производит (01923) 123 456
01923123456 производит (01923) 123 456
01923 hello this is text123456 производит (01923) 123 456

Значение сегмента обмена номера - в скобках - заключается в том, что в Великобритании и большинстве других стран вызовы между номерами в одной и той же телефонной станции могут осуществляться без сегмента обмена. Однако это не относится к телефонным номерам серий 07, 08 и 09.

Я уверен, что есть более эффективные решения, но это оказалось чрезвычайно надежным. Можно легко разместить больше форматов, добавив в конце функцию teleNum.

Процедура вызывается из вызывающего скрипта таким образом

$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;
    }
}
Майк M0ITI
источник
0

Это для стационарных телефонов Великобритании без кода страны.

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

Результат:

2012345678
becomes
20 1234 5678
типокодер
источник
0

Взгляните на функцию на основе substr, которая может изменять форматы

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

Проверить номер телефона

$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;
}
легкий магазин
источник