gordensong/laravel-table-validator 数据表字段验证收集器

Laravel框架
411
0
0
2022-05-29

gordensong/laravel-table-validator

简介

这是一个规则收集器。
  1. 复用规则
  2. 自定义规则
  3. 自动加载表规则
  4. 排除规则
  5. 场景规则
  6. 缓存规则

概念

  1. Validator:规则收集器。
  2. TableValidator:表规则收集器(扩展表字段规则)。
  3. ValidatorCollection:(表)规则收集器集合。
  4. scene :规则场景。表规则收集器可以合并获取指定场景规则。规则收集器集合可以分别获取每个规则收集器的场景规则。

机制

  1. 规则合并优先级: table rules < $rules|customizeRules() < scene rules,优先级高的规则覆盖优先级低的规则。
  2. 同一表字段规则: required 优先级最高,排最前面,

使用

Validator

use GordenSong\Support\Validator;

class AuthorValidator extends Validator
{
    protected $rules = [
        'id' => ['integer'],
        'name' => ['require','string'],
        'age' => ['integer'],
        'birth_date' => ['datetime'],
    ];
    protected $scenes = [
        'new' => ['name', 'age'],
        'age' => ['id' => 'required', 'age' => 'required'],
        'birth_date' => ['id' => 'required', 'birth_date' => 'required'],
    ];
}

1. scene()

scene() 规则覆盖 $rules 规则。
public function scene(string ...$scenes) : static

用法 1.

$validator = new AuthorValidator();

print_r($validator->scene('new')->rules());

Array
(
    [name] => Array
        (
            [0] => required
            [1] => string
        )
    [age] => Array
        (
            [0] => integer
        )
)

demo 用法 2:

print_r($validator->scene('age', 'birth_date')->rules());

Array
(
    [id] => Array
        (
            [0] => required
            [1] => integer
        )
    [age] => Array
        (
            [0] => required
            [1] => integer
        )
    [birth_date] => Array
        (
            [0] => required
            [1] => datetime
        )
)

2. prefix( )

public function prefix(string $prefix, bool $required = false) : static
print_r($validator->prefix('author')->rules());

Array
(
    [author] => Array
        (
            [0] => array // required = false
        )
    [author.id] => Array
        (
            [0] => integer
        )
    [author.name] => Array
        (
            [0] => required
            [1] => string
        )
    ...
)
print_r($validator->prefix('author', true)->rules());

Array
(
    [author] => Array
        (
            [0] => required // required = true
            [1] => array
        )

    [author.id] => Array
        (
            [0] => integer
        )

    [author.name] => Array
        (
            [0] => required
            [1] => string
        )
    ...
)

excludeRules()

排除字段一个或多个规则.

protected function excludeRules() : array {
    return [
        'key1' => ['string'], // 移除 key1 的 string 规则   
        'key2', // 移除整个 key2 规则
    ];
}

demo

namespace Tests\Validator;

use GordenSong\Support\Validator;

class ExcludeValidator extends Validator
{
    // simulate table rules  
    protected $rules = [
        'title' => ['string'],
        'config' => ['string'],
        'created_at' => ['datetime'],
        'updated_at' => ['datetime'],
    ];

    public function customizeRules(): array{
        return [
            'title' => ['string', 'required'],
            'config' => ['array'],
        ];
    }

    public function excludeRules(): array{
        return [
            'config' => ['string'],
            'created_at',
            'updated_at',
        ];
    }
}
$validator = new ExcludeValidator();

self::assertSame([
    'title' => ['required', 'string'],
    'config' => ['array']
], $validator->rules());

TableValidator

abstract class TableValidator extends Validator {
    /** @var null|string  */ 
    protected $connection = null;

    /** @var string */ 
    protected $table;

    public function tableRules(): array {}
}

author migration

Schema::create('author', function (Blueprint $table) {
    $table->id();
    $table->string('name')->nullable(false);
    $table->tinyInteger('age');
    $table->enum('gender', [1, 2]);
});

AuthorTableValidator

class AuthorTableValidator extends TableValidator
{
    protected $table = 'author';

    protected $rules = [
        'name' => ['min:2', 'max:20'],
        'age' => ['max:150'],
        'gender' => ['in:1,2']
    ];
}

tableRules()

public function tableRules(): array
self::assertSame([
    'id' => ['integer', 'min:0',],
    'name' => ['string', 'max:255',], // 注意 这里有 max 规则
    'age' => ['integer', 'min:0', 'max:255',],
    'gender' => ['string',],
], $this->authorValidator->tableRules());

rules()

$rules 覆盖 tableRules() 的规则.
public function rules(): array
self::assertSame([
    'id' => ['integer', 'min:0',],
    'name' => ['string','max:20', 'min:2', ], // table rule 含有 max, 所以 maxmin 前面
    'age' => ['integer', 'min:0', 'max:150',],
    'gender' => ['string', 'in:1,2'],
], $this->authorValidator->rules());

ValidatorCollection

$rules = ValidatorCollection::make(
    (new AuthorValidator())->prefix('author'),
    (new AddressValidator())->prefix('address')
)->rules();

dump($rules);

array:7 [
  "author" => array:1 [
    0 => "array"
  ]
  "author.id" => array:1 [
    0 => "integer"
  ]
  "author.name" => array:2 [
    0 => "required" 
    1 => "string"
  ]
  "author.age" => array:1 [
    0 => "integer"
  ]
  "author.birth_date" => array:1 [
    0 => "datetime"
  ]
  "address" => array:1 [
    0 => "array"
  ]
  "address.city" => array:1 [
    0 => "string"
  ]
]

Macro

Validator::macro('validate', function (array $data) {
    /** @var Factory $factory */ 
    $factory = app(Factory::class);

    /** @var Validator $this */ 
    return $factory->validate($data, $this->rules(), $this->messages(), $this->attributes());
});

$data = [
    'name' => 'a',
    'age' => 10,
];
$validated = (new AuthorValidator())->validate($data);

self::assertSame($data, $validated);
ValidatorCollection::macro('validate', function (array $data) {
    /** @var Factory $factory */ 
    $factory = app(Factory::class);

    /** @var Validator $this */ 
    return $factory->validate($data, $this->rules(), $this->messages(), $this->attributes());
});

$data = [
    'name' => 'a',
    'age' => 10,
];
$validated = ValidatorCollection::make(new AuthorValidator())->validate($data);

self::assertSame($data, $validated);

Command

vendor:publish

php artisan vendor:publish
# select Provider: GordenSong\Providers\LaravelTableValidatorServiceProvider
# publish table-validator.php to /config/

validator

validator
  validator:cache {connection}                  Generate one or more table validator cache
  validator:make {table*} {--connection=mysql} [options] <table>...  Generate one or more table validators
生成 Validator

默认文件位置: app/Validators/BooksValidator.php

php artisan validator:make .         # 为默认数据库所有的表自动生成 Validator 
php artisan validator:make tablename # 为指定表生成 Validator
php artisan validator:make tablename --force # overwrite the file
php artisan validator:make tablename --force --connection=mysql 
缓存表规则

根据 config/table-validator.php 设置规则缓存生成目录。

php artisan validator:cache {connection} {-d}

-d 删除缓存
# bootstrap/cache/table-validator/{$connection}/{$table}.php
php artisan validator:cache mysql