oriatec / validation
对 somnambulist/validation 进行重写,提供类似 Laravel 的验证,符合 psr-7 标准,作为独立库
Requires
- php: >=8.0
- ext-mbstring: *
- psr/http-message: ^1.0
Requires (Dev)
- doctrine/dbal: ~3.1.0
- phpunit/phpunit: ~9.5
- ramsey/uuid: ~4.1
- symfony/var-dumper: ~5.3
README
这是一个 somnambulist/validation 的分支,类似于 Laravel 验证器的独立验证器。
最初,这个包是对 rakit/validation 的重写。与 rakit/validation 保持一致,这个库在使用时没有其他依赖。请注意,内部 API 与 rakit/validation 实质上不同。
这个分支增加了对 PSR-7 的兼容性,特别是对UploadedFileInterface的支持。
跳转到 规则
需求
- PHP 8.0+
- ext/mb-string
- php-fig/http-message
安装
使用 composer 安装,或从 github.com 检出/拉取文件。
- composer require oriatec/validation
用法
使用这个库验证数据有两种方式:使用 make
创建验证对象,然后使用 validate
进行验证;或者直接使用 validate
。
例如
使用 make
<?php require('vendor/autoload.php'); use ORIATEC\Components\Validation\Factory; $validation = (new Factory)->make($_POST + $_FILES, [ 'name' => 'required', 'email' => 'required|email', 'password' => 'required|min:6', 'confirm_password' => 'required|same:password', 'avatar' => 'required|uploaded_file:0,500K,png,jpeg', 'skills' => 'array', 'skills.*.id' => 'required|numeric', 'skills.*.percentage' => 'required|numeric' ]); $validation->validate(); if ($validation->fails()) { // handling errors $errors = $validation->errors(); echo "<pre>"; print_r($errors->firstOfAll()); echo "</pre>"; exit; } else { // validation passes echo "Success!"; }
或者通过 validate
<?php require('vendor/autoload.php'); use Somnambulist\Components\Validation\Factory; $validation = (new Factory)->validate($_POST + $_FILES, [ 'name' => 'required', 'email' => 'required|email', 'password' => 'required|min:6', 'confirm_password' => 'required|same:password', 'avatar' => 'required|uploaded_file:0,500K,png,jpeg', 'skills' => 'array', 'skills.*.id' => 'required|numeric', 'skills.*.percentage' => 'required|numeric' ]); if ($validation->fails()) { // handling errors $errors = $validation->errors(); echo "<pre>"; print_r($errors->firstOfAll()); echo "</pre>"; exit; } else { // validation passes echo "Success!"; }
强烈建议使用依赖注入容器,并将
Factory
作为单例存储,而不是创建新实例。这将减少创建验证实例的代价,并允许更轻松地管理自定义规则。
属性别名
与 rakit/validation
不同,属性名称不会进行任何转换;相反,如果您想命名属性,则必须使用别名。
别名可以通过几种方式定义:在规则本身上,或者在验证中添加别名。请注意,别名应在调用 validate
之前设置。
use Somnambulist\Components\Validation\Factory; $validation = (new Factory)->make([ 'province_id' => $_POST['province_id'], 'district_id' => $_POST['district_id'] ], [ 'province_id:Province' => 'required|numeric', 'district_id:District' => 'required|numeric' ]); // or set the aliases: $validation->setAlias('province_id', 'Province'); $validation->setAlias('district_id', 'District'); // then validate it $validation->validate();
验证消息
验证消息定义在 Resources/i18n/en.php
中。任何消息都可以替换为自定义字符串,或翻译成其他语言。英语字符串始终在 Factory
实例化期间加载。
根据失败类型,将提供各种变量以供使用,但以下变量始终可用于所有消息
:attribute
:正在验证的属性,如果设置了别名,则使用别名:value
:正在验证的属性的值,转换为字符串,数组对象作为 JSON 字符串
Validator 的自定义消息
所有消息都存储在 Factory
实例的 MessageBag
中。可以向此消息包添加更多语言,或在特定的验证实例中进行自定义。此外,可以在 Factory 的消息包上设置默认语言,或在验证实例上设置特定语言。
添加新的消息集
use Somnambulist\Components\Validation\Factory; $factory = new Factory(); $factory->messages()->add('es', [ 'rule.required' => 'Se requiere :attribute', ]); $validation = $factory->validate($inputs, $rules); $validation->setLanguage('es')->validate();
或覆盖默认的英文字符串
use Somnambulist\Components\Validation\Factory; $factory = new Factory(); $factory->messages()->replace('en', 'rule.required', 'Se requiere :attribute'); $validation = $factory->validate($inputs, $rules); $validation->validate();
或设置默认语言
use Somnambulist\Components\Validation\Factory; $factory = new Factory(); $factory->messages()->default('es'); $validation = $factory->validate($inputs, $rules); $validation->validate();
特定属性规则的自定义消息
有时您可能想要为特定属性规则设置自定义消息,以便使其更明确或添加其他信息。这是通过为属性添加一个以 :
和规则名称结尾的消息键来完成的。
例如
use Somnambulist\Components\Validation\Factory; $validator = new Factory(); $validation_a = $validator->make($input, [ 'age' => 'required|min:18' ]); $validation->messages()->add('en', 'age:min', '18+ only'); $validation->validate();
规则的自定义消息
一些规则有多个可能的验证消息。这些消息都命名为 rule.<name>.<check>
。要更改消息,覆盖或添加特定的消息。
例如,uploaded_file
可能因文件、最小/最大尺寸和类型出现错误。这些与以下相关:
- rule.uploaded_file
- rule.uploaded_file.min_size
- rule.uploaded_file.max_size
- rule.uploaded_file.type
要更改任何子消息,请向消息包中添加/覆盖该消息键。
例如
use Somnambulist\Components\Validation\Factory; $validator = new Factory(); $validation_a = $validator->make($input, [ 'age' => 'required|min:18' ]); $validation->messages()->add('en', 'age:min', '18+ only'); $validation->validate();
与
rakit
不同,无法直接在Rule
实例中设置自定义消息。任何消息都必须在消息包中设置。
复杂翻译需求
该库中的翻译系统相当基本。如果您有复杂的需求,或者希望处理可数名词等,那么所有错误消息都存储为包含消息键和该消息变量的ErrorMessage
实例。
您可以使用底层数组(或一个DataBag
实例)来代替使用ErrorBag
显示消息,然后将消息键和变量一起传递给您的翻译系统。
请注意,错误按属性和规则名称嵌套。
与错误消息一起工作
错误消息收集在您可以通过验证实例上的errors()
访问的ErrorBag
实例中。
use Somnambulist\Components\Validation\Factory; $validation = (new Factory())->validate($inputs, $rules); $errors = $validation->errors();
现在,您可以使用以下方法检索消息:
all(string $format = ':message')
获取所有消息作为一个扁平数组
$messages = $errors->all(); // [ // 'email is not a valid email address', // 'password minimum is 6 characters', // 'password must contain capital letters' // ] $messages = $errors->all('<li>:message</li>'); // [ // '<li>email is not a valid email address</li>', // '<li>password minimum is 6 character</li>', // '<li>password must contain capital letters</li>' // ]
firstOfAll(string $format = ':message', bool $dotNotation = false)
从所有现有键中获取第一条消息
$messages = $errors->firstOfAll(); // [ // 'email' => Email is not valid email', // 'password' => 'Password minimum 6 character', // ] $messages = $errors->firstOfAll('<li>:message</li>'); // [ // 'email' => '<li>Email is not valid email</li>', // 'password' => '<li>Password minimum 6 character</li>', // ]
参数$dotNotation
用于数组验证。如果它是false
,它将返回原始数组结构;如果它是true
,它将返回一个具有点符号键的扁平数组。
例如
$messages = $errors->firstOfAll(':message', false); // [ // 'contacts' => [ // 1 => [ // 'email' => 'Email is not valid email', // 'phone' => 'Phone is not valid phone number' // ], // ], // ] $messages = $errors->firstOfAll(':message', true); // [ // 'contacts.1.email' => 'Email is not valid email', // 'contacts.1.phone' => 'Email is not valid phone number', // ]
first(string $key)
获取给定键的第一条消息。如果有错误消息,它将返回string
;如果没有错误,它将返回null
。
例如
if ($emailError = $errors->first('email')) { echo $emailError; }
toArray()
获取ErrorMessage对象的原始底层关联数组。
例如
$messages = $errors->toArray(); // [ // 'email' => [ // 'email' => 'Email is not valid email' // ], // 'password' => [ // 'min' => 'Password minimum 6 character', // 'regex' => Password must contains capital letters' // ] // ]
toDataBag()
获取ErrorMessage对象的原始底层关联数组作为DataBag
实例。
例如
$message = $errors->toDataBag()->filter()->first();
count()
获取错误消息的数量。
has(string $key)
检查给定的键是否有错误。如果有键有错误,它返回true
;否则返回false
。
已验证、有效和无效数据
验证后,数据结果保留在每个验证实例中。例如
use Somnambulist\Components\Validation\Factory; $validation = (new Factory())->validate([ 'title' => 'Lorem Ipsum', 'body' => 'Lorem ipsum dolor sit amet ...', 'published' => null, 'something' => '-invalid-' ], [ 'title' => 'required', 'body' => 'required', 'published' => 'default:1|required|in:0,1', 'something' => 'required|numeric' ]);
现在您可以获取验证数据、只有有效数据或只有无效数据
$validatedData = $validation->getValidatedData(); // [ // 'title' => 'Lorem Ipsum', // 'body' => 'Lorem ipsum dolor sit amet ...', // 'published' => '1' // notice this // 'something' => '-invalid-' // ] $validData = $validation->getValidData(); // [ // 'title' => 'Lorem Ipsum', // 'body' => 'Lorem ipsum dolor sit amet ...', // 'published' => '1' // ] $invalidData = $validation->getInvalidData(); // [ // 'something' => '-invalid-' // ]
可用规则
点击显示详细信息。
accepted
此规则下的字段必须是'on'
、'yes'
、'1'
、'true'
(字符串"true")或true
之一。
after:明天
此规则下的字段必须是一个在给定最小值之后的日期。
参数应该是任何可以被strtotime
解析的有效字符串。例如
- after:下周
- after:2016-12-31
- after:2016
- after:2016-12-31 09:56:02
alpha
此规则下的字段必须是完全由字母字符组成。
alpha_num
此规则下的字段必须是完全由字母数字字符组成。
alpha_dash
此规则下的字段可以包含字母数字字符、连字符和下划线。
alpha_spaces
此规则下的字段可以包含字母字符,以及空格。
any_of:value,value,value
in
的变体:这里的值(默认情况下用逗号分隔)都必须在给定的值中。例如:将order => 'name,date'
与规则any_of:name,id
一起使用将失败验证,因为date
不是允许的值之一。分隔符可以通过在规则实例上调用separator()
来更改。
use Somnambulist\Components\Validation\Factory; use Somnambulist\Components\Validation\Rules\AnyOf; $validation = $factory->validate([ 'field' => 'foo;bar;example' ], [ 'field' => $factory->rule('any_of')->separator(';')->values(['foo', 'bar']), ]); $validation->passes(); // true if field only contains the values in any_of
与in
类似,可以通过在规则上调用->strict(true)
来执行严格匹配。
此规则对于允许用逗号分隔的数据作为单个参数的API非常有用,例如JsonAPI include、order等。如果源已经是数组,则可以使用array|in:...
代替。
array
根据此规则,该字段必须是数组。
between:min,max
根据此规则,该字段的大小必须在min和max参数之间。值的大小计算方式与min
和max
规则相同。
您还可以使用此规则验证上传文件的大小。
$validation = $validator->validate([ 'photo' => $_FILES['photo'] ], [ 'photo' => 'required|between:1M,2M' ]);
布尔型
根据此规则,该字段必须是布尔型。可接受输入包括true
、false
、1
、0
、"1"
和"0"
。
回调函数
定义一个自定义的回调函数来验证值。此规则不能使用字符串语法进行注册。要使用此规则,您必须使用数组语法,并明确指定callback
,或者传递闭包。
$validation = $validator->validate($_POST, [ 'even_number' => [ 'required', function ($value) { // false = invalid return (is_numeric($value) AND $value % 2 === 0); }, 'callback' => fn ($v) => is_numeric($v) && $v % 2 === 0, ] ]);
您可以设置自定义消息,通过返回一个字符串而不是false来实现。
$validation = $validator->validate($_POST, [ 'even_number' => [ 'required', function ($value) { if (!is_numeric($value)) { return ":attribute must be numeric."; } if ($value % 2 !== 0) { return ":attribute is not even number."; } return true; // always return true if validation passes } ] ]);
注意:回调闭包绑定到规则实例,允许通过$this访问规则属性。
日期:格式
根据此规则,该字段必须遵循给定格式的有效日期。参数format
是可选的,默认格式为Y-m-d
。
默认/默认值
如果该属性没有值,此默认值将用于验证数据中。
例如,如果您有如下验证:
use Somnambulist\Components\Validation\Factory; $validation = (new Factory)->validate([ 'enabled' => null ], [ 'enabled' => 'default:1|required|in:0,1' 'published' => 'default:0|required|in:0,1' ]); $validation->passes(); // true // Get the valid/default data $valid_data = $validation->getValidData(); $enabled = $valid_data['enabled']; $published = $valid_data['published'];
验证通过,因为enabled
和published
的默认值分别设置为1
和0
,这是有效的。
不同:another_field
same
的反义;根据此规则,该字段的值必须与another_field
的值不同。
数字:value
正在验证的字段必须是数字,并且必须具有与value
精确的长度。
数字之间:min,max
正在验证的字段必须是数字,并且长度必须在给定的min
和max
之间。
存在:table,column (数据库)
根据此验证,该字段必须在给定的表中存在。这并不检查唯一性,只是检查表中至少有一个记录的值和列与提供的值匹配。
要使用此规则,您必须提供一个DBAL连接。这应该通过依赖注入来完成。
例如
use Somnambulist\Components\Validation\Factory; $validation = (new Factory)->validate([ 'country' => 'GBR' ], [ 'country' => 'exists:countries,id', ]); $validation->passes(); // true if table countries has a record with id GBR
为了进行更精细的验证,可以通过调用->where()
设置闭包来修改底层查询。闭包将传递一个Doctrine\DBAL\Query\QueryBuilder
实例。
use Doctrine\DBAL\Query\QueryBuilder; use Somnambulist\Components\Validation\Factory; use Somnambulist\Components\Validation\Rules\Exists; $factory = new Factory; $factory->addRule('exists', new Exists($dbalConn)); $validation = $factory->validate([ 'country' => 'GBR' ], [ 'country' => $factory->rule('exists')->table('countries')->column('id')->where(fn (QueryBuilder $qb) => $qb->andWhere('active = 1')), ]); $validation->passes(); // true if table countries has a record with id GBR and it is active
扩展名:extension_a,extension_b,...
根据此规则,该字段必须以列表中之一对应的扩展名结束。
这在验证给定路径或url的文件类型时很有用。应该使用mimes
规则来验证上传。
如果您需要严格的MIME检查,应该实现一个自定义的
MimeTypeGuesser
,该闭包可以使用服务器端文件检查器,该检查器使用MIME库。
浮点数
根据此规则,该字段必须是一个浮点数,例如:0.0 12.3456等。值可以是一个包含浮点数的字符串。请注意,整数和0(零)将使用此规则失败验证。
in:value_1,value_2,...
根据此规则,该字段必须包含在给定的值列表中。
为了帮助构建字符串规则,In
(和NotIn
)规则有一个辅助方法。
use Somnambulist\Components\Validation\Factory; use Somnambulist\Components\Validation\Rules\In; $factory = new Factory(); $validation = $factory->validate($data, [ 'enabled' => [ 'required', In::make([true, 1]) ] ]);
此规则使用 in_array
进行验证,默认不进行严格检查。如果您需要严格检查,可以像这样调用规则:
use Somnambulist\Components\Validation\Factory; $factory = new Factory(); $validation = $factory->validate($data, [ 'enabled' => [ 'required', $factory->rule('in')->values([true, 1])->strict() ] ]);
然后 'enabled' 值应为布尔值 true
,或整数 1
。
整数
正在验证的字段必须为整数。
ip
此规则下的字段必须是有效的 ipv4 或 ipv6 地址。
ipv4
此规则下的字段必须是有效的 ipv4 地址。
ipv6
此规则下的字段必须是有效的 ipv6 地址。
json
此验证下的字段必须是有效的 JSON 字符串。
lowercase
此验证下的字段必须为小写。
max:数字
此规则下的字段大小必须小于或等于给定的数字。值大小以与 min
规则相同的方式计算。
您还可以使用此规则验证上传文件的最大大小。
$validation = $validator->validate([ 'photo' => $_FILES['photo'] ], [ 'photo' => 'required|max:2M' ]);
mimes:扩展名_a,扩展名_b,...
正在验证的 $_FILES
项必须具有与列出的扩展名之一对应的 MIME 类型。
这适用于文件扩展名,而不是客户端发送的头部或嵌入的文件类型。如果您需要严格的 MIME 类型验证,建议实现一个使用完整 MIME 类型查找库的
MimeTypeGuesser
并替换内置的 MIME 规则。
可以通过依赖注入和将 MIME 类型猜测器保留为服务来向现有的猜测器添加额外的 MIME 类型。
min:数字
此规则下的字段大小必须大于或等于给定的数字。
对于字符串值,大小对应于字符数。对于整数或浮点值,大小对应于其数值。对于数组,大小对应于数组中的计数。如果您的值是数值字符串,可以使用 numeric
规则将其大小视为数值而不是字符数。
您还可以使用此规则验证上传文件的最小大小。
$validation = $validator->validate([ 'photo' => $_FILES['photo'] ], [ 'photo' => 'required|min:1M' ]);
not_in:值_1,值_2,...
此规则下的字段不得包含在给定的值列表中。
此规则也使用 in_array
并可以启用与 In
相同的严格检查。
nullable
此规则下的字段可以是空的。
numeric
此规则下的字段必须是数值。
present
此规则下的字段必须在输入集中,无论值是什么。
prohibited
此规则下的字段不允许。
prohibited_if
如果 another_field
字段提供了任何值,则此规则下的字段不允许。
prohibited_unless
除非 another_field
具有这些值之一,否则此规则下的字段不允许。这是 prohibited_if
的逆。
regex:/your-regex/
此规则下的字段必须匹配给定的正则表达式。注意:如果您需要使用 |
,则正则表达式规则必须以数组格式编写,而不是字符串。例如
use Somnambulist\Components\Validation\Factory; $validation = (new Factory())->validate([ 'field' => 'value' ], [ 'field' => [ 'required', 'regex' => '/(this|that|value)/' ] ])
rejected
此规则下的字段必须具有与拒绝相对应的值,即 0(零)、"0"、false、no、"false"、off。这是 accepted
规则的逆。
required
此验证下的字段必须存在且不是 '空'。
以下是一些示例
对于上传的文件,$_FILES['key']['error']
必须不是 UPLOAD_ERR_NO_FILE
。
required_if:another_field,value_1,value_2,...
如果 another_field
字段等于任何值,则此规则下的字段必须存在且不为空。
例如,required_if:something,1,yes,on
将在 something
的值为 1
、'1'
、'yes'
或 'on'
时要求必须存在。
required_unless:another_field,value_1,value_2,...
除非 another_field
字段等于任何值,否则验证下的字段必须存在且不为空。
required_with:field_1,field_2,...
只有当指定的其他字段之一存在时,验证字段必须存在且不为空。
required_without:field_1,field_2,...
只有当指定的其他字段之一不存在时,验证字段必须存在且不为空。
required_with_all:field_1,field_2,...
只有当所有指定的其他字段都存在时,验证字段才必须存在且不为空。
required_without_all:field_1,field_2,...
只有当所有指定的其他字段都不存在时,验证字段才必须存在且不为空。
same:another_field
此规则下的字段值必须与another_field
相同。
sometimes
只有当字段存在于输入数据中时,才应对该字段进行验证。例如:field => sometimes|required|email
string
此规则下的字段必须是PHP字符串。
unique:table,column,ignore,ignore_column (数据库)
此验证下的字段在给定表中必须是唯一的。可选:可以忽略一个值,这可以是一个替代列值,如果提供了ignore_column。
要使用此规则,您必须提供一个DBAL连接。这应该通过依赖注入来完成。
例如
use Somnambulist\Components\Validation\Factory; $validation = (new Factory)->validate([ 'email' => 'foo@example.org' ], [ 'email' => 'email|unique:users,email', ]); $validation->passes(); // true if table users does not contain the email
忽略当前用户的电子邮件地址
use Somnambulist\Components\Validation\Factory; $validation = (new Factory)->validate([ 'email' => 'foo@example.org' ], [ 'email' => 'email|unique:users,email,10,id', ]); $validation->passes(); // true if table users ignoring id 10, does not contain email
为了进行更精细的验证,可以通过调用->where()
设置闭包来修改底层查询。闭包将传递一个Doctrine\DBAL\Query\QueryBuilder
实例。
use Doctrine\DBAL\Query\QueryBuilder; use Somnambulist\Components\Validation\Factory; use Somnambulist\Components\Validation\Rules\Unique; $factory = new Factory; $factory->addRule('unique', new Unique($dbalConn)); $validation = $factory->validate([ 'email' => 'foo@example.org' ], [ 'email' => $factory->rule('unique')->table('users')->column('email')->where(fn (QueryBuilder $qb) => $qb->andWhere('active = 1')), ]); $validation->passes(); // true if table users does not contain an active email
uploaded_file:min_size,max_size,extension_a,extension_b,...
此规则将验证来自$_FILES
的数据。此规则下的字段有以下条件
$_FILES['key']['error']
必须是UPLOAD_ERR_OK
或UPLOAD_ERR_NO_FILE
。对于UPLOAD_ERR_NO_FILE
,可以使用required
规则进行验证。- 如果指定了最小大小,上传文件的大小不得低于最小大小。
- 如果指定了最大大小,上传文件的大小不得高于最大大小。
- 如果指定了文件类型,MIME类型必须是给定类型之一。
对于大小约束,在使用字符串定义时必须同时给出。要指定仅最大大小,请使用工厂方法获取规则,并使用方法链。
以下是一些示例定义和说明
uploaded_file
:上传文件是可选的。当它不为空时,它必须是ERR_UPLOAD_OK
。required|uploaded_file
:上传文件是必需的,并且必须是ERR_UPLOAD_OK
。uploaded_file:0,1M
:上传文件大小必须在0 - 1MB之间,但上传文件是可选的。required|uploaded_file:0,1M,png,jpeg
:上传文件大小必须在0 - 1MB之间,并且MIME类型必须是image/jpeg
或image/png
。
对于多文件上传,PHP使用格式_FILES[key][name][0..n+1]
(请参阅PHP手册以获取更多详细信息)。相反,文件数组会自动重新排序为相关属性的嵌套数组。这允许使用相同的规则对多个文件进行验证。
例如,如果您有以下输入文件
<input type="file" name="photos[]"/> <input type="file" name="photos[]"/> <input type="file" name="photos[]"/>
您可以使用以下方式验证所有文件
$validation = (new Factory)->validate($_FILES, [ 'photos.*' => 'uploaded_file:0,2M,jpeg,png' ]); // or $validation = (new Factory)->validate($_FILES, [ 'photos.*' => 'uploaded_file|max:2M|mimes:jpeg,png' ]);
或者,如果您有以下输入文件
<input type="file" name="images[profile]"/> <input type="file" name="images[cover]"/>
您可以像这样验证它
$validation = (new Factory)->validate($_FILES, [ 'images.*' => 'uploaded_file|max:2M|mimes:jpeg,png', ]); // or $validation = (new Factory)->validate($_FILES, [ 'images.profile' => 'uploaded_file|max:2M|mimes:jpeg,png', 'images.cover' => 'uploaded_file|max:5M|mimes:jpeg,png', ]);
uppercase
此验证下的字段必须是大写。
url
此规则下的字段必须是有效的URL格式。默认情况下,它验证常见的格式:any_scheme://...
。如果您愿意,可以指定特定的URL方案。
例如
$validation = (new Factory)->validate($inputs, [ 'random_url' => 'url', // value can be `any_scheme://...` 'https_url' => 'url:http', // value must be started with `https://` 'http_url' => 'url:http,https', // value must be started with `http://` or `https://` 'ftp_url' => 'url:ftp', // value must be started with `ftp://` 'custom_url' => 'url:custom', // value must be started with `custom://` ]);
与
rakit
、mailto和JDBC不同,不支持。请实现自定义规则或正则表达式进行验证。
uuid
此验证下的字段必须是有效的UUID,而不是nil UUID字符串。
注册/覆盖规则
默认情况下,所有内置规则都会自动注册到Factory
实例。其中一些规则是内部必需的(例如required
和callback
);但是,您可以覆盖或添加任意数量的新规则到工厂中,用于您的验证。
这是通过在Factory
上访问addRule()
方法并添加一个新的规则实例来实现的。
例如,您想创建一个检查数据库中字段可用性的unique
验证器。
首先,让我们创建UniqueRule
类
<?php declare(strict_types=1); use Somnambulist\Components\Validation\Rule; class UniqueRule extends Rule { protected string $message = ":attribute :value has been used"; protected array $fillableParams = ['table', 'column', 'except']; protected PDO $pdo; public function __construct(PDO $pdo) { $this->pdo = $pdo; } public function check($value): bool { // make sure required parameters exists $this->assertHasRequiredParameters(['table', 'column']); // getting parameters $column = $this->parameter('column'); $table = $this->parameter('table'); $except = $this->parameter('except'); if ($except && $except == $value) { return true; } // do query $stmt = $this->pdo->prepare(sprintf('select count(*) as count from %s where %s = :value', $table, $column)); $stmt->bindParam(':value', $value); $stmt->execute(); $data = $stmt->fetch(PDO::FETCH_ASSOC); // true for valid, false for invalid return intval($data['count']) === 0; } }
现在要注册这个规则,需要将其添加到Factory
实例中
use Somnambulist\Components\Validation\Factory; $factory = new Factory(); $factory->addRule('unique', new UniqueRule($pdo));
现在您可以使用它这样
$validation = $factory->validate($_POST, [ 'email' => 'email|unique:users,email,exception@mail.com' ]);
在上面的UniqueRule
中,属性$message
用于无效消息。属性$fillableParams
定义了规则参数的顺序和名称。默认情况下,fillParameters
将从字符串规则填充在$fillableParams
中列出的参数。例如,上面的例子中的unique:users,email,exception@mail.com
将设置
$params['table'] = 'users'; $params['column'] = 'email'; $params['except'] = 'exception@mail.com';
如果您希望您的自定义规则接受类似于
in
、not_in
或uploaded_file
规则的参数列表,您需要在您的自定义规则类中覆盖fillParameters(array $params)
方法。
注意,我们上面创建的unique
规则也可以这样使用
$validation = $factory->validate($_POST, [ 'email' => [ 'required', 'email', $factory('unique', 'users', 'email') ] ]);
您可以通过添加一些方法来设置参数,而不是使用字符串格式来改进上面的UniqueRule
类
<?php class UniqueRule extends Rule { public function table(string $table): self { $this->params['table'] = $table; return $this; } public function column(string $column): self { $this->params['column'] = $column; return $this; } public function except(string $value): self { $this->params['except'] = $value; return $this; } }
现在配置规则变为
$validation = $factory->validate($_POST, [ 'email' => [ 'required', 'email', $validator('unique')->table('users')->column('email')->except('exception@mail.com') ] ]);
隐式规则
隐式规则是一种规则,如果它无效,则忽略后续规则。例如,如果属性未通过required*
规则,则下一个规则将是无效的。为了避免不必要的验证和错误消息,我们将required*
规则设置为隐式。
要使您的自定义规则隐式,可以将$implicit
属性值设置为true
。例如
<?php use Somnambulist\Components\Validation\Rule; class YourCustomRule extends Rule { protected bool $implicit = true; }
修改值
在某些情况下,您可能希望您的自定义规则能够像default/defaults
规则一样修改属性值。在当前和下一个规则检查中,将使用您修改的值。
要这样做,您应该在您的自定义规则类中实现Somnambulist\Components\Validation\Rules\Contracts\ModifyValue
并创建modifyValue(mixed $value)
方法。
例如
<?php use Somnambulist\Components\Validation\Rule; use Somnambulist\Components\Validation\Rules\Contracts\ModifyValue; class YourCustomRule extends Rule implements ModifyValue { public function modifyValue(mixed $value): mixed { // Do something with $value return $value; } }
验证前钩子
您可能在运行验证之前做一些准备工作。例如,uploaded_file
规则将解析来自$_FILES
(不希望)数组的属性值,使其成为一个有组织的数组。
要这样做,您应该在您的自定义规则类中实现Somnambulist\Components\Validation\Rules\Contracts\BeforeValidate
并创建beforeValidate()
方法。
例如
<?php use Somnambulist\Components\Validation\Rule; use Somnambulist\Components\Validation\Rules\Contracts\BeforeValidate; class YourCustomRule extends Rule implements BeforeValidate { public function beforeValidate(): void { $attribute = $this->getAttribute(); $validation = $this->validation; // Do something with $attribute and $validation // For example change attribute value $validation->setValue($attribute->getKey(), "your custom value"); } }
测试
使用PHPUnit 9+进行测试。通过vendor/bin/phpunit
运行测试。