13

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 with empty element value :

  • If allowEmpty = false, NotEmptyValidator is added to the top of ValidatorChain with breakOnFailure = true, @see Zend/InputFilter/Input#injectNotEmptyValidator.

  • If allowEmpty = true, Element is considered as Valid, @see Zend/InputFilter/BaseInputFilter#isValid

    if ($input->allowEmpty()) {
        $this->validInputs[$name] = $input;
        continue;
    }
    
7
  • 1
    akrabat.com/zend-framework-2/… Commented Feb 16, 2013 at 13:58
  • It's not what i need because if allow_empty = true and my element value is empty, zf2 consider that element is Valid and will not invoke validators. Commented Feb 16, 2013 at 14:29
  • I think i don't understand your problem then. Either you allow empty values or you don't. If you don't allow empty values, all validators will run, otherwise validation will fail, when an empty input is given. If you do allow them, an empty value doesn't need to be validated any further oO Commented Feb 16, 2013 at 15:29
  • Ok to simplify description, how can i, with zf2, applicate a custom validator on a field even if it's empty. Commented Feb 16, 2013 at 15:47
  • Simplifying isn't the way to go. What do you want to validate? "" is empty - there is no validation for that. It's an empty string, what the heck do you want to validate with this? It just makes not the slightest sense. What EXACTLY do you want to do? Commented Feb 16, 2013 at 17:39

5 Answers 5

27

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;
    }

    // ...
}
Sign up to request clarification or add additional context in comments.

2 Comments

Best answer! Deserves more upvotes. If you set continue_if_empty to true then the InputFilter\Factory does not automatically add a NotEmpty validator, so all validation goes to the user defined validators.
i took 30 minutes to find this option THANKS a lot
14

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() {}
}

3 Comments

You've go it,I want to check against null and empty, so your last solution confirms my implementation. Thanks a lot.
Just do $input->setContinueIfEmpty(true); instead of extending Zend\InputFilter\Input, it will have the same effect, less work and more simple.
NotEmpty::NULL - this helped. For those who uses fogetInputFilterSpecification() with arrays you need the following structure: 'validators' => [[ 'name' => NotEmpty::class, 'options' => [ 'type' => NotEmpty::NULL ]]]'
7

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.

Comments

2

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.

Comments

2

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).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.