hejunjie / schema-validator
一个简单且可扩展的 PHP 参数验证库,支持规则式定义与自定义扩展,适用于任何结构化数据校验场景 | A simple and extensible PHP parameter validation library, supporting rule-based definitions and custom extensions, suitable for any structured data verification scenarios
Requires
- php: ^8.1
Requires (Dev)
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^11.5
- squizlabs/php_codesniffer: ^4.0
README
English | 简体中文
A simple and extensible PHP data validation library with zero dependencies, suitable for any structured data validation scenario.
This project has been parsed by Zread for quick codebase navigation.
Features
- Zero dependencies, works with any PHP 8.1+ project
- Supports both array format and pipe-delimited rule definitions
- Dot notation for accessing nested data (e.g.
user.profile.name) - Each rule is independently encapsulated, easy to extend or replace
- Throws exceptions on validation failure, returning errors grouped by field
Installation
composer require hejunjie/schema-validator
Quick Start
use Hejunjie\SchemaValidator\Validator; use Hejunjie\SchemaValidator\Exceptions\ValidationException; $data = [ 'name' => 'John', 'age' => 28, 'email' => 'invalid-email', ]; try { Validator::validate($data, [ 'name' => ['string', 'min_length:2'], 'age' => ['integer', 'between:18,60'], 'email' => ['required', 'email'], ]); echo "Validation passed"; } catch (ValidationException $e) { print_r($e->getErrors()); } // Output: // Array // ( // [email] => Array // ( // [0] => email // ) // )
Usage
Rule Definition Formats
Two equivalent formats are supported and can be mixed:
// Array format ['email' => ['required', 'email']] // Pipe-delimited format ['email' => 'required|email'] // Rules with parameters ['age' => 'integer|between:18,60'] ['name' => ['string', 'min_length:2']]
Nested Data
Use dot notation to access fields in nested arrays:
$data = [ 'user' => [ 'name' => 'John', 'email' => 'test@example.com', ], ]; Validator::validate($data, [ 'user.name' => ['required', 'string'], 'user.email' => ['required', 'email'], ]);
Custom Rules
Register custom rules via Validator::extend(). A callback returning true means the rule passes; any other return value is treated as failure:
Validator::extend('is_even', function (string $field, mixed $value, mixed $params = null): bool { return is_int($value) && $value % 2 === 0; }); Validator::validate(['num' => 4], ['num' => 'is_even']);
Retrieving Errors
When validation fails, a ValidationException is thrown. Call getErrors() to get errors grouped by field:
try { Validator::validate( ['name' => '', 'email' => 'bad'], ['name' => 'required', 'email' => 'email'] ); } catch (ValidationException $e) { $errors = $e->getErrors(); // [ // 'name' => ['required'], // 'email' => ['email'], // ] }
The error array returns rule names, which you can map to custom error messages as needed.
Built-in Rules
31 rules in total, organized into five categories.
Type
| Rule | Description | Example |
|---|---|---|
string |
Must be a string | ['name' => ['string']] |
integer |
Must be an integer | ['age' => ['integer']] |
boolean |
Must be boolean (true/false or 0/1) | ['flag' => ['boolean']] |
float |
Must be a float | ['price' => ['float']] |
numeric |
Must be numeric (int, float, or numeric string) | ['score' => ['numeric']] |
array |
Must be an array | ['tags' => ['array']] |
object |
Must be an object | ['config' => ['object']] |
Comparison
| Rule | Description | Example |
|---|---|---|
min |
Numeric value or string length must be ≥ the given value | ['age' => ['min:18']] |
max |
Numeric value or string length must be ≤ the given value | ['score' => ['max:100']] |
between |
Numeric value or string length must be within the range | ['age' => ['between:18,60']] |
gt |
Numeric value must be > the given value | ['score' => ['gt:0']] |
gte |
Numeric value must be ≥ the given value | ['score' => ['gte:60']] |
lt |
Numeric value must be < the given value | ['price' => ['lt:100']] |
lte |
Numeric value must be ≤ the given value | ['price' => ['lte:99']] |
length |
String length must equal the given value | ['code' => ['length:6']] |
min_length |
String length must be ≥ the given value | ['name' => ['min_length:2']] |
max_length |
String length must be ≤ the given value | ['desc' => ['max_length:200']] |
Format
| Rule | Description | Example |
|---|---|---|
email |
Must be a valid email address | ['email' => ['email']] |
mobile |
Must be a mainland China mobile number | ['phone' => ['mobile']] |
url |
Must be a valid URL | ['link' => ['url']] |
ip |
Must be a valid IP address (IPv4 or IPv6) | ['addr' => ['ip']] |
json |
Must be a valid JSON string (parsed as array) | ['meta' => ['json']] |
alpha |
Letters only | ['code' => ['alpha']] |
alpha_num |
Letters and numbers only | ['code' => ['alpha_num']] |
alpha_dash |
Letters, numbers, dashes, and underscores only | ['slug' => ['alpha_dash']] |
Boolean
| Rule | Description | Example |
|---|---|---|
required |
Field must be present and not empty | ['name' => ['required']] |
accepted |
Must be yes, on, 1, or true |
['agree' => ['accepted']] |
declined |
Must be no, off, 0, or false |
['reject' => ['declined']] |
String Matching
| Rule | Description | Example |
|---|---|---|
starts_with |
Must start with the given string | ['url' => ['starts_with:https']] |
ends_with |
Must end with the given string | ['file' => ['ends_with:.pdf']] |
contains |
Must contain the given string | ['desc' => ['contains:keyword']] |
Contributing
Issues and pull requests are welcome. Feel free to fork and use it. If you have other commonly used validation rules — even just a single regex — contributions are appreciated.
Give it a ⭐ if you find this project useful.