Before and after validation, you may need to perform some operations on the data, such as formatting values, setting default values, encrypting, decrypting, or formatting data after validation. In these cases, you can use a data processor to accomplish these tasks.
Usage
Operation Value
In the data processor definition array, the first value is the operation value. It can be a specific valuemixed, a method namecallable, a class method string, a closureClosure, or a processor classProcessorInterface.
If you want to specify the type of the operation value, use the ProcessorValueType constant. Otherwise, the default is ProcessorValueType::AUTO.
In Class Properties
To define a preprocessor for a validator, set the $preprocessor property. To define a postprocessor, set the $postprocessor property.
Here's a simple example:
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' => ['Default Name', ProcessorExecCond::WHEN_EMPTY]
];
protected $postprocessor = [
'name' => ['trim', ProcessorParams::Value]
];
}
The code above means that before validation, if the name field is empty, it will be set to a default value of Default Name. After validation, the value of the name field will be trimmed using the trim function and the trimmed value will be passed as a parameter. For more information on optional parameters, please refer to the Data Processor Parameters section.
Execution Timing
By default, data processors will execute at all times. If you don't want a data processor to execute, you can use ProcessorExecCond::WHEN_NOT_EMPTY or ProcessorExecCond::WHEN_EMPTY to specify when the processor should execute.
Usage Multiple Processors
You can define multiple processors for a field by providing the ProcessorOptions::MULTIPLE option. For example:
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,
['Default Name', ProcessorExecCond::WHEN_EMPTY],
['trim', ProcessorParams::Value],
]
];
}
The code above means that multiple data processors have been defined by using ProcessorOptions::MULTIPLE. Before validation, if the name field is empty, it will be set to a default value of Default Name. Then, the value of the name field will be trimmed using the trim function, and the trimmed value will be passed as a parameter for further processing.
Passing Parameters
If you need to pass parameters to the processor, in addition to using ProcessorParams, you can also pass parameters directly, like this:
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);
Output:
array(1) {
["id"]=>
array(5) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
}
}
In Validation Scenes
If you want to use data processors with validation scenes, you can use the preprocessor and postprocessor methods of the validation scene class, for example:
class Test extends Validate
{
protected $rule = [
'name' => 'nullable|string',
];
protected function sceneSave(ValidateScene $scene): void
{
$scene->only(true)
->preprocessor('name', 'Default Name', ProcessorExecCond::WHEN_EMPTY)
->postprocessor('name', 'trim', ProcessorParams::Value);
}
}
$data = Test::make()->scene('save')->check([]);
var_dump($data);
//array(1) {
// ["name"]=>
// string(12) "Default Name"
//}
$data = Test::make()->check([]);
var_dump($data);
//array(0) {
//}
In the example code above, a preprocessor has been defined in the save scene that sets the value of the name field to a default value of Default Name if it is empty. Additionally, a postprocessor has been defined that trims the value of the name field using the trim function and passes the validated value as a parameter.
Definition
Data processors can be defined in several ways:
- Using a scalar value
- Using a function name
- Using a method name in the current class
- Using a class that implements the
ProcessorInterfaceinterface or its fully qualified name - Using a closure in a validation scene
Closure
In a validation scene, a closure can be directly passed as the processor method, like so:
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 'Default Name';
}
return $value;
}, ProcessorParams::Value, ProcessorParams::Attribute, ProcessorParams::OriginalData);
}
}
$data = Test::make()->scene('save')->check([]);
var_dump($data);
//array(1) {
// ["name"]=>
// string(12) "Default Name"
//}
Parameter Order
The order of the parameters passed to the processor is the same as the order in which they are defined. If additional parameters are needed, the constants in ProcessorParams can be used to obtain them.
Class Method
A method can be defined in the current class, and its name can be used as the processor method. The method name should follow this convention: lowercase method name + Processor, for example:
class Test extends Validate
{
protected $rule = [
'name' => 'nullable|string',
];
protected $preprocessor = [
'name' => 'setDefaultName',
];
protected function setDefaultNameProcessor(mixed $value)
{
return empty($value) ? 'Default Name' : $value;
}
}
$data = Test::make()->check([]);
var_dump($data);
//array(1) {
// ["name"]=>
// string(12) "Default Name"
//}
Unspecified Parameters
If no parameters are specified, the default order in which they are passed is: ProcessorParams::Value, ProcessorParams::Attribute, ProcessorParams::OriginalData, ProcessorParams::DataAttribute.
Processor Class
To define a processor class, implement the Itwmw\Validate\Support\Concerns\ProcessorInterface interface and use the class directly without specifying any parameters.
Here's an example of a processor class:
class RemoveScriptProcessor implements ProcessorInterface
{
public function handle($value, string $attribute, array $originalData)
{
// This is a demo for remove scripts, for display purposes only
$value = preg_replace('/<script.*?>.*?<\/script>/si', '', $value);
return strip_tags($value);
}
}
Using Processor Classes:
class Test extends Validate
{
protected $rule = [
'name' => 'nullable|string',
];
protected $postprocessor = [
'name' => RemoveScriptProcessor::class,
];
}
$data = Test::make()->check([
'name' => '<script>alert(1)</script>Name'
]);
var_dump($data);
//array(1) {
// ["name"]=>
// string(6) "Name"
//}
Processor Parameters
The processor class can accept parameters in its constructor, for example:
class RemoveScriptProcessor implements ProcessorInterface
{
protected array $allowTags;
public function __construct(string $allowTags = '')
{
$this->allowTags = explode(',', $allowTags);
}
public function handle($value, string $attribute, array $originalData)
{
// This is a demo for remove scripts, for display purposes only
$value = preg_replace('/<script.*?>.*?<\/script>/si', '', $value);
return strip_tags($value, $this->allowTags);
}
}
Data Processor Parameters
ProcessorValueType
Specifies the type of the operation value. If not specified, the default is AUTO:
ProcessorValueType::FUNCTIONindicates a function or closure.ProcessorValueType::METHODindicates a class method.ProcessorValueType::VALUEindicates a fixed value.ProcessorValueType::AUTOindicates that the type will be inferred automatically.
ProcessorExecCond
Execution conditions for the data processor, which can be combined:
ProcessorOptions::WHEN_NOT_EMPTYExecutes when the field is not empty.ProcessorOptions::WHEN_EMPTYExecutes when the field is empty.ProcessorOptions::WHEN_NOT_EXISTExecutes when the field does not exist.ProcessorOptions::WHEN_EXISTExecutes when the field exists.ProcessorOptions::ALWAYSAlways executes, which is the default behavior.
ProcessorParams
The source of parameters for the data processor:
ProcessorParams::ValueUses the value of the field as a parameter.ProcessorParams::AttributeUses the key of the field as a parameter.ProcessorParams::OriginalDataUses the original data as a parameter.ProcessorParams::DataAttributeProvides aDataAttributeclass as a parameter.
ProcessorOptions
Optional parameters for the data processor:
ProcessorOptions::MULTIPLEUsed when adding multiple processors to the same field.
