Laravel数据校验规则怎么扩展

wen PHP项目 1

本文目录导读:

Laravel数据校验规则怎么扩展

  1. 使用 Validator::extend() 方法
  2. 使用规则类(推荐)
  3. 使用 Validator::extendImplicit()
  4. 带参数的规则扩展
  5. 复杂规则示例:数据库唯一性检查
  6. 国际化支持
  7. 使用自定义验证器类
  8. 通过依赖注入
  9. 最佳实践建议

Laravel 提供了非常灵活的数据校验规则扩展机制,可以通过以下几种方式来自定义校验规则:

使用 Validator::extend() 方法

AppServiceProviderboot() 方法中注册:

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)]
]);

最佳实践建议

  1. 使用规则类:对于复杂规则,优先使用 Rule 类
  2. 单一职责:每个规则只做一件事
  3. 复用性:设计通用的规则,方便复用
  4. 错误消息:提供清晰、友好的错误提示
  5. 测试覆盖:为自定义规则编写单元测试

选择哪种方式取决于具体场景的复杂度和复用需求,对于简单的规则,使用 extend() 方法;对于复杂或需要复用的规则,推荐使用 Rule 类。

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