国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > PHP > 正文

PHP校驗(yàn)15位和18位身份證號的類封裝

2024-05-05 00:05:47
字體:
供稿:網(wǎng)友

新公司框架源碼的時(shí)候,發(fā)現(xiàn)了這個(gè)功能,于是搜索一番并封裝了一下身份證號校驗(yàn)的類。

目前大家的身份證號大多是 18 位的,當(dāng)然,也不排除有些老人的身份證號是 15 位的。

如果強(qiáng)制要求是 18 位的話,會比較好,因?yàn)?15 位的身份證號沒有校驗(yàn)碼,可以說,只要了解大概結(jié)構(gòu),隨手都可以造出一系列身份證號碼來。

當(dāng)然,如果只是單純的程序校驗(yàn), 18 位的身份證號碼也可以偽造,就是需要偽造者花點(diǎn)心思。

最好的還是調(diào)用相關(guān)部門給的接口,進(jìn)行校驗(yàn)。

本文所編寫的身份證號碼校驗(yàn),只是針對相關(guān)規(guī)則下的計(jì)算,是調(diào)用接口前能做的事情。

身份證號規(guī)則

15位:省份(2位) + 地級市(2位) + 縣級市(2位) + 出生年(2位) + 出生月(2位) + 出生日(2位) + 順序號(3位)

18位:省份(2位) + 地級市(2位) + 縣級市(2位) + 出生年(4位) + 出生月(2位) + 出生日(2位) + 順序號(3位) + 校驗(yàn)位(1位)

相比之下, 18位 比 15位 多出生年 2位 、校驗(yàn)位 1位 。

其中,順序號如果是偶數(shù),則說明是女生,順序號是奇數(shù),則說明是男生。

校驗(yàn)位的計(jì)算:

有17位數(shù)字,分別是:

7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2

分別用身份證的前 17 位乘以上面相應(yīng)位置的數(shù)字,然后相加。

接著用相加的和對 11 取模。

用獲得的值在下面 11 個(gè)字符里查找對應(yīng)位置的字符,這個(gè)字符就是校驗(yàn)位。

'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'

15位轉(zhuǎn)18位:

從上述的分析中,可以知道,只要補(bǔ)充上年分和校驗(yàn)位就可以了。

一般情況下年份補(bǔ)充都是加上 19 就可以了。

校驗(yàn)類的實(shí)現(xiàn)

通過分析身份證號的規(guī)則,了解到,有幾點(diǎn)是可以做的:

  • 檢查身份是否正確(一般不會變化,而且省份不多)
  • 檢查地級市和縣級市(如果有這方面的資源,可以考慮,不過一般不建議)
  • 檢查年月日
  • 檢查校驗(yàn)碼

當(dāng)然,因?yàn)榭赡懿糠秩擞玫氖?15位 的身份證號,所以需要一個(gè)轉(zhuǎn)換的方法,不過,這里還是建議限制需要 18位 的身份證號。

下面開始實(shí)現(xiàn):

初始化:

class IDCardFilter{  /**   * 身份證號碼校驗(yàn)   *   * @param string $idCard   * @return bool   */  public function vaild($idCard)  {    // 基礎(chǔ)的校驗(yàn),校驗(yàn)身份證格式是否正確    if (!$this->isCardNumber($idCard)) {      return false;    }    // 將 15 位轉(zhuǎn)換成 18 位    $idCard = $this->fifteen2Eighteen($idCard);    // 檢查省是否存在    if (!$this->checkProvince($idCard)) {      return false;    }    // 檢查生日是否正確    if (!$this->checkBirthday($idCard)) {      return false;    }    // 檢查校驗(yàn)碼    return $this->checkCode($idCard);  }}

上面已經(jīng)實(shí)現(xiàn)了一個(gè)校驗(yàn)的方法,里面調(diào)用了類里的很多方法,下面一一實(shí)現(xiàn)。

檢測是否是身份證號碼:

這一塊的處理比較簡單,一個(gè)正則表達(dá)式搞定了。

其中, (^/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位轉(zhuǎn)18位:

邏輯不復(fù)雜,先判斷是否是15位,然后判斷需要添加的年份,最終生成校驗(yàn)碼拼接返回就OK了。

/** * 15位轉(zhuǎn)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 ? '18' : '19';  // 一般 19 就夠了  $code = '19';  $idCardBase = substr($idCard, 0, 6) . $code . substr($idCard, 6, 9);  return $idCardBase . $this->genCode($idCardBase);}

校驗(yàn)碼的生成:

詳細(xì)計(jì)算規(guī)則見上面,這里就不做重復(fù)的闡述了。

/** * 生成校驗(yàn)碼 * * @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 => "內(nèi)蒙古",  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);}

校驗(yàn)碼比對:

話說, 15位 轉(zhuǎn) 18位 的都完全不用考慮這個(gè)方法了。

/** * 校驗(yàn)碼比對 * * @param string $idCard * @return void */public function checkCode($idCard){  $idCardBase = substr($idCard, 0, 17);  $code = $this->genCode($idCardBase);  return $idCard == ($idCardBase . $code);}

完整代碼

傳送門:IDCardFilter

最后

這個(gè)功能最多算是新穎吧,畢竟之前沒有接觸過。很開心代碼片段里又增加了新的成員。

以上所述是小編給大家介紹的PHP校驗(yàn)15位和18位身份證號的類封裝,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對VeVb武林網(wǎng)網(wǎng)站的支持!


注:相關(guān)教程知識閱讀請移步到PHP教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 公主岭市| 泰宁县| 封丘县| 枣强县| 武功县| 绍兴市| 屯留县| 宁夏| 西昌市| 福建省| 屯昌县| 峨边| 金华市| 启东市| 乡宁县| 正阳县| 全南县| 仙游县| 博客| 桂东县| 临沭县| 玉门市| 宁城县| 兴安盟| 临朐县| 方山县| 凤冈县| 湖南省| 镇沅| 大宁县| 新晃| 巴里| 曲沃县| 肥乡县| 元江| 崇阳县| 错那县| 锡林浩特市| 仁寿县| 秭归县| 天长市|