New conditional validator
froschdesign opened this issue Β· 4 comments
The idea is to add a new validator that executes a validator when a rule is met.
Example
$validator = new Laminas\Validator\ConditionalValidator(
[
'validator' => [
'name' => Laminas\Validator\NotEmpty::class,
],
'rule' => static function (array $context) {
return (bool) ($context['confirm'] ?? false);
},
]
);
$data = [
'registration' => 'foo',
'confirm' => '1',
];
var_dump($validator->isValid($data['registration'], $data)); // true
$data = [
'registration' => '',
'confirm' => '1',
];
var_dump($validator->isValid($data['registration'], $data)); // false
$data = [
'registration' => '',
'confirm' => '',
];
var_dump($validator->isValid($data['registration'], $data)); // true
Implementation
The validator needs the plugin manager and a solution to allow a chain of validators, for example a third option β validators
next to validator
:
$validator = new Laminas\Validator\ConditionalValidator(
[
'validators' => [
[
'name' => Laminas\Validator\StringLength::class,
'options' => [
'min' => 3,
'max' => 255,
],
],
[
'name' => Laminas\I18n\Validator\Alnum::class,
],
],
'rule' => static function (array $context) {
return (bool) ($context['confirm'] ?? false);
},
]
);
Reference
https://book.cakephp.org/5/en/core-libraries/validation.html#conditional-validation
Nice addition for v3 π
@gsteel
Looks like we need the following logic from laminas-inputfilter then also here:
protected function populateValidators(ValidatorChain $chain, $validators)
{
foreach ($validators as $validator) {
if ($validator instanceof ValidatorInterface) {
$chain->attach($validator);
continue;
}
/** @psalm-suppress RedundantConditionGivenDocblockType */
if (is_array($validator)) {
if (! isset($validator['name'])) {
throw new Exception\RuntimeException(
'Invalid validator specification provided; does not include "name" key'
);
}
$name = $validator['name'];
$options = [];
if (isset($validator['options'])) {
$options = $validator['options'];
}
$breakChainOnFailure = false;
if (isset($validator['break_chain_on_failure'])) {
$breakChainOnFailure = $validator['break_chain_on_failure'];
}
$priority = $validator['priority'] ?? ValidatorChain::DEFAULT_PRIORITY;
$chain->attachByName($name, $options, $breakChainOnFailure, $priority);
continue;
}
throw new Exception\RuntimeException(
'Invalid validator specification provided; was neither a validator instance nor an array specification'
);
}
}
Should we create a factory for the validator chain in this package and then used in laminas-inputfilter?
Yes⦠Perhaps a ValidatorChainFactory
defined here would be better than having all the internals of ValidatorChain considered in inputfilter
.
@gsteel
It wasn't the plan for you to take over the implementation, but thank you very much! ππ» π