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