/** * 校验身份证号码是否合法 * @param $str * @param bool $getBasicInfo 是否提取身份证号码中的基本信息(出生日期/性别) * @return mixed */ public static function RegexpMatchIdCard($str, $getBasicInfo = false) { //校验身份证位数和出生日期部分 $pattern = "/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|[xX])$/"; preg_match($pattern, $str, $match); $result = $match ? true : false; if (!$result) { return false; } //校验前两位是否是所有省份代码 $province_code = ['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']; if (!in_array(substr($str, 0, 2), $province_code)) { return false; } //校验身份证最后一位 $ahead17_char = substr($str, 0, 17); $last_char = substr($str, -1); $factor = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); // 前17位的权重 $c = array(1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2); //模11后的对应校验码 $t_res = 0; for ($i = 0; $i < 17; $i++) { $t_res += intval($ahead17_char[$i]) * $factor[$i]; } $calc_last_char = $c [$t_res % 11]; if ($last_char != $calc_last_char) { return false; } if (!$getBasicInfo) { return $result; } //从身份证号码中提取出生日期和性别 $birth_year = substr($str, 6, 4); $birth_month = substr($str, 10, 2); $birth_day = substr($str, 12, 2); if (!checkdate($birth_month, $birth_day, $birth_year)) { return false; } $brithday = $birth_year . "-" . $birth_month . "-" . $birth_day; $gender_char = substr($str, -2, 1); if ($gender_char % 2 == 0) { $gender = 2; //女 } else { $gender = 1; //男 } return [ 'birthday' => $brithday, 'age' => self::getAge(strtotime($brithday)), 'gender' => $gender, ]; } /** * 根据出生日期获取年龄 * @param string $birthday 出生日期时间戳 * @return false|string */ public static function getAge($birthday) { //格式化出生时间年月日 $byear = date('Y', $birthday); $bmonth = date('m', $birthday); $bday = date('d', $birthday); //格式化当前时间年月日 $tyear = date('Y'); $tmonth = date('m'); $tday = date('d'); //计算年龄 $age = $tyear - $byear; if ($bmonth > $tmonth || $bmonth == $tmonth && $bday > $tday) { $age--; } return $age; }