Go straight to code

<? phpclass IDCardFilter
{
    /** * Checks whether the ID number is correct
    const REGX = '#(^\d{15}$)|(^\d{17}(\d|X)$)#';

    /** ** ** **@var array* /
    protected $provinces = [
        11= >"Beijing".12= >"Tianjin".13= >"Hebei".14= >"Shanxi".15= >Inner Mongolia.21= >"Liaoning".22= >"Jilin".23= >"Heilongjiang".31= >"Shanghai".32= >"Jiangsu".33= >"Zhejiang".34= >"Anhui province".35= >"Fujian".36= >"Jiangxi".37= >"Shandong".41= >"Henan".42= >"Hubei".43= >"Hunan".44= >"Guangdong".45= >"Guangxi".46= >"Hainan".50= >"Chongqing".51= >"Sichuan".52= >"Guizhou".53= >"Yunnan".54= >"Tibet".61= >"Shaanxi".62= >"Gansu".63= >"Qinghai".64= >"The ningxia".65= >"Xinjiang".71= >"Taiwan".81= >"Hong Kong".82= >"Macau".91= >"Foreign"
    ];

    /** * id card number check **@param  string $idCard
     * @return boolean* /
    public function vaild($idCard)
    {
        // Check whether the id card format is correct
        if(! $this->isCardNumber($idCard)) {return false;
        }

        // Convert 15 bits to 18 bits
        $idCard = $this->fifteen2Eighteen($idCard);

        // Check whether the province exists
        if(! $this->checkProvince($idCard)) {return false;
        }

        // Check whether the birthday is correct
        if(! $this->checkBirthday($idCard)) {return false;
        }

        // Check the verification code
        return $this->checkCode($idCard);
    }

    /** * check if it is id number **@param  string $idCard
     * @return boolean* /
    public function isCardNumber($idCard)
    {
        return preg_match(self::REGX, $idCard);
    }

    /** ** 15 bits to 18 bits **@param  string $idCard
     * @return void* /
    public function fifteen2Eighteen($idCard)
    {
        if(strlen($idCard) ! =15) {
            return $idCard;
        }

        // If the id sequence code is 996 997 998 999, these are special codes for people over 100 years old
        // $code = array_search(substr($idCard, 12, 3), [996, 997, 998, 999]) ! == false ? '18' : '19';
        // 19 is usually ok
        $code = 'the';
        $idCardBase = substr($idCard, 0.6) . $code . substr($idCard, 6.9);
        return $idCardBase . $this->genCode($idCardBase);
    }

    /** * Check whether the province is correct **@param  string $idCard
     * @return void* /
    public function checkProvince($idCard)
    {
        $provinceNumber = substr($idCard, 0.2);
        return isset($this->provinces[$provinceNumber]);
    }

    /** * Check whether the birthday is correct **@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);
    }

    /** * Parity code comparison **@param  string $idCard
     * @return void* /
    public function checkCode($idCard)
    {
        $idCardBase = substr($idCard, 0.17);
        $code = $this->genCode($idCardBase);
        return $idCard == ($idCardBase . $code);
    }

    /** * Generates the verification code **@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]; }}Copy the code

Read the notes :(click on me)