中國大陸手機號為 11 位數字,首位固定為 1,第二位為 3-9。但簡單的 /^1\d{10}$/ 會放行「18888888888」這類明顯無效號碼。本文遞進式講解:基礎格式校驗 → 運營商段號白名單 → 綜合驗證函數,並提供可直接落地的代碼。
僅檢查長度與首位,適合快速原型或非核心業務。
$mobile = '15858588585';
if (!preg_match('/^1[0-9]{10}$/', $mobile)) {
exit('手機號格式不正確');
}
| 運營商 | 號段(前三位) |
|---|---|
| 移動 | 134、135、136、137、138、139、147、150、151、152、157、158、159、172、178、182、183、184、187、188、195、197、198 |
| 聯通 | 130、131、132、145、155、156、166、167、171、175、176、185、186、196 |
| 電信 | 133、149、153、173、174、177、180、181、189、190、191、193、199 |
| 廣電 | 192 |
| 虛擬運營商 | 170、171、165、167、171 等 |
整理上述號段生成正則,支持新增段號擴展。函數返回布爾值,便於業務邏輯判斷。
function isMobile($str) {
// 移動、聯通、電信、廣電、虛商主流段號
$pattern = '/^1(?:3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/';
return (bool)preg_match($pattern, $str);
}
// 使用示例
$phones = ['13800138000', '18888888888', '19212345678', '12345678901'];
foreach ($phones as $phone) {
echo $phone . ' => ' . (isMobile($phone) ? '有效' : '無效') . "\n";
}
業務場景如發送差異化短信模板、風控分級,需判斷具體運營商。
function getCarrier($mobile) {
if (!isMobile($mobile)) return 'invalid';
$prefix = substr($mobile, 0, 3);
$mobilePrefixes = ['134','135','136','137','138','139','147','150','151','152','157','158','159','172','178','182','183','184','187','188','195','197','198'];
$unicomPrefixes = ['130','131','132','145','155','156','166','167','171','175','176','185','186','196'];
$telecomPrefixes = ['133','149','153','173','174','177','180','181','189','190','191','193','199'];
$broadcastPrefixes = ['192'];
if (in_array($prefix, $mobilePrefixes)) return 'mobile';
if (in_array($prefix, $unicomPrefixes)) return 'unicom';
if (in_array($prefix, $telecomPrefixes)) return 'telecom';
if (in_array($prefix, $broadcastPrefixes)) return 'broadcast';
return 'virtual';
}
libphonenumber 庫而非自寫正則。