用PHP格式化电话号码

Nig*_*ICU 89 php phone-number

我正在开发一个短信应用程序,需要能够将发件人的电话号码从+11234567890转换123-456-7890,以便将其与MySQL数据库中的记录进行比较.

这些数字以后一种格式存储,以便在网站的其他地方使用,我宁愿不改变这种格式,因为它需要修改大量代码.

我将如何使用PHP进行此操作?

谢谢!

Xeo*_*oss 153

这是一款美国手机格式化程序,可以处理比当前任何答案更多的数字版本.

$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";
}
Run Code Online (Sandbox Code Playgroud)

以下是正则表达式的细分:

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 ")"
Run Code Online (Sandbox Code Playgroud)

更新时间:2015年3月11日使用{0,7}而不是{,7}

  • @WesleyMurch 正则表达式匹配似乎发生了变化,现在需要将“{,7}”更新为“{0,7}”。我已经更新了代码。 (2认同)

sli*_*ier 100

$data = '+11234567890';

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

  • @stoutie你错了,$ matches [0]是整个匹配的模式文本,然后你需要在使用它之前使用array_shift($ matches). (3认同)
  • 我为多年前我年轻的、在 tdd 日之前发表的错误评论表示歉意。我保证将来会做得更好。您引用的评论似乎已被删除。一切都很好。节日快乐。 (2认同)

Bry*_*oen 45

此功能将格式化国际(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;
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*per 30

假设您的电话号码始终具有此格式,则可以使用以下代码段:

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


lik*_*eit 20

电话号码很难.对于更强大的国际解决方案,我建议使用这个维护良好的Google libphonenumber库的PHP端口.

像这样使用它,

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
}
Run Code Online (Sandbox Code Playgroud)

您将获得以下输出:

Input: +12123456789
isValid: true
E164: +12123456789
National: (212) 345-6789
International: +1 212-345-6789
Run Code Online (Sandbox Code Playgroud)

我建议使用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
Run Code Online (Sandbox Code Playgroud)

NEATO.

对于美国以外的国家来说,它的效果非常好.只需在parse()参数中使用另一个ISO国家/地区代码.

  • 很棒的库,但请注意,它有 37 MB 和 1500 个文件!就我而言,我要格式化的电话号码数量有限,因此我决定在我的数据库中添加一个 `number_formatted` 列并手动输入格式化的数字。尽管如此,仍然在本地使用 `libphonenumber` 来生成格式化的数字,但是为我的小项目包含如此庞大的库只是过度。 (3认同)

Ris*_*abh 10

它比 RegEx 快。

$input = "0987654321"; 

$output = substr($input, -10, -7) . "-" . substr($input, -7, -4) . "-" . substr($input, -4); 
echo $output;
Run Code Online (Sandbox Code Playgroud)


ski*_*ulk 8

这是我的仅限美国的解决方案,区号为可选组件,扩展名需要分隔符,正则表达式注释:

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;
}
Run Code Online (Sandbox Code Playgroud)

这是测试它的脚本:

$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");
}
Run Code Online (Sandbox Code Playgroud)


Man*_*ngo 6

这是我的看法:

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

//  123-456-7890
Run Code Online (Sandbox Code Playgroud)

sscanf函数将格式字符串作为第二个参数,告诉它如何解释第一个字符串中的字符。在这种情况下,它表示 2 个字符 ( %2c)、3 个字符、3 个字符、4 个字符。

通常,该sscanf函数还包括用于捕获提取数据的变量。如果没有,数据将返回到我调用的数组中$parts

print语句输出插入的字符串。$part[0]被忽略。

我使用了类似的功能来格式化澳大利亚电话号码。

注意从存储电话号码的角度来看:

  • 电话号码是字符串
  • 存储的数据应该包括格式化,诸如空格或连字符


小智 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;
}
Run Code Online (Sandbox Code Playgroud)


Vik*_*mer 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);
Run Code Online (Sandbox Code Playgroud)

它基于 Google 的用于解析、格式化和验证国际电话号码的库:https : //github.com/google/libphonenumber

  • 我认为这是一个有效的答案,但如果您希望它对 Stack Overflow 标准有用,那么您应该编辑以包含一个使用该库解决 OP 问题的示例,而不仅仅是共享链接。 (3认同)