Empty values passed to Zend framework 2 validators

后端 未结 5 1978
滥情空心
滥情空心 2020-12-05 03:47

How can I pass an empty value through Zend framework 2 ValidatorChain to my custom validator?

It was possible on ZF1 by allowEmpty(false)

On ZF2

相关标签:
5条回答
  • 2020-12-05 04:00

    Following works for ZF2 version 2.1.1:

    The problem (if I got it correctly) is that in following example, for empty values of 'fieldName', no validation is triggered. This can be quite annoying, though in

    $input = new \Zend\InputFilter\Input('fieldName');
    
    $input
        ->setAllowEmpty(true)
        ->setRequired(false)
        ->getValidatorChain()
        ->attach(new \Zend\Validator\Callback(function ($value) {
            echo 'called validator!';
    
            return true; // valid
        }));
    
    $inputFilter = new \Zend\InputFilter\InputFilter();
    $inputFilter->add($input);
    
    $inputFilter->setData(array('fieldName' => 'value'));
    var_dump($inputFilter->isValid()); // true, echoes 'called validator!'
    
    $inputFilter->setData(array('fieldName' => ''));
    var_dump($inputFilter->isValid()); // true, no output
    
    $inputFilter->setData(array());
    var_dump($inputFilter->isValid()); // true, no output
    

    This is quite annoying when you have particular cases, like checking an URL assigned to a page in your CMS and avoiding collisions (empty URL is still an URL!).

    There's a way of handling this for empty strings, which is to basically attach the NotEmpty validator on your own, and avoiding calls to setRequired and setAllowEmpty. This will basically tell Zend\InputFilter\Input#injectNotEmptyValidator not to utomatically attach a NotEmpty validator on its own:

    $input = new \Zend\InputFilter\Input('fieldName');
    
    $input
        ->getValidatorChain()
        ->attach(new \Zend\Validator\NotEmpty(\Zend\Validator\NotEmpty::NULL))
        ->attach(new \Zend\Validator\Callback(function ($value) {
            echo 'called validator!';
    
            return true; // valid
        }));
    
    $inputFilter = new \Zend\InputFilter\InputFilter();
    $inputFilter->add($input);
    
    $inputFilter->setData(array('fieldName' => 'value'));
    var_dump($inputFilter->isValid()); // true, echoes 'called validator!'
    
    $inputFilter->setData(array('fieldName' => ''));
    var_dump($inputFilter->isValid()); // true, echoes 'called validator!'
    
    $inputFilter->setData(array());
    var_dump($inputFilter->isValid()); // false (null was passed to the validator)
    

    If you also want to check against null, you will need to extend Zend\InputFilter\Input as following:

    class MyInput extends \Zend\InputFilter\Input
    {
        // disabling auto-injection of the `NotEmpty` validator
        protected function injectNotEmptyValidator() {}
    }
    
    0 讨论(0)
  • 2020-12-05 04:10

    I see often the people making the mistake using allowEmpty in the inputFilter config arrays. The string should be written with underscore separation not with camel case. So allow_empty will work:

    'fieldName' => array(
        'name'        => 'fieldName',
        'required'    => true,
        'allow_empty' => true,
        'filters' => array(
            //... your filters ...
        )
        'validators' => array(
            //... your validators ...
        ),
    );
    

    meaning a field with key 'fieldName' must be present in the data, but its value is allowed to be empty.

    0 讨论(0)
  • 2020-12-05 04:11

    continue_if_empty solved my problem. Thanks to @dson-horácio-junior. This is what I used:

    $this->add(array(
        'name' => 'field',
        'continue_if_empty' => true,
        'filters' => array(
            array('name' => 'StripTags'),
            array('name' => 'StringTrim')
        ),
        'validators' => array(
            array(
                'name' => 'Application\Form\Validator\Sample'
            )
        )
    ));
    
    public function isValid($value, $context = null)
    {
        if ($value == '' && $context['otherfield'] == '') {
            $this->error(self::INVALID_FIELD);
    
            return false;
        }
    
        // ...
    }
    
    0 讨论(0)
  • 2020-12-05 04:13

    If you like to use a separate form validate class or a array notation for validate, you can do as follows:

    $factory     = new Zend\InputFilter\Factory();
    $inputFilter = new Zend\InputFilter\InputFilter();
    
    $inputFilter->add($factory->createInput(array(
        'name' => 'name',
        'required' => false,
        'allowEmpty' => true,
        'filters' => array(
            array('name' => 'StripTags'),
            array('name' => 'StringTrim'),
        ),
        'validators' => array(
            array(
                'name' => 'StringLength',
                'options' => array(
                    'encoding' => 'UTF-8',
                    'min' => '8',
                    'max' => '100',
                ),
            ),
        ),
    )));
    

    You can pass an array with required => false and allowEmpty => true to input filter factory (as I remember you can pass it directly to input filter too - not so sure).

    0 讨论(0)
  • 2020-12-05 04:20

    This triggered validation of my Callback validator when the value was an empty string:

    'required'          => false,
    'allow_empty'       => false,
    'continue_if_empty' => true,
    'validators'        => array(
        array(
            'name'    => 'Callback',
            'options' => array(
                'callback' => function ($value, $context = []) use ($self) {
                    // ...
                }
            )
        )
    )
    

    The allow_empty initially invalidates the empty string and the continue_if_empty allows it to then be evaluated by the validators that follow.

    0 讨论(0)
提交回复
热议问题