mirror of
https://gitee.com/technical-laohu/mpay_v2_webman.git
synced 2026-03-25 20:24:27 +08:00
395 lines
11 KiB
Markdown
395 lines
11 KiB
Markdown
验证器 webman/validation
|
||
基于 illuminate/validation,提供手动验证、注解验证、参数级验证,以及可复用的规则集。
|
||
|
||
安装
|
||
composer require webman/validation
|
||
基本概念
|
||
规则集复用:通过继承 support\validation\Validator 定义可复用的 rules messages attributes scenes,可在手动与注解中复用。
|
||
方法级注解(Attribute)验证:使用 PHP 8 属性注解 #[Validate] 绑定控制器方法。
|
||
参数级注解(Attribute)验证:使用 PHP 8 属性注解 #[Param] 绑定控制器方法参数。
|
||
异常处理:验证失败抛出 support\validation\ValidationException,异常类可通过配置自定义
|
||
数据库验证:如果涉及数据库验证,需要安装 composer require webman/database
|
||
手动验证
|
||
基本用法
|
||
use support\validation\Validator;
|
||
|
||
$data = ['email' => 'user@example.com'];
|
||
|
||
Validator::make($data, [
|
||
'email' => 'required|email',
|
||
])->validate();
|
||
提示
|
||
validate() 校验失败会抛出 support\validation\ValidationException。如果你不希望抛异常,请使用下方的 fails() 写法获取错误信息。
|
||
|
||
自定义 messages 与 attributes
|
||
use support\validation\Validator;
|
||
|
||
$data = ['contact' => 'user@example.com'];
|
||
|
||
Validator::make(
|
||
$data,
|
||
['contact' => 'required|email'],
|
||
['contact.email' => '邮箱格式不正确'],
|
||
['contact' => '邮箱']
|
||
)->validate();
|
||
不抛异常并获取错误信息
|
||
如果你不希望抛异常,可以使用 fails() 判断,并通过 errors()(返回 MessageBag)获取错误信息:
|
||
|
||
use support\validation\Validator;
|
||
|
||
$data = ['email' => 'bad-email'];
|
||
|
||
$validator = Validator::make($data, [
|
||
'email' => 'required|email',
|
||
]);
|
||
|
||
if ($validator->fails()) {
|
||
$firstError = $validator->errors()->first(); // string
|
||
$allErrors = $validator->errors()->all(); // array
|
||
$errorsByField = $validator->errors()->toArray(); // array
|
||
// 处理错误...
|
||
}
|
||
规则集复用(自定义 Validator)
|
||
namespace app\validation;
|
||
|
||
use support\validation\Validator;
|
||
|
||
class UserValidator extends Validator
|
||
{
|
||
protected array $rules = [
|
||
'id' => 'required|integer|min:1',
|
||
'name' => 'required|string|min:2|max:20',
|
||
'email' => 'required|email',
|
||
];
|
||
|
||
protected array $messages = [
|
||
'name.required' => '姓名必填',
|
||
'email.required' => '邮箱必填',
|
||
'email.email' => '邮箱格式不正确',
|
||
];
|
||
|
||
protected array $attributes = [
|
||
'name' => '姓名',
|
||
'email' => '邮箱',
|
||
];
|
||
}
|
||
手动验证复用
|
||
use app\validation\UserValidator;
|
||
|
||
UserValidator::make($data)->validate();
|
||
使用 scenes(可选)
|
||
scenes 是可选能力,只有在你调用 withScene(...) 时,才会按场景只验证部分字段。
|
||
|
||
namespace app\validation;
|
||
|
||
use support\validation\Validator;
|
||
|
||
class UserValidator extends Validator
|
||
{
|
||
protected array $rules = [
|
||
'id' => 'required|integer|min:1',
|
||
'name' => 'required|string|min:2|max:20',
|
||
'email' => 'required|email',
|
||
];
|
||
|
||
protected array $scenes = [
|
||
'create' => ['name', 'email'],
|
||
'update' => ['id', 'name', 'email'],
|
||
];
|
||
}
|
||
use app\validation\UserValidator;
|
||
|
||
// 不指定场景 -> 验证全部规则
|
||
UserValidator::make($data)->validate();
|
||
|
||
// 指定场景 -> 只验证该场景包含的字段
|
||
UserValidator::make($data)->withScene('create')->validate();
|
||
注解验证(方法级)
|
||
直接规则
|
||
use support\Request;
|
||
use support\validation\annotation\Validate;
|
||
|
||
class AuthController
|
||
{
|
||
#[Validate(
|
||
rules: [
|
||
'email' => 'required|email',
|
||
'password' => 'required|string|min:6',
|
||
],
|
||
messages: [
|
||
'email.required' => '邮箱必填',
|
||
'password.required' => '密码必填',
|
||
],
|
||
attributes: [
|
||
'email' => '邮箱',
|
||
'password' => '密码',
|
||
]
|
||
)]
|
||
public function login(Request $request)
|
||
{
|
||
return json(['code' => 0, 'msg' => 'ok']);
|
||
}
|
||
}
|
||
复用规则集
|
||
use app\validation\UserValidator;
|
||
use support\Request;
|
||
use support\validation\annotation\Validate;
|
||
|
||
class UserController
|
||
{
|
||
#[Validate(validator: UserValidator::class, scene: 'create')]
|
||
public function create(Request $request)
|
||
{
|
||
return json(['code' => 0, 'msg' => 'ok']);
|
||
}
|
||
}
|
||
多重验证叠加
|
||
use support\validation\annotation\Validate;
|
||
|
||
class UserController
|
||
{
|
||
#[Validate(rules: ['email' => 'required|email'])]
|
||
#[Validate(rules: ['token' => 'required|string'])]
|
||
public function send()
|
||
{
|
||
return json(['code' => 0, 'msg' => 'ok']);
|
||
}
|
||
}
|
||
验证数据来源
|
||
use support\validation\annotation\Validate;
|
||
|
||
class UserController
|
||
{
|
||
#[Validate(
|
||
rules: ['email' => 'required|email'],
|
||
in: ['query', 'body', 'path']
|
||
)]
|
||
public function send()
|
||
{
|
||
return json(['code' => 0, 'msg' => 'ok']);
|
||
}
|
||
}
|
||
通过in参数来指定数据来源,其中:
|
||
|
||
query http请求的query参数,取自 $request->get()
|
||
body http请求的包体,取自 $request->post()
|
||
path http请求的路径参数,取自 $request->route->param()
|
||
in可为字符串或数组;为数组时按顺序合并,后者覆盖前者。未传递in时默认等效于 ['query', 'body', 'path']。
|
||
|
||
参数级验证(Param)
|
||
基本用法
|
||
use support\validation\annotation\Param;
|
||
|
||
class MailController
|
||
{
|
||
public function send(
|
||
#[Param(rules: 'required|email')] string $from,
|
||
#[Param(rules: 'required|email')] string $to,
|
||
#[Param(rules: 'required|string|min:1|max:500')] string $content
|
||
) {
|
||
return json(['code' => 0, 'msg' => 'ok']);
|
||
}
|
||
}
|
||
验证数据来源
|
||
类似的,参数级也支持in参数指定来源
|
||
|
||
use support\validation\annotation\Param;
|
||
|
||
class MailController
|
||
{
|
||
public function send(
|
||
#[Param(rules: 'required|email', in: ['body'])] string $from
|
||
) {
|
||
return json(['code' => 0, 'msg' => 'ok']);
|
||
}
|
||
}
|
||
rules 支持字符串或数组
|
||
use support\validation\annotation\Param;
|
||
|
||
class MailController
|
||
{
|
||
public function send(
|
||
#[Param(rules: ['required', 'email'])] string $from
|
||
) {
|
||
return json(['code' => 0, 'msg' => 'ok']);
|
||
}
|
||
}
|
||
自定义 messages / attribute
|
||
use support\validation\annotation\Param;
|
||
|
||
class UserController
|
||
{
|
||
public function updateEmail(
|
||
#[Param(
|
||
rules: 'required|email',
|
||
messages: ['email.email' => '邮箱格式不正确'],
|
||
attribute: '邮箱'
|
||
)]
|
||
string $email
|
||
) {
|
||
return json(['code' => 0, 'msg' => 'ok']);
|
||
}
|
||
}
|
||
规则常量复用
|
||
final class ParamRules
|
||
{
|
||
public const EMAIL = ['required', 'email'];
|
||
}
|
||
|
||
class UserController
|
||
{
|
||
public function send(
|
||
#[Param(rules: ParamRules::EMAIL)] string $email
|
||
) {
|
||
return json(['code' => 0, 'msg' => 'ok']);
|
||
}
|
||
}
|
||
方法级 + 参数级混合
|
||
use support\Request;
|
||
use support\validation\annotation\Param;
|
||
use support\validation\annotation\Validate;
|
||
|
||
class UserController
|
||
{
|
||
#[Validate(rules: ['token' => 'required|string'])]
|
||
public function send(
|
||
Request $request,
|
||
#[Param(rules: 'required|email')] string $from,
|
||
#[Param(rules: 'required|integer')] int $id
|
||
) {
|
||
return json(['code' => 0, 'msg' => 'ok']);
|
||
}
|
||
}
|
||
自动规则推导(基于参数签名)
|
||
当方法上使用 #[Validate],或该方法的任意参数使用了 #[Param] 时,本组件会根据方法参数签名自动推导并补全基础验证规则,再与已有规则合并后执行验证。
|
||
|
||
示例:#[Validate] 等价展开
|
||
1) 只开启 #[Validate],不手写规则:
|
||
|
||
use support\validation\annotation\Validate;
|
||
|
||
class DemoController
|
||
{
|
||
#[Validate]
|
||
public function create(string $content, int $uid)
|
||
{
|
||
}
|
||
}
|
||
等价于:
|
||
|
||
use support\validation\annotation\Validate;
|
||
|
||
class DemoController
|
||
{
|
||
#[Validate(rules: [
|
||
'content' => 'required|string',
|
||
'uid' => 'required|integer',
|
||
])]
|
||
public function create(string $content, int $uid)
|
||
{
|
||
}
|
||
}
|
||
2) 只写了部分规则,其余由参数签名补全:
|
||
|
||
use support\validation\annotation\Validate;
|
||
|
||
class DemoController
|
||
{
|
||
#[Validate(rules: [
|
||
'content' => 'min:2',
|
||
])]
|
||
public function create(string $content, int $uid)
|
||
{
|
||
}
|
||
}
|
||
等价于:
|
||
|
||
use support\validation\annotation\Validate;
|
||
|
||
class DemoController
|
||
{
|
||
#[Validate(rules: [
|
||
'content' => 'required|string|min:2',
|
||
'uid' => 'required|integer',
|
||
])]
|
||
public function create(string $content, int $uid)
|
||
{
|
||
}
|
||
}
|
||
3) 默认值/可空类型:
|
||
|
||
use support\validation\annotation\Validate;
|
||
|
||
class DemoController
|
||
{
|
||
#[Validate]
|
||
public function create(string $content = '默认值', ?int $uid = null)
|
||
{
|
||
}
|
||
}
|
||
等价于:
|
||
|
||
use support\validation\annotation\Validate;
|
||
|
||
class DemoController
|
||
{
|
||
#[Validate(rules: [
|
||
'content' => 'string',
|
||
'uid' => 'integer|nullable',
|
||
])]
|
||
public function create(string $content = '默认值', ?int $uid = null)
|
||
{
|
||
}
|
||
}
|
||
异常处理
|
||
默认异常
|
||
验证失败默认抛出 support\validation\ValidationException,继承 Webman\Exception\BusinessException,不会记录错误日志。
|
||
|
||
默认响应行为由 BusinessException::render() 处理:
|
||
|
||
普通请求:返回字符串消息,例如 token 为必填项。
|
||
JSON 请求:返回 JSON 响应,例如 {"code": 422, "msg": "token 为必填项。", "data":....}
|
||
通过自定义异常修改处理方式
|
||
全局配置:config/plugin/webman/validation/app.php 的 exception
|
||
多语言支持
|
||
组件内置中英文语言包,并支持项目覆盖。加载顺序:
|
||
|
||
项目语言包 resource/translations/{locale}/validation.php
|
||
组件内置 vendor/webman/validation/resources/lang/{locale}/validation.php
|
||
Illuminate 内置英文(兜底)
|
||
提示
|
||
webman默认语言由 config/translation.php 配置,也可以通过函数 locale('en'); 更改。
|
||
|
||
本地覆盖示例
|
||
resource/translations/zh_CN/validation.php
|
||
|
||
return [
|
||
'email' => ':attribute 不是有效的邮件格式。',
|
||
];
|
||
中间件自动加载
|
||
组件安装后会通过 config/plugin/webman/validation/middleware.php 自动加载验证中间件,无需手动注册。
|
||
|
||
命令行生成注解
|
||
使用命令 make:validator 生成验证器类(默认生成到 app/validation 目录)。
|
||
|
||
提示
|
||
需要安装 composer require webman/console
|
||
|
||
基础用法
|
||
生成空模板
|
||
php webman make:validator UserValidator
|
||
覆盖已存在文件
|
||
php webman make:validator UserValidator --force
|
||
php webman make:validator UserValidator -f
|
||
从表结构生成规则
|
||
指定表名生成基础规则(会根据字段类型/可空/长度等推导 $rules;默认排除字段与 ORM 相关:laravel 为 created_at/updated_at/deleted_at,thinkorm 为 create_time/update_time/delete_time)
|
||
php webman make:validator UserValidator --table=wa_users
|
||
php webman make:validator UserValidator -t wa_users
|
||
指定数据库连接(多连接场景)
|
||
php webman make:validator UserValidator --table=wa_users --database=mysql
|
||
php webman make:validator UserValidator -t wa_users -d mysql
|
||
场景(scenes)
|
||
生成 CRUD 场景:create/update/delete/detail
|
||
php webman make:validator UserValidator --table=wa_users --scenes=crud
|
||
php webman make:validator UserValidator -t wa_users -s crud
|
||
update 场景会包含主键字段(用于定位记录)以及其余字段;delete/detail 默认仅包含主键字段。 |