[English](README.md) | 中文 # Webman Validation Webman 的验证组件,基于 `illuminate/validation`,提供手动验证、注解验证、参数级验证,以及可复用的规则集。 ## 安装 ```bash 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` ## 手动验证 ### 基本用法 ```php use support\validation\Validator; $data = ['email' => 'user@example.com']; Validator::make($data, [ 'email' => 'required|email', ])->validate(); ``` > **提示** > `validate()` 校验失败会抛出 `support\validation\ValidationException`。如果你不希望抛异常,请使用下方的 `fails()` 写法获取错误信息。 ### 自定义 messages 与 attributes ```php use support\validation\Validator; $data = ['contact' => 'user@example.com']; Validator::make( $data, ['contact' => 'required|email'], ['contact.email' => '邮箱格式不正确'], ['contact' => '邮箱'] )->validate(); ``` ### 不抛异常并获取错误信息 如果你不希望抛异常,可以使用 `fails()` 判断,并通过 `errors()`(返回 `MessageBag`)获取错误信息: ```php 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) ```php 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' => '邮箱', ]; } ``` ### 手动验证复用 ```php use app\validation\UserValidator; UserValidator::make($data)->validate(); ``` ### 使用 scenes(可选) `scenes` 是可选能力,只有在你调用 `withScene(...)` 时,才会按场景只验证部分字段。 ```php 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'], ]; } ``` ```php use app\validation\UserValidator; // 不指定场景 -> 验证全部规则 UserValidator::make($data)->validate(); // 指定场景 -> 只验证该场景包含的字段 UserValidator::make($data)->withScene('create')->validate(); ``` ## 注解验证(方法级) ### 直接规则 ```php 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']); } } ``` ### 复用规则集 ```php 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']); } } ``` ### 多重验证叠加 ```php 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']); } } ``` ### 验证数据来源 ```php 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) ### 基本用法 ```php 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`参数指定来源 ```php 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 支持字符串或数组 ```php use support\validation\annotation\Param; class MailController { public function send( #[Param(rules: ['required', 'email'])] string $from ) { return json(['code' => 0, 'msg' => 'ok']); } } ``` ### 自定义 messages / attribute ```php 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']); } } ``` ### 规则常量复用 ```php 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']); } } ``` ## 方法级 + 参数级混合 ```php 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]`,不手写规则: ```php use support\validation\annotation\Validate; class DemoController { #[Validate] public function create(string $content, int $uid) { } } ``` 等价于: ```php use support\validation\annotation\Validate; class DemoController { #[Validate(rules: [ 'content' => 'required|string', 'uid' => 'required|integer', ])] public function create(string $content, int $uid) { } } ``` 2) 只写了部分规则,其余由参数签名补全: ```php use support\validation\annotation\Validate; class DemoController { #[Validate(rules: [ 'content' => 'min:2', ])] public function create(string $content, int $uid) { } } ``` 等价于: ```php 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) 默认值/可空类型: ```php use support\validation\annotation\Validate; class DemoController { #[Validate] public function create(string $content = '默认值', ?int $uid = null) { } } ``` 等价于: ```php 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` ## 多语言支持 组件内置中英文语言包,并支持项目覆盖。加载顺序: 1. 项目语言包 `resource/translations/{locale}/validation.php` 2. 组件内置 `vendor/webman/validation/resources/lang/{locale}/validation.php` 3. Illuminate 内置英文(兜底) > **提示** > webman默认语言由 `config/translation.php` 配置,也可以通过函数 locale('en'); 更改。 ### 本地覆盖示例 `resource/translations/zh_CN/validation.php` ```php return [ 'email' => ':attribute 不是有效的邮件格式。', ]; ``` ## 中间件自动加载 组件安装后会通过 `config/plugin/webman/validation/middleware.php` 自动加载验证中间件,无需手动注册。 ## 命令行生成注解 使用命令 `make:validator` 生成验证器类(默认生成到 `app/validation` 目录)。 > **提示** > 需要安装 `composer require webman/console` ### 基础用法 - **生成空模板** ```bash php webman make:validator UserValidator ``` - **覆盖已存在文件** ```bash 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`) ```bash php webman make:validator UserValidator --table=wa_users php webman make:validator UserValidator -t wa_users ``` - **指定数据库连接**(多连接场景) ```bash 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` ```bash php webman make:validator UserValidator --table=wa_users --scenes=crud php webman make:validator UserValidator -t wa_users -s crud ``` > `update` 场景会包含主键字段(用于定位记录)以及其余字段;`delete/detail` 默认仅包含主键字段。 ### ORM 选择(laravel(illuminate/database) 与 think-orm) - **自动选择(默认)**:仅安装/配置了哪套就用哪套;都存在时默认用 illuminate - **强制指定** ```bash php webman make:validator UserValidator --table=wa_users --orm=laravel php webman make:validator UserValidator --table=wa_users --orm=thinkorm php webman make:validator UserValidator -t wa_users -o thinkorm ``` ### 综合示例 ```bash php webman make:validator UserValidator -t wa_users -d mysql -s crud -o laravel -f ``` ## 单元测试 进入 `webman/validation` 根目录执行: ```bash composer install vendor\bin\phpunit -c phpunit.xml ``` ## 所有验证规则参考 ## 可用验证规则 > [!IMPORTANT] > - Webman Validation 基于 `illuminate/validation`,规则名称与 Laravel 一致,规则本身无 Webman 特化。 > - 中间件默认验证数据来自 `$request->all()`(GET+POST)并合并路由参数,不包含上传文件;涉及文件规则时,请自行将 `$request->file()` 合并到数据中,或手动调用 `Validator::make`。 > - `current_password` 依赖认证守卫,`exists`/`unique` 依赖数据库连接与查询构建器,未接入对应组件时规则不可用。 以下列出所有可用验证规则及其作用: #### 布尔值
[Accepted](#rule-accepted) [Accepted If](#rule-accepted-if) [Boolean](#rule-boolean) [Declined](#rule-declined) [Declined If](#rule-declined-if)
#### 字符串
[Active URL](#rule-active-url) [Alpha](#rule-alpha) [Alpha Dash](#rule-alpha-dash) [Alpha Numeric](#rule-alpha-num) [Ascii](#rule-ascii) [Confirmed](#rule-confirmed) [Current Password](#rule-current-password) [Different](#rule-different) [Doesnt Start With](#rule-doesnt-start-with) [Doesnt End With](#rule-doesnt-end-with) [Email](#rule-email) [Ends With](#rule-ends-with) [Enum](#rule-enum) [Hex Color](#rule-hex-color) [In](#rule-in) [IP Address](#rule-ip) [IPv4](#rule-ipv4) [IPv6](#rule-ipv6) [JSON](#rule-json) [Lowercase](#rule-lowercase) [MAC Address](#rule-mac) [Max](#rule-max) [Min](#rule-min) [Not In](#rule-not-in) [Regular Expression](#rule-regex) [Not Regular Expression](#rule-not-regex) [Same](#rule-same) [Size](#rule-size) [Starts With](#rule-starts-with) [String](#rule-string) [Uppercase](#rule-uppercase) [URL](#rule-url) [ULID](#rule-ulid) [UUID](#rule-uuid)
#### 数字
[Between](#rule-between) [Decimal](#rule-decimal) [Different](#rule-different) [Digits](#rule-digits) [Digits Between](#rule-digits-between) [Greater Than](#rule-gt) [Greater Than Or Equal](#rule-gte) [Integer](#rule-integer) [Less Than](#rule-lt) [Less Than Or Equal](#rule-lte) [Max](#rule-max) [Max Digits](#rule-max-digits) [Min](#rule-min) [Min Digits](#rule-min-digits) [Multiple Of](#rule-multiple-of) [Numeric](#rule-numeric) [Same](#rule-same) [Size](#rule-size)
#### 数组
[Array](#rule-array) [Between](#rule-between) [Contains](#rule-contains) [Doesnt Contain](#rule-doesnt-contain) [Distinct](#rule-distinct) [In Array](#rule-in-array) [In Array Keys](#rule-in-array-keys) [List](#rule-list) [Max](#rule-max) [Min](#rule-min) [Size](#rule-size)
#### 日期
[After](#rule-after) [After Or Equal](#rule-after-or-equal) [Before](#rule-before) [Before Or Equal](#rule-before-or-equal) [Date](#rule-date) [Date Equals](#rule-date-equals) [Date Format](#rule-date-format) [Different](#rule-different) [Timezone](#rule-timezone)
#### 文件
[Between](#rule-between) [Dimensions](#rule-dimensions) [Encoding](#rule-encoding) [Extensions](#rule-extensions) [File](#rule-file) [Image](#rule-image) [Max](#rule-max) [MIME Types](#rule-mimetypes) [MIME Type By File Extension](#rule-mimes) [Size](#rule-size)
#### 数据库
[Exists](#rule-exists) [Unique](#rule-unique)
#### 工具类
[Any Of](#rule-anyof) [Bail](#rule-bail) [Exclude](#rule-exclude) [Exclude If](#rule-exclude-if) [Exclude Unless](#rule-exclude-unless) [Exclude With](#rule-exclude-with) [Exclude Without](#rule-exclude-without) [Filled](#rule-filled) [Missing](#rule-missing) [Missing If](#rule-missing-if) [Missing Unless](#rule-missing-unless) [Missing With](#rule-missing-with) [Missing With All](#rule-missing-with-all) [Nullable](#rule-nullable) [Present](#rule-present) [Present If](#rule-present-if) [Present Unless](#rule-present-unless) [Present With](#rule-present-with) [Present With All](#rule-present-with-all) [Prohibited](#rule-prohibited) [Prohibited If](#rule-prohibited-if) [Prohibited If Accepted](#rule-prohibited-if-accepted) [Prohibited If Declined](#rule-prohibited-if-declined) [Prohibited Unless](#rule-prohibited-unless) [Prohibits](#rule-prohibits) [Required](#rule-required) [Required If](#rule-required-if) [Required If Accepted](#rule-required-if-accepted) [Required If Declined](#rule-required-if-declined) [Required Unless](#rule-required-unless) [Required With](#rule-required-with) [Required With All](#rule-required-with-all) [Required Without](#rule-required-without) [Required Without All](#rule-required-without-all) [Required Array Keys](#rule-required-array-keys) [Sometimes](#validating-when-present)
#### accepted 验证字段必须是 `"yes"`、`"on"`、`1`、`"1"`、`true` 或 `"true"`。常用于验证用户是否同意服务条款等场景。 #### accepted_if:anotherfield,value,... 当另一个字段等于指定值时,验证字段必须是 `"yes"`、`"on"`、`1`、`"1"`、`true` 或 `"true"`。常用于条件性同意类场景。 #### active_url 验证字段必须具有有效的 A 或 AAAA 记录。该规则会先用 `parse_url` 提取 URL 的主机名,再交给 `dns_get_record` 校验。 #### after:_date_ 验证字段必须是给定日期之后的值。日期会传给 `strtotime` 转为有效的 `DateTime`: ```php use support\validation\Validator; Validator::make($data, [ 'start_date' => 'required|date|after:tomorrow', ])->validate(); ``` 也可以传入另一个字段名进行比较: ```php Validator::make($data, [ 'finish_date' => 'required|date|after:start_date', ])->validate(); ``` 可使用 fluent `date` 规则构造器: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'start_date' => [ 'required', Rule::date()->after(\Carbon\Carbon::today()->addDays(7)), ], ])->validate(); ``` `afterToday` 和 `todayOrAfter` 可便捷表达“必须晚于今天”或“必须是今天或之后”: ```php Validator::make($data, [ 'start_date' => [ 'required', Rule::date()->afterToday(), ], ])->validate(); ``` #### after_or_equal:_date_ 验证字段必须是给定日期之后或等于给定日期。更多说明见 [after](#rule-after) 规则。 可使用 fluent `date` 规则构造器: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'start_date' => [ 'required', Rule::date()->afterOrEqual(\Carbon\Carbon::today()->addDays(7)), ], ])->validate(); ``` #### anyOf `Rule::anyOf` 允许指定“满足任意一个规则集即可”。例如,下面规则表示 `username` 要么是邮箱地址,要么是至少 6 位的字母数字下划线/短横线字符串: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'username' => [ 'required', Rule::anyOf([ ['string', 'email'], ['string', 'alpha_dash', 'min:6'], ]), ], ])->validate(); ``` #### alpha 验证字段必须是 Unicode 字母([\p{L}](https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AL%3A%5D&g=&i=) 与 [\p{M}](https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AM%3A%5D&g=&i=))。 若仅允许 ASCII(`a-z`、`A-Z`),可添加 `ascii` 选项: ```php Validator::make($data, [ 'username' => 'alpha:ascii', ])->validate(); ``` #### alpha_dash 验证字段只能包含 Unicode 字母数字([\p{L}](https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AL%3A%5D&g=&i=)、[\p{M}](https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AM%3A%5D&g=&i=)、[\p{N}](https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AN%3A%5D&g=&i=)),以及 ASCII 短横线(`-`)与下划线(`_`)。 若仅允许 ASCII(`a-z`、`A-Z`、`0-9`),可添加 `ascii` 选项: ```php Validator::make($data, [ 'username' => 'alpha_dash:ascii', ])->validate(); ``` #### alpha_num 验证字段只能包含 Unicode 字母数字([\p{L}](https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AL%3A%5D&g=&i=)、[\p{M}](https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AM%3A%5D&g=&i=)、[\p{N}](https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AN%3A%5D&g=&i=))。 若仅允许 ASCII(`a-z`、`A-Z`、`0-9`),可添加 `ascii` 选项: ```php Validator::make($data, [ 'username' => 'alpha_num:ascii', ])->validate(); ``` #### array 验证字段必须是 PHP `array`。 当 `array` 规则带有额外参数时,输入数组的键必须在参数列表中。示例中 `admin` 键不在允许列表中,因此无效: ```php use support\validation\Validator; $input = [ 'user' => [ 'name' => 'Taylor Otwell', 'username' => 'taylorotwell', 'admin' => true, ], ]; Validator::make($input, [ 'user' => 'array:name,username', ])->validate(); ``` 建议在实际项目中明确数组允许的键。 #### ascii 验证字段只能包含 7-bit ASCII 字符。 #### bail 当某字段首个规则验证失败时,停止继续验证该字段的其它规则。 该规则只影响当前字段。若需要“全局首错即停”,请直接使用 Illuminate 的验证器并调用 `stopOnFirstFailure()`。 #### before:_date_ 验证字段必须早于给定日期。日期会传给 `strtotime` 转为有效的 `DateTime`。同 [after](#rule-after) 规则,可传入另一个字段名进行比较。 可使用 fluent `date` 规则构造器: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'start_date' => [ 'required', Rule::date()->before(\Carbon\Carbon::today()->subDays(7)), ], ])->validate(); ``` `beforeToday` 与 `todayOrBefore` 可便捷表达“必须早于今天”或“必须是今天或之前”: ```php Validator::make($data, [ 'start_date' => [ 'required', Rule::date()->beforeToday(), ], ])->validate(); ``` #### before_or_equal:_date_ 验证字段必须早于或等于给定日期。日期会传给 `strtotime` 转为有效的 `DateTime`。同 [after](#rule-after) 规则,可传入另一个字段名进行比较。 可使用 fluent `date` 规则构造器: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'start_date' => [ 'required', Rule::date()->beforeOrEqual(\Carbon\Carbon::today()->subDays(7)), ], ])->validate(); ``` #### between:_min_,_max_ 验证字段的大小必须在给定的 _min_ 和 _max_ 之间(含边界)。字符串、数值、数组、文件的评估规则与 [size](#rule-size) 相同。 #### boolean 验证字段必须可转换为布尔值。可接受的输入包括 `true`、`false`、`1`、`0`、`"1"`、`"0"`。 可通过 `strict` 参数仅允许 `true` 或 `false`: ```php Validator::make($data, [ 'foo' => 'boolean:strict', ])->validate(); ``` #### confirmed 验证字段必须有一个匹配字段 `{field}_confirmation`。例如字段为 `password` 时,需要 `password_confirmation`。 也可以指定自定义确认字段名,如 `confirmed:repeat_username` 将要求 `repeat_username` 与当前字段匹配。 #### contains:_foo_,_bar_,... 验证字段必须是数组,且必须包含所有给定参数值。该规则常用于数组校验,可使用 `Rule::contains` 构造: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'roles' => [ 'required', 'array', Rule::contains(['admin', 'editor']), ], ])->validate(); ``` #### doesnt_contain:_foo_,_bar_,... 验证字段必须是数组,且不能包含任何给定参数值。可使用 `Rule::doesntContain` 构造: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'roles' => [ 'required', 'array', Rule::doesntContain(['admin', 'editor']), ], ])->validate(); ``` #### current_password 验证字段必须与当前认证用户的密码匹配。可通过第一个参数指定认证 guard: ```php Validator::make($data, [ 'password' => 'current_password:api', ])->validate(); ``` > [!WARNING] > 该规则依赖认证组件与 guard 配置,未接入认证时请勿使用。 #### date 验证字段必须是 `strtotime` 可识别的有效(非相对)日期。 #### date_equals:_date_ 验证字段必须等于给定日期。日期会传给 `strtotime` 转为有效的 `DateTime`。 #### date_format:_format_,... 验证字段必须匹配给定格式之一。使用 `date` 或 `date_format` 二选一即可。该规则支持 PHP [DateTime](https://www.php.net/manual/en/class.datetime.php) 的所有格式。 可使用 fluent `date` 规则构造器: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'start_date' => [ 'required', Rule::date()->format('Y-m-d'), ], ])->validate(); ``` #### decimal:_min_,_max_ 验证字段必须是数值,且小数位数符合要求: ```php Validator::make($data, [ 'price' => 'decimal:2', ])->validate(); Validator::make($data, [ 'price' => 'decimal:2,4', ])->validate(); ``` #### declined 验证字段必须是 `"no"`、`"off"`、`0`、`"0"`、`false` 或 `"false"`。 #### declined_if:anotherfield,value,... 当另一个字段等于指定值时,验证字段必须是 `"no"`、`"off"`、`0`、`"0"`、`false` 或 `"false"`。 #### different:_field_ 验证字段必须与 _field_ 不同。 #### digits:_value_ 验证字段必须是整数且长度为 _value_。 #### digits_between:_min_,_max_ 验证字段必须是整数且长度在 _min_ 与 _max_ 之间。 #### dimensions 验证字段必须是图片,并满足维度约束: ```php Validator::make($data, [ 'avatar' => 'dimensions:min_width=100,min_height=200', ])->validate(); ``` 可用约束:_min\_width_、_max\_width_、_min\_height_、_max\_height_、_width_、_height_、_ratio_。 _ratio_ 为宽高比,可用分数或浮点表示: ```php Validator::make($data, [ 'avatar' => 'dimensions:ratio=3/2', ])->validate(); ``` 该规则参数较多,建议使用 `Rule::dimensions` 构造: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'avatar' => [ 'required', Rule::dimensions() ->maxWidth(1000) ->maxHeight(500) ->ratio(3 / 2), ], ])->validate(); ``` #### distinct 当验证数组时,字段值不能重复: ```php Validator::make($data, [ 'foo.*.id' => 'distinct', ])->validate(); ``` 默认使用宽松比较。需严格比较可添加 `strict`: ```php Validator::make($data, [ 'foo.*.id' => 'distinct:strict', ])->validate(); ``` 可添加 `ignore_case` 忽略大小写差异: ```php Validator::make($data, [ 'foo.*.id' => 'distinct:ignore_case', ])->validate(); ``` #### doesnt_start_with:_foo_,_bar_,... 验证字段不能以指定值开头。 #### doesnt_end_with:_foo_,_bar_,... 验证字段不能以指定值结尾。 #### email 验证字段必须是有效邮箱地址。该规则依赖 [egulias/email-validator](https://github.com/egulias/EmailValidator),默认使用 `RFCValidation`,也可指定其他验证方式: ```php Validator::make($data, [ 'email' => 'email:rfc,dns', ])->validate(); ``` 可用验证方式列表:
- `rfc`: `RFCValidation` - 按 RFC 规范验证邮箱([支持的 RFC](https://github.com/egulias/EmailValidator?tab=readme-ov-file#supported-rfcs))。 - `strict`: `NoRFCWarningsValidation` - RFC 校验时遇到警告即失败(如结尾点号或连续点号)。 - `dns`: `DNSCheckValidation` - 校验域名是否有有效的 MX 记录。 - `spoof`: `SpoofCheckValidation` - 防止同形异义或欺骗性 Unicode 字符。 - `filter`: `FilterEmailValidation` - 使用 PHP `filter_var` 验证。 - `filter_unicode`: `FilterEmailValidation::unicode()` - 允许 Unicode 的 `filter_var` 验证。
可使用 fluent 规则构造器: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ 'required', Rule::email() ->rfcCompliant(strict: false) ->validateMxRecord() ->preventSpoofing(), ], ])->validate(); ``` > [!WARNING] > `dns` 与 `spoof` 需要 PHP `intl` 扩展。 #### encoding:*encoding_type* 验证字段必须匹配指定字符编码。该规则使用 `mb_check_encoding` 检测文件或字符串编码。可配合文件规则构造器使用: ```php use Illuminate\Validation\Rules\File; use support\validation\Validator; Validator::make($data, [ 'attachment' => [ 'required', File::types(['csv'])->encoding('utf-8'), ], ])->validate(); ``` #### ends_with:_foo_,_bar_,... 验证字段必须以指定值之一结尾。 #### enum `Enum` 是基于类的规则,用于验证字段值是否为合法枚举值。构造时传入枚举类名。验证基本类型值时,应使用 Backed Enum: ```php use app\enums\ServerStatus; use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'status' => [Rule::enum(ServerStatus::class)], ])->validate(); ``` 可用 `only`/`except` 限制枚举值: ```php use app\enums\ServerStatus; use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'status' => [ Rule::enum(ServerStatus::class) ->only([ServerStatus::Pending, ServerStatus::Active]), ], ])->validate(); Validator::make($data, [ 'status' => [ Rule::enum(ServerStatus::class) ->except([ServerStatus::Pending, ServerStatus::Active]), ], ])->validate(); ``` 可使用 `when` 进行条件限制: ```php use app\Enums\ServerStatus; use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'status' => [ Rule::enum(ServerStatus::class)->when( $isAdmin, fn ($rule) => $rule->only(ServerStatus::Active), fn ($rule) => $rule->only(ServerStatus::Pending), ), ], ])->validate(); ``` #### exclude 验证字段会从 `validate`/`validated` 返回的数据中排除。 #### exclude_if:_anotherfield_,_value_ 当 _anotherfield_ 等于 _value_ 时,验证字段会从 `validate`/`validated` 返回的数据中排除。 如需复杂条件,可使用 `Rule::excludeIf`: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'role_id' => Rule::excludeIf($isAdmin), ])->validate(); Validator::make($data, [ 'role_id' => Rule::excludeIf(fn () => $isAdmin), ])->validate(); ``` #### exclude_unless:_anotherfield_,_value_ 除非 _anotherfield_ 等于 _value_,否则验证字段会从 `validate`/`validated` 返回的数据中排除。若 _value_ 为 `null`(如 `exclude_unless:name,null`),则只有当比较字段为 `null` 或不存在时才保留该字段。 #### exclude_with:_anotherfield_ 当 _anotherfield_ 存在时,验证字段会从 `validate`/`validated` 返回的数据中排除。 #### exclude_without:_anotherfield_ 当 _anotherfield_ 不存在时,验证字段会从 `validate`/`validated` 返回的数据中排除。 #### exists:_table_,_column_ 验证字段必须存在于指定数据库表中。 #### Exists 规则的基础用法 ```php Validator::make($data, [ 'state' => 'exists:states', ])->validate(); ``` 未指定 `column` 时,默认使用字段名。因此该例会验证 `states` 表中 `state` 列是否存在。 #### 指定自定义列名 可在表名后追加列名: ```php Validator::make($data, [ 'state' => 'exists:states,abbreviation', ])->validate(); ``` 如需指定数据库连接,可在表名前加连接名: ```php Validator::make($data, [ 'email' => 'exists:connection.staff,email', ])->validate(); ``` 也可传入模型类名,由框架解析表名: ```php Validator::make($data, [ 'user_id' => 'exists:app\model\User,id', ])->validate(); ``` 若需自定义查询条件,可使用 `Rule` 规则构造器: ```php use Illuminate\Database\Query\Builder; use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ 'required', Rule::exists('staff')->where(function (Builder $query) { $query->where('account_id', 1); }), ], ])->validate(); ``` 也可在 `Rule::exists` 中直接指定列名: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'state' => [Rule::exists('states', 'abbreviation')], ])->validate(); ``` 验证一组值是否存在时,可结合 `array` 规则: ```php Validator::make($data, [ 'states' => ['array', Rule::exists('states', 'abbreviation')], ])->validate(); ``` 当 `array` 与 `exists` 同时存在时,会生成单条查询验证全部值。 #### extensions:_foo_,_bar_,... 验证上传文件的扩展名是否在允许列表内: ```php Validator::make($data, [ 'photo' => ['required', 'extensions:jpg,png'], ])->validate(); ``` > [!WARNING] > 不要仅依赖扩展名验证文件类型,建议与 [mimes](#rule-mimes) 或 [mimetypes](#rule-mimetypes) 搭配使用。 #### file 验证字段必须是成功上传的文件。 #### filled 当字段存在时,其值不能为空。 #### gt:_field_ 验证字段必须大于给定 _field_ 或 _value_。两个字段类型必须一致。字符串、数值、数组、文件的评估规则与 [size](#rule-size) 相同。 #### gte:_field_ 验证字段必须大于等于给定 _field_ 或 _value_。两个字段类型必须一致。字符串、数值、数组、文件的评估规则与 [size](#rule-size) 相同。 #### hex_color 验证字段必须是有效的 [十六进制颜色值](https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color)。 #### image 验证字段必须是图片(jpg、jpeg、png、bmp、gif 或 webp)。 > [!WARNING] > 出于 XSS 风险,默认不允许 SVG。如需允许,可加 `allow_svg`:`image:allow_svg`。 #### in:_foo_,_bar_,... 验证字段必须在给定值列表中。可使用 `Rule::in` 构造: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'zones' => [ 'required', Rule::in(['first-zone', 'second-zone']), ], ])->validate(); ``` 与 `array` 规则组合时,输入数组的每个值都必须在 `in` 列表内: ```php use support\validation\Rule; use support\validation\Validator; $input = [ 'airports' => ['NYC', 'LAS'], ]; Validator::make($input, [ 'airports' => [ 'required', 'array', ], 'airports.*' => Rule::in(['NYC', 'LIT']), ])->validate(); ``` #### in_array:_anotherfield_.* 验证字段必须存在于 _anotherfield_ 的值列表中。 #### in_array_keys:_value_.* 验证字段必须是数组,且至少包含给定值之一作为键: ```php Validator::make($data, [ 'config' => 'array|in_array_keys:timezone', ])->validate(); ``` #### integer 验证字段必须是整数。 可使用 `strict` 参数要求字段类型必须为整数,字符串形式的整数将视为无效: ```php Validator::make($data, [ 'age' => 'integer:strict', ])->validate(); ``` > [!WARNING] > 该规则仅验证是否能通过 PHP 的 `FILTER_VALIDATE_INT`,如需强制数值类型,请与 [numeric](#rule-numeric) 配合使用。 #### ip 验证字段必须是合法 IP 地址。 #### ipv4 验证字段必须是合法 IPv4 地址。 #### ipv6 验证字段必须是合法 IPv6 地址。 #### json 验证字段必须是有效的 JSON 字符串。 #### lt:_field_ 验证字段必须小于给定 _field_。两个字段类型必须一致。字符串、数值、数组、文件的评估规则与 [size](#rule-size) 相同。 #### lte:_field_ 验证字段必须小于等于给定 _field_。两个字段类型必须一致。字符串、数值、数组、文件的评估规则与 [size](#rule-size) 相同。 #### lowercase 验证字段必须是小写。 #### list 验证字段必须是列表数组。列表数组的键必须是从 0 到 `count($array) - 1` 的连续数字。 #### mac_address 验证字段必须是合法 MAC 地址。 #### max:_value_ 验证字段必须小于或等于 _value_。字符串、数值、数组、文件的评估规则与 [size](#rule-size) 相同。 #### max_digits:_value_ 验证字段必须是整数,且长度不超过 _value_。 #### mimetypes:_text/plain_,... 验证文件的 MIME 类型是否在列表内: ```php Validator::make($data, [ 'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime', ])->validate(); ``` MIME 类型通过读取文件内容猜测,可能与客户端提供的 MIME 不一致。 #### mimes:_foo_,_bar_,... 验证文件的 MIME 类型是否与给定扩展名对应: ```php Validator::make($data, [ 'photo' => 'mimes:jpg,bmp,png', ])->validate(); ``` 尽管参数是扩展名,该规则会读取文件内容判断 MIME。扩展名与 MIME 对照表见: [https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types](https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types) #### MIME 类型与扩展名 该规则不验证“文件名扩展名”与“实际 MIME”是否一致。例如,`mimes:png` 会将内容为 PNG 的 `photo.txt` 视为合法。如果需要验证扩展名,请使用 [extensions](#rule-extensions)。 #### min:_value_ 验证字段必须大于或等于 _value_。字符串、数值、数组、文件的评估规则与 [size](#rule-size) 相同。 #### min_digits:_value_ 验证字段必须是整数,且长度不少于 _value_。 #### multiple_of:_value_ 验证字段必须是 _value_ 的倍数。 #### missing 验证字段必须不存在于输入数据中。 #### missing_if:_anotherfield_,_value_,... 当 _anotherfield_ 等于任一 _value_ 时,验证字段必须不存在。 #### missing_unless:_anotherfield_,_value_ 除非 _anotherfield_ 等于任一 _value_,否则验证字段必须不存在。 #### missing_with:_foo_,_bar_,... 当任意指定字段存在时,验证字段必须不存在。 #### missing_with_all:_foo_,_bar_,... 当所有指定字段都存在时,验证字段必须不存在。 #### not_in:_foo_,_bar_,... 验证字段必须不在给定值列表中。可使用 `Rule::notIn` 构造: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'toppings' => [ 'required', Rule::notIn(['sprinkles', 'cherries']), ], ])->validate(); ``` #### not_regex:_pattern_ 验证字段不能匹配给定正则表达式。 该规则使用 PHP `preg_match`。正则必须带分隔符,例如:`'email' => 'not_regex:/^.+$/i'`。 > [!WARNING] > 使用 `regex` / `not_regex` 时,如正则包含 `|`,建议用数组形式声明规则,避免与 `|` 分隔符冲突。 #### nullable 验证字段允许为 `null`。 #### numeric 验证字段必须是 [numeric](https://www.php.net/manual/en/function.is-numeric.php)。 可使用 `strict` 参数仅允许整数或浮点类型,数值字符串将视为无效: ```php Validator::make($data, [ 'amount' => 'numeric:strict', ])->validate(); ``` #### present 验证字段必须存在于输入数据中。 #### present_if:_anotherfield_,_value_,... 当 _anotherfield_ 等于任一 _value_ 时,验证字段必须存在。 #### present_unless:_anotherfield_,_value_ 除非 _anotherfield_ 等于任一 _value_,否则验证字段必须存在。 #### present_with:_foo_,_bar_,... 当任意指定字段存在时,验证字段必须存在。 #### present_with_all:_foo_,_bar_,... 当所有指定字段都存在时,验证字段必须存在。 #### prohibited 验证字段必须缺失或为空。字段“为空”指:
- 值为 `null`。 - 值为空字符串。 - 值为空数组或空的 `Countable` 对象。 - 为上传文件且路径为空。
#### prohibited_if:_anotherfield_,_value_,... 当 _anotherfield_ 等于任一 _value_ 时,验证字段必须缺失或为空。字段“为空”指:
- 值为 `null`。 - 值为空字符串。 - 值为空数组或空的 `Countable` 对象。 - 为上传文件且路径为空。
如需复杂条件,可使用 `Rule::prohibitedIf`: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'role_id' => Rule::prohibitedIf($isAdmin), ])->validate(); Validator::make($data, [ 'role_id' => Rule::prohibitedIf(fn () => $isAdmin), ])->validate(); ``` #### prohibited_if_accepted:_anotherfield_,... 当 _anotherfield_ 为 `"yes"`、`"on"`、`1`、`"1"`、`true` 或 `"true"` 时,验证字段必须缺失或为空。 #### prohibited_if_declined:_anotherfield_,... 当 _anotherfield_ 为 `"no"`、`"off"`、`0`、`"0"`、`false` 或 `"false"` 时,验证字段必须缺失或为空。 #### prohibited_unless:_anotherfield_,_value_,... 除非 _anotherfield_ 等于任一 _value_,否则验证字段必须缺失或为空。字段“为空”指:
- 值为 `null`。 - 值为空字符串。 - 值为空数组或空的 `Countable` 对象。 - 为上传文件且路径为空。
#### prohibits:_anotherfield_,... 当验证字段存在且不为空时,_anotherfield_ 中所有字段必须缺失或为空。字段“为空”指:
- 值为 `null`。 - 值为空字符串。 - 值为空数组或空的 `Countable` 对象。 - 为上传文件且路径为空。
#### regex:_pattern_ 验证字段必须匹配给定正则表达式。 该规则使用 PHP `preg_match`。正则必须带分隔符,例如:`'email' => 'regex:/^.+@.+$/i'`。 > [!WARNING] > 使用 `regex` / `not_regex` 时,如正则包含 `|`,建议用数组形式声明规则,避免与 `|` 分隔符冲突。 #### required 验证字段必须存在且不能为空。字段“为空”指:
- 值为 `null`。 - 值为空字符串。 - 值为空数组或空的 `Countable` 对象。 - 为上传文件且路径为空。
#### required_if:_anotherfield_,_value_,... 当 _anotherfield_ 等于任一 _value_ 时,验证字段必须存在且不能为空。 如需复杂条件,可使用 `Rule::requiredIf`: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'role_id' => Rule::requiredIf($isAdmin), ])->validate(); Validator::make($data, [ 'role_id' => Rule::requiredIf(fn () => $isAdmin), ])->validate(); ``` #### required_if_accepted:_anotherfield_,... 当 _anotherfield_ 为 `"yes"`、`"on"`、`1`、`"1"`、`true` 或 `"true"` 时,验证字段必须存在且不能为空。 #### required_if_declined:_anotherfield_,... 当 _anotherfield_ 为 `"no"`、`"off"`、`0`、`"0"`、`false` 或 `"false"` 时,验证字段必须存在且不能为空。 #### required_unless:_anotherfield_,_value_,... 除非 _anotherfield_ 等于任一 _value_,否则验证字段必须存在且不能为空。若 _value_ 为 `null`(如 `required_unless:name,null`),则只有当比较字段为 `null` 或不存在时才允许验证字段为空。 #### required_with:_foo_,_bar_,... 当任意指定字段存在且不为空时,验证字段必须存在且不能为空。 #### required_with_all:_foo_,_bar_,... 当所有指定字段都存在且不为空时,验证字段必须存在且不能为空。 #### required_without:_foo_,_bar_,... 当任意指定字段为空或不存在时,验证字段必须存在且不能为空。 #### required_without_all:_foo_,_bar_,... 当所有指定字段都为空或不存在时,验证字段必须存在且不能为空。 #### required_array_keys:_foo_,_bar_,... 验证字段必须是数组,且至少包含指定的键。 #### sometimes 仅当字段存在时,才应用后续验证规则。常用于“可选但一旦存在就必须合法”的字段: ```php Validator::make($data, [ 'nickname' => 'sometimes|string|max:20', ])->validate(); ``` #### same:_field_ 验证字段必须与 _field_ 相同。 #### size:_value_ 验证字段大小必须等于给定 _value_。字符串为字符数;数值为指定整数(需配合 `numeric` 或 `integer`);数组为元素数;文件为 KB 大小。示例: ```php Validator::make($data, [ 'title' => 'size:12', 'seats' => 'integer|size:10', 'tags' => 'array|size:5', 'image' => 'file|size:512', ])->validate(); ``` #### starts_with:_foo_,_bar_,... 验证字段必须以指定值之一开头。 #### string 验证字段必须是字符串。如需允许 `null`,请配合 `nullable` 使用。 #### timezone 验证字段必须是有效时区标识符(来自 `DateTimeZone::listIdentifiers`)。可传入该方法支持的参数: ```php Validator::make($data, [ 'timezone' => 'required|timezone:all', ])->validate(); Validator::make($data, [ 'timezone' => 'required|timezone:Africa', ])->validate(); Validator::make($data, [ 'timezone' => 'required|timezone:per_country,US', ])->validate(); ``` #### unique:_table_,_column_ 验证字段在指定表中必须唯一。 **指定自定义表/列名:** 可直接指定模型类名: ```php Validator::make($data, [ 'email' => 'unique:app\model\User,email_address', ])->validate(); ``` 可指定列名(不指定时默认字段名): ```php Validator::make($data, [ 'email' => 'unique:users,email_address', ])->validate(); ``` **指定数据库连接:** ```php Validator::make($data, [ 'email' => 'unique:connection.users,email_address', ])->validate(); ``` **忽略指定 ID:** ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ 'required', Rule::unique('users')->ignore($user->id), ], ])->validate(); ``` > [!WARNING] > `ignore` 不应接收用户输入,仅应使用系统生成的唯一 ID(自增 ID 或模型 UUID),否则可能存在 SQL 注入风险。 也可传入模型实例: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ Rule::unique('users')->ignore($user), ], ])->validate(); ``` 若主键不是 `id`,可指定主键名: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ Rule::unique('users')->ignore($user->id, 'user_id'), ], ])->validate(); ``` 默认以字段名作为唯一列,亦可指定列名: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ Rule::unique('users', 'email_address')->ignore($user->id), ], ])->validate(); ``` **添加额外条件:** ```php use Illuminate\Database\Query\Builder; use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ Rule::unique('users')->where( fn (Builder $query) => $query->where('account_id', 1) ), ], ])->validate(); ``` **忽略软删除记录:** ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [Rule::unique('users')->withoutTrashed()], ])->validate(); ``` 若软删除列名不是 `deleted_at`: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [Rule::unique('users')->withoutTrashed('was_deleted_at')], ])->validate(); ``` #### uppercase 验证字段必须为大写。 #### url 验证字段必须是有效 URL。 可指定允许的协议: ```php Validator::make($data, [ 'url' => 'url:http,https', 'game' => 'url:minecraft,steam', ])->validate(); ``` #### ulid 验证字段必须是有效 [ULID](https://github.com/ulid/spec)。 #### uuid 验证字段必须是有效的 RFC 9562 UUID(版本 1、3、4、5、6、7 或 8)。 可指定版本: ```php Validator::make($data, [ 'uuid' => 'uuid:4', ])->validate(); ```