新公司框架源码的时候,发现了这个功能,于是搜索一番并封装了一下身份证号校验的类。
目前大家的身份证号大多是 18 位的,当然,也不排除有些老人的身份证号是 15 位的。
如果强制要求是 18 位的话,会比较好,因为 15 位的身份证号没有校验码,可以说,只要了解大概结构,随手都可以造出一系列身份证号码来。
当然,如果只是单纯的程序校验, 18 位的身份证号码也可以伪造,就是需要伪造者花点心思。
最好的还是调用相关部门给的接口,进行校验。
本文所编写的身份证号码校验,只是针对相关规则下的计算,是调用接口前能做的事情。
身份证号规则
15位:省份(2位) + 地级市(2位) + 县级市(2位) + 出生年(2位) + 出生月(2位) + 出生日(2位) + 顺序号(3位)
18位:省份(2位) + 地级市(2位) + 县级市(2位) + 出生年(4位) + 出生月(2位) + 出生日(2位) + 顺序号(3位) + 校验位(1位)
相比之下, 18位 比 15位 多出生年 2位 、校验位 1位 。
其中,顺序号如果是偶数,则说明是女生,顺序号是奇数,则说明是男生。
校验位的计算:
有17位数字,分别是:
7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2
分别用身份证的前 17 位乘以上面相应位置的数字,然后相加。
接着用相加的和对 11 取模。
用获得的值在下面 11 个字符里查找对应位置的字符,这个字符就是校验位。
'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'
15位转18位:
从上述的分析中,可以知道,只要补充上年分和校验位就可以了。
一般情况下年份补充都是加上 19 就可以了。
校验类的实现
通过分析身份证号的规则,了解到,有几点是可以做的:
- 检查身份是否正确(一般不会变化,而且省份不多)
- 检查地级市和县级市(如果有这方面的资源,可以考虑,不过一般不建议)
- 检查年月日
- 检查校验码
当然,因为可能部分人用的是 15位 的身份证号,所以需要一个转换的方法,不过,这里还是建议限制需要 18位 的身份证号。
下面开始实现:
初始化:
class IDCardFilter { /** * 身份证号码校验 * * @param string $idCard * @return bool */ public function vaild($idCard) { // 基础的校验,校验身份证格式是否正确 if (!$this->isCardNumber($idCard)) { return false; } // 将 15 位转换成 18 位 $idCard = $this->fifteen2Eighteen($idCard); // 检查省是否存在 if (!$this->checkProvince($idCard)) { return false; } // 检查生日是否正确 if (!$this->checkBirthday($idCard)) { return false; } // 检查校验码 return $this->checkCode($idCard); } }
上面已经实现了一个校验的方法,里面调用了类里的很多方法,下面一一实现。
检测是否是身份证号码:
这一块的处理比较简单,一个正则表达式搞定了。
其中, (^\d{15}$) 用于匹配 15位 身份证号的情况; (^\d{17}(\d|X)$) 用于匹配 18位 身份证号的情况。
const REGX = '#(^\d{15}$)|(^\d{17}(\d|X)$)#';
/** * 检测是否是身份证号码 * * @param string $idCard * @return boolean */ public function isCardNumber($idCard) { return preg_match(self::REGX, $idCard); }
15位转18位:
逻辑不复杂,先判断是否是15位,然后判断需要添加的年份,最终生成校验码拼接返回就OK了。
/** * 15位转18位 * * @param string $idCard * @return void */ public function fifteen2Eighteen($idCard) { if (strlen($idCard) != 15) { return $idCard; } // 如果身份证顺序码是996 997 998 999,这些是为百岁以上老人的特殊编码 // $code = array_search(substr($idCard, 12, 3), [996, 997, 998, 999]) !== false "htmlcode">/** * 生成校验码 * * @param string $idCardBase * @return void */ final protected function genCode($idCardBase) { $idCardLength = strlen($idCardBase); if ($idCardLength != 17) { return false; } $factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; $verifyNumbers = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']; $sum = 0; for ($i = 0; $i < $idCardLength; $i++) { $sum += substr($idCardBase, $i, 1) * $factor[$i]; } $index = $sum % 11; return $verifyNumbers[$index]; }检查省份是否正确:
protected $provinces = [ 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 => "澳门", 91 => "国外" ]; /** * 检查省份是否正确 * * @param string $idCard * @return void */ public function checkProvince($idCard) { $provinceNumber = substr($idCard, 0, 2); return isset($this->provinces[$provinceNumber]); }检测生日是否正确:
这里也是用正则匹配,匹配出年月日的。
/** * 检测生日是否正确 * * @param string $idCard * @return void */ public function checkBirthday($idCard) { $regx = '#^\d{6}(\d{4})(\d{2})(\d{2})\d{3}[0-9X]$#'; if (!preg_match($regx, $idCard, $matches)) { return false; } array_shift($matches); list($year, $month, $day) = $matches; return checkdate($month, $day, $year); }校验码比对:
话说, 15位 转 18位 的都完全不用考虑这个方法了。
/** * 校验码比对 * * @param string $idCard * @return void */ public function checkCode($idCard) { $idCardBase = substr($idCard, 0, 17); $code = $this->genCode($idCardBase); return $idCard == ($idCardBase . $code); }完整代码
传送门:IDCardFilter
最后
这个功能最多算是新颖吧,毕竟之前没有接触过。很开心代码片段里又增加了新的成员。
以上所述是小编给大家介绍的PHP校验15位和18位身份证号的类封装,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 【雨果唱片】中国管弦乐《鹿回头》WAV
- APM亚流新世代《一起冒险》[FLAC/分轨][106.77MB]
- 崔健《飞狗》律冻文化[WAV+CUE][1.1G]
- 罗志祥《舞状元 (Explicit)》[320K/MP3][66.77MB]
- 尤雅.1997-幽雅精粹2CD【南方】【WAV+CUE】
- 张惠妹.2007-STAR(引进版)【EMI百代】【WAV+CUE】
- 群星.2008-LOVE情歌集VOL.8【正东】【WAV+CUE】
- 罗志祥《舞状元 (Explicit)》[FLAC/分轨][360.76MB]
- Tank《我不伟大,至少我能改变我。》[320K/MP3][160.41MB]
- Tank《我不伟大,至少我能改变我。》[FLAC/分轨][236.89MB]
- CD圣经推荐-夏韶声《谙2》SACD-ISO
- 钟镇涛-《百分百钟镇涛》首批限量版SACD-ISO
- 群星《继续微笑致敬许冠杰》[低速原抓WAV+CUE]
- 潘秀琼.2003-国语难忘金曲珍藏集【皇星全音】【WAV+CUE】
- 林东松.1997-2039玫瑰事件【宝丽金】【WAV+CUE】