laravel 中自动批量注册验证规则到验证器

laravel 中自动批量注册验证规则到验证器

创建抽象验证规则 App\Rules\RuleApp\Rules\RegexRule

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Str;

abstract class Rule implements ValidationRule
{
    abstract public function passes(string $attribute, mixed $value): bool;

    public function validate(string $attribute, mixed $value, \Closure $fail): void
    {
        if (! $this->passes($attribute, $value)) {
            $fail(static::message())->translate();
        }
    }

    /**
     * 规则名称
     */
    public static function name(): string
    {
        return Str::of(class_basename(static::class))->replaceLast('Rule', '')->snake();
    }

    /**
     * 错误消息
     */
    public static function message(): string
    {
        $transMessage = __($transKey = sprintf('validation.%s', static::name()));

        return $transMessage === $transKey ? static::fallbackMessage() : $transMessage;
    }

    /**
     * 扩展方法
     */
    public static function extendMethod(): string
    {
        $ruleReflectionClass = new \ReflectionClass(static::class);

        $isImplicit = $ruleReflectionClass->getDefaultProperties()['implicit'] ?? false;
        if ($isImplicit) {
            return 'extendImplicit';
        }

        // extendDependent todo

        return 'extend';
    }

    /**
     * 回退错误消息
     */
    protected static function fallbackMessage(): string
    {
        return __(
            app()->isLocale('zh_CN')
                ? ':Attribute [:input] 必须是有效的 :Name。'
                : 'The :attribute [:input] must be a valid :Name.',
            [
                'name' => value(static function () {
                    $name = __($key = sprintf('validation.attributes.%s', static::name()));

                    return $name === $key ? str(static::name())->replace('_', ' ') : $name;
                }),
            ]
        );
    }
}
<?php

namespace App\Rules;

abstract class RegexRule extends Rule
{
    abstract protected function pattern(): string;

    public function passes(string $attribute, mixed $value): bool
    {
        return (bool) preg_match($this->pattern(), $value);
    }
}

创建验证规则特性 App\Rules\Concerns\DataAwareApp\Rules\Concerns\ValidatorAware

<?php

namespace App\Rules\Concerns;

trait DataAware
{
    protected array $data;

    public function setData(array $data): self
    {
        $this->data = $data;

        return $this;
    }
}
<?php

namespace App\Rules\Concerns;

use Illuminate\Validation\Validator;

trait ValidatorAware
{
    protected Validator $validator;

    public function setValidator(Validator $validator): self
    {
        $this->validator = $validator;

        return $this;
    }
}

创建验证规则

普通验证规则

<?php

namespace App\Rules;

final class Base64Rule extends Rule
{
    public function passes(string $attribute, mixed $value): bool
    {
        return base64_encode(base64_decode($value, true)) === $value;
    }
}

正则验证规则

<?php

namespace App\Rules;

final class PhoneRule extends RegexRule
{
    protected function pattern(): string
    {
        /** @lang PhpRegExp */
        return '/^(?:(?:\+|00)86)?1[3-9]\d{9}$/';
    }
}

隐式验证规则

<?php

namespace App\Rules;

use App\Rules\Concerns\DataAware;
use App\Rules\Concerns\ValidatorAware;
use Illuminate\Contracts\Validation\ValidatorAwareRule;

final class DefaultRule extends Rule implements ValidatorAwareRule
{
    // use DataAware;
    use ValidatorAware;

    public bool $implicit = true;

    public function __construct(protected mixed $default) {}

    public function passes(string $attribute, mixed $value): bool
    {
        if ($value === null) {
            $data = $this->validator->getData();
            $data[$attribute] = $this->default;
            $this->validator->setData($data);
        }

        return true;
    }
}

注册验证规则到验证器

创建类发现器 App\Support\Discover

注册验证规则

<?php

namespace App\Providers;

use App\Rules\Rule;
use App\Support\Discover;
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidatorAwareRule;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void {}

    public function boot(): void
    {
        Discover::in('Rules')
            ->instanceOf(Rule::class)
            ->all()
            ->each(static function (\ReflectionClass $ruleReflectionClass, $ruleClass): void {
                /** @var Rule&class-string $ruleClass */
                Validator::{$ruleClass::extendMethod()}(
                    $ruleClass::name(),
                    static fn (
                        string $attribute,
                        mixed $value,
                        array $parameters,
                        \Illuminate\Validation\Validator $validator
                    ): bool => tap(new $ruleClass(...$parameters), static function (Rule $rule) use ($validator): void {
                        $rule instanceof ValidatorAwareRule and $rule->setValidator($validator);
                        $rule instanceof DataAwareRule and $rule->setData($validator->getData());
                    })->passes($attribute, $value),
                    $ruleClass::message()
                );
            });
    }
}

验证

<?php

use App\Rules\Base64Rule;
use App\Rules\PhoneRule;
use Illuminate\Support\Facades\Validator;

$validator = Validator::make(
    [
        'base64' => 'foo',
        'phone' => 'bar',
    ],
    [
        // 'base64' => new Base64Rule(),
        'base64' => 'base64', // 验证规则名称
        'phone' => new PhoneRule(), // 验证规则实例
        // 'phone' => 'phone',
    ]
);
dump($validator->errors()->all());

$validator = Validator::make(
    [
        // 'default' => 'baz',
    ],
    [
        'default' => 'default:baz',
    ]
);
dump($validator->validate());
array:2 [
  0 => "Base64 [foo] 必须是有效的 Base64。"
  1 => "电话 [bar] 必须是有效的 电话。"
]

array:1 [
  "default" => "baz"
]

相关连接

原文连接

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值