本文目录导读:

在PHP中实现身份证验证规则,需要针对中国大陆的身份证号码进行校验,以下是完整的实现方案,包含格式验证、位数字校验和加权因子校验。
完整身份证验证函数
<?php
/**
* 验证中国大陆身份证号码
*
* @param string $idCard 身份证号码
* @return bool|array 返回false或包含验证信息的数组
*/
function validateIdCard($idCard) {
// 去除空格并转大写
$idCard = strtoupper(trim($idCard));
// 基础格式验证
if (!preg_match('/^\d{17}[\dX]$/', $idCard)) {
return [
'valid' => false,
'message' => '身份证号码格式不正确'
];
}
// 加权因子
$weightFactor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
// 校验码对应值
$checkCode = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
// 计算校验码
$sum = 0;
for ($i = 0; $i < 17; $i++) {
$sum += intval($idCard[$i]) * $weightFactor[$i];
}
$mod = $sum % 11;
$expectedCheckCode = $checkCode[$mod];
// 验证校验码
if ($idCard[17] !== $expectedCheckCode) {
return [
'valid' => false,
'message' => '身份证号码校验码不正确'
];
}
// 验证出生日期
$birthYear = substr($idCard, 6, 4);
$birthMonth = substr($idCard, 10, 2);
$birthDay = substr($idCard, 12, 2);
if (!checkdate((int)$birthMonth, (int)$birthDay, (int)$birthYear)) {
return [
'valid' => false,
'message' => '身份证号码中的出生日期无效'
];
}
// 验证年龄(可选:限制年龄范围)
$birthDate = new DateTime("$birthYear-$birthMonth-$birthDay");
$today = new DateTime();
$age = $today->diff($birthDate)->y;
// 成功验证
return [
'valid' => true,
'message' => '身份证号码有效',
'data' => [
'age' => $age,
'birthday' => "$birthYear-$birthMonth-$birthDay",
'gender' => (intval($idCard[16]) % 2 == 0) ? '女' : '男',
'area_code' => substr($idCard, 0, 6)
]
];
}
// 使用示例
$result = validateIdCard('110105199003072710');
if ($result && $result['valid']) {
echo "验证成功: " . $result['message'] . "\n";
echo "年龄: " . $result['data']['age'] . "\n";
echo "性别: " . $result['data']['gender'] . "\n";
var_dump($result);
} else {
echo "验证失败: " . ($result ? $result['message'] : '无效输入');
}
?>
简化版验证(只验证格式和校验码)
<?php
/**
* 简化版身份证验证
*
* @param string $idCard 身份证号码
* @return bool 是否有效
*/
function simpleIdCardValidate($idCard) {
$idCard = strtoupper(trim($idCard));
// 格式验证
if (!preg_match('/^\d{17}[\dX]$/', $idCard)) {
return false;
}
// 加权因子
$weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
// 校验码
$checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
// 计算校验和
$sum = 0;
for ($i = 0; $i < 17; $i++) {
$sum += intval($idCard[$i]) * $weight[$i];
}
$mod = $sum % 11;
return $idCard[17] === $checkCodes[$mod];
}
// 使用示例
$idCard = '110105199003072710';
if (simpleIdCardValidate($idCard)) {
echo "身份证号有效";
} else {
echo "身份证号无效";
}
?>
使用表单验证示例
<?php
/**
* 表单验证类中的身份证验证方法
*/
class IdCardValidator {
/**
* 验证身份证号码
*
* @param string $idCard 需要验证的身份证号
* @return bool
*/
public function validate($idCard) {
return $this->checkFormat($idCard) &&
$this->checkCheckCode($idCard) &&
$this->checkBirthDate($idCard);
}
/**
* 检查格式
*/
private function checkFormat($idCard) {
return (bool)preg_match('/^\d{17}[\dX]$/', strtoupper(trim($idCard)));
}
/**
* 检查校验码
*/
private function checkCheckCode($idCard) {
$idCard = strtoupper(trim($idCard));
$weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
$checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
$sum = 0;
for ($i = 0; $i < 17; $i++) {
$sum += intval($idCard[$i]) * $weight[$i];
}
$mod = $sum % 11;
return $idCard[17] === $checkCodes[$mod];
}
/**
* 检查出生日期
*/
private function checkBirthDate($idCard) {
$year = substr($idCard, 6, 4);
$month = substr($idCard, 10, 2);
$day = substr($idCard, 12, 2);
return checkdate((int)$month, (int)$day, (int)$year);
}
}
// 使用示例
$validator = new IdCardValidator();
if ($validator->validate('110105199003072710')) {
echo "身份证有效";
} else {
echo "身份证无效";
}
?>
前端JavaScript验证(配合使用)
// 前端验证函数
function validateIdCardJs(idCard) {
// 去除空格
idCard = idCard.toUpperCase().replace(/\s/g, '');
// 格式验证
if (!/^\d{17}[\dX]$/.test(idCard)) {
return { valid: false, message: '格式错误' };
}
// 加权因子
const weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
// 计算校验码
let sum = 0;
for (let i = 0; i < 17; i++) {
sum += parseInt(idCard[i]) * weight[i];
}
const mod = sum % 11;
const expectedCode = checkCodes[mod];
if (idCard[17] !== expectedCode) {
return { valid: false, message: '校验码错误' };
}
// 验证日期
const year = parseInt(idCard.substring(6, 10));
const month = parseInt(idCard.substring(10, 12));
const day = parseInt(idCard.substring(12, 14));
const date = new Date(year, month - 1, day);
if (date.getFullYear() !== year ||
date.getMonth() !== month - 1 ||
date.getDate() !== day) {
return { valid: false, message: '日期无效' };
}
return { valid: true, message: '有效' };
}
// 使用示例
console.log(validateIdCardJs('110105199003072710'));
验证规则说明
身份证号码结构:
- 前6位:地址码(地区编码)
- 中间8位:出生日期(YYYYMMDD)
- 后4位:顺序码(第17位奇数为男,偶数为女)
- 最后1位:校验码(0-9或X)
加权因子和校验码计算:
- 前17位数字分别乘以对应的加权因子
- 求和后除以11取余数
- 余数对应的校验码字符
使用建议
- 双重验证:前端和后端都进行验证
- 安全性:不要存储身份证号码明文,必须加密存储
- 隐私保护:展示时部分掩码处理
- 性能:对于大量验证,使用预编译正则表达式
这个实现完整覆盖了身份证验证的所有关键步骤,可以根据实际需求选择使用完整版或简化版。