# PHP Phone Number Formatting

## Problem

I’m working on an SMS app and need to convert the sender’s phone number from +11234567890 to 123-456-7890 so that it can be compared to MySQL database information.

The numbers are saved in the latter format for use elsewhere on the site, and I’d rather not alter it because it would necessitate a significant amount of code modification.

How would I approach this in PHP?

Thanks!

## Solution #1

This is a phone formatter for the United States that works with more number variations than any of the other options.

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

Here’s how the regex is broken down:

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

Updated on March 11, 2015 to use 0,7 rather than,7.

## Solution #2

``````\$data = '+11234567890';

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

## Solution #3

This function formats phone numbers that are international (10+ digits), non-international (10 digits), or old school (7 digits). Any numbers with more than ten digits, ten digits, or seven digits will be left unformatted.

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

## Solution #4

You can use this snippet if your phone numbers always have this identical format:

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

## Solution #5

Phone numbers are difficult to remember. I would recommend this well-maintained PHP implementation of Google’s libphonenumber library for a more robust, multinational solution.

Using it in this manner,

``````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
``````

For duplicate checks, I propose using the E164 format. You might also use PhoneNumberUtil::getNumberType() to see if the number is a mobile number or not, or if it’s even a US number (using PhoneNumberUtil::getRegionCodeForNumber()).

In addition, the library can handle almost any input. If you use the code above to call 1-800-JETBLUE, for example, you will obtain

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

Neato.

It works equally well in countries other than the United States. Simply change the parse() input to another ISO country code.