Laravel自定义身份证验证怎么写

wen PHP项目 3

本文目录导读:

Laravel自定义身份证验证怎么写

  1. 方案一:使用 Validator Extend(推荐)
  2. 方案二:创建自定义验证规则类
  3. 方案三:使用表单请求验证
  4. 方案四:简化版验证(快速入门)
  5. 推荐使用

在 Laravel 中自定义身份证验证有多种方式,我为您提供几种常用且完整的实现方案:

使用 Validator Extend(推荐)

创建自定义验证规则

AppServiceProviderboot 方法中注册:

<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Validator::extend('identity_card', function ($attribute, $value, $parameters, $validator) {
            // 身份证号码验证逻辑
            return $this->validateIdentityCard($value);
        }, '身份证号码格式不正确');
        Validator::replacer('identity_card', function ($message, $attribute, $rule, $parameters) {
            return str_replace(':attribute', $attribute, $message);
        });
    }
    /**
     * 身份证验证核心逻辑
     */
    private function validateIdentityCard($idCard)
    {
        // 去除空格
        $idCard = strtoupper(trim($idCard));
        // 长度验证
        if (strlen($idCard) != 18 && strlen($idCard) != 15) {
            return false;
        }
        // 18位验证
        if (strlen($idCard) == 18) {
            return $this->validate18IdCard($idCard);
        }
        // 15位验证
        if (strlen($idCard) == 15) {
            return $this->validate15IdCard($idCard);
        }
        return false;
    }
    /**
     * 验证18位身份证
     */
    private function validate18IdCard($idCard)
    {
        // 正则基本格式验证
        if (!preg_match('/^\d{17}[\dX]$/', $idCard)) {
            return false;
        }
        // 验证出生日期
        $birthday = substr($idCard, 6, 8);
        if (!$this->validateBirthday($birthday)) {
            return false;
        }
        // 验证校验码
        $verifyCode = $this->getIdCardVerifyCode($idCard);
        if (substr($idCard, 17, 1) != $verifyCode) {
            return false;
        }
        return true;
    }
    /**
     * 验证15位身份证
     */
    private function validate15IdCard($idCard)
    {
        // 正则基本格式验证
        if (!preg_match('/^\d{15}$/', $idCard)) {
            return false;
        }
        // 验证出生日期(15位身份证出生日期格式为:yymmdd)
        $birthday = '19' . substr($idCard, 6, 6);
        if (!$this->validateBirthday($birthday)) {
            return false;
        }
        return true;
    }
    /**
     * 验证出生日期
     */
    private function validateBirthday($birthday)
    {
        $year = substr($birthday, 0, 4);
        $month = substr($birthday, 4, 2);
        $day = substr($birthday, 6, 2);
        // 检查日期是否有效
        if (!checkdate((int)$month, (int)$day, (int)$year)) {
            return false;
        }
        // 检查年份范围(假设当前年份为2024年)
        $currentYear = date('Y');
        if ($year < 1900 || $year > $currentYear) {
            return false;
        }
        return true;
    }
    /**
     * 计算18位身份证校验码
     */
    private function getIdCardVerifyCode($idCard)
    {
        // 加权因子
        $weightFactor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
        // 校验码对应值
        $verifyCode = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
        $idCard17 = substr($idCard, 0, 17);
        $sum = 0;
        for ($i = 0; $i < 17; $i++) {
            $sum += intval($idCard17[$i]) * $weightFactor[$i];
        }
        $mod = $sum % 11;
        return $verifyCode[$mod];
    }
}

在控制器中使用

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
    public function store(Request $request)
    {
        $request->validate([
            'identity_card' => 'required|identity_card',
        ]);
        // 验证通过,继续处理
    }
}

创建自定义验证规则类

创建规则类

