在验证前后需要对数据进行一些处理,比如:格式化数值,设置默认值等,验证完毕后对数据进行加密,解密,格式化等操作,这时候就可以使用数据处理器来实现。

使用

通过类属性

为验证器定义前置处理器的属性为 $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_EMPTYProcessorExecCond::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在新窗口打开 操作,并传递验证值作为参数。

通过验证场景

如需在验证场景中使用数据处理器,可以需要验证场景类preprocessorpostprocessor 方法,如:

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) "名称"
//}

数据处理器的参数

  • ProcessorExecCond 为数据处理器的执行时机,有三个值
    • ProcessorOptions::WHEN_NOT_EMPTY 当字段不为空时执行
    • ProcessorOptions::WHEN_EMPTY 当字段为空时执行
    • ProcessorOptions::ALWAYS 总是执行,默认行为
  • ProcessorParams 为数据处理器的参数来源,有四个值
    • ProcessorParams::Value 使用字段的值作为参数
    • ProcessorParams::Attribute 使用字段的键作为参数
    • ProcessorParams::OriginalData 使用原始数据作为参数
    • ProcessorParams::DataAttribute 提供一个DataAttribute类作为参数
  • ProcessorOptions 为数据处理器的可选参数,有两个值
    • ProcessorOptions::MULTIPLE 为同一个字段添加多个处理器时使用
    • ProcessorOptions::VALUE_IS_ARRAY 当值为一个数组时使用,添加此选项后,验证器会将除了ProcessorExecCond以外的参数传入处理器中,如果不添加此选项,验证器会将第一个值作为参数传入处理器中