前置处理
使用自定义验证规则之前,必须先定义自定义验证规则的命名空间前缀
ValidateConfig::instance()->setRulesPath('W7\\App\\Model\\Validate\\Rules\\');
建议在Provider
中定义验证相关的设置
使用规则对象
验证器内有很多有用的验证规则;同时也支持自定义规则。注册自定义验证规则的方法之一,就是新建一个规则并继承W7\Validate\Support\Rule\BaseRule
。新的规则存放在你设置好的目录中
一旦创建了规则,我们就可以定义它的行为。 passes
方法接收属性值和名称,并根据属性值是否符合规则而返回true
或false
。 message
属性为验证失败时使用的验证错误消息,此错误消息可被验证器中定义的message
覆盖:
namespace W7\App\Model\Validate\Rules;
class Chs extends BaseRule
{
/**
* 默认错误消息
* @var string
*/
protected $message = ':attribute的值只能具有中文';
/**
* 确定验证规则是否通过。
*
* @param mixed $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value): bool
{
return is_scalar($value) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', (string)$value);
}
}
一旦规则对象被定义好后,你可以通过将规则对象的实例和其他验证规则一起来传递给验证器:
protected $rule = [
'title' => 'required|chs',
];
规则也支持独立调用使用
Chs::make()->check("名字");
验证通过返回true
,失败返回false
自定义规则传入参数
自定义规则,和其他规则一样,也支持传入参数,类似于max:100
,in:0,1,2
此类,参数将按顺序传入自定义规则类中的构造函数中,如下:
class Length extends BaseRule
{
protected $message = ':attribute的长度不符合要求';
protected $size;
public function __construct(int $size)
{
$this->size = $size;
}
public function passes($attribute, $value): bool
{
return strlen($value) === $this->size;
}
}
格式化错误消息
在上诉代码中,错误提示可能并不是那么清晰,将$size
变量放入错误提示,也许会更好,我们提供了$messageParam
参数,用于支持格式化错误消息,如下:
class Length extends BaseRule
{
protected $message = ':attribute的长度需为%d个字节';
protected $size;
public function __construct(int $size)
{
$this->size = $size;
$this->messageParam = [$size];
}
public function passes($attribute, $value): bool
{
return strlen($value) === $this->size;
}
}
$messageParam
是一个数组类型,所以传入的值必须为数组,如使用规则为length:10
,则触发后的消息为::attribute的长度需为10个字节
$message
字段定义:
格式化格式 | 说明 |
---|---|
%% | 返回一个百分号 % |
%b | 二进制数 |
%c | ASCII 值对应的字符 |
%d | 包含正负号的十进制数(负数、0、正数) |
%e | 使用小写的科学计数法(例如 1.2e+2) |
%E | 使用大写的科学计数法(例如 1.2E+2) |
%u | 不包含正负号的十进制数(大于等于 0) |
%f | 浮点数(本地设置) |
%F | 浮点数(非本地设置) |
%g | 较短的 %e 和 %f |
%G | 较短的 %E 和 %f |
%o | 八进制数 |
%s | 字符串 |
%x | 十六进制数(小写字母) |
%X | 十六进制数(大写字母) |
附加的格式值。必需放置在 % 和字母之间(例如 %.2f):
\+
(在数字前面加上 + 或 - 来定义数字的正负性。默认情况下,只有负数才做标记,正数不做标记)'
(规定使用什么作为填充,默认是空格。它必须与宽度指定器一起使用。例如:%'x20s(使用 "x" 作为填充))\-
(左调整变量值)[0-9]
(规定变量值的最小宽度).[0-9]
(规定小数位数或最大字符串长度)
注意
如果使用多个上述的格式值,$messageParam
的参数必须按照上面的顺序进行使用,不能打乱。
关于错误消息的更多支持请查看自定义错误消息
使用扩展
extend 扩展方法
注册自定义的验证规则的另一种方法是使用Validate
中的 extend
方法。让我们在验证器中使用这个方法来注册自定义验证规则:
public function __construct()
{
self::extend("check_admin",function($attribute, $value, $parameters, $validator){
return $value === "owner";
});
}
自定义的验证闭包接收四个参数:要被验证的属性名称 $attribute
、属性的值 $value
、传入验证规则的参数数组 $parameters
、以及 Validator
实例。 除了使用闭包,你也可以传入类和方法到extend
方法中:
Validate::extend("check_admin","permissionValidate@checkAdmin");
请注意
传入类和方法需要指定方法为public
类型,类要传入完整的命名空间,如果你的方法为静态方法,还可以通过数组形式进行传入[完整类名,方法名],如方法名没有传,则默认方法名为validate
使用类方法
自定义规则也支持直接使用当前验证器类下的方法,规则为rule
+ 规则名,如ruleCheckLogin
请注意
这里的checkLogin
和当前验证器下的其他方法注册的规则名不能重复,否则会覆盖
自定义规则方法类方法接收四个参数:要被验证的属性名称 $attribute
、属性的值 $value
、传入验证规则的参数数组 $parameters
、以及 Validator
实例。
class LoginValidate extends Validate
{
protected $rule = [
'user' => 'required|alphaNum|checkLogin'
];
protected $message = [
'user.checkLogin' => '登录失败'
];
public function ruleCheckLogin($attribute, $value, $parameters, $validator): bool
{
return 'admin' === $value;
}
}
replacer 错误信息替换器
如果需要定义错误消息,可以在extend
的第三个参数中填入,或通过replacer
方法进行定义 replacer
方法接受两个参数ruleName
和一个闭包参数,闭包接受四个参数:错误消息$message
, 被验证的属性名称$attribute
, 当前的规则名称$rule
,传入验证规则的参数数组$parameters
Validate::replacer("check_admin",function($message,$attribute,$rule,$parameters){
return "自定义错误消息"
});
除了使用闭包以外,也支持传入类和方法到replacer
方法中
Validate::replacer("check_admin","permissionValidate@checkAdminMessage");
请注意
传入类和方法需要指定方法为public
类型,类要传入完整的命名空间,不支持数组传递,如方法名没有传,则默认方法名为replace
可以覆盖默认规则的自定义消息,如果要定义自定义方法的错误消息,一定要先定义错误规则extend
,再定义错误消息replacer
使用方式同使用规则对象
protected $rule = [
'title' => 'required|chs|check_admin',
];
extendImplicit 隐式扩展
默认情况下,当所要验证的属性不存在或包含一个空字符串时,使用包含自定义扩展的正常的验证规则是不会执行的。例如,unique
规则将不会检验空字符串:
$rules = ['name' => 'unique:users,name'];
$input = ['name' => ''];
// 验证通过
如果即使属性为空也要验证规则,则一定要暗示属性是必须的。要创建这样一个「隐式」扩展,可以使用 Validate
中的extendImplicit()
方法:
Validate::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
ImplicitRule 隐式规则对象
如果你想要在属性为空时执行规则对象,你应该实现 Illuminate\Contracts\Validation\ImplicitRule
接口。这个接口将充当验证器的「标记接口」;因此,它不包含你要实现的任何方法。
extendDependent 依赖性验证器
如果想定义一个自定义扩展对数组进行验证时,我们会发现extend
和extendImplicit
均不会解析*
,这个时候就需要用到Validate
中的extendDependent
方法:
Validate::extendDependent('contains', function ($attribute, $value, $parameters, $validator) {
// 下面验证器传来的$parameters是['*.provider'],当我们暗示这个自定义规则是依赖性的时候
// 验证器往往会按照我们要验证的原始属性,用当前的指数替换星号,所以*.provider会被替换成0.provider
// 现在我们可以使用Arr:get()来获取其他字段的值。
// 所以这个自定义规则验证了属性值包含了其他给定属性的值。
return str_contains($value,Arr::get($validator->getData(),$parameters[0]));
});
$v = new Validate($request);
$v->setRules([
'*.email' => 'contains:*.provider'
])->check([
[
'email' => '995645888@qq.com', 'provider' => 'qq.com'
]
]);
正则表达式规则
支持直接使用正则验证,例如:
'id' => 'regex:/^\d+$/',
如果你的正则表达式中包含有|
符号的话,必须使用数组方式定义。
'id' => ['regex:/^\d+$/']
也可以实现预定义正则表达式后直接调用,例如在验证器类中定义regex
属性,然后在规则中使用regex:
+ 正则名称
class Test extends \W7\Validate\Validate
{
protected $regex = [
'number' => '/^\d+$/'
];
protected $rule = [
'id' => 'regex:number'
];
}