English | [中文](./README.zh-CN.md) # Webman Validation Webman's validation component, based on `illuminate/validation`, provides manual validation, annotation-based validation, parameter-level validation, and reusable rule sets. ## Installation ```bash composer require webman/validation ``` ## Basic Concepts - **Rule Set Reuse**: Define reusable `rules`, `messages`, `attributes`, and `scenes` by extending `support\validation\Validator`, which can be reused in manual and annotation validation. - **Annotation (Attribute) Validation - Method-Level**: Use the PHP 8 attribute `#[Validate]` to bind validation to controller methods. - **Annotation (Attribute) Validation - Parameter-Level**: Use the PHP 8 attribute `#[Param]` to bind validation to controller method parameters. - **Exception Handling**: Throws `support\validation\ValidationException` on validation failure; the exception class is configurable via config. - **Database Validation**: If database validation is involved, you need to install `composer require webman/database`. ## Manual Validation ### Basic Usage ```php use support\validation\Validator; $data = ['email' => 'user@example.com']; Validator::make($data, [ 'email' => 'required|email', ])->validate(); ``` > **Note** > `validate()` will throw `support\validation\ValidationException` if validation fails. If you prefer not to throw exceptions, use `fails()` as shown below. ### Custom Messages and Attributes ```php use support\validation\Validator; $data = ['contact' => 'user@example.com']; Validator::make( $data, ['contact' => 'required|email'], ['contact.email' => 'Invalid email format'], ['contact' => 'Email'] )->validate(); ``` ### Validate Without Exception (Get Error Messages) If you don't want exceptions, use `fails()` and read errors from the `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 // handle errors... } ``` ## Rule Set Reuse (Custom 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' => 'Name is required', 'email.required' => 'Email is required', 'email.email' => 'Invalid email format', ]; protected array $attributes = [ 'name' => 'Name', 'email' => 'Email', ]; } ``` ### Manual Validation Reuse ```php use app\validation\UserValidator; UserValidator::make($data)->validate(); ``` ### Use Scenes (Optional) Scenes are optional. They are only used when you call `withScene(...)` to validate a subset of fields. ```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; // No scene specified -> validate all rules UserValidator::make($data)->validate(); // Specify scene -> validate only fields in that scene UserValidator::make($data)->withScene('create')->validate(); ``` ## Annotation Validation (Method-Level) ### Direct Rules ```php use support\Request; use support\validation\annotation\Validate; class AuthController { #[Validate( rules: [ 'email' => 'required|email', 'password' => 'required|string|min:6', ], messages: [ 'email.required' => 'Email is required', 'password.required' => 'Password is required', ], attributes: [ 'email' => 'Email', 'password' => 'Password', ] )] public function login(Request $request) { return json(['code' => 0, 'msg' => 'ok']); } } ``` ### Reusing Rule Sets ```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']); } } ``` ### Multiple Validation Overlays ```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']); } } ``` ### Validation Data Source ```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']); } } ``` Use `in` to specify where validation data comes from: * **query** – HTTP query parameters from `$request->get()` * **body** – HTTP body from `$request->post()` * **path** – Path/route parameters from `$request->route->param()` `in` can be a string or array; when it's an array, values are merged in order and later sources override earlier ones. When `in` is omitted, it defaults to the equivalent of `['query', 'body', 'path']`. ## Parameter-Level Validation (Param) ### Basic Usage ```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']); } } ``` ### Validation Data Source Parameter-level validation also supports the `in` parameter to specify data source: ```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 Support String or Array ```php use support\validation\annotation\Param; class MailController { public function send( #[Param(rules: ['required', 'email'])] string $from ) { return json(['code' => 0, 'msg' => 'ok']); } } ``` ### Custom Messages / Attribute ```php use support\validation\annotation\Param; class UserController { public function updateEmail( #[Param( rules: 'required|email', messages: ['email.email' => 'Invalid email format'], attribute: 'Email' )] string $email ) { return json(['code' => 0, 'msg' => 'ok']); } } ``` ### Reusing Rule Constants ```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']); } } ``` ## Method-Level + Parameter-Level Mixing ```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']); } } ``` ## Automatic Rule Inference (Signature-Based) When a method uses `#[Validate]`, or any parameter on that method uses `#[Param]`, this package will **infer and auto-complete basic validation rules from the PHP method signature**, then merge them with your existing rules and run validation. ### Examples: `#[Validate]` Equivalent Expansion 1) Enable `#[Validate]` without writing rules: ```php use support\validation\annotation\Validate; class DemoController { #[Validate] public function create(string $content, int $uid) { } } ``` Equivalent to: ```php use support\validation\annotation\Validate; class DemoController { #[Validate(rules: [ 'content' => 'required|string', 'uid' => 'required|integer', ])] public function create(string $content, int $uid) { } } ``` 2) Only partial rules provided, the rest is inferred: ```php use support\validation\annotation\Validate; class DemoController { #[Validate(rules: [ 'content' => 'min:2', ])] public function create(string $content, int $uid) { } } ``` Equivalent to: ```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) Default values / nullable types: ```php use support\validation\annotation\Validate; class DemoController { #[Validate] public function create(string $content = 'default', ?int $uid = null) { } } ``` Equivalent to: ```php use support\validation\annotation\Validate; class DemoController { #[Validate(rules: [ 'content' => 'string', 'uid' => 'integer|nullable', ])] public function create(string $content = 'default', ?int $uid = null) { } } ``` ## Exception Handling ### Default Exception Validation failure throws `support\validation\ValidationException`, which inherits from `Webman\Exception\BusinessException` and does not log errors. Default response behavior is handled by `BusinessException::render()`: - Non-JSON requests: return a plain string message, e.g. `token is required.` - JSON requests: return JSON response, e.g. `{"code": 422, "msg": "token is required.", "data":....}` ### Customize with a custom exception - Global config: `exception` in `config/plugin/webman/validation/app.php` ## Multi-Language Support The component includes built-in Chinese and English language packs and supports project overrides. Loading order: 1. Project language pack `resource/translations/{locale}/validation.php` 2. Component built-in `vendor/webman/validation/resources/lang/{locale}/validation.php` 3. Illuminate built-in English (fallback) > **Note** > The default language of webman is configured in `config/translation.php`, and it can also be changed using the function `locale('en');`. ### Local Override Example `resource/translations/en/validation.php` ```php return [ 'email' => 'The :attribute is not a valid email format.', ]; ``` ## Middleware Auto-Loading After installation, the component automatically loads the validation middleware via `config/plugin/webman/validation/middleware.php`, no manual registration required. ## CLI Generator Use `make:validator` to generate a validator class (generated under `app/validation` by default). > **Tip** > You need to install `composer require webman/console` ### Basic - **Generate an empty template** ```bash php webman make:validator UserValidator ``` - **Overwrite if the file already exists** ```bash php webman make:validator UserValidator --force php webman make:validator UserValidator -f ``` ### Generate rules from a table - **Generate rules from a table schema** (infers `$rules` from column type/nullability/length; default excluded columns depend on ORM: laravel uses `created_at/updated_at/deleted_at`, thinkorm uses `create_time/update_time/delete_time`) ```bash php webman make:validator UserValidator --table=wa_users php webman make:validator UserValidator -t wa_users ``` - **Select a database connection** (multi-connection) ```bash php webman make:validator UserValidator --table=wa_users --database=mysql php webman make:validator UserValidator -t wa_users -d mysql ``` ### Scenes - **Generate CRUD scenes**: `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 ``` > The `update` scene includes the primary key (to locate the record) plus the other fields; `delete/detail` include only primary key fields by default. ### ORM selection (laravel(illuminate/database) vs think-orm) - **Auto (default)**: uses the available ORM; if both exist, defaults to illuminate - **Force** ```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 ``` ### Example ```bash php webman make:validator UserValidator -t wa_users -d mysql -s crud -o laravel -f ``` ## Unit Testing Enter the `webman/validation` root directory and execute: ```bash composer install vendor\bin\phpunit -c phpunit.xml ``` ## All Validation Rules Reference ## Available Validation Rules > [!IMPORTANT] > - Webman Validation is based on `illuminate/validation`, with rule names consistent with Laravel, and the rules themselves have no Webman-specific modifications. > - The middleware validates data from `$request->all()` (GET+POST) by default and merges route parameters, excluding uploaded files; for file-related rules, manually merge `$request->file()` into the data or call `Validator::make` manually. > - `current_password` depends on authentication guards, `exists`/`unique` depend on database connections and query builders, and these rules are unavailable without integrating the corresponding components. The following lists all available validation rules and their functions: #### Boolean Values
[Accepted](#rule-accepted) [Accepted If](#rule-accepted-if) [Boolean](#rule-boolean) [Declined](#rule-declined) [Declined If](#rule-declined-if)
#### Strings
[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)
#### Numbers
[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)
#### Arrays
[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)
#### Dates
[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)
#### Files
[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)
#### Database
[Exists](#rule-exists) [Unique](#rule-unique)
#### Utilities
[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 The field under validation must be `"yes"`, `"on"`, `1`, `"1"`, `true`, or `"true"`. This is commonly used for scenarios like confirming agreement to terms of service. #### accepted_if:anotherfield,value,... The field under validation must be `"yes"`, `"on"`, `1`, `"1"`, `true`, or `"true"` when another field equals the specified value. This is useful for conditional agreement scenarios. #### active_url The field under validation must have a valid A or AAAA record. The rule first extracts the hostname using `parse_url` and then validates it with `dns_get_record`. #### after:_date_ The field under validation must be a value after the given date. The date is converted to a valid `DateTime` using `strtotime`: ```php use support\validation\Validator; Validator::make($data, [ 'start_date' => 'required|date|after:tomorrow', ])->validate(); ``` You can also pass another field name for comparison: ```php Validator::make($data, [ 'finish_date' => 'required|date|after:start_date', ])->validate(); ``` You can use the fluent `date` rule builder: ```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` and `todayOrAfter` can conveniently express "must be after today" or "must be today or later": ```php Validator::make($data, [ 'start_date' => [ 'required', Rule::date()->afterToday(), ], ])->validate(); ``` #### after_or_equal:_date_ The field under validation must be after or equal to the given date. For more details, see the [after](#rule-after) rule. You can use the fluent `date` rule builder: ```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` allows specifying "pass if any one of the rule sets is satisfied". For example, the following rule means `username` is either an email address or an alphanumeric string with underscores/dashes of at least 6 characters: ```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 The field under validation must consist of Unicode letters ([\p{L}](https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AL%3A%5D&g=&i=) and [\p{M}](https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3AM%3A%5D&g=&i=)). To allow only ASCII (`a-z`, `A-Z`), add the `ascii` option: ```php Validator::make($data, [ 'username' => 'alpha:ascii', ])->validate(); ``` #### alpha_dash The field under validation can only contain Unicode alphanumeric characters ([\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=)), as well as ASCII dashes (`-`) and underscores (`_`). To allow only ASCII (`a-z`, `A-Z`, `0-9`), add the `ascii` option: ```php Validator::make($data, [ 'username' => 'alpha_dash:ascii', ])->validate(); ``` #### alpha_num The field under validation can only contain Unicode alphanumeric characters ([\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=)). To allow only ASCII (`a-z`, `A-Z`, `0-9`), add the `ascii` option: ```php Validator::make($data, [ 'username' => 'alpha_num:ascii', ])->validate(); ``` #### array The field under validation must be a PHP `array`. When the `array` rule includes additional parameters, the keys in the input array must be in the parameter list. In the example, the `admin` key is not in the allowed list, so it is invalid: ```php use support\validation\Validator; $input = [ 'user' => [ 'name' => 'Taylor Otwell', 'username' => 'taylorotwell', 'admin' => true, ], ]; Validator::make($input, [ 'user' => 'array:name,username', ])->validate(); ``` It is recommended to explicitly specify the allowed keys for arrays in actual projects. #### ascii The field under validation can only contain 7-bit ASCII characters. #### bail When the first validation rule for a field fails, stop validating the other rules for that field. This rule only affects the current field. For "stop on first failure globally", use Illuminate's validator directly and call `stopOnFirstFailure()`. #### before:_date_ The field under validation must be before the given date. The date is converted to a valid `DateTime` using `strtotime`. Similar to the [after](#rule-after) rule, you can pass another field name for comparison. You can use the fluent `date` rule builder: ```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` and `todayOrBefore` can conveniently express "must be before today" or "must be today or earlier": ```php Validator::make($data, [ 'start_date' => [ 'required', Rule::date()->beforeToday(), ], ])->validate(); ``` #### before_or_equal:_date_ The field under validation must be before or equal to the given date. The date is converted to a valid `DateTime` using `strtotime`. Similar to the [after](#rule-after) rule, you can pass another field name for comparison. You can use the fluent `date` rule builder: ```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_ The field under validation must have a size between the given _min_ and _max_ (inclusive). Strings, numbers, arrays, and files are evaluated using the same rules as [size](#rule-size). #### boolean The field under validation must be convertible to a boolean value. Acceptable inputs include `true`, `false`, `1`, `0`, `"1"`, `"0"`. You can use the `strict` parameter to allow only `true` or `false`: ```php Validator::make($data, [ 'foo' => 'boolean:strict', ])->validate(); ``` #### confirmed The field under validation must have a matching field `{field}_confirmation`. For example, if the field is `password`, `password_confirmation` is required. You can also specify a custom confirmation field name, such as `confirmed:repeat_username`, which requires `repeat_username` to match the current field. #### contains:_foo_,_bar_,... The field under validation must be an array and must contain all the given parameter values. This rule is often used for array validation and can be constructed using `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_,... The field under validation must be an array and must not contain any of the given parameter values. You can use `Rule::doesntContain` to construct: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'roles' => [ 'required', 'array', Rule::doesntContain(['admin', 'editor']), ], ])->validate(); ``` #### current_password The field under validation must match the current authenticated user's password. You can specify the authentication guard via the first parameter: ```php Validator::make($data, [ 'password' => 'current_password:api', ])->validate(); ``` > [!WARNING] > This rule depends on the authentication component and guard configuration; do not use it without integrating authentication. #### date The field under validation must be a valid (non-relative) date recognized by `strtotime`. #### date_equals:_date_ The field under validation must equal the given date. The date is converted to a valid `DateTime` using `strtotime`. #### date_format:_format_,... The field under validation must match one of the given formats. Use either `date` or `date_format`. This rule supports all formats of PHP [DateTime](https://www.php.net/manual/en/class.datetime.php). You can use the fluent `date` rule builder: ```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_ The field under validation must be a number with the specified number of decimal places: ```php Validator::make($data, [ 'price' => 'decimal:2', ])->validate(); Validator::make($data, [ 'price' => 'decimal:2,4', ])->validate(); ``` #### declined The field under validation must be `"no"`, `"off"`, `0`, `"0"`, `false`, or `"false"`. #### declined_if:anotherfield,value,... The field under validation must be `"no"`, `"off"`, `0`, `"0"`, `false`, or `"false"` when another field equals the specified value. #### different:_field_ The field under validation must be different from _field_. #### digits:_value_ The field under validation must be an integer with a length of _value_. #### digits_between:_min_,_max_ The field under validation must be an integer with a length between _min_ and _max_. #### dimensions The field under validation must be an image and satisfy the dimension constraints: ```php Validator::make($data, [ 'avatar' => 'dimensions:min_width=100,min_height=200', ])->validate(); ``` Available constraints: _min_width_, _max_width_, _min_height_, _max_height_, _width_, _height_, _ratio_. _ratio_ is the aspect ratio, which can be expressed as a fraction or float: ```php Validator::make($data, [ 'avatar' => 'dimensions:ratio=3/2', ])->validate(); ``` Due to the many parameters in this rule, it is recommended to use `Rule::dimensions` to construct: ```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 When validating an array, the field values must not be duplicated: ```php Validator::make($data, [ 'foo.*.id' => 'distinct', ])->validate(); ``` By default, loose comparison is used. For strict comparison, add `strict`: ```php Validator::make($data, [ 'foo.*.id' => 'distinct:strict', ])->validate(); ``` You can add `ignore_case` to ignore case differences: ```php Validator::make($data, [ 'foo.*.id' => 'distinct:ignore_case', ])->validate(); ``` #### doesnt_start_with:_foo_,_bar_,... The field under validation must not start with the specified values. #### doesnt_end_with:_foo_,_bar_,... The field under validation must not end with the specified values. #### email The field under validation must be a valid email address. This rule relies on [egulias/email-validator](https://github.com/egulias/EmailValidator), defaulting to `RFCValidation`, but other validation methods can be specified: ```php Validator::make($data, [ 'email' => 'email:rfc,dns', ])->validate(); ``` Available validation methods:
- `rfc`: `RFCValidation` - Validates email according to RFC standards ([supported RFCs](https://github.com/egulias/EmailValidator?tab=readme-ov-file#supported-rfcs)). - `strict`: `NoRFCWarningsValidation` - Fails on warnings during RFC validation (e.g., trailing dots or consecutive dots). - `dns`: `DNSCheckValidation` - Checks if the domain has a valid MX record. - `spoof`: `SpoofCheckValidation` - Prevents homoglyph or deceptive Unicode characters. - `filter`: `FilterEmailValidation` - Validates using PHP `filter_var`. - `filter_unicode`: `FilterEmailValidation::unicode()` - Unicode-allowed `filter_var` validation.
You can use the fluent rule builder: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ 'required', Rule::email() ->rfcCompliant(strict: false) ->validateMxRecord() ->preventSpoofing(), ], ])->validate(); ``` > [!WARNING] > `dns` and `spoof` require the PHP `intl` extension. #### encoding:*encoding_type* The field under validation must match the specified character encoding. This rule uses `mb_check_encoding` to detect the encoding of files or strings. It can be used with the file rule builder: ```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_,... The field under validation must end with one of the specified values. #### enum `Enum` is a class-based rule used to validate if the field value is a valid enum value. Pass the enum class name during construction. For validating basic type values, use Backed Enum: ```php use app\enums\ServerStatus; use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'status' => [Rule::enum(ServerStatus::class)], ])->validate(); ``` You can use `only`/`except` to restrict enum values: ```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(); ``` You can use `when` for conditional restrictions: ```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 The field under validation will be excluded from the data returned by `validate`/`validated`. #### exclude_if:_anotherfield_,_value_ The field under validation will be excluded from the data returned by `validate`/`validated` when _anotherfield_ equals _value_. For complex conditions, use `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_ The field under validation will be excluded from the data returned by `validate`/`validated` unless _anotherfield_ equals _value_. If _value_ is `null` (e.g., `exclude_unless:name,null`), the field is retained only if the comparison field is `null` or does not exist. #### exclude_with:_anotherfield_ The field under validation will be excluded from the data returned by `validate`/`validated` when _anotherfield_ exists. #### exclude_without:_anotherfield_ The field under validation will be excluded from the data returned by `validate`/`validated` when _anotherfield_ does not exist. #### exists:_table_,_column_ The field under validation must exist in the specified database table. #### Basic Usage of Exists Rule ```php Validator::make($data, [ 'state' => 'exists:states', ])->validate(); ``` If `column` is not specified, the field name is used by default. Thus, this example validates if the `state` column exists in the `states` table. #### Specifying a Custom Column Name You can append the column name after the table name: ```php Validator::make($data, [ 'state' => 'exists:states,abbreviation', ])->validate(); ``` To specify a database connection, prepend the connection name to the table: ```php Validator::make($data, [ 'email' => 'exists:connection.staff,email', ])->validate(); ``` You can also pass a model class name, and the framework will resolve the table name: ```php Validator::make($data, [ 'user_id' => 'exists:app\model\User,id', ])->validate(); ``` To customize query conditions, use the `Rule` rule builder: ```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(); ``` You can also specify the column name directly in `Rule::exists`: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'state' => [Rule::exists('states', 'abbreviation')], ])->validate(); ``` When validating if a group of values exists, combine with the `array` rule: ```php Validator::make($data, [ 'states' => ['array', Rule::exists('states', 'abbreviation')], ])->validate(); ``` When `array` and `exists` coexist, a single query is generated to validate all values. #### extensions:_foo_,_bar_,... The uploaded file's extension must be in the allowed list: ```php Validator::make($data, [ 'photo' => ['required', 'extensions:jpg,png'], ])->validate(); ``` > [!WARNING] > Do not rely solely on extension validation for file types; it is recommended to use it with [mimes](#rule-mimes) or [mimetypes](#rule-mimetypes). #### file The field under validation must be a successfully uploaded file. #### filled When the field exists, its value must not be empty. #### gt:_field_ The field under validation must be greater than the given _field_ or _value_. The two fields must be of the same type. Strings, numbers, arrays, and files are evaluated using the same rules as [size](#rule-size). #### gte:_field_ The field under validation must be greater than or equal to the given _field_ or _value_. The two fields must be of the same type. Strings, numbers, arrays, and files are evaluated using the same rules as [size](#rule-size). #### hex_color The field under validation must be a valid [hexadecimal color value](https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color). #### image The field under validation must be an image (jpg, jpeg, png, bmp, gif, or webp). > [!WARNING] > SVG is not allowed by default due to XSS risks. To allow it, add `allow_svg`: `image:allow_svg`. #### in:_foo_,_bar_,... The field under validation must be in the given list of values. You can use `Rule::in` to construct: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'zones' => [ 'required', Rule::in(['first-zone', 'second-zone']), ], ])->validate(); ``` When combined with the `array` rule, every value in the input array must be in the `in` list: ```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_.* The field under validation must exist in the value list of _anotherfield_. #### in_array_keys:_value_.* The field under validation must be an array and must contain at least one of the given values as a key: ```php Validator::make($data, [ 'config' => 'array|in_array_keys:timezone', ])->validate(); ``` #### integer The field under validation must be an integer. You can use the `strict` parameter to require the field type to be integer; string representations of integers will be considered invalid: ```php Validator::make($data, [ 'age' => 'integer:strict', ])->validate(); ``` > [!WARNING] > This rule only checks if it passes PHP's `FILTER_VALIDATE_INT`; to enforce numeric types, use it with [numeric](#rule-numeric). #### ip The field under validation must be a valid IP address. #### ipv4 The field under validation must be a valid IPv4 address. #### ipv6 The field under validation must be a valid IPv6 address. #### json The field under validation must be a valid JSON string. #### lt:_field_ The field under validation must be less than the given _field_. The two fields must be of the same type. Strings, numbers, arrays, and files are evaluated using the same rules as [size](#rule-size). #### lte:_field_ The field under validation must be less than or equal to the given _field_. The two fields must be of the same type. Strings, numbers, arrays, and files are evaluated using the same rules as [size](#rule-size). #### lowercase The field under validation must be lowercase. #### list The field under validation must be a list array. The keys in a list array must be consecutive numbers from 0 to `count($array) - 1`. #### mac_address The field under validation must be a valid MAC address. #### max:_value_ The field under validation must be less than or equal to _value_. Strings, numbers, arrays, and files are evaluated using the same rules as [size](#rule-size). #### max_digits:_value_ The field under validation must be an integer with a length not exceeding _value_. #### mimetypes:_text/plain_,... The file's MIME type must be in the list: ```php Validator::make($data, [ 'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime', ])->validate(); ``` The MIME type is guessed by reading the file content, which may differ from the client-provided MIME. #### mimes:_foo_,_bar_,... The file's MIME type must correspond to the given extension: ```php Validator::make($data, [ 'photo' => 'mimes:jpg,bmp,png', ])->validate(); ``` Although the parameters are extensions, this rule reads the file content to determine the MIME. The extension-to-MIME mapping is from: [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 Types and Extensions This rule does not validate if the "filename extension" matches the "actual MIME". For example, `mimes:png` will consider `photo.txt` with PNG content as valid. To validate extensions, use [extensions](#rule-extensions). #### min:_value_ The field under validation must be greater than or equal to _value_. Strings, numbers, arrays, and files are evaluated using the same rules as [size](#rule-size). #### min_digits:_value_ The field under validation must be an integer with a length of at least _value_. #### multiple_of:_value_ The field under validation must be a multiple of _value_. #### missing The field under validation must not exist in the input data. #### missing_if:_anotherfield_,_value_,... The field under validation must not exist when _anotherfield_ equals any _value_. #### missing_unless:_anotherfield_,_value_ The field under validation must not exist unless _anotherfield_ equals any _value_. #### missing_with:_foo_,_bar_,... The field under validation must not exist when any of the specified fields exist. #### missing_with_all:_foo_,_bar_,... The field under validation must not exist when all specified fields exist. #### not_in:_foo_,_bar_,... The field under validation must not be in the given list of values. You can use `Rule::notIn` to construct: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'toppings' => [ 'required', Rule::notIn(['sprinkles', 'cherries']), ], ])->validate(); ``` #### not_regex:_pattern_ The field under validation must not match the given regular expression. This rule uses PHP `preg_match`. The regex must include delimiters, e.g., `'email' => 'not_regex:/^.+$/i'`. > [!WARNING] > When using `regex` / `not_regex`, if the regex contains `|`, it is recommended to declare rules in array form to avoid conflicts with the `|` separator. #### nullable The field under validation may be `null`. #### numeric The field under validation must be [numeric](https://www.php.net/manual/en/function.is-numeric.php). You can use the `strict` parameter to allow only integer or float types; numeric strings will be considered invalid: ```php Validator::make($data, [ 'amount' => 'numeric:strict', ])->validate(); ``` #### present The field under validation must exist in the input data. #### present_if:_anotherfield_,_value_,... The field under validation must exist when _anotherfield_ equals any _value_. #### present_unless:_anotherfield_,_value_ The field under validation must exist unless _anotherfield_ equals any _value_. #### present_with:_foo_,_bar_,... The field under validation must exist when any of the specified fields exist. #### present_with_all:_foo_,_bar_,... The field under validation must exist when all specified fields exist. #### prohibited The field under validation must be missing or empty. A field is "empty" if:
- The value is `null`. - The value is an empty string. - The value is an empty array or empty `Countable` object. - It is an uploaded file with an empty path.
#### prohibited_if:_anotherfield_,_value_,... The field under validation must be missing or empty when _anotherfield_ equals any _value_. A field is "empty" if:
- The value is `null`. - The value is an empty string. - The value is an empty array or empty `Countable` object. - It is an uploaded file with an empty path.
For complex conditions, use `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_,... The field under validation must be missing or empty when _anotherfield_ is `"yes"`, `"on"`, `1`, `"1"`, `true`, or `"true"`. #### prohibited_if_declined:_anotherfield_,... The field under validation must be missing or empty when _anotherfield_ is `"no"`, `"off"`, `0`, `"0"`, `false`, or `"false"`. #### prohibited_unless:_anotherfield_,_value_,... The field under validation must be missing or empty unless _anotherfield_ equals any _value_. A field is "empty" if:
- The value is `null`. - The value is an empty string. - The value is an empty array or empty `Countable` object. - It is an uploaded file with an empty path.
#### prohibits:_anotherfield_,... When the field under validation exists and is not empty, all fields in _anotherfield_ must be missing or empty. A field is "empty" if:
- The value is `null`. - The value is an empty string. - The value is an empty array or empty `Countable` object. - It is an uploaded file with an empty path.
#### regex:_pattern_ The field under validation must match the given regular expression. This rule uses PHP `preg_match`. The regex must include delimiters, e.g., `'email' => 'regex:/^.+@.+$/i'`. > [!WARNING] > When using `regex` / `not_regex`, if the regex contains `|`, it is recommended to declare rules in array form to avoid conflicts with the `|` separator. #### required The field under validation must exist and not be empty. A field is "empty" if:
- The value is `null`. - The value is an empty string. - The value is an empty array or empty `Countable` object. - It is an uploaded file with an empty path.
#### required_if:_anotherfield_,_value_,... The field under validation must exist and not be empty when _anotherfield_ equals any _value_. For complex conditions, use `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_,... The field under validation must exist and not be empty when _anotherfield_ is `"yes"`, `"on"`, `1`, `"1"`, `true`, or `"true"`. #### required_if_declined:_anotherfield_,... The field under validation must exist and not be empty when _anotherfield_ is `"no"`, `"off"`, `0`, `"0"`, `false`, or `"false"`. #### required_unless:_anotherfield_,_value_,... The field under validation must exist and not be empty unless _anotherfield_ equals any _value_. If _value_ is `null` (e.g., `required_unless:name,null`), the field is allowed to be empty only if the comparison field is `null` or does not exist. #### required_with:_foo_,_bar_,... The field under validation must exist and not be empty when any specified field exists and is not empty. #### required_with_all:_foo_,_bar_,... The field under validation must exist and not be empty when all specified fields exist and are not empty. #### required_without:_foo_,_bar_,... The field under validation must exist and not be empty when any specified field is empty or does not exist. #### required_without_all:_foo_,_bar_,... The field under validation must exist and not be empty when all specified fields are empty or do not exist. #### required_array_keys:_foo_,_bar_,... The field under validation must be an array and must contain at least the specified keys. #### sometimes Apply subsequent validation rules only when the field exists. Commonly used for fields that are "optional but must be valid if present": ```php Validator::make($data, [ 'nickname' => 'sometimes|string|max:20', ])->validate(); ``` #### same:_field_ The field under validation must be the same as _field_. #### size:_value_ The field under validation must have a size equal to the given _value_. For strings, it is the character count; for numbers, it is the specified integer (use with `numeric` or `integer`); for arrays, it is the element count; for files, it is the size in KB. Example: ```php Validator::make($data, [ 'title' => 'size:12', 'seats' => 'integer|size:10', 'tags' => 'array|size:5', 'image' => 'file|size:512', ])->validate(); ``` #### starts_with:_foo_,_bar_,... The field under validation must start with one of the specified values. #### string The field under validation must be a string. To allow `null`, use with `nullable`. #### timezone The field under validation must be a valid timezone identifier (from `DateTimeZone::listIdentifiers`). Parameters supported by this method can be passed: ```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_ The field under validation must be unique in the specified table. **Specifying Custom Table/Column Names:** You can directly specify the model class name: ```php Validator::make($data, [ 'email' => 'unique:app\model\User,email_address', ])->validate(); ``` You can specify the column name (defaults to the field name if not specified): ```php Validator::make($data, [ 'email' => 'unique:users,email_address', ])->validate(); ``` **Specifying Database Connection:** ```php Validator::make($data, [ 'email' => 'unique:connection.users,email_address', ])->validate(); ``` **Ignoring a Specific ID:** ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ 'required', Rule::unique('users')->ignore($user->id), ], ])->validate(); ``` > [!WARNING] > `ignore` should not receive user input; only use system-generated unique IDs (auto-increment IDs or model UUIDs), otherwise there may be SQL injection risks. You can also pass a model instance: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ Rule::unique('users')->ignore($user), ], ])->validate(); ``` If the primary key is not `id`, specify the primary key name: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ Rule::unique('users')->ignore($user->id, 'user_id'), ], ])->validate(); ``` By default, the field name is used as the unique column, but you can specify the column name: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [ Rule::unique('users', 'email_address')->ignore($user->id), ], ])->validate(); ``` **Adding Extra Conditions:** ```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(); ``` **Ignoring Soft-Deleted Records:** ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [Rule::unique('users')->withoutTrashed()], ])->validate(); ``` If the soft-delete column name is not `deleted_at`: ```php use support\validation\Rule; use support\validation\Validator; Validator::make($data, [ 'email' => [Rule::unique('users')->withoutTrashed('was_deleted_at')], ])->validate(); ``` #### uppercase The field under validation must be uppercase. #### url The field under validation must be a valid URL. You can specify allowed protocols: ```php Validator::make($data, [ 'url' => 'url:http,https', 'game' => 'url:minecraft,steam', ])->validate(); ``` #### ulid The field under validation must be a valid [ULID](https://github.com/ulid/spec). #### uuid The field under validation must be a valid RFC 9562 UUID (versions 1, 3, 4, 5, 6, 7, or 8). You can specify the version: ```php Validator::make($data, [ 'uuid' => 'uuid:4', ])->validate(); ```