Monday, February 23, 2009

Translate and format phone number with PHP

Prior to writing some function that I plan reusing in couple of different places I often do a research at how other people solve my problem. Sometimes it saves time by giving an easily modifiable and customizable piece of code, sometimes shows how not to do, sometimes just lets me know where my personal solution would've failed and how to fix it.
Also my memory is not very good so I often forget functions I rarely use or haven't used at all but read it's docs.

This one got me really frustrated that most of solutions I've seen within first 3 or 4 pages on Google and with couple of different search queries (all together I saw over 50 solutions including identical) were written in a very long form, which did not add functionality to the code but even made it more limited for different variations of phone number 'spelling'.

In USA phone number can be at least written in these forms and there will be many other ways that I didn't think off (why am I supposed to think of every way phone number could be spelled if I am writing a universal function??):

+1 (800) 282-8623
800.282.8623
(800) 282 - 8623
1.800.CUCUMBER

May be I was searching wrong but I didn't find a short all in one universal solution. I didn't find a solution that would be shorter than mine. But main thing that I didn't find was converting branded phone number (i.e. 1800flowers.com) to it's numeric representation. Obviously I knew I can do it with a simple enough RegEx but I hoped I will see how other people do it.

So here's what I've got in the first place:

function _format_phone ($phone) {
$regex = array('/[^0-9A-Z]/i','/[ABC]/i','/[DEF]/i','/[GHI]/i','/[JKL]/i','/[MNO]/i','/[PQRS]/i','/[TUV]/i','/[WXYZ]/i');
$replace = array('',2,3,4,5,6,7,8,9);
$new_phone = preg_replace($regex,$replace,$phone);
if (preg_match("/^[1]?[2-9][0-8]\d[2-9]\d{2}\d{4}\d*$/",$new_phone)) {
return preg_replace("/^[1]?([2-9][0-8]\d)([2-9]\d{2})(\d{4})([0-9]*)$/", "$1-$2-$3", $new_phone);
} else {
return $phone;
}
}
OR:
function _format_phone ($phone) {
$new_phone = preg_replace('/[^0-9A-Z]/i','',$phone);
$new_phone = strtr($phone,'abcdefghijklmnopqrstuvwxyz','22233344455566677778889999');
if (preg_match("/^[1]?[2-9][0-8]\d[2-9]\d{2}\d{4}\d*$/",$new_phone)) {
return preg_replace("/^[1]?([2-9][0-8]\d)([2-9]\d{2})(\d{4})([0-9]*)$/", "$1-$2-$3", $new_phone);
} else {
return $phone;
}
}
Well, after bashing other solutions I accept that my solution is not ideal either. At least I'm concerned about IF statement containing check for RegEx while using preg_replace() twice. However I think it's much more functional and shorter than many others at the same time. At least in 7-8 lines it provides more functionality:
  • Cleanup all formatting characters
  • Translate letters to numbers
  • Format phone number to desired standard (very customizable)
  • Fail silently by returning original phone number if something went wrong

5 comments:

  1. I like the 2nd, it's more readable.
    You forgot extensions ;-)

    I'm messing around with isapi_rewrite and their tech sux. Wanna help?

    ReplyDelete
  2. No I didn't but this is really a choice of two - either this code is compatible with 800CUCUMBER or with EXT 163 - depends on how you will format output:
    "($1) $2-$3 Ext. $4"

    And yes this is not a universal solution. Though it is shorter and more functional/customizable then many of what you can find on google

    ReplyDelete
  3. Yeah actually you right, it lacks a check for words Ext. and so. It's just another regex which will stripe it out.

    However I'd say that even if you ask for a phone number in one field, extension field should be another field otherwise i think it will be confusing.

    ReplyDelete
  4. Regarding isapi_rewrite - what exactly you need?

    ReplyDelete
  5. HI;

    thaks for posting the function. is there a way to format international numbers ?

    thanks

    ReplyDelete

Please be moderate saying your thoughts and do not offend others.