<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class IdentityCardRule implements Rule
{
    /**
     * 验证规则名称
     */
    protected $ruleName = '身份证号码';
    /**
     * 判断验证规则是否通过
     */
    public function passes($attribute, $value)
    {
        $idCard = strtoupper(trim($value));
        // 长度验证
        if (strlen($idCard) != 18 && strlen($idCard) != 15) {
            return false;
        }
        // 18位验证
        if (strlen($idCard) == 18) {
            return $this->validate18IdCard($idCard);
        }
        // 15位验证
        if (strlen($idCard) == 15) {
            return $this->validate15IdCard($idCard);
        }
        return false;
    }
    /**
     * 获取验证错误消息
     */
    public function message()
    {
        return ':attribute 格式不正确,请输入有效的' . $this->ruleName;
    }
    private function validate18IdCard($idCard)
    {
        if (!preg_match('/^\d{17}[\dX]$/', $idCard)) {
            return false;
        }
        $birthday = substr($idCard, 6, 8);
        if (!$this->validateBirthday($birthday)) {
            return false;
        }
        $verifyCode = $this->getIdCardVerifyCode($idCard);
        return substr($idCard, 17, 1) == $verifyCode;
    }
    private function validate15IdCard($idCard)
    {
        if (!preg_match('/^\d{15}$/', $idCard)) {
            return false;
        }
        $birthday = '19' . substr($idCard, 6, 6);
        return $this->validateBirthday($birthday);
    }
    private function validateBirthday($birthday)
    {
        $year = (int)substr($birthday, 0, 4);
        $month = (int)substr($birthday, 4, 2);
        $day = (int)substr($birthday, 6, 2);
        return checkdate($month, $day, $year) && 
               $year >= 1900 && 
               $year <= (int)date('Y');
    }
    private function getIdCardVerifyCode($idCard)
    {
        $weightFactor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
        $verifyCode = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
        $idCard17 = substr($idCard, 0, 17);
        $sum = 0;
        for ($i = 0; $i < 17; $i++) {
            $sum += (int)$idCard17[$i] * $weightFactor[$i];
        }
        return $verifyCode[$sum % 11];
    }
}

在控制器中使用

use App\Rules\IdentityCardRule;
public function store(Request $request)
{
    $request->validate([
        'identity_card' => ['required', new IdentityCardRule],
    ]);
}

使用表单请求验证

创建表单请求

php artisan make:request StoreUserRequest

编辑表单请求类

<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use App\Rules\IdentityCardRule;
class StoreUserRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }
    public function rules()
    {
        return [
            'name' => 'required|string|max:255',
            'identity_card' => ['required', new IdentityCardRule],
        ];
    }
    public function messages()
    {
        return [
            'identity_card.required' => '请输入身份证号码',
        ];
    }
}

在控制器中使用

use App\Http\Requests\StoreUserRequest;
public function store(StoreUserRequest $request)
{
    // 验证已通过,可以直接获取验证过的数据
    $validated = $request->validated();
    // 继续处理业务逻辑
}

简化版验证(快速入门)

如果您只需要基本验证,可以使用更简单的版本:

// 在 AppServiceProvider 中
Validator::extend('identity_card', function ($attribute, $value, $parameters, $validator) {
    $idCard = strtoupper(trim($value));
    // 基本格式验证
    if (!preg_match('/^\d{17}[\dX]$/', $idCard) && !preg_match('/^\d{15}$/', $idCard)) {
        return false;
    }
    // 验证出生日期
    if (strlen($idCard) == 18) {
        $birthday = substr($idCard, 6, 8);
    } else {
        $birthday = '19' . substr($idCard, 6, 6);
    }
    $year = substr($birthday, 0, 4);
    $month = substr($birthday, 4, 2);
    $day = substr($birthday, 6, 2);
    return checkdate((int)$month, (int)$day, (int)$year);
}, '身份证号码格式不正确');

推荐使用

  • 方案一(Validator Extend):如果您需要全局使用,推荐此方法
  • 方案二(自定义规则类):如果您需要更复杂的验证逻辑,推荐此方法
  • 方案三(表单请求验证):如果您使用表单请求进行验证,推荐此方法

选择适合您项目需求的方案即可,如果还需要其他扩展功能,请告诉我!

抱歉,评论功能暂时关闭!