推荐使用 Laravel-Phone 包验证手机号,它基于 Google libphonenumber,可准确识别有效性、归属地和类型;手写正则仅适用于纯国内11位场景,但无法识别空号、不支持国际格式。

直接用 phone 规则,别手写正则——除非你明确只要中国 11 位手机号,且不打算支持国际用户或带国家码的格式。
用 Laravel-Phone 包验证(推荐)
它基于 Google 的 libphonenumber,能真正识别号码有效性、归属地、类型(移动/固话),不是简单匹配长度或前缀。
- 安装:
composer require propaganistas/laravel-phone - 验证指定国家(如只允许中国和美国):
'phone' => 'phone:CN,US' - 动态读取国家字段(比如表单有
country_code字段):'phone' => 'phone:country_code',同时确保该字段存在且是两位 ISO 码 - 限制为移动号码:
'phone' => 'phone:mobile';排除免费号码:'phone' => 'phone:!toll_free' - 错误提示会自动使用
resources/lang/xx/validation.php中定义的'phone' => 'The :attribute field must be a valid number.'
手写正则验证(仅限国内 11 位)
适合极简场景,比如后台内部系统、纯国内用户、无国际扩展需求。但注意:它无法识别空号、销户号、虚拟运营商号段变更,也拒绝所有带 + 或国家码的合法格式(如 +8613912345678)。
- 基础正则:
'phone' => 'required|regex:/^1[3-9]\d{9}$/' - 带国家码可选:
'phone' => 'required|regex:/^\+?861[3-9]\d{9}$/' - 如果字段可能含空格、横线、括号等,先走中间件清理:
$request->merge(['phone' => preg_replace('/[^0-9+]/', '', $request->phone)])
结合短信验证码时的关键点
验证规则只是第一步。真实流程中,phone 字段必须和短信发送、校验、防刷环节对齐,否则规则再准也没用。
- 数据库字段建议设为
string(非整型),保留前导零和国家码 - 存库前统一转成 E.164 格式(如
+8613912345678),可用E164PhoneNumberCast自动处理 - 短信发送前,必须用
phone规则先过一遍——避免向无效号码发信浪费配额 -
unique:users,phone要配合格式标准化,否则13912345678和+8613912345678会被当成两个号码
最易被忽略的是:验证规则和数据库存储格式不一致。比如前端传 +86 139-1234-5678,后端用正则只认 13912345678,但存库时又没清理干净,导致唯一性校验失效或重复注册。务必在验证前做归一化。


















