身份证号码验证.php

php

浏览数:363

2019-1-7


身份证号码验证.php

<?php
/**
 * 身份证验证器接口
 */
interface IdentityCardValidatorInterface {
    /**
     * 证件号有效性验证
     * @param $data
     * @return mixed
     */
    public function validateData($data);
}

/**
 * 基类
 */
abstract class Basic implements IdentityCardValidatorInterface {
    /**
     * 身份证件号码
     * @var null
     */
    public $identity_card = null;

    /**
     * 地址码
     * @var null
     */
    public $addressCode = null;

    /**
     * 年
     * @var null
     */
    public $yearCode = null;

    /**
     * 月
     * @var null
     */
    public $monthCode = null;

    /**
     * 日
     * @var null
     */
    public $dayCode = null;

    /**
     * 顺序码
     * @var null
     */
    public $seqCode = null;

    /**
     * @param $data
     * @return mixed
     */
    abstract public function validateData($data);

    /**
     * @param null $card
     */
    public function __construct($card = null) {
        if ($card) {
            $this->setIdentityCard($card);
        }
    }

    /**
     * @param $identity_card
     * @return $this
     */
    public function setIdentityCard($identity_card) {
        $this->identity_card = $identity_card;
        return $this;
    }
}

/**
 * 15位身份证验证类
 */
class IdentityCard15 extends Basic {
    /**
     * 证件号有效性验证
     * @param null $data
     * @return bool
     * @throws Exception
     */
    public function validateData($data = null) {
        $data = $data ? $data : $this->identity_card;
        $this->extractData($data);

        if ( ! $data || ! is_string($data)) {
            throw new Exception('证件号必须存在且为字符串!');
        }

        if (strlen($data) != 15) {
            throw new Exception('证件号位数不对!');
        }

        if ($this->monthCode < 0 || $this->monthCode > 12) {
            return false;
        }

        if ($this->dayCode < 0 || $this->dayCode > 31) {
            return false;
        }

        return (bool)preg_match('|\d{15}|', $data);
    }

    /**
     * 证件号各字段分解
     * @param null $data
     * @return $this
     * @throws Exception
     */
    public function extractData($data = null) {
        $data = $data ? $data : $this->identity_card;

        if ( ! $data || ! is_string($data)) {
            throw new Exception('证件号必须存在且为字符串!');
        }

        if (strlen($data) != 15) {
            throw new Exception('证件号位数不对!');
        }

        $this->addressCode  = substr($data, 0, 6);
        $this->yearCode     = substr($data, 6, 2);
        $this->monthCode    = substr($data, 8, 2);
        $this->dayCode      = substr($data, 10, 2);
        $this->seqCode      = substr($data, 12, 3);
        return $this;
    }
}

/**
 * 18位身份证验证类
 * @link http://blog.jobbole.com/102601/
 */
class IdentityCard18 extends Basic {
    /**
     * 加权因子
     * @var array
     */
    protected  $weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];

    /**
     * 效验码因子
     * @var array
     */
    protected $validate = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2];

    /**
     * 效验码
     * @var null
     */
    protected $validateCode = null;

    /**
     * 证件号有效性验证
     * @param null $data
     * @return bool
     * @throws Exception
     */
    public function validateData($data = null) {
        $data = $data ? $data : $this->identity_card;
        $this->extractData($data);

        if ($this->monthCode < 0 || $this->monthCode > 12) {
            return false;
        }

        if ($this->dayCode < 0 || $this->dayCode > 31) {
            return false;
        }

        $code = $this->getValidateCode($data);
        return (bool)($code == $this->validateCode);
    }

    /**
     * 效验码换算
     * @param null $data
     * @return mixed
     * @throws Exception
     */
    public function getValidateCode($data = null) {
        $data = $data ? $data : $this->identity_card;

        if ( ! $data || ! is_string($data)) {
            throw new Exception('证件号必须存在且为字符串!');
        }

        if (strlen($data) != 18) {
            throw new Exception('证件号位数不对!');
        }

        $data = str_split($data);
        $sum  = 0;
        for ($i = 0; $i < 17; $i++) {
            $sum += ($data[$i] * $this->weight[$i]);
        }

        return $this->validate[$sum % 11];
    }

    /**
     * 证件号各字段分解
     * @param null $data
     * @return $this
     * @throws Exception
     */
    public function extractData($data = null) {
        $data = $data ? $data : $this->identity_card;

        if ( ! $data || ! is_string($data)) {
            throw new Exception('证件号必须存在且为字符串!');
        }

        if (strlen($data) != 18) {
            throw new Exception('证件号位数不对!');
        }

        $this->addressCode  = substr($data, 0, 6);
        $this->yearCode     = substr($data, 6, 4);
        $this->monthCode    = substr($data, 10, 2);
        $this->dayCode      = substr($data, 12, 2);
        $this->seqCode      = substr($data, 14, 3);
        $this->validateCode = substr($data, 17, 1);
        return $this;
    }
}

/**
 * 工厂类
 */
class Factory {
    /**
     * @param null $card
     * @return mixed
     * @throws Exception
     */
    static public function getInstance($card = null) {
        $class = 'IdentityCard' . strlen($card);
        if ( ! class_exists($class)) {
            throw new Exception("{$class}类不存在!");
        }

        return new $class($card);
    }
}

## 18位证件号
$validator = Factory::getInstance('441621196305044309');
var_dump($validator->validateData());
var_dump($validator);

## 15位证件号
$validator = Factory::getInstance('330322800611746');
var_dump($validator->validateData());
var_dump($validator);