zf2/zf3 how to validate dependent inputs in collec

2019-03-04 01:04发布

问题:

I have a form. The form has a Collection whose target element is a fieldset with a checkbox and a couple of text fields. The fieldset attached as the target element to Collection looks like this (simplified to avoid too much code):

class AFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function __construct(HydratorInterface $hydrator) 
    {
        parent::__construct();

        $this->setHydrator($hydrator)
            ->setObject(new SomeObject());

        $this->add([
            'type' => Hidden::class,
            'name' => 'id',
        ]);

        $this->add([
            'type' => Checkbox::class,
            'name' => 'selectedInForm',
        ]);

        $this->add([
            'type' => Text::class,
            'name' => 'textField1',
        ]);

        $this->add([
            'type' => Text::class,
            'name' => 'textField2',
        ]);
    }
    public function getInputFilterSpecification()
    {
        return [
            'selectedInForm' => [
                'required' => false,
                'continue_if_empty' => true,
                'validators' => [
                    ['name' => Callback::class // + options for the validator],
                ],
            ],
            'id' => [
                'requred' => false,
                'continue_if_empty' => true,
            ],
            'textField1' => [
                'required' => false,
                'continue_if_empty' => true,
                'validators' => [
                    ['name' => SomeValidator::class],
                ],
            ],
            'textField2' => [
                'required' => true,
                'validators' => [
                    ['name' => SomeValidator::class],
                ],
            ],
        ],
    }
}

I'd like to validate textField1 and textField2 based on if selectedInForm checkbox is checked in the form.

How could I do this?

I though of using a Callback validator for selectedInForm checkbox like this:

'callback' => function($value) {
    if ($value) {
        $this->get('textField1')->isValid();
        // or $this->get('textField1')->getValue() and do some validation with it
    }
}

but the problem with it is that, for some reason, the posted value of textField1 value isn't attached to the input yet. Same is true for textField2.

回答1:

Two option is available. One is where you started, with callback validators.

The other one is to write a custom validator, and to make it reusable I recommend this solution.

<?php

use Zend\Validator\NotEmpty;

class IfSelectedInFormThanNotEmpty extends NotEmpty
{
    public function isValid($value, array $context = null): bool
    {
        if (! empty($context['selectedInForm']) && $context['selectedInForm']) {
            return parent::isValid($value);
        }
        return true;
    }
}

And then you can use it as every other validator:

'textField2' => [
    'required' => true,
    'validators' => [
        ['name' => IfSelectedInFormThanNotEmpty::class],
    ],
],

This may not be your exact case, but I hope it helped to get the idea.

You may define options to make it more reusable with a configurable conditional field in public function __construct($options = null).