首先判断身份证号码是否符合15位或18位的基本格式,再验证出生日期的合法性,最后对18位身份证进行校验码计算以确保其正确性。

身份证号码验证是Web开发中常见的需求,尤其是在用户注册、实名认证等场景。使用PHP结合正则表达式可以高效地完成这一任务。下面介绍如何通过PHP正则表达式实现对18位和15位身份证号的合法校验。
基本格式校验(15位与18位)
中国大陆居民身份证有15位(旧版)和18位(新版)两种格式。可以通过正则初步判断格式是否正确。
15位身份证规则: 全部由数字组成,第1-6位为地区码,7-12位为出生年月日(年份为两位),13-15位为顺序码。
18位身份证规则: 前17位为数字,最后一位可能是数字或X(大写)。其中第7-14位为出生年月日(完整四位年份)。
立即学习“PHP免费学习笔记(深入)”;
示例代码: ```php function validateIdCard($id) { // 15位身份证:6位地区 + 6位年月日(YYMMDD)+ 3位顺序码 $regex_15 = '/^\d{15}$/';// 18位身份证:6位地区 + 8位年月日(YYYYMMDD)+ 3位顺序码 + 1位校验码(0-9或X)
$regex_18 = '/^\d{17}[\dXx]$/';
if (preg_match($regex_15, $id)) {
return true;
}
if (preg_match($regex_18, $id)) {
return true;
}
return false;}
增强校验:加入出生日期合法性
仅格式匹配还不够,还需验证身份证中的出生日期是否真实存在,例如不能出现2月30日或13月。
改进方案: ```php function validateIdCardWithDate($id) { $regex_15 = '/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/'; $regex_18 = '/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([\dXx])$/'; if (preg_match($regex_15, $id, $matches)) { $year = '19' . $matches[2]; // 15位年份默认为19XX $month = $matches[3]; $day = $matches[4]; } elseif (preg_match($regex_18, $id, $matches)) { $year = $matches[2]; $month = $matches[3]; $day = $matches[4]; } else { return false; } // 验证日期有效性 if (!checkdate((int)$month, (int)$day, (int)$year)) { return false; } return true; }
进一步:18位身份证校验码验证
18位身份证最后一位是根据前17位计算得出的校验码,可用ISO 7064:1983标准MOD 11-2算法验证。
校验码计算逻辑:- 将前17位分别乘以对应权重(如 [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2])
- 求和后对11取模,得到余数
- 根据余数查表得出校验码(0~10对应 1,0,X,9,8,7,6,5,4,3,2)
function validateCheckDigit($id) {
if (!preg_match('/^\d{17}[\dXx]$/', $id)) {
return false;
}
$weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
$validCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
$sum = 0;
for ($i = 0; $i < 17; $i++) {
$sum += (int)$id[$i] * $weights[$i];
}
$mod = $sum % 11;
$expected = $validCodes[$mod];
return strtoupper($id[17]) === $expected;
}综合验证函数
将以上逻辑整合成一个完整的身份证验证函数:
```php function isIdCardValid($id) { $id = trim($id);// 格式与长度检查
if (strlen($id) == 15) {
return validateIdCardWithDate($id);
} elseif (strlen($id) == 18) {
if (!validateIdCardWithDate($id)) {
return false;
}
return validateCheckDigit($id);
}
return false;}
// 使用示例 var_dump(isIdCardValid('11010519491231002X')); // true 或 false
基本上就这些。实际项目中可根据需要选择是否启用全部校验层级。











