valitron icon indicating copy to clipboard operation
valitron copied to clipboard

Implement OneOf logic

Open magicaljyy opened this issue 7 years ago • 2 comments

Hello I think it will be useful to have a feature where you can validate if one the rules is satisfied instead always validate if all rules are satisfied.

magicaljyy avatar Jun 12 '17 19:06 magicaljyy

I'm having a hard time coming up with a practical example of this use-case, to be honest. Can you provide me with some (pseudo-)code or explain in a bit more detail what you're trying to do?

willemwollebrants avatar Jun 22 '17 18:06 willemwollebrants

I think this is roughly they meant:

func validateOneOf(value, rules):
    for rules as rule:
        if rule.check(value):
            return true
        endif
    endfor
    return false
endfunc

Essentially another rule where multiple rules can be specified, and if any one of them is correct the field will be considered valid.

If this is what you want to do @magicaljyy, you can create a custom rule which evaluates all of these yourself:

Valitron\Validator::addRule('oneOf', function($field, $value, array $params, array $fields) {

    $data = ['value' => $value];

    foreach( $params as $param ){

        $v = new Valitron\Validator($data);

        $rule_name = array_shift($param);

        $rules = [
            $rule_name => [array_merge(['value'], $param)]
        ];

        $v->rules($rules);

        if($v->validate()) {
            return true;
        } 

    }

    return false;

}, 'Error messages are going to be a pain for this one.');

Working example here.

In most cases this is not an optimal solution, it's messy and just not nice to play with. I'd suggest you make a custom rule, eg 'integerOrBoolean', and make another instance Valitron inside of that rule.

Oh - this won't play nicely with the 'required' and 'optional' rules.

ducsuus avatar Jul 16 '17 19:07 ducsuus