PHP身份证验证规则怎么实现

wen PHP项目 2

本文目录导读:

PHP身份证验证规则怎么实现

  1. 完整身份证验证函数
  2. 简化版验证(只验证格式和校验码)
  3. 使用表单验证示例
  4. 前端JavaScript验证(配合使用)
  5. 验证规则说明
  6. 使用建议

在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)

加权因子和校验码计算:

  1. 前17位数字分别乘以对应的加权因子
  2. 求和后除以11取余数
  3. 余数对应的校验码字符

使用建议

  1. 双重验证:前端和后端都进行验证
  2. 安全性:不要存储身份证号码明文,必须加密存储
  3. 隐私保护:展示时部分掩码处理
  4. 性能:对于大量验证,使用预编译正则表达式

这个实现完整覆盖了身份证验证的所有关键步骤,可以根据实际需求选择使用完整版或简化版。

抱歉,评论功能暂时关闭!