PHP Function for Validating Chinese ID Card Numbers

This article explains the structure of Chinese citizen ID numbers and provides a PHP function that validates both 15‑digit and 18‑digit IDs by checking format, birthdate correctness, and computing the checksum according to ISO 7064, accompanied by example usage.

Laravel Tech Community
Laravel Tech Community
Laravel Tech Community
PHP Function for Validating Chinese ID Card Numbers

Chinese citizen ID numbers consist of a 17‑digit body code and a final checksum digit. The body code is composed of a six‑digit address code, an eight‑digit birthdate (YYYYMMDD), a three‑digit sequence code (odd for males, even for females), and the checksum digit.

The validation process includes:

Verifying the overall format with regular expressions for 15‑digit and 18‑digit IDs.

Extracting and checking the birthdate part using strtotime to ensure it represents a real date.

For 18‑digit IDs, calculating the checksum according to ISO 7064:1983.MOD 11‑2, where the weighting factors are 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 and the possible check characters are 0‑9 and X.

The following PHP function implements these steps:

<?php
function is_idcard($id)
{
    $id = strtoupper($id);
    $regx = "/(^\d{15}$)|(^\d{17}([0-9]|X)$)/";
    $arr_split = array();
    if (!preg_match($regx, $id)) {
        return FALSE;
    }
    // 15‑digit handling
    if (15 == strlen($id)) {
        $regx = "/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/";
        @preg_match($regx, $id, $arr_split);
        $dtm_birth = "19".$arr_split[2]."/".$arr_split[3]."/".$arr_split[4];
        if (!strtotime($dtm_birth)) {
            return FALSE;
        } else {
            return TRUE;
        }
    } else {
        // 18‑digit handling
        $regx = "/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/";
        @preg_match($regx, $id, $arr_split);
        $dtm_birth = $arr_split[2]."/".$arr_split[3]."/".$arr_split[4];
        if (!strtotime($dtm_birth)) {
            return FALSE;
        }
        // checksum calculation
        $arr_int = array(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2);
        $arr_ch  = array('1','0','X','9','8','7','6','5','4','3','2');
        $sign = 0;
        for ($i = 0; $i < 17; $i++) {
            $b = (int)$id{$i};
            $w = $arr_int[$i];
            $sign += $b * $w;
        }
        $n = $sign % 11;
        $val_num = $arr_ch[$n];
        if ($val_num != substr($id, 17, 1)) {
            return FALSE;
        } else {
            return TRUE;
        }
    }
}
?>

Example usage:

<?php
$rest = is_idcard('123456789012345678');
var_dump($rest); // bool(false)
?>
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

validationregexchecksumidcard
Laravel Tech Community
Written by

Laravel Tech Community

Specializing in Laravel development, we continuously publish fresh content and grow alongside the elegant, stable Laravel framework.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.