Adam Adam - 1 year ago 73
PHP Question

ZF2 - different error messages with NotEmpty validator

I got stuck with this stupid error messages in Zend Framework 2. Spent two hours and nothing, I still got two different error messages with NotEmpty validator.

$nameNotEmptyMessage = 'Pole wymagane';

$inputFilter->add(array(
'name' => 'name',
'required' => true,
'filters' => array(
new Filter\StringTrim()
),
'validators' => array(
new Validator\NotEmpty(array(
'messages' => array(
Validator\NotEmpty::INVALID => $nameNotEmptyMessage,
Validator\NotEmpty::IS_EMPTY => $nameNotEmptyMessage
)
))
)
));


And what? It works pretty cool when I send form with "name" element inside it. When it's empty, I've got my message. But, when I send form without the "name" element inside it, the message is still "Value is required and can't be empty"! Why?

I need to have in both cases the same message because sometimes the form won't have "name" element.

Thank you guys very much!

Answer Source

Thanks for replying to the comment to clarify the problem. First I must say, I feel your pain on this one. After having not used ZF2 for over a year and spending some time figuring this out, it highlights yet another painful thing in ZF2.

That said, here is my simple solution. Not necessary correct, or the best way to go about it but it solves your problem with the least amount of code. In your controller where you instantiate and validate the form, add this code before you call new Form:

if (!isset($_POST['name'])) {
    $this->getRequest()
         ->setPost(
             new \Zend\Stdlib\Parameters(
                 array('name' => '')
             )
         );
}

This seemed the simplest route rather than setting up a default validation translator and adding a duplicate message. It is just checking to see if the name field was not present, and if so sets it with any empty value.

Now the reason why we have to do this:

This happens because of how \Zend\InputFilter\Input works. When the InputFilter runs, it sees the element is missing. It then checks the required property, sees it's true but the input has no value. No value being different than empty.

When the filter is required but has no input, \Zend\InputFilter\Input::prepareRequiredValidationFailureMessage is called. If you look at the source of that function, you'll see:

protected function prepareRequiredValidationFailureMessage()
{
    $notEmpty = new NotEmpty();
    $templates = $notEmpty->getOption('messageTemplates');
    return [
        NotEmpty::IS_EMPTY => $templates[NotEmpty::IS_EMPTY],
    ];
}

Notice how it creates a new NotEmpty validator and fetches its default message, thus bypassing the translation you set within the InputFilter.

The alternative:

One alternative, which may be more correct, but also requires more code and could arguably be more confusing looking back later would be to create a new class implementing \Zend\Validator\Translator\TranslatorInterface and set an array with the translation for that message and then calling \Zend\Validator\AbstractValidator::setDefaultTranslator passing that so the default translator will be used on that message.

This is just difficult because there is no short way of setting up that object because of how the classes are inherited and I wasn't able to find a quick solution to set up the default translator with just that message. Also, if you have another translator in place, it might interfere with it.

So it seems the simplest thing is to just check for the absence of that form field and populate it with any empty value if it's missing.

Hope that helps!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download