本文目录导读:

- 使用
Validator::extend()方法 - 使用规则类(推荐)
- 使用
Validator::extendImplicit() - 带参数的规则扩展
- 复杂规则示例:数据库唯一性检查
- 国际化支持
- 使用自定义验证器类
- 通过依赖注入
- 最佳实践建议
Laravel 提供了非常灵活的数据校验规则扩展机制,可以通过以下几种方式来自定义校验规则:
使用 Validator::extend() 方法
在 AppServiceProvider 的 boot() 方法中注册:
use Illuminate\Support\Facades\Validator;
public function boot()
{
Validator::extend('phone', function ($attribute, $value, $parameters, $validator) {
// 自定义验证逻辑
return preg_match('/^1[3-9]\d{9}$/', $value);
});
// 可以自定义错误消息
Validator::replacer('phone', function ($message, $attribute, $rule, $parameters) {
return str_replace(':attribute', $attribute, '手机号格式不正确');
});
}
使用方式:
$request->validate([
'phone' => 'required|phone'
]);
使用规则类(推荐)
创建自定义规则类:
php artisan make:rule PhoneNumber
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class PhoneNumber implements Rule
{
public function passes($attribute, $value)
{
return preg_match('/^1[3-9]\d{9}$/', $value);
}
public function message()
{
return ':attribute 必须是有效的手机号';
}
}
使用方式:
use App\Rules\PhoneNumber;
$request->validate([
'phone' => ['required', new PhoneNumber]
]);
使用 Validator::extendImplicit()
对于空值也要进行验证的规则:
Validator::extendImplicit('required_phone', function ($attribute, $value, $parameters, $validator) {
// 即使值为空也会执行此规则
if (empty($value)) {
return false;
}
return preg_match('/^1[3-9]\d{9}$/', $value);
});
带参数的规则扩展
Validator::extend('greater_than', function ($attribute, $value, $parameters, $validator) {
$min_field = $parameters[0];
$data = $validator->getData();
$min_value = $data[$min_field];
return $value > $min_value;
});
Validator::replacer('greater_than', function ($message, $attribute, $rule, $parameters) {
return str_replace([':attribute', ':other'], [$attribute, $parameters[0]], ':attribute 必须大于 :other');
});
使用方式:
$request->validate([
'end_date' => 'required|greater_than:start_date',
'start_date' => 'required'
]);
复杂规则示例:数据库唯一性检查
Validator::extend('unique_together', function ($attribute, $value, $parameters, $validator) {
list($table, $field1, $field2) = $parameters;
$data = $validator->getData();
$exists = DB::table($table)
->where($field1, $data[$field1])
->where($field2, $value)
->exists();
return !$exists;
});
国际化支持
在 resources/lang/zh/validation.php 中添加:
'custom' => [
'phone' => [
'phone' => ':attribute 格式不正确',
],
],
使用自定义验证器类
创建 app/Validators/CustomValidator.php:
namespace App\Validators;
use Illuminate\Validation\Validator;
class CustomValidator extends Validator
{
public function validatePhone($attribute, $value, $parameters)
{
return preg_match('/^1[3-9]\d{9}$/', $value);
}
}
在 AppServiceProvider 中注册:
use App\Validators\CustomValidator;
public function boot()
{
Validator::resolver(function($translator, $data, $rules, $messages) {
return new CustomValidator($translator, $data, $rules, $messages);
});
}
通过依赖注入
在构造函数中注入依赖:
class UniqueTitle implements Rule
{
protected $category;
public function __construct($category)
{
$this->category = $category;
}
public function passes($attribute, $value)
{
return !Post::where('category_id', $this->category)
->where('title', $value)
->exists();
}
public function message()
{
return '该分类下已存在相同的标题';
}
}
使用方式:
$request->validate([ => ['required', new UniqueTitle($request->category_id)] ]);
最佳实践建议
- 使用规则类:对于复杂规则,优先使用 Rule 类
- 单一职责:每个规则只做一件事
- 复用性:设计通用的规则,方便复用
- 错误消息:提供清晰、友好的错误提示
- 测试覆盖:为自定义规则编写单元测试
选择哪种方式取决于具体场景的复杂度和复用需求,对于简单的规则,使用 extend() 方法;对于复杂或需要复用的规则,推荐使用 Rule 类。