การจัดรูปแบบหมายเลขโทรศัพท์ใน PHP


103

ฉันกำลังทำงานกับแอป SMSและจำเป็นต้องสามารถแปลงหมายเลขโทรศัพท์ของผู้ส่งจาก+11234567890เป็น123-456-7890เพื่อให้สามารถเปรียบเทียบกับบันทึกในฐานข้อมูล MySQLได้

ตัวเลขจะถูกเก็บไว้ในรูปแบบหลังเพื่อใช้ที่อื่นบนไซต์และฉันไม่อยากเปลี่ยนรูปแบบนั้นเพราะจะต้องมีการแก้ไขโค้ดจำนวนมาก

ฉันจะทำอย่างไรกับ PHP นี้

ขอบคุณ!


13
อ่า .... NOOOO .... ทำไมเก็บเบอร์โทรไว้แบบนั้น!? เป็นสตริง? เลวเลว! คุณควรจัดเก็บเป็น ints ขนาดใหญ่ ... พื้นที่เก็บข้อมูลน้อยลงดัชนีเร็วขึ้นเรียงลำดับได้เร็วขึ้น
sethvargo

7
ไม่ค่อยมีปัญหากับการจัดเก็บหมายเลขโทรศัพท์เป็นสตริง (ไม่สามารถหลีกเลี่ยงได้เมื่อคุณต้องการจัดเก็บ +61 (0) 812345678) - แต่การจัดเก็บรูปแบบเฉพาะนั้นค่อนข้างยาก (เช่นตัวแยก) - ควรจัดรูปแบบให้ดีที่สุด ที่ชั้นการนำเสนอแทนที่จะเป็นชั้นข้อมูล
HorusKol

3
@NightMICU - นั่นเป็นวิธีที่ผิด 100% ในการทำเช่นนั้น ... คุณควรจัดเก็บเป็นจำนวนเต็มและมีฟังก์ชันที่ใช้ซ้ำได้ซึ่งจัดรูปแบบสำหรับการแสดงผล
sethvargo

231
การจัดเก็บหมายเลขโทรศัพท์เป็นจำนวนเต็มเพื่อประหยัดพื้นที่จัดเก็บเป็นความคิดที่น่ากลัว หมายเลขโทรศัพท์ไม่ใช่ตัวเลขในความหมายทั่วไปที่คุณจะคำนวณกับมัน ช่วงเวลาที่คุณต้องจัดเก็บหมายเลขนอกรูปแบบเฉพาะของสหรัฐอเมริกาซึ่งตัวเลขสามารถเริ่มต้นด้วย 0 คุณจะพบปัญหา ควรจัดเก็บข้อมูลนี้เป็นสตริง
Charles Sprayberry

2
@NightMICU ถ้ามันทำให้คุณรู้สึกดีขึ้นเกี่ยวกับการจัดเก็บเป็นสตริงแม้แต่ Jon Skeet ผู้ยิ่งใหญ่ก็บอกว่าอย่าเก็บเป็นจำนวนเต็มสำหรับปัญหาศูนย์ชั้นนำ stackoverflow.com/a/3483166/746010
Charles Sprayberry

คำตอบ:


109
$data = '+11234567890';

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

1
ในการจับช่องว่างที่เป็นไปได้และรูปแบบอื่น ๆ ของตัวเลขสากล: / ^ (\ +? \ d {1,2}?) [.-]? (? (\ d {3}))? [.-]? (\ d {3}) [.-]? (\ d {4}) $ /
TeckniX

3
@stoutie คุณคิดผิด $ ตรงกับ [0] คือข้อความรูปแบบที่ตรงกันทั้งหมดจากนั้นคุณต้อง array_shift ($ ที่ตรงกัน) ก่อนที่จะใช้ในลักษณะนั้น
Alexandre Reis Ribeiro

การจัดรูปแบบที่เอาต์พุตจะเร็วกว่าหรือไม่ ใช้sprintfหรือ `` printf``? ใครบางคนโปรดอธิบายให้ฉัน ฉันกำลังทำงานกับหมายเลขโทรศัพท์ในสหรัฐอเมริกาเท่านั้นและไม่คิดว่าการเรียกใช้ผ่านฟังก์ชันเอาต์พุตโดยใช้สตริงย่อยเป็นวิธีที่ดีที่สุด
Rafael

ฉันคิดว่าดังนั้นควรรวมการโหวตลงในความคิดเห็น ความคิดเห็นของ @Stoutie ทำให้เข้าใจผิด
peterchaula

