首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 手機號碼驗證:正則表達式與最佳實踐完整指南

     編輯:PHP 相關知識

前言

在 Web 開發中,手機號碼驗證是表單檢核的基礎環節。雖然正則表達式能快速實現格式檢查,但隨著運營商不斷推出新號段,單純靠正則維護已力不從心。本文將系統梳理 PHP 手機號驗證的演進歷程,提供從基礎正則到號段白名單的完整方案,並探討實戰中的避坑指南。

一、中國大陸手機號段分佈(截至 2023 年)

了解號段分佈是編寫正則的前提。三大運營商核心號段如下:

  • 移動:134、135、136、137、138、139、147、148、150、151、152、157、158、159、172、178、182、183、184、187、188、195、197、198
  • 聯通:130、131、132、145、146、155、156、166、167、171、175、176、185、186、196
  • 電信:133、149、153、173、174、177、180、181、189、190、191、193、199
  • 虛擬運營商:170、171、165、167、162 等
提示:號段更新頻率極高,建議定期同步工信部最新公告,或接入第三方號段庫 API。

二、常見正則表達式演進

1. 早期簡易版(僅驗證 11 位數字開頭)

$pattern = '/^1[3-9]\d{9}$/';

優點:簡潔、效能高;缺點:無法過濾不存在的號段(如 120、110 等)。

2. 進階版(針對已知號段)

$pattern = '/^(?:13\d|14[5-9]|15[0-35-9]|16[25-7]|17[0-8]|18\d|19[0-35-9])\d{8}$/';

涵蓋主流號段,但新號段推出後需手動維護。

3. 實戰推薦:號段白名單 + 正則雙重驗證

function isMobile(string $mobile): bool
{
    // 1. 基礎格式檢查
    if (!preg_match('/^1[3-9]\d{9}$/', $mobile)) {
        return false;
    }

    // 2. 號段白名單檢查(建議從配置檔或資料庫讀取)
    $prefix = substr($mobile, 0, 3);
    $validPrefixes = [
        130,131,132,133,134,135,136,137,138,139,
        145,146,147,148,149,
        150,151,152,153,155,156,157,158,159,
        162,165,166,167,
        170,171,172,173,174,175,176,177,178,
        180,181,182,183,184,185,186,187,188,189,
        190,191,192,193,195,196,197,198,199
    ];

    return in_array((int)$prefix, $validPrefixes, true);
}

三、完整驗證類封裝

class MobileValidator
{
    private static array $prefixCache = [];

    public static function validate(string $mobile, bool $strict = true): bool
    {
        $mobile = trim($mobile);
        if ($mobile === '') return false;

        // 基礎正則
        if (!preg_match('/^1[3-9]\d{9}$/', $mobile)) {
            return false;
        }

        if (!$strict) return true;

        // 嚴格模式:號段白名單
        $prefix = (int)substr($mobile, 0, 3);
        return self::isValidPrefix($prefix);
    }

    private static function isValidPrefix(int $prefix): bool
    {
        if (empty(self::$prefixCache)) {
            self::$prefixCache = array_flip([
                130,131,132,133,134,135,136,137,138,139,
                145,146,147,148,149,
                150,151,152,153,155,156,157,158,159,
                162,165,166,167,
                170,171,172,173,174,175,176,177,178,
                180,181,182,183,184,185,186,187,188,189,
                190,191,192,193,195,196,197,198,199
            ]);
        }
        return isset(self::$prefixCache[$prefix]);
    }
}

// 使用範例
$mobile = '13800138000';
if (MobileValidator::validate($mobile)) {
    echo '手機號格式正確';
} else {
    echo '手機號格式錯誤';
}

四、進階場景:批量提取與驗證

從文本中批量提取手機號並驗證:

function extractMobiles(string $text): array
{
    preg_match_all('/1[3-9]\d{9}/', $text, $matches);
    $mobiles = array_unique($matches[0] ?? []);
    return array_filter($mobiles, fn($m) => MobileValidator::validate($m));
}

$content = '聯繫電話:13800138000,備用:15912345678,無效:12012345678';
$validMobiles = extractMobiles($content);
// 結果:['13800138000', '15912345678']

五、常見坑點與避雷指南

  1. 不要寫死正則:號段變動頻繁,硬編碼正則會導致誤判。採用「正則 + 白名單」架構,白名單獨立維護。
  2. 區分「格式合法」與「真實可用」:正則只能驗證格式,無法確認號碼是否真實在用。關鍵業務(如註冊、支付)必須配合短信驗證碼。
  3. 注意隱私合規:收集手機號需遵循《個人信息保護法》,最小化原則,加密存儲,明確告知用途。
  4. 國際化場景:若支援港澳台或海外號碼,建議引入 libphonenumber 等成熟庫,勿自行維護跨國正則。

六、效能優化建議

  • 高頻調用時,將白名單緩存至 Redis 或 APCu,避免重複陣列建構。
  • 使用 isset($cache[$prefix]) 替代 in_array(),時間複雜度從 O(n) 降為 O(1)。
  • 批量驗證時,先用正則過濾明顯無效值,再進入白名單檢查,減少無效計算。

七、總結

PHP 手機號驗證的核心不在於寫一個「完美正則」,而在於建立可維護的驗證體系:基礎正則攔截格式錯誤 → 白名單精準過濾號段 → 短信驗證確認真實性。將號段白名單外部化(配置檔、資料表、遠端 API),才能應對運營商頻繁變更的號段策略,實現長期穩定的驗證能力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved