数据验证 #

一、验证概述 #

1.1 验证方式 #

Laravel提供多种验证方式:

text
验证方式
├── 控制器验证
│   └── $request->validate()
├── 表单请求验证
│   └── FormRequest类
├── 手动验证
│   └── Validator::make()
└── 验证规则
    └── Rule类

1.2 快速验证 #

php
public function store(Request $request)
{
    $validated = $request->validate([
        'name' => 'required|string|max:255',
        'email' => 'required|email|unique:users',
        'password' => 'required|min:8|confirmed',
    ]);
    
    User::create($validated);
    
    return redirect()->route('users.index');
}

二、验证规则 #

2.1 常用规则 #

php
$validated = $request->validate([
    // 必填
    'name' => 'required',
    
    // 字符串
    'name' => 'string',
    'name' => 'string|min:3|max:255',
    
    // 数字
    'age' => 'integer',
    'age' => 'numeric|min:0|max:150',
    
    // 数组
    'tags' => 'array',
    'tags.*' => 'string',  // 数组元素验证
    
    // 日期
    'birthday' => 'date',
    'birthday' => 'date_format:Y-m-d',
    'start_date' => 'before:end_date',
    'end_date' => 'after:start_date',
    
    // 邮箱
    'email' => 'email',
    'email' => 'email:rfc,dns',
    
    // URL
    'website' => 'url',
    'website' => 'active_url',
    
    // 布尔值
    'active' => 'boolean',
    
    // 文件
    'avatar' => 'file',
    'avatar' => 'image',
    'avatar' => 'mimes:jpeg,png,jpg',
    'avatar' => 'max:1024',  // KB
    
    // 唯一性
    'email' => 'unique:users',
    'email' => 'unique:users,email',
    'email' => 'unique:users,email,' . $userId,  // 排除当前用户
    
    // 存在性
    'user_id' => 'exists:users,id',
    
    // 确认
    'password' => 'confirmed',  // 需要password_confirmation字段
    
    // 正则
    'phone' => 'regex:/^1[3-9]\d{9}$/',
    
    // IP
    'ip' => 'ip',
    'ip' => 'ipv4',
    'ip' => 'ipv6',
    
    // JSON
    'data' => 'json',
]);

2.2 条件验证 #

php
// 有时验证(字段存在时验证)
$request->validate([
    'bio' => 'nullable|string|max:500',
]);

// 条件规则
$rules = [
    'name' => 'required',
];

if ($request->input('role') === 'admin') {
    $rules['secret'] = 'required';
}

$request->validate($rules);

// 使用sometimes方法
$validator = Validator::make($request->all(), [
    'name' => 'required',
]);

$validator->sometimes('reason', 'required|max:500', function ($input) {
    return $input->status === 'rejected';
});

2.3 复杂验证 #

php
use Illuminate\Validation\Rule;

$request->validate([
    // 枚举值
    'status' => ['required', Rule::in(['pending', 'active', 'inactive'])],
    
    // 不在枚举中
    'status' => ['required', Rule::notIn(['deleted'])],
    
    // 唯一性(高级)
    'email' => [
        'required',
        Rule::unique('users')->ignore($user->id)->where(function ($query) {
            $query->where('active', 1);
        }),
    ],
    
    // 存在性(高级)
    'user_id' => [
        'required',
        Rule::exists('users')->where(function ($query) {
            $query->where('active', 1);
        }),
    ],
]);

三、错误消息 #

3.1 自定义错误消息 #

php
$messages = [
    'name.required' => '姓名不能为空',
    'email.required' => '邮箱不能为空',
    'email.email' => '邮箱格式不正确',
    'email.unique' => '该邮箱已被注册',
];

$request->validate([
    'name' => 'required',
    'email' => 'required|email|unique:users',
], $messages);

3.2 自定义属性名 #

php
$attributes = [
    'name' => '姓名',
    'email' => '邮箱',
];

$request->validate([
    'name' => 'required',
    'email' => 'required|email',
], [], $attributes);

3.3 语言文件 #

php
// resources/lang/zh_CN/validation.php
return [
    'required' => ':attribute 不能为空',
    'email' => ':attribute 格式不正确',
    'attributes' => [
        'name' => '姓名',
        'email' => '邮箱',
    ],
];

四、显示错误 #

4.1 在视图中显示错误 #

blade
@if($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

4.2 显示单个字段错误 #

blade
@error('email')
    <div class="invalid-feedback">{{ $message }}</div>
@enderror

4.3 获取错误信息 #

php
// 检查是否有错误
if ($errors->has('email')) {
    //
}

// 获取第一个错误
$error = $errors->first('email');

// 获取所有错误
$allErrors = $errors->all();

// 获取指定字段所有错误
$emailErrors = $errors->get('email');

五、表单请求验证 #

5.1 创建表单请求 #

bash
php artisan make:request StoreUserRequest

5.2 定义规则 #

php
// app/Http/Requests/StoreUserRequest.php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreUserRequest extends FormRequest
{
    public function authorize()
    {
        return true;  // 授权检查
    }

    public function rules()
    {
        return [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:8|confirmed',
        ];
    }

    public function messages()
    {
        return [
            'name.required' => '姓名不能为空',
            'email.required' => '邮箱不能为空',
        ];
    }

    public function attributes()
    {
        return [
            'name' => '姓名',
            'email' => '邮箱',
        ];
    }
}

5.3 使用表单请求 #

php
public function store(StoreUserRequest $request)
{
    // 验证已通过
    $user = User::create($request->validated());
    
    return redirect()->route('users.show', $user);
}

5.4 准备验证数据 #

php
protected function prepareForValidation()
{
    $this->merge([
        'slug' => Str::slug($this->title),
    ]);
}

5.5 验证后钩子 #

php
public function withValidator($validator)
{
    $validator->after(function ($validator) {
        if ($this->somethingElseInvalid()) {
            $validator->errors()->add('field', '额外验证失败');
        }
    });
}

六、手动验证 #

6.1 创建验证器 #

php
use Illuminate\Support\Facades\Validator;

$validator = Validator::make($request->all(), [
    'name' => 'required|string|max:255',
    'email' => 'required|email|unique:users',
]);

if ($validator->fails()) {
    return redirect()->back()
        ->withErrors($validator)
        ->withInput();
}

$validated = $validator->validated();

6.2 自动重定向 #

php
Validator::make($request->all(), [
    'name' => 'required',
])->validate();

// 验证失败自动重定向

6.3 AJAX验证 #

php
public function store(Request $request)
{
    $validator = Validator::make($request->all(), [
        'name' => 'required',
    ]);

    if ($validator->fails()) {
        return response()->json([
            'errors' => $validator->errors(),
        ], 422);
    }

    // ...
}

七、自定义验证规则 #

7.1 使用闭包 #

php
$request->validate([
    'phone' => [
        'required',
        function ($attribute, $value, $fail) {
            if (!preg_match('/^1[3-9]\d{9}$/', $value)) {
                $fail('手机号格式不正确');
            }
        },
    ],
]);

7.2 创建规则对象 #

bash
php artisan make:rule Phone
php
// app/Rules/Phone.php
namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Phone implements Rule
{
    public function passes($attribute, $value)
    {
        return preg_match('/^1[3-9]\d{9}$/', $value);
    }

    public function message()
    {
        return '手机号格式不正确';
    }
}

// 使用
use App\Rules\Phone;

$request->validate([
    'phone' => ['required', new Phone],
]);

7.3 使用Rule对象 #

php
use Illuminate\Contracts\Validation\InvokableRule;

class Phone implements InvokableRule
{
    public function __invoke(string $attribute, mixed $value, Closure $fail): void
    {
        if (!preg_match('/^1[3-9]\d{9}$/', $value)) {
            $fail('手机号格式不正确');
        }
    }
}

八、条件验证 #

8.1 排除字段 #

php
$request->validate([
    'has_car' => 'boolean',
    'car_model' => 'required_if:has_car,1',
    'car_color' => 'required_if:has_car,1',
]);

// 或使用exclude规则
$request->validate([
    'has_car' => 'boolean',
    'car_model' => 'exclude_if:has_car,0|required',
    'car_color' => 'exclude_if:has_car,0|required',
]);

8.2 条件规则 #

php
Validator::make($data, [
    'password' => 'required_unless:login_type,oauth',
]);

九、总结 #

9.1 核心规则 #

规则 说明
required 必填
string 字符串
integer 整数
email 邮箱格式
unique 唯一
exists 存在
confirmed 确认
min/max 最小/最大

9.2 下一步 #

掌握了数据验证后,让我们继续学习 表单请求,深入了解表单请求验证!

最后更新:2026-03-28