本文目录导读:

- 为什么身份证号验证不能只用正则?——算法原理篇
- 手把手封装:支持18位与15位的PHP验证身份证号函数(核心代码)
- 深度答疑:常见陷阱(X大小写、出生日期校验、地区码Check)
- SEO优化宝典:如何让您的PHP教程在必应/谷歌排名靠前
** PHP验证身份证号函数:从校验规则到高效实现的完整指南(含18位与15位兼容)
目录导读
- 为什么身份证号验证不能只用正则?——算法原理篇
- 手把手封装:支持18位与15位的PHP验证身份证号函数(核心代码)
- 深度答疑:常见陷阱(X大小写、出生日期校验、地区码Check)
- 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进行二次验证。