验证器定义
通过一条命令直接生成想要的类,这条命令会自动在应用目录下生成一个 validate 文件夹,并生成 User.php类(class User extends Validate):
php think make:validate User
自动生成了两个属性:$rule表示定义规则,$message表示错误提示信息:
/**
* 定义验证规则
* 格式:'字段名' => ['规则1','规则2'...]
*
* @var array
*/
protected $rule = [];
/**
* 定义错误信息
* 格式:'字段名.规则名' => '错误信息'
*
* @var array
*/
protected $message = [];
自动生成了两个属性:$rule表示定义规则,$message表示错误提示信息。
验证器定义好了之后,我们需要进行调用测试,创建一个Verify.php控制器:
<?php
namespace app\controller;
use app\BaseController;
use app\validate\User;
use think\exception\ValidateException;
class Verify extends BaseController{
public function check(){
try{
validate(User::class)->check([
'name' => '蜡笔小新',
'price' => 90,
'email' => 'xiaoxing@163.com',
]);
}catch(ValidateException $e){
dump($e->getError());
}
}
}
默认情况下,出现一个错误就会停止后面字段的验证,我们也可以设置批量验证:
validate(User::class)->batch(true)
系统提供了常用的规则让开发者直接使用,也可以自行定义独有的特殊规则:
protected $rule = [
'name' => 'require|max:20|checkName:peppa',
];
//自定义规则,名称中不得是“李炎恢”
protected function checkName($value, $rule) {
return $rule != $value ? true : '名称存在非法称谓';
}
对于自定义规则中,一共可以有五个参数:
protected function checkName($value, $rule, $data, $field, $title) {
//所有数据信息
dump($data);
//当前字段名
dump($field);
//字段描述,没有就是字段名
dump($title);
}
如何设置字段描述,只要在字段名用|后设置即可:
'name|用户名' => 'require|max:20|checkName:peppa',
验证规则和错误信息
验证规则
在上一节验证器定义的时候,我们采用的字符串模式,也支持数组模式。数组模式在验证规则很多很乱的情况下,更容易管理,可读性更高:
protected $rule = [
'name' => [
'require',
'max' => 10,
'checkName' => 'peppa'
],
'price' => [
'number',
'between' => '1,100'
],
'email' => 'email'
];
如果你想使用独立验证,就是手动调用验证类,而不是调用 User.php验证类,这种调用方式,一般来说,就是独立、唯一,并不共享的调用方式:
$validate = Validate::rule([
'name' => 'require|max:20',
'price' => 'number|between:1,100',
'email' => 'email'
]);
$result = $validate->check([
'name' => 'peppa',
'price' => 90,
'email' => 'xiaoxin163.com'
]);
if (!$result) {
dump($validate->getError());
}
独立验证默认也是返回一条错误信息,如果要批量返回所有错误使用batch():
$result = $validate->batch(true)->check
独立验支持对象化的定义方式,但不支持在属性方式的定义:
$validate = Validate::rule([
'name' => ValidateRule::isRequire()->max(20),
'price' => ValidateRule::isNumber()->between([1, 100]),
'email' => ValidateRule::isEmail()
]);
独立验支持闭包的自定义方式,但这种方式会不支持字段的多规则:
$validate = Validate::rule([
'name' => function ($value) {
return $value != '' ? true : '姓名不得为空';
},
'price'=> function ($value) {
return $value > 0 ? true : '价格不得小于零';
}
]);
错误信息
独立验证的自定义错误提示,可以在方法的第二参数,参数一是规则。也可以独立使用 message()方法,来设置相关错误信息:
ValidateRule::isEmail(null, '邮箱格式不正确!');
ValidateRule::isNumber()->between([1, 100], '价格范围1-100之间')
$validate->message([
'name.require' => '姓名不得为空',
'name.max' => '姓名不可以超过20个字'
]);
'name.require' => ['code'=>1001, 'msg'=>'姓名不得为空'],
验证场景和路由验证
验证场景
验证场景设置,即特定的场景下是否进行验证,独立验证不存在场景验证。举一个简单的例子,新增数据需要验证邮箱,而修改更新时不验证邮箱。可以在验证类User.php中,设置一个$scene属性,用来限定场景验证:
protected $scene = [
'insert' => ['name', 'price', 'email'],
'edit' => ['name', 'price'],
];
上述中,insert新增需要验证三个字段,而 edit更新则只要验证两个字段。在控制器端,验证时,根据不同的验证手段,绑定相关场景进行验证即可:
$validate->scene('edit')->check($data)
在验证类端,可以设置一个公共方法对场景的细节进行定义:
public function sceneEdit()
{
$edit = $this->only(['name', 'price']) //仅对两个字段验证
->remove('name', 'max') //移出掉最大字段的限制
->append('price', 'require'); //增加一个不能为空的限制
return $edit;
}
注意:请不要对一个字段进行两个或以上的移出和添加,会被覆盖:
remove('name', 'xxx|yyy|zzz')或 remove('name', ['xxx', 'yyy', 'zzz']);
// remove('name', 'xxx')->remove('name', 'yyy')->remove('name', 'zzz');
路由验证
路由验证,即在路由的参数来调用验证类进行验证,和字段验证一模一样:
protected $rule = [
'id' => 'number|between:1,10'
];
protected $message = [
'id.between' => 'id只能是1-10之间',
'id.number' => 'id必须是数字'
];
Route::rule('vr/:id','Verify/route')
->validate(\app\validate\User::class, 'route');
如果不使用验证器类,也可以使用独立的验证方式,也可以使用对象化:
Route::rule('vr/:id','Verify/route')
->validate([
'id' => 'number|between:1,10',
'email' => \think\validate\ValidateRule::isEmail()
], null, [
'id.between' => 'id限定在1-10之间',
'email' => '邮箱格式错误'
], true);
验证内置规则
内置规则
内置的规则内容较多,并且严格区分大小写,这里按照类别一一列出。静态方法支持两种形式,比如::number()或者 isNumber()均可。而 require是 PHP保留字,那么就必须用 isRequire()或 must();
格式验证类
长度和区间验证类
字段比较类
其它验证类
单个验证和注解验证
单个验证
静态调用,即使用 facade模式进行调用验证,非常适合单个数据的验证。引入 facade中的 Validate时,和其它 Validate会冲突,要特别注意。静态调用返回的结果是false和true,方便你进行条件判断。
//验证邮箱是否合法
dump(Validate::isEmail('xiaoxin@163.com'));
//验证是否为空
dump(Validate::isRequre(''));
//验证是否为数值
dump(Validate::isNumber(10));
静态调用,也是支持多规则验证的,使用 checkRule()方法实现:
//验证数值合法性
dump(Validate::checkRule(10, 'number|between:1,10'));
checkRule()不支持错误信息,需要自己实现,但支持对象化规则定义:
dump(Validate::checkRule(10, ValidateRule::isNumber()->between('1,10')))
注解验证
可以结合之前课程中注解路由的传参,使用验证方式,对其进行验证:
use think\annotation\Route;
use think\annotation\route\Validate;
/**
* @param $id
* @return string
* @route("vr/:id")
* @Validate(User::class)
*/