2
ฉันขอโทษสำหรับน้องก่อนวันที่ตัวเองโพสต์ความคิดเห็นที่ผิดพลาดเมื่อหลายปีก่อน ฉันสัญญาว่าจะทำให้ดีขึ้นในอนาคต ความคิดเห็นที่คุณอ้างอิงดูเหมือนจะถูกลบไปแล้ว ทั้งหมดเป็นอย่างดี. สุขสันต์วันหยุด.
Stoutie

165

นี่คือฟอร์แมตเตอร์โทรศัพท์ของสหรัฐอเมริกาที่ทำงานกับหมายเลขเวอร์ชันต่างๆมากกว่าคำตอบปัจจุบัน

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

และนี่คือรายละเอียดของ 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 ")"

อัปเดต: 11 มีนาคม 2015 เพื่อใช้{0,7}แทน{,7}


จะเกิดอะไรขึ้นถ้าหมายเลขโทรศัพท์มีนามสกุล?
SpYk3HH

1
จุดดี - เรามีตัวอย่างลักษณะของส่วนขยายทั่วโลกหรือไม่? Proabaly บางอย่างเช่น~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})(?:[ \D#\-]*(\d{3,6}))?.*~.
Xeoncross

1
จะเกิดอะไรขึ้นหากผู้ใช้เว็บไซต์ของฉันไม่ใส่รหัสพื้นที่
skibulk

เราสามารถดูรายละเอียดว่าส่วนต่างๆของ regex กำลังทำอะไรอยู่ (ดังที่แสดงด้านล่างในคำตอบอื่น) ie: (\d{3}) // 3 digits [\d]// อักขระที่ไม่ใช่ตัวเลข
roberthuttinger

1
@WesleyMurch ดูเหมือนว่าจะมีการเปลี่ยนแปลงที่จับคู่นิพจน์ปกติที่ตอนนี้ต้องได้รับการปรับปรุงเพื่อ{,7} {0,7}ฉันได้อัปเดตรหัสแล้ว
Xeoncross

55

ฟังก์ชันนี้จะจัดรูปแบบหมายเลขโทรศัพท์ระหว่างประเทศ (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;
}

นี่เป็นสิ่งที่ดี แต่ฉันอยากจะชี้ให้เห็นว่าวงเล็บรอบรหัสพื้นที่หมายถึงตัวเลขที่ไม่บังคับ เขตอำนาจศาลส่วนใหญ่ไม่ถือว่ารหัสพื้นที่เป็นทางเลือกอีกต่อไปดังนั้นการแยกด้วยยัติภังค์อย่างง่ายจะแม่นยำกว่า
Vincent

31

สมมติว่าหมายเลขโทรศัพท์ของคุณมีรูปแบบที่แน่นอนเสมอคุณสามารถใช้ข้อมูลโค้ดนี้:

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

เพียงแค่สะท้อน $ ถึง var ... รักมันทำงานให้ฉันแค่นายอำเภอ
Samuel Ramzan

22

หมายเลขโทรศัพท์เป็นเรื่องยาก สำหรับโซลูชันสากลที่มีประสิทธิภาพมากขึ้นฉันขอแนะนำพอร์ต PHP ที่ได้รับการดูแลอย่างดีของlibphonenumberของ Googleไลบรารี

การใช้มันเช่นนี้

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

ฉันขอแนะนำให้ใช้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

Neato.

ทำงานได้ดีเช่นเดียวกับประเทศอื่น ๆ นอกเหนือจากสหรัฐอเมริกา เพียงใช้รหัสประเทศ ISO อื่นในparse()อาร์กิวเมนต์


2
ห้องสมุดที่ยอดเยี่ยม แต่โปรดทราบว่ามีขนาด 37 MB และ 1,500 ไฟล์! ในกรณีของฉันฉันมีหมายเลขโทรศัพท์จำนวน จำกัด ในการจัดรูปแบบดังนั้นฉันจึงตัดสินใจเพิ่มnumber_formattedคอลัมน์ในฐานข้อมูลของฉันและป้อนหมายเลขที่จัดรูปแบบด้วยตนเอง ยังคงใช้libphonenumberในเครื่องเพื่อสร้างตัวเลขที่จัดรูปแบบ แต่การรวมไลบรารีขนาดใหญ่สำหรับโครงการขนาดเล็กของฉันนั้นเกินความจำเป็น
Magnus W

9

นี่คือโซลูชันเฉพาะในสหรัฐอเมริกาของฉันโดยมีรหัสพื้นที่เป็นส่วนประกอบเสริมตัวคั่นที่จำเป็นสำหรับส่วนขยายและความคิดเห็น regex:

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

และนี่คือสคริปต์เพื่อทดสอบ:

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

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


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

ใช้ไลบรารีของ Google สำหรับการแยกวิเคราะห์การจัดรูปแบบและการตรวจสอบหมายเลขโทรศัพท์ระหว่างประเทศ: https://github.com/google/libphonenumber


3
ฉันคิดว่านี่เป็นคำตอบที่ถูกต้อง แต่ถ้าคุณต้องการให้เป็นประโยชน์ตามมาตรฐาน Stack Overflow คุณควรแก้ไขเพื่อรวมตัวอย่างการแก้ปัญหาของ OP โดยใช้ไลบรารีแทนที่จะแชร์ลิงก์
Alecg_O

1
ขอบคุณ @Alecg_O! ฉันได้เพิ่มตัวอย่าง
Viktor Jarnheimer

4

ฉันเห็นว่าสิ่งนี้เป็นไปได้โดยใช้ regex หรือการเรียก substr สองสามตัว (สมมติว่าอินพุตเป็นรูปแบบนั้นเสมอและไม่เปลี่ยนความยาวเป็นต้น)

สิ่งที่ต้องการ

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

ควรทำ


2

ลองสิ่งที่ชอบ:

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

นี้จะใช้เวลาเป็นจำนวน $ ของและแปลง8881112222 888-111-2222หวังว่านี่จะช่วยได้


1
แหล่งที่มาของคำแนะนำของคุณ: hotscripts.com/forums/php/36805-php-format-phone-numbers.html '.'ควรอัปเดตstr_replace ของ'-'หรือลบออก รวมอยู่ด้วยเนื่องจากกรณีการใช้งานเฉพาะที่ต้องเผชิญ - ด้วยความพยายามเพียงเล็กน้อยที่คุณสามารถแปลงpreg_replace('/\d{3}/', '$0-', substr($number, 2))และตอบคำถามได้โดยตรง
Iiridayn

2

อีกทางเลือกหนึ่ง - อัปเดตได้ง่ายเพื่อรับรูปแบบจากการกำหนดค่า

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

1

ทั้งหมด,

ฉันคิดว่าฉันแก้ไขแล้ว ทำงานกับไฟล์อินพุตปัจจุบันและมี 2 ฟังก์ชั่นต่อไปนี้ให้เสร็จสิ้น!

ฟังก์ชัน 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

ฟังก์ชัน 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

สังเกตว่าฉันมีสิ่งนี้ในคลาส lib ดังนั้นการเรียก "self :: validate_phone_number" จากฟังก์ชัน / วิธีการแรก

บรรทัดประกาศ # 32 ของฟังก์ชัน "validate_phone_number" ที่ฉันเพิ่ม:

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

เพื่อขอคืนสินค้าปลอมที่จำเป็นหากไม่ใช่หมายเลขโทรศัพท์ที่ถูกต้อง

ยังคงต้องทดสอบสิ่งนี้กับข้อมูลเพิ่มเติม แต่กำลังทำงานกับข้อมูลปัจจุบันด้วยรูปแบบปัจจุบันและฉันใช้สไตล์ '8' สำหรับชุดข้อมูลนี้โดยเฉพาะ

นอกจากนี้ฉันยังแสดงความคิดเห็นเกี่ยวกับตรรกะ "ส่วนขยาย" เนื่องจากฉันได้รับข้อผิดพลาดจากมันอยู่ตลอดเวลาโดยที่ฉันไม่มีข้อมูลนั้นในข้อมูลของฉัน


1

ซึ่งใช้เวลา 7, 10 และ 11 หลักลบอักขระเพิ่มเติมและเพิ่มขีดกลางโดยไปทางขวาไปซ้ายผ่านสตริง เปลี่ยนเส้นประเป็นช่องว่างหรือจุด

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

1

ฉันรู้ว่า OP กำลังขอรูปแบบ 123-456-7890 แต่จากคำตอบของ John Dulฉันได้แก้ไขเพื่อส่งคืนหมายเลขโทรศัพท์ในรูปแบบวงเล็บเช่น (123) 456-7890 หมายเลขนี้รองรับเฉพาะตัวเลข 7 และ 10 หลักเท่านั้น

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

1

นี่คือสิ่งที่ฉันทำ:

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

//  123-456-7890

sscanfฟังก์ชั่นใช้เวลาเป็นพารามิเตอร์ที่สองรูปแบบของสตริงบอกวิธีการตีความตัวละครจากสายแรก ในกรณีนี้หมายถึง 2 ตัวอักษร (%2c ) 3 ตัว 3 ตัว 4 ตัว

โดยปกติsscanfฟังก์ชันจะรวมตัวแปรเพื่อจับข้อมูลที่แยกออกมาด้วย หากไม่เป็นเช่นนั้นข้อมูลจะถูกส่งกลับในอาร์เรย์ที่ฉันเรียก$partsถ้าไม่ได้ข้อมูลที่เป็นผลตอบแทนในอาร์เรย์ซึ่งเราเรียก

printคำสั่ง outputs สตริงหยัน$part[0]ถูกละเว้น

ฉันใช้ฟังก์ชันที่คล้ายกันเพื่อจัดรูปแบบหมายเลขโทรศัพท์ของออสเตรเลีย

โปรดทราบว่าจากมุมมองของการจัดเก็บหมายเลขโทรศัพท์:

  • หมายเลขโทรศัพท์เป็นสตริง
  • ข้อมูลที่จัดเก็บไม่ควรมีการจัดรูปแบบเช่นเว้นวรรคหรือยัติภังค์

นี่เป็นโซลูชันที่สวยงามและอ่านง่ายที่สุด จูบ. ไม่ต้องเลื่อนอีกต่อไปหากสตริงอินพุตของคุณเป็นไปตามรูปแบบเดียวกันเสมอ ขอบคุณสำหรับการเพิ่มนี้
Musa

1

รูปแบบโทรศัพท์ของสหราชอาณาจักร

สำหรับแอปพลิเคชันที่ฉันพัฒนาขึ้นฉันพบว่าผู้คนป้อนหมายเลขโทรศัพท์ของตน 'ถูกต้อง' จากรูปแบบที่มนุษย์อ่านได้ แต่แทรกอักขระสุ่มต่างๆเช่น '-' '/' '+44' เป็นต้นปัญหาคือแอประบบคลาวด์ที่ จำเป็นต้องพูดคุยด้วยค่อนข้างเฉพาะเจาะจงเกี่ยวกับรูปแบบ แทนที่จะใช้นิพจน์ทั่วไป (อาจทำให้ผู้ใช้หงุดหงิด) ฉันสร้างคลาสอ็อบเจ็กต์ซึ่งประมวลผลตัวเลขที่ป้อนให้อยู่ในรูปแบบที่ถูกต้องก่อนที่จะประมวลผลโดยโมดูลการคงอยู่ แนวทางในการจัดรูปแบบตัวเลขซึ่งยังช่วยให้มนุษย์จดจำได้ด้วยการแบ่งตัวเลขที่ยาวออกเป็นกลุ่มเล็ก ๆ ที่จดจำได้ง่าย

รูปแบบของเอาต์พุตช่วยให้มั่นใจได้ว่าซอฟต์แวร์การรับใด ๆ ตีความผลลัพธ์เป็นข้อความแทนที่จะเป็นจำนวนเต็ม (ซึ่งจะเสียศูนย์นำหน้าทันที) และรูปแบบจะสอดคล้องกับBritish Telecoms


+441234567890 สร้าง (01234)
5677890 02012345678 สร้าง (020) 1234 5678
1923123456 สร้าง (01923)
123456 01923123456 สร้าง (01923)
123456 01923hello นี่คือ text123456 สร้าง (01923) 123456

ความสำคัญของส่วนการแลกเปลี่ยนของตัวเลข - ในวงเล็บ - คือในสหราชอาณาจักรและประเทศอื่น ๆ ส่วนใหญ่การโทรระหว่างหมายเลขในการแลกเปลี่ยนเดียวกันสามารถละเว้นส่วนการแลกเปลี่ยนได้ อย่างไรก็ตามใช้ไม่ได้กับหมายเลขโทรศัพท์ชุด 07, 08 และ 09

ฉันแน่ใจว่ามีโซลูชันที่มีประสิทธิภาพมากกว่านี้ แต่วิธีนี้ได้รับการพิสูจน์แล้วว่าเชื่อถือได้มาก รูปแบบอื่น ๆ สามารถรองรับได้อย่างง่ายดายโดยการเพิ่มฟังก์ชัน teleNum ในตอนท้าย

ขั้นตอนถูกเรียกใช้จากสคริปต์การโทรดังนั้น

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

0

สำหรับโทรศัพท์บ้านในสหราชอาณาจักรที่ไม่มีรหัสประเทศ

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

ผลลัพธ์:

2012345678
becomes
20 1234 5678

0

โปรดดูฟังก์ชันที่ใช้ย่อยที่สามารถเปลี่ยนรูปแบบได้

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

0

ตรวจสอบหมายเลขโทรศัพท์

$phone = '+385 99 1234 1234'

$str = preg_match('/^\+?\d{1,3}[\s-]?\d{1,3}[\s-]?\d{1,4}[\s-]?\d{1,4}$/', $phone);

if($str){
return true;
}else{
return false;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.