1

There is a class Item. It has an attribute type, that can be a, b, or c. For all the types there is a common minimal set of attributes / input fields: type and other ones. Every type has some further attributes:

default set of the common fields
  type
  ...
additional fields in case of type=a
  foo
additional fields in case of type=b
  bar
  baz
additional fields in case of type=c
  bar
  baz
  buz

Furthermore the validation rules for bar and bar are slightly different for the cases type=b and type=c.

How to set up the validation in a ZF2/Apigilty application depending on the value of a field (or multiple fields)? For this concrete case: How to set up the validation depending on the type?


UPDATE

The attribute type is an independent one. That means -- it should not become invalid, if the set of the additional fields (foo, bar etc.) doesn't match to it. (It's required and gets validated agains an array of the allowed values, that's it.)

So, it should work in the opposite direction:

IF (type == 'a') {
    proper "required" and validation rules the additional fields
} ELSEIF (type == 'b') {
    proper "required" and validation rules the additional fields
} ELSEIF (type == 'c') {
    proper "required" and validation rules the additional fields
}
automatix
  • 14,018
  • 26
  • 105
  • 230

1 Answers1

0

You can write a ValidTypeInputFilter with your custom logic and attach a config that looks something similar like this:

array(
    'type' => array(
        'name' => 'type',
        'required' => true,
        'validators' => array(
            array(
                'name' => 'CustomTypeValidator'
            )
        )
    ),
    'qwer' => array(
        'name' => 'qwer',
        'required' => true,
        'filters' => array(
        )
        'validators' => array(
        )
    ),
    'asdf' => array(
        'name' => 'asdf',
        'required' => true,
        'filters' => array(
        )
        'validators' => array(
        )
    ),
    'yxcv' => array(
        'name' => 'yxcv',
        'required' => true,
        'filters' => array(
        )
        'validators' => array(
        )
    )
)

And your custom validator class:

<?php
namespace Application\Validator;

class CustomTypeValidator extends AbstractValidator{

    const INVALID_TYPE = 'invalid_type';    

    const NOT_ARRAY = 'not_an_array';    

    protected $messageTemplates = array(
        self::NOT_ARRAY => "Type must be an array",
        self::INVALID_TYPE => "Type must be a, b or c",
    );

    public function isValid($value)
    {
        $this->setValue($value);

        if (!is_array($value)) {
            $this->error(self::NOT_ARRAY);
            return false;
        }

        if(key($value) === 'a'){
            //... validate a
        }

        if(key($value) === 'b'){
            //... validate b
        }

        if(key($value) === 'c'){
            //... validate c
        }

        $this->error(self::INVALID_TYPE);
        return false;
    }
}

For validating a, b and c you can also write validator classes and instantiate and use them inside your custom type validator:

    if(key($value) === 'a'){
        $validator = new TypeAValidator():
        $valid = $validator->isValid($value['a']);
        return $valid;
    }
Wilt
  • 41,477
  • 12
  • 152
  • 203
  • Thank you for your answer! I'm yet not getting your example. Where do you want to validate the fields `foo`, `bar`, `baz`, and `buz` (that should have different rules dependent on the `type` value)? – automatix Sep 29 '15 at 08:45
  • Inside your custom validator `CustomTypeValidator`. There you can add all custom logic. You can read more in [the documentation](http://framework.zend.com/manual/current/en/modules/zend.validator.writing-validators.html) on how to create a custom validator. – Wilt Sep 29 '15 at 08:56
  • What might work, is a solution with [`\Zend\Validator\Callback`. But here it's a bit inconvenient: 1. It's not good (for the performance -- if we want to cache configs) to define callbacks in the `module.config.php`, so we have to define all the stuff as a class (or in the `Modle.php`). Well, it's not a big problem. But 2. We have to duplicate a lot of code: For each non-common / type dependent field (`foo`, `bar`, `baz`, `buz`) we need to write a callback with the same logic: `switch ($type) case "a": ... ; "b": ... ; "c": ... ;`. – automatix Sep 29 '15 at 09:03
  • @automatix I added more code to my answer. With this example you should be able to manage... – Wilt Sep 29 '15 at 09:07
  • We seem to misanderstand each other. Maybe my problem explanation is confusing. I've tried to correct it, please see the question **UPDATE**. – automatix Sep 29 '15 at 10:41