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"
]

相关连接

原文连接

本作品采用《CC 协议》,转载必须注明作者和本文链接
No practice, no gain in one's wit. 我的 Gitub
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
56
粉丝
127
喜欢
972
收藏
1336
排名:46
访问:15.3 万
私信
所有博文
社区赞助商