PHP身份证校验需结合长度、格式、加权因子和模11校验,仅正则易漏校验码错误等问题;手机号应适配新号段并区分虚拟运营商;邮箱推荐filter_var()但需防注入和验证MX记录。

PHP校验身份证号:18位规则比正则更可靠
只用正则匹配^\d{17}[\dXx]$会漏掉校验码错误、出生年份超限、地区码无效等问题。真实业务中必须补全加权因子和模11校验逻辑。
实操建议:
- 先用
strlen($id)快速排除长度不对的字符串(非18位直接返回false) - 用
preg_match('/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/', $id)筛出格式骨架,注意年份限定在1800–2099,月份日期需合法(但不校验闰年细节,交由checkdate()) - 最后计算校验码:取前17位,按
[7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]加权求和,对11取模得余数,查表['1','0','X','9','8','7','6','5','4','3','2']比对第18位
PHP验证手机号:别硬套通用正则,看运营商号段变化
国内手机号正则^1[3-9]\d{9}$已不够用——192、195、197、198等新号段上线,且虚拟运营商号段(如170/171)存在地域限制和实名要求差异。
实操建议:
- 优先用
filter_var($phone, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^1[3-9]\d{9}$/']])做基础过滤,但仅作第一道防线 - 对170/171/172开头的号,需额外查号段归属(可用第三方API或本地号段库),部分号段仅限特定省份入网
- 避免在注册环节强校验短信可达性,把
sendSms()和verifyCode()拆成两步,否则用户输错就卡死
PHP验证邮箱:filter_var()够用,但要注意陷阱
filter_var($email, FILTER_VALIDATE_EMAIL)能覆盖绝大多数合法邮箱格式,但它不验证域名是否存在、MX记录是否有效,也不拒绝明显钓鱼格式(如admin@localhost或test@123.45)。
实操建议:
- 开发环境可加
strpos($email, '@') !== false && substr_count($email, '@') === 1防注入式邮箱(如user@example.com%00@test.com) - 生产环境若需更高可信度,用
checkdnsrr($domain, 'MX')查域名MX记录(注意超时和DNS污染风险) - 禁用
preg_match('/^.+@.+\..+$/', $email)这类弱正则——它会放过a@b.c.d.e.f.g这种明显异常长域名
组合校验时顺序和短路很重要
多个字段一起校验时,PHP的&&天然短路,但写成函数调用链容易掩盖失败原因。比如validateId($id) && validatePhone($phone) && validateEmail($email),一旦$id失败,后面两个根本不执行,日志里看不到$phone是否也非法。
实操建议:
- 单字段校验函数统一返回
['valid' => true, 'error' => null]结构,便于聚合结果 - 关键接口(如注册)用
array_filter()收集所有字段错误,而不是用if嵌套逐个判断 - 手机号和邮箱校验后,记得
trim()再存库——前端空格没清理干净会导致重复注册
真正难的不是写对正则,而是知道什么时候不该信正则。身份证末位X大小写、手机号携号转网后的归属地漂移、邮箱域名被墙导致SMTP连不通……这些都得在正则之外补逻辑。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











