本文目录导读:

在 Laravel 中自定义身份证验证有多种方式,我为您提供几种常用且完整的实现方案:
使用 Validator Extend(推荐)
创建自定义验证规则
在 AppServiceProvider 的 boot 方法中注册:
<?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):如果您需要全局使用,推荐此方法
- 方案二(自定义规则类):如果您需要更复杂的验证逻辑,推荐此方法
- 方案三(表单请求验证):如果您使用表单请求进行验证,推荐此方法
选择适合您项目需求的方案即可,如果还需要其他扩展功能,请告诉我!