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
ProcessorInterface
interface 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::FUNCTION
indicates a function or closure.ProcessorValueType::METHOD
indicates a class method.ProcessorValueType::VALUE
indicates a fixed value.ProcessorValueType::AUTO
indicates that the type will be inferred automatically.
ProcessorExecCond
Execution conditions for the data processor, which can be combined:
ProcessorOptions::WHEN_NOT_EMPTY
Executes when the field is not empty.ProcessorOptions::WHEN_EMPTY
Executes when the field is empty.ProcessorOptions::WHEN_NOT_EXIST
Executes when the field does not exist.ProcessorOptions::WHEN_EXIST
Executes when the field exists.ProcessorOptions::ALWAYS
Always executes, which is the default behavior.
ProcessorParams
The source of parameters for the data processor:
ProcessorParams::Value
Uses the value of the field as a parameter.ProcessorParams::Attribute
Uses the key of the field as a parameter.ProcessorParams::OriginalData
Uses the original data as a parameter.ProcessorParams::DataAttribute
Provides aDataAttribute
class as a parameter.
ProcessorOptions
Optional parameters for the data processor:
ProcessorOptions::MULTIPLE
Used when adding multiple processors to the same field.