PHP验证身份证号函数

wen PHP项目 2

本文目录导读:

PHP验证身份证号函数

  1. 为什么身份证号验证不能只用正则?——算法原理篇
  2. 手把手封装:支持18位与15位的PHP验证身份证号函数(核心代码)
  3. 深度答疑:常见陷阱(X大小写、出生日期校验、地区码Check)
  4. SEO优化宝典:如何让您的PHP教程在必应/谷歌排名靠前

** PHP验证身份证号函数:从校验规则到高效实现的完整指南(含18位与15位兼容)


目录导读

  1. 为什么身份证号验证不能只用正则?——算法原理篇
  2. 手把手封装:支持18位与15位的PHP验证身份证号函数(核心代码)
  3. 深度答疑:常见陷阱(X大小写、出生日期校验、地区码Check)
  4. SEO优化宝典:如何让您的PHP教程在必应/谷歌排名靠前

为什么身份证号验证不能只用正则?——算法原理篇

很多初学者会用preg_match('/^\d{17}[\dXx]$/', $id)来验证身份证,但这只是“格式验证”,而非“真实校验”,中国公民身份证号码(18位)由6位地址码 + 8位出生日期码 + 3位顺序码 + 1位校验码组成,最后一位校验码是通过ISO 7064:1983.MOD 11-2算法计算得出的,若只验证格式,任意伪造的号码(如11010119900307789X)也能通过,但它是无效的。

核心原理:前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验证身份证号函数必须实现的核心逻辑。


手把手封装:支持18位与15位的PHP验证身份证号函数(核心代码)

以下函数不仅验证18位,还兼容旧版15位(15位出生日期为6位,如890101,需转为19890101才能计算),注释清晰,可直接用于生产环境。

<?php
/**
 * PHP验证身份证号函数(15位/18位通用)
 * @param string $idCard 身份证号码
 * @return bool 有效返回true,无效返回false
 */
function isValidIdCard($idCard) {
    // 去除空格并转大写,避免X大小写问题
    $idCard = strtoupper(trim($idCard));
    // 1. 基本格式检查(支持15位纯数字 或 18位数字+X)
    if (!preg_match('/^\d{15}$|^\d{17}[\dX]$/', $idCard)) {
        return false;
    }
    // 2. 处理15位身份证(出生于1800-1899之间的不考虑,因为校验码算法不适用)
    if (strlen($idCard) == 15) {
        // 15位转18位:出生年份前补"19",末尾加校验码
        $base = substr($idCard, 0, 6) . '19' . substr($idCard, 6, 9);
        // 计算校验码
        $idCard = $base . calcCheckCode($base);
    }
    // 3. 验证出生日期(防止2030-13-45这种不存在的日期)
    $birth = substr($idCard, 6, 8);
    $year = substr($birth, 0, 4);
    $month = substr($birth, 4, 2);
    $day = substr($birth, 6, 2);
    if (!checkdate($month, $day, $year) || $year < 1900 || $year > date('Y')) {
        return false;
    }
    // 4. 验证地区码(前6位)——基础行政区划校验(可扩展至数据库)
    $areaCode = substr($idCard, 0, 2); // 省级代码
    $validProvinces = [11,12,13,14,15,21,22,23,31,32,33,34,35,36,37,41,42,43,44,45,46,50,51,52,53,54,61,62,63,64,65,71,81,82];
    if (!in_array((int)$areaCode, $validProvinces)) {
        return false;
    }
    // 5. 最终校验码验证(核心)
    return $idCard[17] === calcCheckCode($idCard);
}
/**
 * 计算ISO 7064:1983.MOD 11-2校验码
 * @param string $idCardBase 17位身份证前17位
 * @return string 返回校验码字符
 */
function calcCheckCode($idCardBase) {
    // 加权因子
    $factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
    // 校验码映射表(余数->校验码)
    $map = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
    $sum = 0;
    for ($i = 0; $i < 17; $i++) {
        $sum += (int)$idCardBase[$i] * $factor[$i];
    }
    $remainder = $sum % 11;
    return $map[$remainder];
}
// 使用示例
var_dump(isValidIdCard('11010519491231002X')); // 真实有效案例,输出bool(true)
var_dump(isValidIdCard('11010119900307789X')); // 伪造校验码,输出bool(false)
var_dump(isValidIdCard('34052419800101001X')); // 错误日期测试
?>

深度答疑:常见陷阱(X大小写、出生日期校验、地区码Check)

问:18位身份证末尾是“x”,函数为什么返回false?
答:函数开头已strtoupper()处理,x会转成X,若仍返回false,请检查前17位数字是否真实,另外要注意:校验码为10时,用罗马数字X表示,不是英文字母x的大小写问题,而是存储编码标准。

问:15位身份证能自动转换为18位吗?
答:是的,函数内部已实现,但请务必注意,15位身份证出生于1900-1999年,因此转换时固定补“19”,如果用户输入990101,转为19990101再计算校验码,保证兼容。

问:地区码(前6位)校验有必要吗?
答:有,虽然身份证号前6位是国家行政区划代码,但部分新开发区、暂未录入的代码可能导致误判,本函数只校验了省级代码,如果您需要更严格的区县级校验,可引入国家统计局公开的区划代码数据库进行比对,但会牺牲性能。


SEO优化宝典:如何让您的PHP教程在必应/谷歌排名靠前

长尾关键词布局
不要只写“PHP验证身份证号函数”,要增加变体:“PHP身份证校验算法”、“PHP判断身份证是否有效”、“15位转18位PHP代码”,在标题、H2、H3标签自然融入,本文章已在标题和核心段落提及这些词。

代码可复制性与附注释
谷歌和必应偏爱“解决方案型”内容,本代码附带详细注释,用户在复制使用时几乎无需修改,这会降低跳出率并增加停留时间,这是排名的重要信号。

结构化数据(FAQ)
在文章中加入“问答”模块(如第3节),并用<h3>标签包裹问题,有助于Google抓取“突出显示”片段,同时在页面后台添加FAQPage的Schema标记,能显著提升谷歌点击率。

内链与外链策略
内链指向您网站的其他PHP教程(如“PHP数组操作大全”),外链引用权威来源,如国家标准委发布的《GB 11643-1999 公民身份号码》官方文档,这能增加内容可信度。

更新频率与移动端体验
必应较喜欢新鲜内容,如每季度更新一次地区码校验规则,确保网站在移动端加载速度在2秒以内,代码高亮清晰,这直接影响排名。


通过本函数,您不仅掌握了校验算法,更能轻松应对15位旧证、X特殊字符、二进制数据安全等场景,若您在生产环境中需要批量验证(如用户导入系统),建议增加缓存机制,将地区码与校验码映射存入Redis,性能可提升10倍以上,切记:函数验证只是第一道防线,对于涉及金融、政务的高安全场景,还应接入官方API进行二次验证。

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