gordensong/laravel-table-validator 规则收集器

gordensong / laravel-table-validator

gordensong/laravel-table-validator

简介

这是一个基于 laravel 的规则收集器。将规则可以像积木一样任意搭建。可以自定义调用方式。

  1. 复用规则
  2. 自定义规则
  3. 自动加载表规则
  4. 排除规则
  5. 场景规则
  6. 缓存规则

概念

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

机制

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

2. 基础篇

2.1 migrations

user

Schema::create('user', function (Blueprint $table) {
    $table->id();
    $table->string('username', 50)->nullable(false);
    $table->string('password', 50)->nullable(false);
    $table->timestamps();
    $table->softDeletes();
});

user_info

Schema::create('user_info', function (Blueprint $table) {
    $table->id();
    $table->integer('user_id')->nullable(false)->default(0);
    $table->string('xing')->nullable(true)->comment('姓');
    $table->string('ming')->nullable(true)->comment('名');
    $table->integer('age')->default(0);
    $table->json('config1');
    $table->text('config2')->comment('序列化字段');
});

user_address

Schema::create('user_address', function (Blueprint $table) {
    $table->id();
    $table->integer('user_id')->nullable(false)->default(0);
    $table->string('province')->default('')->comment('省');
    $table->string('city')->default('')->comment('市');
    $table->string('district')->default('')->comment('区');
    $table->string('address', 255)->default('')->comment('详细地址');
    $table->timestamps();
    $table->softDeletes();
});

2.2 命令创建 Table Validator

2.2.1 创建指定表的 Validator

php artisan validator:make user user_info --connection=mysql --force

输出

Table validator created: /home/gorden/Workspace/laravel-model-validator-app/app/Validators/Mysql/UserValidator.php

2.2.2 创建所有表的 Validator

php artisan validator:make . --connection=mysql --force

输出

Table validator created: /home/gorden/Workspace/laravel-model-validator-app/app/Validators/Mysql/UserValidator.php
Table validator created: /home/gorden/Workspace/laravel-model-validator-app/app/Validators/Mysql/UserAddressValidator.php
Table validator created: /home/gorden/Workspace/laravel-model-validator-app/app/Validators/Mysql/UserInfoValidator.php

以下是自动生成的 Validator

UserValidator
<?php

namespace App\Validators\Mysql;

class UserValidator extends \GordenSong\Support\TableValidator
{
    protected $connection = 'mysql'; // 作者注: 默认 mysql 可以不设置
    protected $table = 'user';

    public function customizeRules(): array
    {
        return [
            'id' => ['required'],       // 作者注: 数据库非空所以自动追加 'required' 规则 
            'username' => ['required'],
            'password' => ['required'],
            'created_at' => [],
            'updated_at' => [],
            'deleted_at' => [],
        ];
    }

    /**
    * 作者注:验证要排除的字段
    */
    public function excludeRules(): array
    {
        return [
            'created_at',
            'updated_at',
            'deleted_at',
        ];
    }

    protected $messages = [
    ];

    protected $attributes = [
    ];

    protected $scenes = [

    ];
}
UserInfoValidator
<?php

namespace App\Validators\Mysql;

class UserInfoValidator extends \GordenSong\Support\TableValidator
{
    protected $connection = 'mysql';
    protected $table = 'user_info';

    public function customizeRules(): array
    {
        return [
            'id' => ['required'],
            'user_id' => ['required'],
            'xing' => [],
            'ming' => [],
            'age' => ['required'],
            'config1' => ['required'],
            'config2' => ['required'],
        ];
    }

    public function excludeRules(): array
    {
        return [
        ];
    }

    protected $messages = [
    ];

    protected $attributes = [
    ];

    protected $scenes = [
    ];
}
UserAddressValidator
<?php

namespace App\Validators\Mysql;

class UserAddressValidator extends \GordenSong\Support\TableValidator
{
    protected $connection = 'mysql';
    protected $table = 'user_address';

    public function customizeRules(): array
    {
        return [
            'id' => ['required'],
            'user_id' => ['required'],
            'province' => ['required'],
            'city' => ['required'],
            'district' => ['required'],
            'address' => ['required'],
            'created_at' => [],
            'updated_at' => [],
            'deleted_at' => [],
        ];
    }

    public function excludeRules(): array
    {
        return [
            'created_at',
            'updated_at',
            'deleted_at',
        ];
    }

    protected $messages = [
    ];

    protected $attributes = [
    ];

    protected $scenes = [
    ];
}

2.2.3 方法介绍

2.2.3.1 rules() 获取规则

右边的规则覆盖左边的规则: tableRules, customizeRules, excludeRules, scene rules.

$rules = UserValidator::instance()->rules();
dump($rules);

array:3 [
  "id" => array:3 [
    0 => "required"
    1 => "integer"
    2 => "min:0"
  ]
  "username" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:50"
  ]
  "password" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:50"
  ]
]

2.2.3.2 customizeRules() 定制规则

如对 UserValidator 的规则不满意,你可以

  1. 追加
  2. 覆盖
public function customizeRules(): array
{
    return [
        // ...
        'username' => ['required', 'max:30', 'min:3'],
        //...
    ];
}

// 结果
array:3 [
  "id" => ...
  "username" => array:4 [
    0 => "required"
    1 => "string"
    2 => "max:30"
    3 => "min:3"
  ]
  "password" => ...
]

2.2.3.3 excludeRules() 排除规则

你对结果还是不满意,想去掉 username 的规则 min:3

