120

I am working on an SMS app and need to be able to convert the sender's phone number from +11234567890 to 123-456-7890 so it can be compared to records in a MySQL database.

The numbers are stored in the latter format for use elsewhere on the site and I would rather not change that format as it would require modifying a lot of code.

How would I go about this with PHP?

Thanks!

Hamza Zafeer
  • 2,360
  • 13
  • 30
  • 42
NightMICU
  • 9,000
  • 30
  • 89
  • 121
  • 14
    ahhhhh.... NOOOO.... why are you storing phone numbers like that!? as a string? Bad bad bad! You should store them as big ints... less storage required, faster index, faster sorting – sethvargo Jan 16 '11 at 21:45
  • Is it always going to be `+1` or are there other country codes or variations like the (incorrect) `+001`? – Pekka Jan 16 '11 at 21:45
  • @seth Storing as a string so that I can assure uniform data entry in my forms and display on pages. There are several numbers per individual so this was the easiest way. Also only pulling the individual's cell number and the list is very short (less than 50) @Pekka - the SMS gateway sends the number in that format, all users will be in the US – NightMICU Jan 16 '11 at 21:56
  • 8
    not so much a problem with storing phone numbers as strings (can't be avoided when you need to store +61(0)812345678 ) - but storing a specific format is a bit dodgy (ie, the seperators) - best to do formatting at the presentation layer rather than the data layer. – HorusKol Jan 16 '11 at 22:20
  • 3
    @NightMICU - that's 100% the wrong way to do that... You should be storing as an integer and have a reusable function that formats for display – sethvargo Jan 16 '11 at 22:21
  • 1
    Just an update, went ahead and updated my table as suggested. Thanks for the tip, +1 to both who suggested this. Ended up making the original question obsolete but I learned both how to use preg_match and a valuable MySQL lesson – NightMICU Jan 17 '11 at 02:52
  • 273
    Storing phone numbers as integers to save storage space is a horrible idea. Phone numbers are not numbers in the general sense that you will do math on them. The moment you have to store numbers outside of a US specific format where the number can start with a 0 you will encounter problems. Better to store this information as a string. – Charles Sprayberry Jan 18 '13 at 16:44
  • 3
    @NightMICU If it makes you feel better about storing as string even the great Jon Skeet says to not store as integer for the leading zero problem. http://stackoverflow.com/a/3483166/746010 – Charles Sprayberry Jan 20 '13 at 01:06
  • 1
    I definitely agree phone numbers should be stored as strings, but do any phone numbers actually start with a leading zero? – Wesley Murch Mar 11 '15 at 06:00
  • @WesleyMurch In this case, no – NightMICU Mar 11 '15 at 11:06
  • Apparently some do, I never knew (see comments): http://stackoverflow.com/a/3483166/398242 – Wesley Murch Mar 11 '15 at 18:27
  • @WesleyMurch so far every phone number I've had to enter into a table is US based, so no weird combinations here.. :) – NightMICU Mar 11 '15 at 18:34
  • 1
    @WesleyMurch In Germany for example, all numbers start with a leading zero as far as I am aware, unless you use international format. Exceptions are local calls which leave out the city code, but you wouldn't be storing only the local bits in a database. – Christian Oct 29 '15 at 16:01
  • 1
    Please follow @cspray's input on storing using strings. Storing as an integer or big int as proposed by sethvargo is incorrect. – BajaBob Dec 10 '15 at 18:45
  • @sethvargo Sorry, but that is extremely bad advice. Phone numbers are not numbers in that they don’t count anything. They are strings with a specialiased character set, viz digits. As strings they are easier to parse. – Manngo Jan 10 '20 at 04:28
  • Phone numbers in Australia start with 0. – mickmackusa Jul 16 '22 at 02:14

22 Answers22

178

This is a US phone formatter that works on more versions of numbers than any of the current answers.

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

And here is a breakdown of the 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 ")"

Updated: March 11, 2015 to use {0,7} instead of {,7}

Xeoncross
  • 55,620
  • 80
  • 262
  • 364
  • What if the phone number has an extension? – SpYk3HH May 10 '13 at 21:13
  • 1
    Good point - do we have some examples of how extensions look around the world? Proabaly something like `~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})(?:[ \D#\-]*(\d{3,6}))?.*~`. – Xeoncross Jun 13 '13 at 18:49
  • 1
    What if my website users have left out the area code? – skibulk Feb 03 '14 at 14:10
  • Can we get a breakdown of what the various parts of the regex are doing (as shown below in another answer)? ie: `(\d{3}) // 3 digits` `[\d]` // character that is not a digit – roberthuttinger May 08 '14 at 19:27
  • only worked for me in the original form before pruning to {,7}. so reposting the old syntax: return preg_replace('~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4}).*~', '($1) $2-$3', $number); – xeo Dec 28 '14 at 19:11
  • I should mention that there is no limit to the number of characters `.*` matches which is why I limited it to something sane like `{,7}`. Be warned that you could trigger a PHP error if you reach the backtrace limit using `.*`. If you need more than 7 characters between each number set then use `{,20}` or whatever number you need. – Xeoncross Dec 29 '14 at 19:14
  • 2
    @WesleyMurch There seems to be a change the regular expression matching that now requires `{,7}` to be updated to `{0,7}`. I've updated the code. – Xeoncross Mar 11 '15 at 18:02
  • [Awesome](http://codepad.org/Qp1lfv0S), thanks! Wasn't sure what was up since I had no results with the accepted answer either. – Wesley Murch Mar 11 '15 at 18:29
117
$data = '+11234567890';

if(  preg_match( '/^\+\d(\d{3})(\d{3})(\d{4})$/', $data,  $matches ) )
{
    $result = $matches[1] . '-' .$matches[2] . '-' . $matches[3];
    return $result;
}
slier
  • 6,511
  • 6
  • 36
  • 55
  • 1
    To capture possible spaces and other formats of international numbers:/^(\+?\d{1,2}?)[ .-]?\(?(\d{3})\)?[ .-]?(\d{3})[ .-]?(\d{4})$/ – TeckniX May 20 '14 at 16:51
  • 4
    @stoutie you wrong, $matches[0] is the entire matched pattern text, then you need to array_shift($matches) before use it that way. – Dreanmer Jun 26 '14 at 12:34
  • Would it be faster to format this at output? Using `sprintf` or `printf``? Someone please explain to me. I am working with U.S. only phone numbers and don't think running them through an output function using substring is the best method. – Rafael Mar 02 '15 at 17:06
  • I think SO should include downvotes on comments. @Stoutie 's comment is misleading. – Peter Chaula Dec 23 '16 at 04:33
  • 3
    I apologize for my younger, pre-tdd day self posting erroneous comments so many years ago. I promise to do better in the future. The comment you reference seems to have been deleted. All is well. Happy holidays. – Stoutie Dec 24 '16 at 05:16
70

This function will format international (10+ digit), non-international (10 digit) or old school (7 digit) phone numbers. Any numbers other than 10+, 10 or 7 digits will remain 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;
}
Bryan Schoen
  • 741
  • 5
  • 3
  • This is great but I would just like to point out that the parentheses around the area code imply optional numbers. Most jurisdictions no longer consider the area code optional so separating with a simple hyphen is more accurate. – Vincent Apr 27 '20 at 18:40
35

Assuming that your phone numbers always have this exact format, you can use this snippet:

$from = "+11234567890";
$to = sprintf("%s-%s-%s",
              substr($from, 2, 3),
              substr($from, 5, 3),
              substr($from, 8));
Daniel Hepper
  • 28,981
  • 10
  • 72
  • 75
31

Phone numbers are hard. For a more robust, international solution, I would recommend this well-maintained PHP port of Google's libphonenumber library.

Using it like this,

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
}

you will get the following output:

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

I'd recommend using the E164 format for duplicate checks. You could also check whether the number is a actually mobile number or not (using PhoneNumberUtil::getNumberType()), or whether it's even a US number (using PhoneNumberUtil::getRegionCodeForNumber()).

As a bonus, the library can handle pretty much any input. If you, for instance, choose to run 1-800-JETBLUE through the code above, you will get

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

Neato.

It works just as nicely for countries other than the US. Just use another ISO country code in the parse() argument.

likeitlikeit
  • 5,563
  • 5
  • 42
  • 56
  • 4
    Great library, but note that it is 37 MB and 1500 files! In my case, I have a limited number of phone numbers to format, so I decided to just add a `number_formatted` column in my database and manually enter the formatted numbers. Still use `libphonenumber` locally to generate the formatted numbers though, but including such a huge library for my small project is just overkill. – Magnus Jan 31 '18 at 05:04
  • 1
    This should have more upvotes. – Jay Are Jan 17 '23 at 07:33
18

It's faster than RegEx.

$input = "0987654321"; 

$output = substr($input, -10, -7) . "-" . substr($input, -7, -4) . "-" . substr($input, -4); 
echo $output;
bru02
  • 360
  • 2
  • 10
Rishabh
  • 546
  • 5
  • 8
  • Great solution. Very simple. For brazillian celular numbers with 11 digits, i did like this: $numberOutput = '('.substr($celnumber, -11, -9).') '. substr($celnumber, 2, 1).'.'. substr($celnumber, -8, -4).'.'. substr($celnumber, -4); – Michel Xavier Feb 08 '23 at 12:31
10

Here's my USA-only solution, with the area code as an optional component, required delimiter for the extension, and regex comments:

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

And here's the script to test it:

$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
  • 3,088
  • 1
  • 34
  • 42
9

Here’s my take:

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

//  123-456-7890

The sscanf function (https://www.php.net/manual/en/function.sscanf.php) takes as a second parameter a format string telling it how to interpret the characters from the first string. In this case, it means 2 characters (%2c), 3 characters, 3 characters, 4 characters.

Normally the sscanf function would also include additional parameter variables to capture the extracted data. If not, the data is return in an array which I have called $parts.

The print statement outputs the interpolated string. $part[0] is ignored.

I have used a similar function to format Australian phone numbers.

Note that from the perspective of storing the phone number:

  • phone numbers are strings
  • stored data should not include formatting, such as spaces or hyphens
Manngo
  • 14,066
  • 10
  • 88
  • 110
  • 1
    This is the most elegant and readable solution. KISS. Scroll no further if your input strings always follow the exact same pattern. Thank you for this addition. – Musa Aug 11 '20 at 18:02
7

Don't reinvent the wheel! Import this amazing library:
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);

It is based on Google's library for parsing, formatting, and validating international phone numbers: https://github.com/google/libphonenumber

5

Here's a simple function for formatting phone numbers with 7 to 10 digits in a more European (or Swedish?) manner:

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
  • 51
  • 1
  • 1
4

I see this being possible using either some regex, or a few substr calls (assuming the input is always of that format, and doesn't change length etc.)

something like

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

should do it.

Ali Lown
  • 2,323
  • 1
  • 18
  • 22
3

My advice on a VERY similar (earlier asked) question (Format 10-digit string into hyphenated phone number]) needs very little modification to be successful here.

There are earlier answers that use sscanf() or sprintf(), but no one bothered to put both excellent functions together.

The placeholder-based syntax in the format arguments offers a high degree of control to the developer. Customizing/Maintaining this approach should be less daunting than regex for most developers.

vprintf() allows you to declare placeholders to be populated using a single array of values.

Code: (Demo)

$string = '+11234567890';

vprintf('%s-%s-%s', sscanf($string, '+1%3s%3s%4s'));
// 123-456-7890

Or because only adding hyphens, you can use implode.

echo implode('-', sscanf($string, '+1%3s%3s%4s'));
// 123-456-7890
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
2

Another option - easily updated to receive a format from 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.
  • 355
  • 2
  • 9
2

Try something like:

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

this would take a $number of 8881112222 and convert to 888-111-2222. Hope this helps.

RobertPitt
  • 56,863
  • 21
  • 114
  • 161
  • 1
    Source of your suggestion: http://www.hotscripts.com/forums/php/36805-php-format-phone-numbers.html. The str_replace of `'.'` should also be updated to `'-'`, or removed. It was included because of the particular use case faced - with very little effort you could have converted it to `preg_replace('/\d{3}/', '$0-', substr($number, 2))` and answered the question directly. – Iiridayn Aug 12 '11 at 14:42
1

All,

I think I fixed it. Working for current input files and have following 2 functions to get this done!

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

function 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

Notice I have this in a class lib, so thus the "self::validate_phone_number" call from the first function/method.

Notice line # 32 of the "validate_phone_number" function where I added the:

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

to get me the false return needed if not valid phone number.

Still need to test this against more data, but working on current data, with current format and I'm using style '8' for this particular data batch.

Also I commented out the "extension" logic as I was constantly getting errors from it, seeing I do not have any of that info in my data.

kaiser
  • 21,817
  • 17
  • 90
  • 110
1

This is for UK landlines without the Country Code

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

Result:

2012345678
becomes
20 1234 5678
typocoder
  • 355
  • 1
  • 3
  • 10
1

this takes 7, 10 and 11 digit, removes additional characters and adds dashes by going right to left through the string. change the dash to a space or dot.

$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
  • 11
  • 1
1

I know the OP is requesting a 123-456-7890 format, but, based on John Dul's answer, I modified it to return the phone number in parentheses format, e.g. (123) 456-7890. This one only handles 7 and 10 digit numbers.

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
  • 2,874
  • 3
  • 23
  • 28
  • Not sure why you want to return parentheses,as they imply that the numbers are optional which is rarely the case anymore. – Vincent Mar 31 '21 at 23:14
1

Please have a look at substr based function that can change formats

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
  • 37,872
  • 26
  • 173
  • 191
1

United Kingdom Phone Formats

For the application I developed, I found that people entered their phone number 'correctly' from a human readable form, but inserted varous random characters such as '-' '/' '+44' etc. The problem was that the cloud app that it needed to talk to was quite specific about the format. Rather than use a regular expression (can be frustrating for the user) I created an object class which processes the entered number into the correct format before being processed by the persistence module.

The format of the output ensures that any receiving software interprets the output as text rather than an integer (which would then immediately lose the leading zero) and the format is consistent with British Telecoms guidelines on number formatting - which also aids human memorability by dividing a long number into small, easily memorised, groups.


+441234567890 produces (01234) 567 890
02012345678 produces (020) 1234 5678
1923123456 produces (01923) 123 456
01923123456 produces (01923) 123 456
01923hello this is text123456 produces (01923) 123 456

The significance of the exchange segment of the number - in parentheses - is that in the UK, and most other countries, calls between numbers in the same exchange can be made omitting the exchange segment. This does not apply to 07, 08 and 09 series phone numbers however.

I'm sure that there are more efficient solutions, but this one has proved extremely reliable. More formats can easily be accomodated by adding to the teleNum function at the end.

The procedure is invoked from the calling script thus

$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
  • 31
  • 1
  • 5
1

Here is one that accepts a phonenumber as well as a country code, like formatPhoneNumber('+254722456789','KE')

            function StripPhoneNumber($code, &$phoneNumber)
            {
                $code = strtoupper($code);
                $code = preg_replace('/[^A-Z]/','',$code);
                $countryCode = "";
                $countries = [];
                $countries[] = array("code" => "AF", "name" => "Afghanistan", "d_code" => "+93");
                $countries[] = array("code" => "AL", "name" => "Albania", "d_code" => "+355");
                $countries[] = array("code" => "DZ", "name" => "Algeria", "d_code" => "+213");
                $countries[] = array("code" => "AS", "name" => "American Samoa", "d_code" => "+1");
                $countries[] = array("code" => "AD", "name" => "Andorra", "d_code" => "+376");
                $countries[] = array("code" => "AO", "name" => "Angola", "d_code" => "+244");
                $countries[] = array("code" => "AI", "name" => "Anguilla", "d_code" => "+1");
                $countries[] = array("code" => "AG", "name" => "Antigua", "d_code" => "+1");
                $countries[] = array("code" => "AR", "name" => "Argentina", "d_code" => "+54");
                $countries[] = array("code" => "AM", "name" => "Armenia", "d_code" => "+374");
                $countries[] = array("code" => "AW", "name" => "Aruba", "d_code" => "+297");
                $countries[] = array("code" => "AU", "name" => "Australia", "d_code" => "+61");
                $countries[] = array("code" => "AT", "name" => "Austria", "d_code" => "+43");
                $countries[] = array("code" => "AZ", "name" => "Azerbaijan", "d_code" => "+994");
                $countries[] = array("code" => "BH", "name" => "Bahrain", "d_code" => "+973");
                $countries[] = array("code" => "BD", "name" => "Bangladesh", "d_code" => "+880");
                $countries[] = array("code" => "BB", "name" => "Barbados", "d_code" => "+1");
                $countries[] = array("code" => "BY", "name" => "Belarus", "d_code" => "+375");
                $countries[] = array("code" => "BE", "name" => "Belgium", "d_code" => "+32");
                $countries[] = array("code" => "BZ", "name" => "Belize", "d_code" => "+501");
                $countries[] = array("code" => "BJ", "name" => "Benin", "d_code" => "+229");
                $countries[] = array("code" => "BM", "name" => "Bermuda", "d_code" => "+1");
                $countries[] = array("code" => "BT", "name" => "Bhutan", "d_code" => "+975");
                $countries[] = array("code" => "BO", "name" => "Bolivia", "d_code" => "+591");
                $countries[] = array("code" => "BA", "name" => "Bosnia and Herzegovina", "d_code" => "+387");
                $countries[] = array("code" => "BW", "name" => "Botswana", "d_code" => "+267");
                $countries[] = array("code" => "BR", "name" => "Brazil", "d_code" => "+55");
                $countries[] = array("code" => "IO", "name" => "British Indian Ocean Territory", "d_code" => "+246");
                $countries[] = array("code" => "VG", "name" => "British Virgin Islands", "d_code" => "+1");
                $countries[] = array("code" => "BN", "name" => "Brunei", "d_code" => "+673");
                $countries[] = array("code" => "BG", "name" => "Bulgaria", "d_code" => "+359");
                $countries[] = array("code" => "BF", "name" => "Burkina Faso", "d_code" => "+226");
                $countries[] = array("code" => "MM", "name" => "Burma Myanmar", "d_code" => "+95");
                $countries[] = array("code" => "BI", "name" => "Burundi", "d_code" => "+257");
                $countries[] = array("code" => "KH", "name" => "Cambodia", "d_code" => "+855");
                $countries[] = array("code" => "CM", "name" => "Cameroon", "d_code" => "+237");
                $countries[] = array("code" => "CA", "name" => "Canada", "d_code" => "+1");
                $countries[] = array("code" => "CV", "name" => "Cape Verde", "d_code" => "+238");
                $countries[] = array("code" => "KY", "name" => "Cayman Islands", "d_code" => "+1");
                $countries[] = array("code" => "CF", "name" => "Central African Republic", "d_code" => "+236");
                $countries[] = array("code" => "TD", "name" => "Chad", "d_code" => "+235");
                $countries[] = array("code" => "CL", "name" => "Chile", "d_code" => "+56");
                $countries[] = array("code" => "CN", "name" => "China", "d_code" => "+86");
                $countries[] = array("code" => "CO", "name" => "Colombia", "d_code" => "+57");
                $countries[] = array("code" => "KM", "name" => "Comoros", "d_code" => "+269");
                $countries[] = array("code" => "CK", "name" => "Cook Islands", "d_code" => "+682");
                $countries[] = array("code" => "CR", "name" => "Costa Rica", "d_code" => "+506");
                $countries[] = array("code" => "CI", "name" => "Côte d'Ivoire", "d_code" => "+225");
                $countries[] = array("code" => "HR", "name" => "Croatia", "d_code" => "+385");
                $countries[] = array("code" => "CU", "name" => "Cuba", "d_code" => "+53");
                $countries[] = array("code" => "CY", "name" => "Cyprus", "d_code" => "+357");
                $countries[] = array("code" => "CZ", "name" => "Czech Republic", "d_code" => "+420");
                $countries[] = array("code" => "CD", "name" => "Democratic Republic of Congo", "d_code" => "+243");
                $countries[] = array("code" => "DK", "name" => "Denmark", "d_code" => "+45");
                $countries[] = array("code" => "DJ", "name" => "Djibouti", "d_code" => "+253");
                $countries[] = array("code" => "DM", "name" => "Dominica", "d_code" => "+1");
                $countries[] = array("code" => "DO", "name" => "Dominican Republic", "d_code" => "+1");
                $countries[] = array("code" => "EC", "name" => "Ecuador", "d_code" => "+593");
                $countries[] = array("code" => "EG", "name" => "Egypt", "d_code" => "+20");
                $countries[] = array("code" => "SV", "name" => "El Salvador", "d_code" => "+503");
                $countries[] = array("code" => "GQ", "name" => "Equatorial Guinea", "d_code" => "+240");
                $countries[] = array("code" => "ER", "name" => "Eritrea", "d_code" => "+291");
                $countries[] = array("code" => "EE", "name" => "Estonia", "d_code" => "+372");
                $countries[] = array("code" => "ET", "name" => "Ethiopia", "d_code" => "+251");
                $countries[] = array("code" => "FK", "name" => "Falkland Islands", "d_code" => "+500");
                $countries[] = array("code" => "FO", "name" => "Faroe Islands", "d_code" => "+298");
                $countries[] = array("code" => "FM", "name" => "Federated States of Micronesia", "d_code" => "+691");
                $countries[] = array("code" => "FJ", "name" => "Fiji", "d_code" => "+679");
                $countries[] = array("code" => "FI", "name" => "Finland", "d_code" => "+358");
                $countries[] = array("code" => "FR", "name" => "France", "d_code" => "+33");
                $countries[] = array("code" => "GF", "name" => "French Guiana", "d_code" => "+594");
                $countries[] = array("code" => "PF", "name" => "French Polynesia", "d_code" => "+689");
                $countries[] = array("code" => "GA", "name" => "Gabon", "d_code" => "+241");
                $countries[] = array("code" => "GE", "name" => "Georgia", "d_code" => "+995");
                $countries[] = array("code" => "DE", "name" => "Germany", "d_code" => "+49");
                $countries[] = array("code" => "GH", "name" => "Ghana", "d_code" => "+233");
                $countries[] = array("code" => "GI", "name" => "Gibraltar", "d_code" => "+350");
                $countries[] = array("code" => "GR", "name" => "Greece", "d_code" => "+30");
                $countries[] = array("code" => "GL", "name" => "Greenland", "d_code" => "+299");
                $countries[] = array("code" => "GD", "name" => "Grenada", "d_code" => "+1");
                $countries[] = array("code" => "GP", "name" => "Guadeloupe", "d_code" => "+590");
                $countries[] = array("code" => "GU", "name" => "Guam", "d_code" => "+1");
                $countries[] = array("code" => "GT", "name" => "Guatemala", "d_code" => "+502");
                $countries[] = array("code" => "GN", "name" => "Guinea", "d_code" => "+224");
                $countries[] = array("code" => "GW", "name" => "Guinea-Bissau", "d_code" => "+245");
                $countries[] = array("code" => "GY", "name" => "Guyana", "d_code" => "+592");
                $countries[] = array("code" => "HT", "name" => "Haiti", "d_code" => "+509");
                $countries[] = array("code" => "HN", "name" => "Honduras", "d_code" => "+504");
                $countries[] = array("code" => "HK", "name" => "Hong Kong", "d_code" => "+852");
                $countries[] = array("code" => "HU", "name" => "Hungary", "d_code" => "+36");
                $countries[] = array("code" => "IS", "name" => "Iceland", "d_code" => "+354");
                $countries[] = array("code" => "IN", "name" => "India", "d_code" => "+91");
                $countries[] = array("code" => "ID", "name" => "Indonesia", "d_code" => "+62");
                $countries[] = array("code" => "IR", "name" => "Iran", "d_code" => "+98");
                $countries[] = array("code" => "IQ", "name" => "Iraq", "d_code" => "+964");
                $countries[] = array("code" => "IE", "name" => "Ireland", "d_code" => "+353");
                $countries[] = array("code" => "IL", "name" => "Israel", "d_code" => "+972");
                $countries[] = array("code" => "IT", "name" => "Italy", "d_code" => "+39");
                $countries[] = array("code" => "JM", "name" => "Jamaica", "d_code" => "+1");
                $countries[] = array("code" => "JP", "name" => "Japan", "d_code" => "+81");
                $countries[] = array("code" => "JO", "name" => "Jordan", "d_code" => "+962");
                $countries[] = array("code" => "KZ", "name" => "Kazakhstan", "d_code" => "+7");
                $countries[] = array("code" => "KE", "name" => "Kenya", "d_code" => "+254");
                $countries[] = array("code" => "KI", "name" => "Kiribati", "d_code" => "+686");
                $countries[] = array("code" => "XK", "name" => "Kosovo", "d_code" => "+381");
                $countries[] = array("code" => "KW", "name" => "Kuwait", "d_code" => "+965");
                $countries[] = array("code" => "KG", "name" => "Kyrgyzstan", "d_code" => "+996");
                $countries[] = array("code" => "LA", "name" => "Laos", "d_code" => "+856");
                $countries[] = array("code" => "LV", "name" => "Latvia", "d_code" => "+371");
                $countries[] = array("code" => "LB", "name" => "Lebanon", "d_code" => "+961");
                $countries[] = array("code" => "LS", "name" => "Lesotho", "d_code" => "+266");
                $countries[] = array("code" => "LR", "name" => "Liberia", "d_code" => "+231");
                $countries[] = array("code" => "LY", "name" => "Libya", "d_code" => "+218");
                $countries[] = array("code" => "LI", "name" => "Liechtenstein", "d_code" => "+423");
                $countries[] = array("code" => "LT", "name" => "Lithuania", "d_code" => "+370");
                $countries[] = array("code" => "LU", "name" => "Luxembourg", "d_code" => "+352");
                $countries[] = array("code" => "MO", "name" => "Macau", "d_code" => "+853");
                $countries[] = array("code" => "MK", "name" => "Macedonia", "d_code" => "+389");
                $countries[] = array("code" => "MG", "name" => "Madagascar", "d_code" => "+261");
                $countries[] = array("code" => "MW", "name" => "Malawi", "d_code" => "+265");
                $countries[] = array("code" => "MY", "name" => "Malaysia", "d_code" => "+60");
                $countries[] = array("code" => "MV", "name" => "Maldives", "d_code" => "+960");
                $countries[] = array("code" => "ML", "name" => "Mali", "d_code" => "+223");
                $countries[] = array("code" => "MT", "name" => "Malta", "d_code" => "+356");
                $countries[] = array("code" => "MH", "name" => "Marshall Islands", "d_code" => "+692");
                $countries[] = array("code" => "MQ", "name" => "Martinique", "d_code" => "+596");
                $countries[] = array("code" => "MR", "name" => "Mauritania", "d_code" => "+222");
                $countries[] = array("code" => "MU", "name" => "Mauritius", "d_code" => "+230");
                $countries[] = array("code" => "YT", "name" => "Mayotte", "d_code" => "+262");
                $countries[] = array("code" => "MX", "name" => "Mexico", "d_code" => "+52");
                $countries[] = array("code" => "MD", "name" => "Moldova", "d_code" => "+373");
                $countries[] = array("code" => "MC", "name" => "Monaco", "d_code" => "+377");
                $countries[] = array("code" => "MN", "name" => "Mongolia", "d_code" => "+976");
                $countries[] = array("code" => "ME", "name" => "Montenegro", "d_code" => "+382");
                $countries[] = array("code" => "MS", "name" => "Montserrat", "d_code" => "+1");
                $countries[] = array("code" => "MA", "name" => "Morocco", "d_code" => "+212");
                $countries[] = array("code" => "MZ", "name" => "Mozambique", "d_code" => "+258");
                $countries[] = array("code" => "NA", "name" => "Namibia", "d_code" => "+264");
                $countries[] = array("code" => "NR", "name" => "Nauru", "d_code" => "+674");
                $countries[] = array("code" => "NP", "name" => "Nepal", "d_code" => "+977");
                $countries[] = array("code" => "NL", "name" => "Netherlands", "d_code" => "+31");
                $countries[] = array("code" => "AN", "name" => "Netherlands Antilles", "d_code" => "+599");
                $countries[] = array("code" => "NC", "name" => "New Caledonia", "d_code" => "+687");
                $countries[] = array("code" => "NZ", "name" => "New Zealand", "d_code" => "+64");
                $countries[] = array("code" => "NI", "name" => "Nicaragua", "d_code" => "+505");
                $countries[] = array("code" => "NE", "name" => "Niger", "d_code" => "+227");
                $countries[] = array("code" => "NG", "name" => "Nigeria", "d_code" => "+234");
                $countries[] = array("code" => "NU", "name" => "Niue", "d_code" => "+683");
                $countries[] = array("code" => "NF", "name" => "Norfolk Island", "d_code" => "+672");
                $countries[] = array("code" => "KP", "name" => "North Korea", "d_code" => "+850");
                $countries[] = array("code" => "MP", "name" => "Northern Mariana Islands", "d_code" => "+1");
                $countries[] = array("code" => "NO", "name" => "Norway", "d_code" => "+47");
                $countries[] = array("code" => "OM", "name" => "Oman", "d_code" => "+968");
                $countries[] = array("code" => "PK", "name" => "Pakistan", "d_code" => "+92");
                $countries[] = array("code" => "PW", "name" => "Palau", "d_code" => "+680");
                $countries[] = array("code" => "PS", "name" => "Palestine", "d_code" => "+970");
                $countries[] = array("code" => "PA", "name" => "Panama", "d_code" => "+507");
                $countries[] = array("code" => "PG", "name" => "Papua New Guinea", "d_code" => "+675");
                $countries[] = array("code" => "PY", "name" => "Paraguay", "d_code" => "+595");
                $countries[] = array("code" => "PE", "name" => "Peru", "d_code" => "+51");
                $countries[] = array("code" => "PH", "name" => "Philippines", "d_code" => "+63");
                $countries[] = array("code" => "PL", "name" => "Poland", "d_code" => "+48");
                $countries[] = array("code" => "PT", "name" => "Portugal", "d_code" => "+351");
                $countries[] = array("code" => "PR", "name" => "Puerto Rico", "d_code" => "+1");
                $countries[] = array("code" => "QA", "name" => "Qatar", "d_code" => "+974");
                $countries[] = array("code" => "CG", "name" => "Republic of the Congo", "d_code" => "+242");
                $countries[] = array("code" => "RE", "name" => "Réunion", "d_code" => "+262");
                $countries[] = array("code" => "RO", "name" => "Romania", "d_code" => "+40");
                $countries[] = array("code" => "RU", "name" => "Russia", "d_code" => "+7");
                $countries[] = array("code" => "RW", "name" => "Rwanda", "d_code" => "+250");
                $countries[] = array("code" => "BL", "name" => "Saint Barthélemy", "d_code" => "+590");
                $countries[] = array("code" => "SH", "name" => "Saint Helena", "d_code" => "+290");
                $countries[] = array("code" => "KN", "name" => "Saint Kitts and Nevis", "d_code" => "+1");
                $countries[] = array("code" => "MF", "name" => "Saint Martin", "d_code" => "+590");
                $countries[] = array("code" => "PM", "name" => "Saint Pierre and Miquelon", "d_code" => "+508");
                $countries[] = array("code" => "VC", "name" => "Saint Vincent and the Grenadines", "d_code" => "+1");
                $countries[] = array("code" => "WS", "name" => "Samoa", "d_code" => "+685");
                $countries[] = array("code" => "SM", "name" => "San Marino", "d_code" => "+378");
                $countries[] = array("code" => "ST", "name" => "São Tomé and Príncipe", "d_code" => "+239");
                $countries[] = array("code" => "SA", "name" => "Saudi Arabia", "d_code" => "+966");
                $countries[] = array("code" => "SN", "name" => "Senegal", "d_code" => "+221");
                $countries[] = array("code" => "RS", "name" => "Serbia", "d_code" => "+381");
                $countries[] = array("code" => "SC", "name" => "Seychelles", "d_code" => "+248");
                $countries[] = array("code" => "SL", "name" => "Sierra Leone", "d_code" => "+232");
                $countries[] = array("code" => "SG", "name" => "Singapore", "d_code" => "+65");
                $countries[] = array("code" => "SK", "name" => "Slovakia", "d_code" => "+421");
                $countries[] = array("code" => "SI", "name" => "Slovenia", "d_code" => "+386");
                $countries[] = array("code" => "SB", "name" => "Solomon Islands", "d_code" => "+677");
                $countries[] = array("code" => "SO", "name" => "Somalia", "d_code" => "+252");
                $countries[] = array("code" => "ZA", "name" => "South Africa", "d_code" => "+27");
                $countries[] = array("code" => "KR", "name" => "South Korea", "d_code" => "+82");
                $countries[] = array("code" => "ES", "name" => "Spain", "d_code" => "+34");
                $countries[] = array("code" => "LK", "name" => "Sri Lanka", "d_code" => "+94");
                $countries[] = array("code" => "LC", "name" => "St. Lucia", "d_code" => "+1");
                $countries[] = array("code" => "SD", "name" => "Sudan", "d_code" => "+249");
                $countries[] = array("code" => "SR", "name" => "Suriname", "d_code" => "+597");
                $countries[] = array("code" => "SZ", "name" => "Swaziland", "d_code" => "+268");
                $countries[] = array("code" => "SE", "name" => "Sweden", "d_code" => "+46");
                $countries[] = array("code" => "CH", "name" => "Switzerland", "d_code" => "+41");
                $countries[] = array("code" => "SY", "name" => "Syria", "d_code" => "+963");
                $countries[] = array("code" => "TW", "name" => "Taiwan", "d_code" => "+886");
                $countries[] = array("code" => "TJ", "name" => "Tajikistan", "d_code" => "+992");
                $countries[] = array("code" => "TZ", "name" => "Tanzania", "d_code" => "+255");
                $countries[] = array("code" => "TH", "name" => "Thailand", "d_code" => "+66");
                $countries[] = array("code" => "BS", "name" => "The Bahamas", "d_code" => "+1");
                $countries[] = array("code" => "GM", "name" => "The Gambia", "d_code" => "+220");
                $countries[] = array("code" => "TL", "name" => "Timor-Leste", "d_code" => "+670");
                $countries[] = array("code" => "TG", "name" => "Togo", "d_code" => "+228");
                $countries[] = array("code" => "TK", "name" => "Tokelau", "d_code" => "+690");
                $countries[] = array("code" => "TO", "name" => "Tonga", "d_code" => "+676");
                $countries[] = array("code" => "TT", "name" => "Trinidad and Tobago", "d_code" => "+1");
                $countries[] = array("code" => "TN", "name" => "Tunisia", "d_code" => "+216");
                $countries[] = array("code" => "TR", "name" => "Turkey", "d_code" => "+90");
                $countries[] = array("code" => "TM", "name" => "Turkmenistan", "d_code" => "+993");
                $countries[] = array("code" => "TC", "name" => "Turks and Caicos Islands", "d_code" => "+1");
                $countries[] = array("code" => "TV", "name" => "Tuvalu", "d_code" => "+688");
                $countries[] = array("code" => "UG", "name" => "Uganda", "d_code" => "+256");
                $countries[] = array("code" => "UA", "name" => "Ukraine", "d_code" => "+380");
                $countries[] = array("code" => "AE", "name" => "United Arab Emirates", "d_code" => "+971");
                $countries[] = array("code" => "GB", "name" => "United Kingdom", "d_code" => "+44");
                $countries[] = array("code" => "US", "name" => "United States", "d_code" => "+1");
                $countries[] = array("code" => "UY", "name" => "Uruguay", "d_code" => "+598");
                $countries[] = array("code" => "VI", "name" => "US Virgin Islands", "d_code" => "+1");
                $countries[] = array("code" => "UZ", "name" => "Uzbekistan", "d_code" => "+998");
                $countries[] = array("code" => "VU", "name" => "Vanuatu", "d_code" => "+678");
                $countries[] = array("code" => "VA", "name" => "Vatican City", "d_code" => "+39");
                $countries[] = array("code" => "VE", "name" => "Venezuela", "d_code" => "+58");
                $countries[] = array("code" => "VN", "name" => "Vietnam", "d_code" => "+84");
                $countries[] = array("code" => "WF", "name" => "Wallis and Futuna", "d_code" => "+681");
                $countries[] = array("code" => "YE", "name" => "Yemen", "d_code" => "+967");
                $countries[] = array("code" => "ZM", "name" => "Zambia", "d_code" => "+260");
                $countries[] = array("code" => "ZW", "name" => "Zimbabwe", "d_code" => "+263");

                $code = strtoupper($code);
                $UsephoneNumber = " "."+";
                $UsephoneNumber = $UsephoneNumber.(preg_replace('/[^0-9]/','',$phoneNumber));

                for($index=0; $index<count($countries); $index++)
                {
                    $array1 = $countries[$index];
                    if($array1['code'] == $code)
                    {
                        $dCode = $array1['d_code'];
                        $explode_ = explode($dCode, $UsephoneNumber, 2);
                        if(count($explode_) == 2)
                        {
                            $phoneNumber = $explode_[1];
                            $countryCode = $dCode;
                        }
                        break;
                    }
                }

                return $countryCode;
            }


            function formatPhoneNumber($phoneNumber, $code="") {

                $countryCode = StripPhoneNumber($code, $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;
                }
                else
                {
                    $sub = "";
                    while(strlen($phoneNumber) >= 3)
                    {
                        if( strlen($phoneNumber) >= 3 && (strlen($phoneNumber) % 2 != 0) )
                        {
                            $sub = $sub.substr($phoneNumber, 0, 3)." ";
                            $phoneNumber = substr($phoneNumber, 3);
                        }
                        else
                        if( (strlen($phoneNumber) % 2 == 0) && strlen($phoneNumber) >= 2 )
                        {
                           $sub = $sub.substr($phoneNumber, 0, 2)." ";
                           $phoneNumber = substr($phoneNumber, 2);
                        }
                    }

                    if( strlen($phoneNumber) > 0)
                    {
                        $sub = $sub.$phoneNumber." ";
                    }

                    $phoneNumber = trim($sub," ");

                }

                return $countryCode." ".$phoneNumber;
            }
Mnyikka
  • 1,223
  • 17
  • 12
  • Where did you get this code from? Did you write it yourself? If not, you need to provide [attribution](https://stackoverflow.com/help/referencing) to the original source. – Cody Gray - on strike Oct 13 '21 at 10:36
0

This is a little function I use for a lot of my code. I know this SO question is pretty old, but I stumbled on it while looking for something else so figured maybe this would help someone else, idk...

/**
 * Format a provided phone number, with options
 * 
 * @param  string  $phone        The phone number to validate
 * @param  string  $phoneFormat  The format we want the number to be in, standard 10 digit no CC by default
 * @param  string  $countryCode  The country code, default is 1 for US
 * @return string                The formatted phone number, or 'INVALID' if the number could not be parsed 
 *                                 to the given format, or 'EMPTY' if this lead has no phone
 */
function validatePhone(string $phone, string $phoneFormat = "<NPA><NXX><XXXX>", string $countryCode = '1'): string
{
    if (empty($phone)) {
        return "EMPTY";
    }

    $phone = preg_replace("/(^\+1)|(^\+)|(^1)/", "", $phone);
    if (preg_match("/^.*(?P<NPA>\d{3}).*(?P<NXX>\d{3}).*(?P<XXXX>\d{4})$/", $phone, $parts)) {
        $phoneFormat = preg_replace('/<CC>/', $countryCode, $phoneFormat);
        $phoneFormat = preg_replace('/<NPA>/', $parts['NPA'], $phoneFormat);
        $phoneFormat = preg_replace('/<NXX>/', $parts['NXX'], $phoneFormat);
        $phoneFormat = preg_replace('/<XXXX>/', $parts['XXXX'], $phoneFormat);

        return $phoneFormat;
    } else {
        return "INVALID";
    }
}
ajax1515
  • 190
  • 1
  • 13