首先先了解 身份证号码的编码规则,从百度经验上找到了别人的分享php
:http://jingyan.baidu.com/article/7f41ececff944a593d095c8c.htmlhtml
感谢。正则表达式
15位长度的验证正则是从网上找的,但发现并非万能的(月份能够出现00,日期能够出现00等),算法
因此作了以下改良,但仍旧存在一些问题,如880231这样的生日也能够验证功过编码
因此能够考虑将身份证号码的年月日单独判断,在此略去。3d
18位长度的就按校验规则来校验便可。code
function chkIdNo($idNo) { //身份证正则表达式(15位) //isIDCard1=/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/; ////身份证正则表达式(18位) //isIDCard2=/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$/; $len = strlen($idNo); //十五位身份证1999 10 01再也不办理 if($len == 15) { //13 04 03 991001 002 //$pattern = '/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{2}[Xx0-9]$/'; //修复 月份 天 不能同时为00 $pattern = '/^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2]\d)|3[0-1])\d{2}[Xx0-9]$/'; $res = preg_match($pattern, $idNo); if($res) return true; return false; } if($len == 18){ //前17位对应的权重数字算法 (2<<($len - 2 - n)%11 $bits = str_split($idNo); //每位对应的权重数字 $weights = array(); //求和 $sum = 0; for($i = 0; $i < 17; $i++) { //计算权重 $weights[$i] = (2 << ($len - 2 - $i)) % 11; $sum += $bits[$i] * $weights[$i]; } $mod = $sum % 11; //校验码array(1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2); $chkCodes = array(1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2); $code = isset($chkCodes[$mod]) ? $chkCodes[$mod].'' : ''; if($code !== $bits[$len - 1]) { return false; } return true; } return false; }