phpzend-framework2zend-inputfilter

ZF2 : Filedset validation is not working


My ZF2 Form Field set validation is not working but form validation is working I have tried same a form validation, but these are not working.

I have implemented InputFilterProviderInterface in field set but it is not working.

Below is my code:

class CompanyCreditLimitFieldset extends Fieldset implements InputFilterProviderInterface {

    protected $_curency = null;
    protected $inputFilter;

    public function __construct($name = null, $options = array()) {
        $this
                ->setHydrator(new ClassMethodsHydrator(false))
                ->setObject(new \Application\Entity\PhvCompanyCurrencyCredit())
        ;

        parent::__construct($name, $options);



        $this->add(array(
            'name' => 'credit_limit',
            'type' => 'text',
            'attributes' => array(
                'id' => 'credit_limit',
                'class' => 'form-control maxlength-simple credit_limit',
                'placeholder' => 'Credit Limit'
            ),
            'options' => array(
                'label' => 'Credit Limit',
            )
        ));

        $this->add(array(
            'name' => 'mininum_balance_limit',
            'type' => 'text',
            'attributes' => array(
                'id' => 'mininum_balance_limit',
                'class' => 'form-control maxlength-simple mininum_balance_limit',
                'placeholder' => 'Minimum Balance Limit'
            ),
            'options' => array(
                'label' => 'Minimum Balance Limit',
            )
        ));
    }


    public function getInputFilterSpecification() {
        return array(
            'credit_limit' => array(
                'filters' => array(
                    array('name' => 'StringTrim')
                ),
                'validators' => array(
                    array('name' => 'NotEmpty')
                )
            ),
            'mininum_balance_limit' => array(
                'filters' => array(
                    array('name' => 'StringTrim')
                ),
                'validators' => array(
                    array('name' => 'NotEmpty')
                )
            ),

        );
    }

}

Form

class AddCompanyForm extends AbstractForm implements InputFilterAwareInterface {

    protected $inputFilter;
    protected $dbAdapter;
    private $_country = null;

    public function __construct($id = null, $name = null) {
        $this->entity = new \Application\Entity\PhvCompany();
        parent::__construct($name);

        $this
                ->setHydrator(new ClassMethodsHydrator(false))
                ->setObject(new \Application\Entity\PhvCompany())
        ;

        $this->__addElements();
    }

    private function __addElements() {
        $this->setAttribute('method', 'post');

        $this->add(array(
            'type' => 'Zend\Form\Element\Collection',
            'name' => 'creditlimitfieldset',
            'options' => array(
                'label' => 'Credit Limits',
                'count' => 3,
                'allow_add' => true,
                'should_create_template' => true,
                'template_placeholder' => '__placeholder__',
                'target_element' => array(
                'type' => 'Application\Form\Fieldset\CompanyCreditLimitFieldset',
                ),
            ),
//             'type' => 'Application\Form\Fieldset\CompanyCreditLimitFieldset',
//             'options' => array('label' => 'Credit Limits',)
        ));


        $this->add(array(
            'name' => 'submit',
            'attributes' => array(
                'type' => 'submit',
                'value' => 'Save',
                'class' => 'btn btn-inline btn-secondary btn-rounded'
            )
        ));




    }

    public function setDbAdapter($dbAdapter) {
        $this->dbAdapter = $dbAdapter;
    }

    public function setInputFilter(InputFilterInterface $inputFilter) {
        throw new \Exception("Not used");
    }

}

Can you please help me to solve this issue.


