bradietilley/laravel-rules

v1.2.0 2024-04-22 22:29 UTC

This package is auto-updated.

Last update: 2024-09-20 03:34:48 UTC


README

Rules 提供了一种优雅的链式面向对象方法,用于为 Laravel 验证定义规则。

Static Analysis Tests

    'email' => Rule::make()
        ->bail()
        ->when(
            $this->method() === 'POST',
            Rule::make()->required(),
            Rule::make()->sometimes(),
        )
        ->string()
        ->email()
        ->unique(
            table: User::class,
            column: 'email',
            ignore: $this->route('user')?->id,
        ),
    'password' => rule()
        ->bail()
        ->when(
            $this->method() === 'POST',
            rule()->required(),
            rule()->sometimes(),
        )
        ->string()
        ->password(
            min: 8,
            letters: true,
            numbers: true,
        ),

安装

使用 composer 获取

composer require bradietilley/laravel-rules

文档

快速示例

use BradieTilley\Rules\Rule;

return [
    'my_field' => Rule::make()->required()->string(),
];

这将产生以下规则集(当传递给 Validator 实例或从你的 Request::rules() 方法返回时)

[
    'my_field' => [
        'required',
        'string',
    ],
]

可用规则

你熟悉的 Laravel 中的每个规则都将与这个包一起工作。每个核心规则(如 requiredstringmin 等)都通过同名方法提供。例如,在 digitsBetween:3,4 中,每个规则(如 min 3 和 max 4)的参数作为方法参数提供,例如:->digitsBetween(min: 3, max: 4)

->rule() 方法作为一个通配符来支持你需要放入那里的任何规则。

例如

Rule::make()
    /**
     * You can use the methods provided
     */
    ->required()

    /**
     * You can pass in any raw string rule as per "default Laravel"
     */
    ->rule('min:2')

    /**
     * You can pass in another Rule object which will be merged in
     */
    ->rule(Rule::make()->max(255))

    /**
     * You can pass in a `\Illuminate\Contracts\Validation\Rule` object
     *
     * Note: This Laravel interface is deprecated and will be dropped in 11.x
     */
    ->rule(new RuleThatImplementsRule())

    /**
     * You can pass in a `\Illuminate\Contracts\Validation\InvokableRule` object
     *
     * Note: This Laravel interface is deprecated and will be dropped in 11.x
     */
    ->rule(new RuleThatImplementsInvokableRule())

    /**
     * You can pass in a `\Illuminate\Contracts\Validation\ValidationRule` object
     */
    ->rule(new RuleThatImplementsValidationRule())

    /**
     * You can pass in any array of rules. The array values can be any of the
     * above rule types: strings, Rule objects, ValidationRule instances, etc
     */
    ->rule([
        'max:2',
        new Unique('table', 'column'),
    ]);

条件规则

你可以指定条件定义的规则。例如,你可能希望创建时字段为 required,更新时为 sometimes。在这种情况下,你可以定义如下

public function rules(): array
{
    $create = $this->method() === 'POST';

    return [
        'name' => Rule::make()
            ->when($create, Rule::make()->required(), Rule::make()->sometimes())
            ->string(),
    ];
}

// or 

public function rules(): array
{
    $create = $this->method() === 'POST';

    return [
        'name' => Rule::make()
            ->when($create, 'required', 'sometimes')
            ->string(),
    ];
}

你提供的条件规则(如上例中的 required 和 sometimes)可以是 ->rule() 方法支持的任何变量类型(如文档所述这里)。

可重用规则

规则中的 ->with(...) 方法为你提供了指定可重用规则逻辑的灵活性,无论你在哪里需要它。

以下是一个示例

/**
 * Example using a closure
 */
public function rules(): array
{
    $integerRule = function (Rule $rule) {
        $rule->integer()->max(100);
    }

    return [
        'percent' => Rule::make()
            ->with($integerRule),
    ];
}

