手機號碼驗證是表單檢核的高頻需求,但運營商號段持續擴展,硬編碼舊版正則極易導致誤判。本文記錄一次真實的正則修正歷程,並給出可長期維護的最佳實踐。
// 原版正則:僅支援 13、15 開頭
function funcMtel($str) {
return (bool)preg_match("/(?:13\d{1}|15[03689])\d{8}$/", $str);
}
var_dump(funcMtel('18678785887')); // false ❌
測試發現 186 開頭的號碼驗證失敗,原因在於正則未涵蓋 18、17、19 等新號段。
function funcMtel($str) {
// 支援 13/14/15/17/18/19 開頭,第二位依運營商規則
return (bool)preg_match("/^1[3-9]\d{9}$/", $str);
}
var_dump(funcMtel('18678785887')); // true ✅
簡化為 ^1[3-9]\d{9}$ 即可覆蓋當前所有合法手機號(11 位、首位 1、第二位 3-9),既簡潔又具前瞻性。
號段規則隨時可能變更,建議將驗證邏輯封裝在共用庫中:
// common/Validator.php
class Validator {
public static function mobile($phone) {
return (bool)preg_match('/^1[3-9]\d{9}$/', $phone);
}
}
// 業務代碼中調用
if (!Validator::mobile($input)) {
throw new InvalidArgumentException('手機號格式錯誤');
}
未來調整號段規則時,只需修改一處,所有呼叫端自動生效,避免分散式硬編碼帶來的維護災難。
若業務需區分三大運營商,可進一步細化第二、三位規則,但需同步關注工信部最新號段公告,建議引入定期更新的第三方號段庫(如 overtrue/phonenumber)。