Solution

  • Frankly, this type of problem is why I always build a separate InputFilter hierarchy matching the Form structure instead of relying on ZF's "magic" input filter builder. Here's a great article on how to do that:

    When working with collections in this manner you'll need to add a CollectionInputFilter to the form's input filter for each Collection form element. That class is completely undocumented IIRC, but you can find an example here and the class here.


    I wrote a short script that reproduces what you're seeing:

    <?php
    <<<CONFIG
    packages:
        - "zendframework/zend-form: ^2.0"
        - "zendframework/zend-servicemanager: ^3.0"
        - "zendframework/zend-hydrator: ^2.0"
    CONFIG;
    // Run this script with Melody: http://melody.sensiolabs.org/
    
    
    use Zend\Form\Fieldset;
    use Zend\InputFilter\InputFilterProviderInterface;
    use Zend\Form\Form;
    
    class ChildFieldset extends Fieldset implements InputFilterProviderInterface
    {
        public function __construct($name = null, $options = array())
        {
        parent::__construct($name, $options);
    
        $this->add(array(
            'name' => 'fieldA',
            'type' => 'text',
            'attributes' => array(
                'id' => 'fieldA',
            ),
            'options' => array(
                'label' => 'Field A',
            )
        ));
        }
    
        public function getInputFilterSpecification()
        {
        return array(
            'fieldA' => array(
                'required'          => true,
                'allow_empty'       => false,
                'continue_if_empty' => false,
                'filters' => array(
                    array('name' => 'StringTrim')
                ),
                'validators' => array(
                    array('name' => 'NotEmpty')
                )
            ),
        );
        }
    }
    
    class ParentForm extends Form
    {
        public function __construct($name, array $options)
        {
        parent::__construct($name, $options);
    
        $this->add(array(
            'type' => 'Zend\Form\Element\Collection',
            'name' => 'childForms',
            'options' => array(
                'label' => 'Child Forms',
                'allow_add' => true,
                'should_create_template' => true,
                'template_placeholder' => '__placeholder__',
                'target_element' => array(
                    'type' => 'ChildFieldset',
                ),
            ),
        ));
    
        $this->add(array(
            'name' => 'submit',
            'attributes' => array(
                'type' => 'submit',
                'value' => 'Save',
            )
        ));
        }
    }
    
    $form = new ParentForm('foo', []);
    
    $data = [];
    $form->setData($data);
    echo "Dataset: " . print_r($data, true) . "\n";
    echo "Result: " . ($form->isValid() ? 'valid' : 'invalid');
    echo "\n\n--------------------------------------\n\n";
    
    
    $data = [
        'childForms' => []
    ];
    $form->setData($data);
    echo "Dataset: " . print_r($data, true) . "\n";
    echo "Result: " . ($form->isValid() ? 'valid' : 'invalid');
    echo "\n\n--------------------------------------\n\n";
    
    
    $data = [
        'childForms' => [
        ['fieldA' => ''],
        ],
    ];
    $form->setData($data);
    echo "Dataset: " . print_r($data, true) . "\n";
    echo "Result: " . ($form->isValid() ? 'valid' : 'invalid') . "\n\n";
    echo "\n\n--------------------------------------\n\n";
    
    
    $data = [
        'childForms' => [
        ['fieldA' => 'fff'],
        ],
    ];
    $form->setData($data);
    echo "Dataset: " . print_r($data, true) . "\n";
    echo "Result: " . ($form->isValid() ? 'valid' : 'invalid') . "\n\n";
    

    and when I run it (PHP 7.0.9) I get this:

    Dataset: Array
    (
    )
    
    Result: valid
    (wrong)
    
    --------------------------------------
    
    Dataset: Array
    (
        [childForms] => Array
        (
        )
    
    )
    
    Result: valid
    (wrong)
    
    --------------------------------------
    
    Dataset: Array
    (
        [childForms] => Array
        (
            [0] => Array
                (
                    [fieldA] => 
                )
    
        )
    
    )
    
    Result: invalid
    (correct!)
    
    
    --------------------------------------
    
    Dataset: Array
    (
        [childForms] => Array
        (
            [0] => Array
                (
                    [fieldA] => fff
                )
    
        )
    
    )
    
    Result: valid
    (correct!)
    

    The input filter on the child fieldset is only triggered when the full hierarchy of keys exist in the data. It's not a bug per se, but it's not what you expect to happen.