123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- <?php
- namespace app\common\Rule;
- /**
- * 身份证验证工具类
- */
- class IdCardRule
- {
- /**
- * 验证身份证号格式
- * @param string $idCard 身份证号
- * @return array 返回验证结果 ['valid' => true/false, 'message' => '错误信息']
- */
- public static function validate($idCard)
- {
- // 去除空格
- $idCard = trim($idCard);
-
- // 检查长度(18位)
- if (strlen($idCard) !== 18) {
- return ['valid' => false, 'message' => '身份证号必须为18位'];
- }
-
- // 检查前17位是否为数字
- if (!ctype_digit(substr($idCard, 0, 17))) {
- return ['valid' => false, 'message' => '身份证号前17位必须为数字'];
- }
-
- // 检查最后一位(数字或X)
- $lastChar = strtoupper(substr($idCard, 17, 1));
- if (!ctype_digit($lastChar) && $lastChar !== 'X') {
- return ['valid' => false, 'message' => '身份证号最后一位必须为数字或字母X'];
- }
-
- // 验证日期部分(第7-14位)
- $year = substr($idCard, 6, 4);
- $month = substr($idCard, 10, 2);
- $day = substr($idCard, 12, 2);
-
- // 检查年份范围(1900-当前年份)
- $currentYear = date('Y');
- if ($year < 1900 || $year > $currentYear) {
- return ['valid' => false, 'message' => '身份证号中的出生年份不正确'];
- }
-
- // 检查月份
- if ($month < 1 || $month > 12) {
- return ['valid' => false, 'message' => '身份证号中的出生月份不正确'];
- }
-
- // 检查日期
- if (!checkdate($month, $day, $year)) {
- return ['valid' => false, 'message' => '身份证号中的出生日期不正确'];
- }
-
- // 验证校验码
- $checkResult = self::validateCheckCode($idCard);
- if (!$checkResult['valid']) {
- return $checkResult;
- }
-
- return ['valid' => true, 'message' => '身份证号格式正确'];
- }
-
- /**
- * 验证校验码
- * @param string $idCard 身份证号
- * @return array
- */
- private static function validateCheckCode($idCard)
- {
- $weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
- $checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
-
- $sum = 0;
- for ($i = 0; $i < 17; $i++) {
- $sum += intval(substr($idCard, $i, 1)) * $weights[$i];
- }
-
- $checkCode = $checkCodes[$sum % 11];
- $lastChar = strtoupper(substr($idCard, 17, 1));
-
- if ($lastChar !== $checkCode) {
- return ['valid' => false, 'message' => '身份证号校验码不正确'];
- }
-
- return ['valid' => true, 'message' => '校验码正确'];
- }
-
- /**
- * 从身份证号获取生日
- * @param string $idCard 身份证号
- * @return string|false 生日(Y-m-d)或false
- */
- public static function getBirthday($idCard)
- {
- $result = self::validate($idCard);
- if (!$result['valid']) {
- return false;
- }
-
- $year = substr($idCard, 6, 4);
- $month = substr($idCard, 10, 2);
- $day = substr($idCard, 12, 2);
-
- return $year . '-' . $month . '-' . $day;
- }
-
- /**
- * 从身份证号获取年龄
- * @param string $idCard 身份证号
- * @return int|false 年龄或false
- */
- public static function getAge($idCard)
- {
- $birthday = self::getBirthday($idCard);
- if (!$birthday) {
- return false;
- }
-
- $birthTime = strtotime($birthday);
- $age = floor((time() - $birthTime) / (365 * 24 * 3600));
-
- return $age;
- }
-
- /**
- * 从身份证号获取性别
- * @param string $idCard 身份证号
- * @return string|false 'male'(男)或'female'(女)或false
- */
- public static function getGender($idCard)
- {
- $result = self::validate($idCard);
- if (!$result['valid']) {
- return false;
- }
-
- $genderCode = intval(substr($idCard, 16, 1));
- return $genderCode % 2 === 0 ? 'female' : 'male';
- }
- }
|