/**
 * Example using a first class callable
 */
function integerRule()
{
    $rule->integer()->max(100);
}

public function rules(): array
{
    return [
        'percent' => Rule::make()
            ->with(integerRule(...)),
    ];
}

/**
 * Example using a callable invokable class
 */
class IntegerRule
{
    public function __invoke(Rule $rule)
    {
        $rule->integer()->max(100);
    }
}

public function rules(): array
{
    return [
        'percent' => Rule::make()
            ->with(new IntegerRule()),
    ];
}

/**
 * The above examples would all return:
 */
[
    'percent' => [
        'integer',
        'max:100',
    ],
]

->with(...) 方法接受任何形式的 callable,例如

  • 闭包(例如 function () { }
  • 传统的可调用表示法(例如 [$this, 'methodName']
  • 一等可调用(例如 $this->methodName(...)
  • 可调用类(例如具有 __invoke 魔术方法的类)
  • PHP 定义为 callable 的任何其他内容。

此包允许你定义“宏”,这些宏可以作为流畅的配置常见规则的工具。

例如,以下代码向 Rule 类添加了一个 australianPhoneNumber 方法

Rule::macro('australianPhoneNumber', function () {
    /** @var Rule $this */
    return $this->rule('regex:/^\+614\d{8}$/');
});

return [
    'phone' => Rule::make()
        ->required()
        ->string()
        ->australianPhoneNumber(),
];

/**
 * The above would return:
 */
[
    'phone' => [
        'required',
        'string',
        'regex:/^\+614\d{8}$/',
    ],
]

优点

更好的语法

类似于在迁移中链式定义数据库列架构,此包旨在提供干净、优雅的链式语法。

参数洞察

处理基于字符串的验证规则(如 decimal)时,记住可用的参数可能会变得麻烦。作为方法,你可以获得自动完成和更深入的参数洞察,以及快速 @link 到验证规则。

变量注入

你不必以尴尬的方式拼接变量(如 'min:'.getMinValue()),而是可以清楚地以方法参数的形式注入变量,如 ->min(getMinValue())

条件逻辑

使用 ->when()->unless() 方法,可以轻松地根据条件添加验证规则。

广泛的规则支持

它不仅支持所有核心 Laravel 规则,还支持你定义的任何自定义规则类。

完全可定制

使用 条件规则可重用规则 进行完全定制。

性能

此包的性能因自然 PHP 执行时间而异。单个验证器测试,该测试针对字符串和整数进行验证,其有效性(基于 min/max 规则)不同,结果差异范围为 -20 微秒到 20 微秒,平均延迟为 14 微秒。

包在单个请求中使用得越多,相对开销就越小。例如,用20个不同的字符串和整数运行相同的验证规则,平均耗时9微秒甚至更少。

这里的开销不再比使用Laravel本身更多。如果你迫切想要节省那几微秒,那么运行一个定制的轻量级框架可能更好——而不是Laravel。

可中断规则

这是一种可选的不同方法,用于处理ValidationRule,它移除了Closure $fail参数的糟糕签名。要实现可中断规则,只需将BradieTilley\Rules\Haltable\HaltableRule特质添加到你的ValidationRule类中,并用run方法替换你的validate方法。

而不是这样

public function validate(string $attribute, mixed $value, Closure $fail): void
{
    if ($this->someCondition) {
        return; // pass
    }

    if ($this->otherCondition) {
        $fail('Some error message');

        return;
    }

    // ...
}

你将改为这样

public function run(string $attribute, mixed $value): void
{
    if ($this->someCondition) {
        $this->passed();
    }

    if ($this->otherCondition) {
        $this->failed('Some error message');
    }

    // ...
}

passedfailed方法会抛出内部异常,这些异常会被捕获并中断规则的验证,而不需要return

如果你对$value的类型有信心,你可以将其类型提示为预期的原始类型。

作者