在验证前后需要对数据进行一些处理,比如:格式化数值,设置默认值等,验证完毕后对数据进行加密,解密,格式化等操作,这时候就可以使用数据处理器来实现。
使用
操作值
在数据处理器定义数组中,第一个值为操作值
,可以是一个具体的值mixed, 也可以为一个方法名称callable,还可以是一个 类方法string, 闭包Closure, 处理器类ProcessorInterface等。
如果你想指定操作值
的类型,请使用 ProcessorValueType 常量,否则默认为 ProcessorValueType::AUTO
。
通过类属性
为验证器定义前置处理器的属性为 $preprocessor
,定义后置处理器的属性为 $postprocessor
。
以下是一个简单的示例:
use Itwmw\Validate\Support\Processor\ProcessorExecCond;
use Itwmw\Validate\Support\Processor\ProcessorOptions;
use Itwmw\Validate\Support\Processor\ProcessorParams;
use Itwmw\Validate\Validate;
class Test extends Validate
{
protected $rule = [
'name' => 'nullable|string',
];
protected $preprocessor = [
'name' => ['默认名称', ProcessorExecCond::WHEN_EMPTY]
];
protected $postprocessor = [
'name' => ['trim', ProcessorParams::Value]
];
}
以上代码的含义为:在验证之前,当 name
字段为空时,将其设置为默认名称
,当验证完毕后,将 name
字段的值进行 trim 操作,并传递验证值作为参数。关于可选参数, 可以查看数据处理器的参数
执行时机
处理器默认任何时候都会执行,如果不想执行,可以使用ProcessorExecCond::WHEN_NOT_EMPTY
或ProcessorExecCond::WHEN_EMPTY
来指定执行时机。
使用多个处理器
可以通过为给处理器提供一个ProcessorOptions::MULTIPLE
来声明定义多个处理器,如:
use Itwmw\Validate\Support\Processor\ProcessorExecCond;
use Itwmw\Validate\Support\Processor\ProcessorOptions;
use Itwmw\Validate\Support\Processor\ProcessorParams;
use Itwmw\Validate\Validate;
class Test extends Validate
{
protected $rule = [
'name' => 'nullable|string',
];
protected $preprocessor = [
'name' => [
ProcessorOptions::MULTIPLE,
['默认名称', ProcessorExecCond::WHEN_EMPTY],
['trim', ProcessorParams::Value],
]
];
}
以上代码的含义为:使用 ProcessorOptions::MULTIPLE
声明,定义了多个处理器, 在验证之前,当 name
字段为空时,将其设置为默认名称
,然后将 name
字段的值进行 trim 操作,并传递验证值作为参数。
传递参数
如果需要为处理器传递参数,除了使用 ProcessorParams 以外,还可以直接传递参数,如:
class Test extends Validate
{
protected $rule = [
'id' => 'required|string'
];
protected $postprocessor = [
'id' => [
ProcessorOptions::MULTIPLE,
['explode', ',', ProcessorParams::Value],
['array_map', 'intval', ProcessorParams::Value],
],
];
}
$data = Test::make()->check([
'id' => '1,2,3,4,5'
]);
var_dump($data);
输出:
array(1) {
["id"]=>
array(5) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
}
}
通过验证场景
如需在验证场景中使用数据处理器,可以需要验证场景类的 preprocessor 和 postprocessor 方法,如:
class Test extends Validate
{
protected $rule = [
'name' => 'nullable|string',
];
protected function sceneSave(ValidateScene $scene): void
{
$scene->only(true)
->preprocessor('name', '默认名称', ProcessorExecCond::WHEN_EMPTY)
->postprocessor('name', 'trim', ProcessorParams::Value);
}
}
$data = Test::make()->scene('save')->check([]);
var_dump($data);
//array(1) {
// ["name"]=>
// string(12) "默认名称"
//}
$data = Test::make()->check([]);
var_dump($data);
//array(0) {
//}
在上述示例代码中,场景 save
中定义了一个前置处理器,当验证值为空时,将其设置为默认名称
, 并且定义了一个后置处理器,将 name
字段的值进行 trim 操作,并传递验证值作为参数。
定义
数据处理器支持以下几种定义方式:
- 直接使用标量
- 使用函数名称
- 使用当前类下的处理器方法名
- 实现了
ProcessorInterface
接口的类或者完整类名 - 在验证场景中使用闭包方法
闭包
在验证场景中,可以直接传递一个闭包作为处理器方法,如:
class Test extends Validate
{
protected $rule = [
'name' => 'nullable|string',
];
protected function sceneSave(ValidateScene $scene): void
{
$scene->only(true)
->preprocessor('name', function (mixed $value, string $attribute, array $data) {
if (empty($value)) {
return '默认名称';
}
return $value;
}, ProcessorParams::Value, ProcessorParams::Attribute, ProcessorParams::OriginalData);
}
}
$data = Test::make()->scene('save')->check([]);
var_dump($data);
//array(1) {
// ["name"]=>
// string(12) "默认名称"
//}
参数顺序
处理器获取的参数顺序和定义的参数顺序一致,如果需要获取其他参数,可以使用 ProcessorParams
中的常量来获取。
类方法
在当前类中定义一个方法,然后将方法名作为处理器,方法名的定义规则为:首字母小写的方法名 + Processor
,如:
class Test extends Validate
{
protected $rule = [
'name' => 'nullable|string',
];
protected $preprocessor = [
'name' => 'setDefaultName',
];
protected function setDefaultNameProcessor(mixed $value)
{
return empty($value) ? '默认名称' : $value;
}
}
$data = Test::make()->check([]);
var_dump($data);
//array(1) {
// ["name"]=>
// string(12) "默认名称"
//}
未指定参数
如果没有指定参数,那么默认按序传递 ProcessorParams::Value
, ProcessorParams::Attribute
, ProcessorParams::OriginalData
, ProcessorParams::DataAttribute
四个参数
处理器类
定义处理器类,需要实现 Itwmw\Validate\Support\Concerns\ProcessorInterface
接口,然后直接使用,无需指定参数。
定义一个处理器类:
class RemoveScriptProcessor implements ProcessorInterface
{
public function handle($value, string $attribute, array $originalData)
{
// 处理script demo,仅供展示
$value = preg_replace('/<script.*?>.*?<\/script>/si', '', $value);
return strip_tags($value);
}
}
使用处理器类:
class Test extends Validate
{
protected $rule = [
'name' => 'nullable|string',
];
protected $postprocessor = [
'name' => RemoveScriptProcessor::class,
];
}
$data = Test::make()->check([
'name' => '<script>alert(1)</script>名称'
]);
var_dump($data);
//array(1) {
// ["name"]=>
// string(6) "名称"
//}
处理器参数
处理器类可以在构造函数中接受参数,如:
class RemoveScriptProcessor implements ProcessorInterface
{
protected array $allowTags;
public function __construct(string $allowTags = '')
{
$this->allowTags = explode(',', $allowTags);
}
public function handle($value, string $attribute, array $originalData)
{
// 处理script demo,仅供展示
$value = preg_replace('/<script.*?>.*?<\/script>/si', '', $value);
return strip_tags($value, $this->allowTags);
}
}
数据处理器的参数
ProcessorValueType
指定操作值类型,如不指定,则默认为AUTO
:
ProcessorValueType::FUNCTION
表明这是一个函数,闭包ProcessorValueType::METHOD
表明这是一个类方法ProcessorValueType::VALUE
表明这是一个固定值ProcessorValueType::AUTO
表明需要程序自行推导
ProcessorExecCond
数据处理器的执行时机,多个可组合使用:
ProcessorOptions::WHEN_NOT_EMPTY
当字段不为空时执行ProcessorOptions::WHEN_EMPTY
当字段为空时执行ProcessorOptions::WHEN_NOT_EXIST
当字段不存在时执行ProcessorOptions::WHEN_EXIST
当字段存在时执行ProcessorOptions::ALWAYS
总是执行,默认行为
ProcessorParams
数据处理器的参数来源
ProcessorParams::Value
使用字段的值作为参数ProcessorParams::Attribute
使用字段的键作为参数ProcessorParams::OriginalData
使用原始数据作为参数ProcessorParams::DataAttribute
提供一个DataAttribute
类作为参数
ProcessorOptions
数据处理器的可选参数
ProcessorOptions::MULTIPLE
为同一个字段添加多个处理器时使用