samandeggs / validation
PHP Laravel 类的独立验证库 - 基于 Rakit/Validation
Requires
- php: >=7.0
- ext-mbstring: *
Requires (Dev)
This package is not auto-updated.
Last update: 2024-09-19 10:06:04 UTC
README
samandeggs/validation 是 rakit/validation 的分支 - 仅因为它不再维护,我们只需要移除 php8 的弃用功能。这里不会添加其他功能。
以下是原始 README.md
Rakit Validation - PHP 独立验证库
PHP 独立库,用于验证数据。受 Laravel 的 Illuminate\Validation
启发。
功能
- 类似 Laravel 验证的 API。
- 数组验证。
- 支持多个文件的
$_FILES
验证。 - 自定义属性别名。
- 自定义验证消息。
- 自定义规则。
要求
- PHP 7.0 或更高版本
- Composer 用于安装
快速开始
安装
composer require "rakit/validation"
用法
使用此库验证数据有两种方式。使用 make
创建验证对象,然后使用 validate
进行验证。或者直接使用 validate
。示例
使用 make
<?php require('vendor/autoload.php'); use Rakit\Validation\Validator; $validator = new Validator; // make it $validation = $validator->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' ]); // then validate $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 Rakit\Validation\Validator; $validator = new Validator; $validation = $validator->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!"; }
在这种情况下,上面的两个示例将输出相同的结果。
但是使用 make
你可以在验证运行之前设置一些自定义的无效消息,自定义属性别名等。
属性别名
默认情况下,我们将您的属性转换成更易读的文本。例如 confirm_password
将显示为 Confirm password
。但是您可以使用 setAlias
或 setAliases
方法将其设置为任何您想要的内容。
示例
$validator = new Validator; // To set attribute alias, you should use `make` instead `validate`. $validation->make([ 'province_id' => $_POST['province_id'], 'district_id' => $_POST['district_id'] ], [ 'province_id' => 'required|numeric', 'district_id' => 'required|numeric' ]); // now you can set aliases using this way: $validation->setAlias('province_id', 'Province'); $validation->setAlias('district_id', 'District'); // or this way: $validation->setAliases([ 'province_id' => 'Province', 'district_id' => 'District' ]); // then validate it $validation->validate();
现在如果 province_id
的值为空,错误消息将是 'Province is required'。
自定义验证消息
在注册/设置自定义消息之前,这里有一些您可以在自定义消息中使用的变量
:attribute
: 将替换为属性别名。:value
: 将替换为属性值的字符串表示。对于数组和对像将替换为 JSON。
并且还有根据其规则的一些消息变量。
以下是一些注册/设置您自定义消息的方法
Validator 的自定义消息
使用这种方法,每次您使用 make
或 validate
进行验证时,都会为它设置自定义消息。这对于本地化非常有用。
为此,您可以像这样将自定义消息作为构造函数的第一个参数设置
$validator = new Validator([ 'required' => ':attribute harus diisi', 'email' => ':email tidak valid', // etc ]); // then validation belows will use those custom messages $validation_a = $validator->validate($dataset_a, $rules_for_a); $validation_b = $validator->validate($dataset_b, $rules_for_b);
或者使用 setMessages
方法像这样
$validator = new Validator; $validator->setMessages([ 'required' => ':attribute harus diisi', 'email' => ':email tidak valid', // etc ]); // now validation belows will use those custom messages $validation_a = $validator->validate($dataset_a, $rules_for_dataset_a); $validation_b = $validator->validate($dataset_b, $rules_for_dataset_b);
验证的自定义消息
有时您可能想为特定的验证设置自定义消息。为此,您可以将自定义消息作为 $validator->make
或 $validator->validate
的第三个参数设置,如下所示
$validator = new Validator; $validation_a = $validator->validate($dataset_a, $rules_for_dataset_a, [ 'required' => ':attribute harus diisi', 'email' => ':email tidak valid', // etc ]);
或者您可以使用 $validation->setMessages
如此
$validator = new Validator; $validation_a = $validator->make($dataset_a, $rules_for_dataset_a); $validation_a->setMessages([ 'required' => ':attribute harus diisi', 'email' => ':email tidak valid', // etc ]); ... $validation_a->validate();
特定属性规则的自定义消息
有时您可能想为特定的规则属性设置自定义消息。为此,您可以使用 :
作为消息分隔符或使用链式方法。
示例
$validator = new Validator; $validation_a = $validator->make($dataset_a, [ 'age' => 'required|min:18' ]); $validation_a->setMessages([ 'age:min' => '18+ only', ]); $validation_a->validate();
或者使用链式方法
$validator = new Validator; $validation_a = $validator->make($dataset_a, [ 'photo' => [ 'required', $validator('uploaded_file')->fileTypes('jpeg|png')->message('Photo must be jpeg/png image') ] ]); $validation_a->validate();
翻译
翻译与自定义消息不同。当您使用自定义消息为规则 in
、not_in
、mimes
和 uploaded_file
时,可能需要翻译。
例如,如果您使用规则in:1,2,3
,我们将设置无效信息,如“属性仅允许‘1’、‘2’或‘3’”,其中“‘1’、‘2’或‘3’”部分来自“:allowed_values”标签。因此,如果您有自定义的印尼语信息“:attribute hanya memperbolehkan :allowed_values”,我们将设置无效信息如“Attribute hanya memperbolehkan ‘1’,‘2’或‘3’”,其中的“or”词不是印尼语的一部分。
因此,为了解决这个问题,我们可以使用以下翻译
// Set translation for words 'and' and 'or'. $validator->setTranslations([ 'and' => 'dan', 'or' => 'atau' ]); // Set custom message for 'in' rule $validator->setMessage('in', ":attribute hanya memperbolehkan :allowed_values"); // Validate $validation = $validator->validate($inputs, [ 'nomor' => 'in:1,2,3' ]); $message = $validation->errors()->first('nomor'); // "Nomor hanya memperbolehkan '1', '2', atau '3'"
实际上,我们内置的规则只使用您可能需要翻译的单词“and”和“or”。
处理错误信息
错误信息收集在Rakit\Validation\ErrorBag
对象中,您可以使用errors()
方法获取它。
$validation = $validator->validate($inputs, $rules); $errors = $validation->errors(); // << ErrorBag
现在您可以使用以下方法检索错误信息
all(string $format = ':message')
获取所有消息作为扁平数组。
示例
$messages = $errors->all(); // [ // 'Email is not valid email', // 'Password minimum 6 character', // 'Password must contains capital letters' // ] $messages = $errors->all('<li>:message</li>'); // [ // '<li>Email is not valid email</li>', // '<li>Password minimum 6 character</li>', // '<li>Password must contains 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()
按其键分组获取所有消息。
例如
$messages = $errors->toArray(); // [ // 'email' => [ // 'Email is not valid email' // ], // 'password' => [ // 'Password minimum 6 character', // 'Password must contains capital letters' // ] // ]
count()
获取消息数量。
has(string $key)
检查给定的键是否有错误。如果键有错误,则返回bool
,否则返回。
获取已验证、有效和无效数据
例如,您有如下验证
$validation = $validator->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-' // ]
可用规则
点击显示详细信息。
required
此验证字段必须存在且不为‘空’。
以下是一些示例
对于上传的文件,$_FILES['key']['error']
不得为UPLOAD_ERR_NO_FILE
。
required_if:another_field,value_1,value_2,...
此规则下的字段必须存在且不为空,如果另一个字段等于任何值。
例如required_if:something,1,yes,on
,如果something
值为1
、'1'
、'yes'
或'on'
之一,则必须进行验证。
required_unless:another_field,value_1,value_2,...
验证字段必须存在且不为空,除非另一个字段等于任何值。
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,...
验证字段必须存在且不为空,只有当所有其他指定字段都不存在时。
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 - 1 MB 之间,但上传的文件是可选的。required|uploaded_file:0,1M,png,jpeg
:上传的文件大小必须在 0 - 1MB 之间,并且 MIME 类型必须是image/jpeg
或image/png
。
可选地,如果您想在大小和类型验证之间有单独的错误信息。您可以使用 mimes
规则来验证文件类型,并使用 min
、max
或 between
来验证它的大小。
对于多个文件上传,PHP 将给出不希望的 $_FILES
结构(在此处是主题)。因此,我们创建了一个 uploaded_file
规则,可以自动将您的 $_FILES
值解析为良好的数组结构。这意味着,您不仅可以使用 min
、max
、between
或 mimes
规则来验证多个文件上传。您应该仅使用 uploaded_file
来解析它的值并确保该值是正确的上传文件值。
例如,如果您有如下输入文件
<input type="file" name="photos[]" /> <input type="file" name="photos[]" /> <input type="file" name="photos[]" />
您可以直接这样验证
$validation = $validator->validate($_FILES, [ 'photos.*' => 'uploaded_file:0,2M,jpeg,png' ]); // or $validation = $validator->validate($_FILES, [ 'photos.*' => 'uploaded_file|max:2M|mimes:jpeg,png' ]);
或者如果您有如下输入文件
<input type="file" name="images[profile]" /> <input type="file" name="images[cover]" />
您可以这样验证
$validation = $validator->validate($_FILES, [ 'images.*' => 'uploaded_file|max:2M|mimes:jpeg,png', ]); // or $validation = $validator->validate($_FILES, [ 'images.profile' => 'uploaded_file|max:2M|mimes:jpeg,png', 'images.cover' => 'uploaded_file|max:5M|mimes:jpeg,png', ]);
现在,当您使用 getValidData()
或 getInvalidData()
时,您将得到良好的数组结构,就像单个文件上传一样。
mimes:extension_a,extension_b,...
正在验证的 $_FILES
项必须有一个与列出的扩展名对应的 MIME 类型。
default/defaults
这是一个特殊的规则,它不进行任何验证。它只是当属性为空或不存在时将默认值设置到您的属性中。
例如,如果您有如下验证
$validation = $validator->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
,它们是有效的。然后我们可以获取有效/默认数据。
此验证下的字段必须是有效的电子邮件地址。
uppercase
此验证下的字段必须是有效的大写。
lowercase
此验证下的字段必须是有效的小写。
json
此验证下的字段必须是有效的 JSON 字符串。
alpha
此规则下的字段必须是全部字母字符。
numeric
此规则下的字段必须是数字。
alpha_num
此规则下的字段必须是全部字母数字字符。
alpha_dash
此规则下的字段可以包含字母数字字符,以及破折号和下划线。
alpha_spaces
此规则下的字段可以包含字母字符,以及空格。
in:value_1,value_2,...
此规则下的字段必须在给定的值列表中。
此规则使用 in_array
来检查值。默认情况下,in_array
禁用严格检查。因此,它不检查数据类型。如果您想启用严格检查,可以像以下示例一样调用验证器
$validation = $validator->validate($data, [ 'enabled' => [ 'required', $validator('in', [true, 1])->strict() ] ]);
然后 'enabled' 的值应该是布尔值 true
,或者整数 1
。
not_in:value_1,value_2,...
此规则下的字段不包含在给定的值列表中。
此规则也使用 in_array
。您可以通过调用验证器并调用 strict()
(如上述规则 in
中的示例)来启用严格检查。
min:number
此规则下的字段必须大于或等于给定数字的大小。
对于字符串值,大小对应字符数量。对于整数或浮点值,大小对应其数值。对于数组,大小对应数组计数。如果你的值是数字字符串,你可以添加numeric
规则来按数值处理大小,而不是按字符数量。
你还可以使用此规则验证上传的文件,以验证上传文件的最小大小。例如
$validation = $validator->validate([ 'photo' => $_FILES['photo'] ], [ 'photo' => 'required|min:1M' ]);
max:number
此规则下的字段大小必须小于或等于给定数字。值大小计算方式与min
规则相同。
你还可以使用此规则验证上传文件,以验证上传文件的最大大小。例如
$validation = $validator->validate([ 'photo' => $_FILES['photo'] ], [ 'photo' => 'required|max:2M' ]);
between:min,max
此规则下的字段大小必须在min和max参数之间。值大小计算方式与min
和max
规则相同。
你还可以使用此规则验证上传文件,以验证上传文件的大小。例如
$validation = $validator->validate([ 'photo' => $_FILES['photo'] ], [ 'photo' => 'required|between:1M,2M' ]);
digits:value
验证的字段必须是数字,且长度必须与value
精确匹配。
digits_between:min,max
验证的字段长度必须在给定的min
和max
之间。
url
此规则下的字段必须是有效的URL格式。默认情况下,它检查常见的URL方案格式如any_scheme://...
。但你可以指定URL方案。
例如
$validation = $validator->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://` 'mailto_url' => 'url:mailto', // value must conatin valid mailto URL scheme like `mailto:a@mail.com,b@mail.com` 'jdbc_url' => 'url:jdbc', // value must contain valid jdbc URL scheme like `jdbc:mysql:///dbname` ]);
对于常见的URL方案和mailto,我们结合
FILTER_VALIDATE_URL
来验证URL格式,并使用preg_match
来验证方案。除了JDBC URL外,目前它仅检查有效的JDBC方案。
integer
此规则下的字段必须是整数。boolean
此规则下的字段必须是布尔值。接受的输入包括true
、false
、1
、0
、"1"
和"0"
。
ip
此规则下的字段必须是有效的IPv4或IPv6。
ipv4
此规则下的字段必须是有效的IPv4。
ipv6
此规则下的字段必须是有效的IPv6。
extension:extension_a,extension_b,...
此规则下的字段必须以列表中指定的扩展名之一结尾。
这适用于验证给定路径或URL的文件类型。应使用mimes
规则验证上传。
array
此规则下的字段必须是数组。
same:another_field
此规则下的字段值必须与another_field
值相同。
regex:/your-regex/
此规则下的字段必须与给定的正则表达式匹配。
date:format
此规则下的字段必须是有效的日期格式。参数format
是可选的,默认格式是Y-m-d
。
accepted
此规则下的字段必须是'on'
、'yes'
、'1'
、'true'
或true
之一。
present
此规则下的字段必须存在,无论其值如何。
different:another_field
与same
相反。此规则下的字段值必须与another_field
值不同。
after:tomorrow
可以将任何可以被strtotime
解析的日期传递给此规则作为参数。有效的示例包括
- after:next week
- after:2016-12-31
- after:2016
- after:2016-12-31 09:56:02
before:yesterday
这同样适用于after规则。传递任何可以被strtotime
解析的日期。
callback
你可以使用此规则来定义自己的验证规则。此规则不能使用字符串管道进行注册。要使用此规则,你应该将闭包放在规则数组中。
例如
$validation = $validator->validate($_POST, [ 'even_number' => [ 'required', function ($value) { // false = invalid return (is_numeric($value) AND $value % 2 === 0); } ] ]);
你可以通过返回一个字符串来设置无效消息。例如,上面的示例将是
$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."; } // you can return true or don't return anything if value is valid } ] ]);
注意:
Rakit\Validation\Rules\Callback
实例已绑定到您的闭包中。因此,您可以使用$this
访问规则属性和方法。
可空
此规则下的字段可能为空。
注册/覆盖规则
使用自定义验证规则的另一方法是创建一个扩展 Rakit\Validation\Rule
的类。然后使用 setValidator
或 addValidator
注册它。
例如,您想创建一个 unique
验证器,用于从数据库中检查字段可用性。
首先,创建 UniqueRule
类
<?php use Rakit\Validation\Rule; class UniqueRule extends Rule { protected $message = ":attribute :value has been used"; protected $fillableParams = ['table', 'column', 'except']; protected $pdo; public function __construct(PDO $pdo) { $this->pdo = $pdo; } public function check($value): bool { // make sure required parameters exists $this->requireParameters(['table', 'column']); // getting parameters $column = $this->parameter('column'); $table = $this->parameter('table'); $except = $this->parameter('except'); if ($except AND $except == $value) { return true; } // do query $stmt = $this->pdo->prepare("select count(*) as count from `{$table}` where `{$column}` = :value"); $stmt->bindParam(':value', $value); $stmt->execute(); $data = $stmt->fetch(PDO::FETCH_ASSOC); // true for valid, false for invalid return intval($data['count']) === 0; } }
然后您需要将 UniqueRule
实例注册到验证器中,如下所示
use Rakit\Validation\Validator; $validator = new Validator; $validator->addValidator('unique', new UniqueRule($pdo));
现在您可以像这样使用它
$validation = $validator->validate($_POST, [ 'email' => 'email|unique:users,email,exception@mail.com' ]);
在上面的 UniqueRule
中,属性 $message
用于默认无效消息。属性 $fillable_params
用于 fillParameters
方法(在 Rakit\Validation\Rule
类中定义)。默认情况下,fillParameters
将填充 $fillable_params
中列出的参数。例如,上述示例中的 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 = $validator->validate($_POST, [ 'email' => [ 'required', 'email', $validator('unique', 'users', 'email')->message('Custom message') ] ]);
因此,您可以通过添加一些返回其自身实例的方法来改进上面的 UniqueRule
类
<?php use Rakit\Validation\Rule; class UniqueRule extends Rule { ... public function table($table) { $this->params['table'] = $table; return $this; } public function column($column) { $this->params['column'] = $column; return $this; } public function except($value) { $this->params['except'] = $value; return $this; } ... }
然后您可以用这种方式使用它
$validation = $validator->validate($_POST, [ 'email' => [ 'required', 'email', $validator('unique')->table('users')->column('email')->except('exception@mail.com')->message('Custom message') ] ]);
隐式规则
隐式规则是一种规则,如果它无效,则忽略后续规则。例如,如果属性没有通过 required*
规则,大多数情况下,其后续规则也将无效。因此,为了防止我们的后续规则消息被收集,我们将 required*
规则设置为隐式。
要使您的自定义规则为隐式,您可以设置 $implicit
属性值为 true
。例如
<?php use Rakit\Validation\Rule; class YourCustomRule extends Rule { protected $implicit = true; }
修改值
在某些情况下,您可能希望自定义规则能够修改其属性值,如我们的 default/defaults
规则。因此,在当前和后续规则检查中,将使用您修改的值。
为此,您应该实现 Rakit\Validation\Rules\Interfaces\ModifyValue
并在您的自定义规则类中创建 modifyValue($value)
方法。
例如
<?php use Rakit\Validation\Rule; use Rakit\Validation\Rules\Interfaces\ModifyValue; class YourCustomRule extends Rule implements ModifyValue { ... public function modifyValue($value) { // Do something with $value return $value; } ... }
验证前钩子
您可能想在验证运行之前做一些准备工作。例如,我们的 uploaded_file
规则将解决来自 $_FILES
(不理想的)数组结构的属性值,以使其成为良好的组织结构,这样我们就可以像验证其他数据一样验证多个文件上传。
为此,您应该实现 Rakit\Validation\Rules\Interfaces\BeforeValidate
并在您的自定义规则类中创建 beforeValidate()
方法。
例如
<?php use Rakit\Validation\Rule; use Rakit\Validation\Rules\Interfaces\BeforeValidate; class YourCustomRule extends Rule implements BeforeValidate { ... public function beforeValidate() { $attribute = $this->getAttribute(); // Rakit\Validation\Attribute instance $validation = $this->validation; // Rakit\Validation\Validation instance // Do something with $attribute and $validation // For example change attribute value $validation->setValue($attribute->getKey(), "your custom value"); } ... }