public function excludeRules(): array
{
    return [
        // 排除整个验证字段
        'created_at',
        'updated_at',
        'deleted_at', 

        // 排除指定字段的部分规则
        // 你可以写多个规则, 你可以简写规则,只写“:”前面的内容。
        'username' => ['min'],  
    ];
}

array:3 [
  ...,
  "username" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:30"
  ],
  ...
]

2.2.3.4 prefix($prefix, bool $required = false)

示例 1
$validator = UserValidator::instance()->prefix('user');

dump($validator->rules());

array:4 [
  "user" => array:1 [
    0 => "array"
  ]
  "user.id" => array:3 [
    0 => "required"
    1 => "integer"
    2 => "min:0"
  ]
  "user.username" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:30"
  ]
  "user.password" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:50"
  ]
]
示例2: 表单数组
$validator = UserValidator::instance()->prefix('users.*', true);

dump($validator->rules());

array:5 [
  "users" => array:2 [
    0 => "required"
    1 => "array"
  ]
  "users.*" => array:2 [
    0 => "required"
    1 => "array"
  ]
  "users.*.id" => array:3 [
    0 => "required"
    1 => "integer"
    2 => "min:0"
  ]
  "users.*.username" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:30"
  ]
  "users.*.password" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:50"
  ]
]

2.2.3.5 addRule(string $key, array $rules) 追加规则

$validator = UserValidator::instance()->addRule('password_confirm', ['required']);

dump($validator->rules());

array:4 [
  "id" => array:3 [
    0 => "required"
    1 => "integer"
    2 => "min:0"
  ]
  "username" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:30"
  ]
  "password" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:50"
  ]
  "password_confirm" => array:1 [
    0 => "required"
  ]
]

2.2.3.6 exclude(array $rules) 排除规则

$validator = UserValidator::instance()->exclude(['id', 'password' => ['required']]);

dump($validator->rules());

array:2 [
  "username" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:30"
  ]
  "password" => array:2 [
    0 => "string"
    1 => "max:50"
  ]
]

3 中级用法

3.1 scene(string ...$scene)

scene() 规则覆盖 $rules 规则。

<?php

namespace Tests\Validators\Mysql;

class UserInfoValidator extends \GordenSong\Support\TableValidator
{
    protected $connection = 'mysql';
    protected $table = 'user_info';

    public function customizeRules(): array
    {
        return [
            'id' => ['required'],
            'user_id' => ['required'],
            'xing' => [],
            'ming' => [],
            'age' => ['required'],
            'config1' => ['required'],
            'config2' => ['required'],
        ];
    }

    protected $scenes = [
        'edit-name' => ['user_id' => 'required', 'xing' => 'required', 'ming' => 'required'],
        'edit-age' => ['user_id' => 'required', 'age'],
    ];
}

示例 1

$validator = UserInfoValidator::instance()->scene('edit-name');
dump($validator->rules());

array:3 [
  "user_id" => array:4 [
    0 => "required"
    1 => "integer"
    2 => "min:-2147483648"
    3 => "max:2147483647"
  ]
  "xing" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:255"
  ]
  "ming" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:255"
  ]
]

示例 2

$validator = UserInfoValidator::instance()->scene('edit-name', 'edit-age');
dump($validator->rules());

array:4 [
  "user_id" => array:4 [
    0 => "required"
    1 => "integer"
    2 => "min:-2147483648"
    3 => "max:2147483647"
  ]
  "xing" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:255"
  ]
  "ming" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:255"
  ]
  "age" => array:4 [
    0 => "required"
    1 => "integer"
    2 => "min:-2147483648"
    3 => "max:2147483647"
  ]
]

3.2 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);
Collection::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 = Collection::make(new AuthorValidator())->validate($data);

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

你也可以 $validator->validateRequest(),你想怎么用怎么用!

4 高级用法

Validator, Collection 就像一个个积木,发挥你的想象力,使用它吧。

$collection = Collection::make([
    Collection::make([
        UserValidator::instance(),
        EmailValidator::instance(),
        QqValidator::instance()
    ])->prefix('user'),
    UserInfoValidator::instance()->exclude(['id', 'user_id'])->prefix('user_info'),
    UserAddressValidator::instance()->exclude(['id', 'user_id'])->prefix('user_address.*'),
]);
dump($collection->rules());

array:22 [
  "user" => array:1 [
    0 => "array"
  ]
  "user.id" => array:3 [
    0 => "required"
    1 => "integer"
    2 => "min:0"
  ]
  "user.username" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:30"
  ]
  "user.password" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:50"
  ]
  "user.email" => array:2 [
    0 => "string"
    1 => "email"
  ]
  "user.qq" => array:1 [
    0 => "numeric"
  ]
  "user_info" => array:1 [
    0 => "array"
  ]
  "user_info.xing" => array:2 [
    0 => "string"
    1 => "max:255"
  ]
  "user_info.ming" => array:2 [
    0 => "string"
    1 => "max:255"
  ]
  "user_info.age" => array:4 [
    0 => "required"
    1 => "integer"
    2 => "min:-2147483648"
    3 => "max:2147483647"
  ]
  "user_info.config1" => array:2 [
    0 => "required"
    1 => "json"
  ]
  "user_info.config2" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:65535"
  ]
  "user_address" => array:1 [
    0 => "array"
  ]
  "user_address.*" => array:1 [
    0 => "array"
  ]
  "user_address.*.province" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:255"
  ]
  "user_address.*.city" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:255"
  ]
  "user_address.*.district" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:255"
  ]
  "user_address.*.address" => array:3 [
    0 => "required"
    1 => "string"
    2 => "max:255"
  ]
]

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
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 1

望各位基友不吝赐教。

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!