ZF-5603: Zend_Form_Element_Multicheckbox / Multi throws warning, doesn't show errors after using errorMessages

Description


$form = new Zend_Form();
$form->addElements(array(
    array('multiCheckbox','foobar',array(
        'label' => 'Some label',
        'required' => true,
        'multiOptions' => array(
            '1'=>'Foo',
            '2'=>'bar',
        ),
        'errorMessages' => array('You have not selected anything!'),
    )),
));

With default decorators this will throw warning and will not show errors box.


 Warning: htmlspecialchars() expects parameter 1 to be string, array given in [...] system/library/Zend/View/Abstract.php on line 804
12  0.3047  2529936 Zend_Form->render( ??? )    ../%%8E^8E3^8E32E77A%%index.tpl.php:83
13  0.3068  2538848 Zend_Form_Decorator_FormElements->render( ??? ) ../Form.php:2595
14  0.3362  2601416 Zend_Form_Element->render( ??? )    ../FormElements.php:100
15  0.3462  2617836 Zend_Form_Decorator_Errors->render( ??? )   ../Element.php:1911
16  0.3463  2617836 Zend_View_Smarty->formErrors( ???, ??? )    ../Errors.php:60
17  0.3463  2617836 Zend_View_Abstract->__call( ???, ??? )  ../Abstract.php:0
18  0.3463  2617836 call_user_func_array ( ???, ??? )   ../Abstract.php:318
19  0.3464  2617836 Zend_View_Helper_FormErrors->formErrors( ???, ??? ) ../Abstract.php:0
20  0.3465  2618084 Zend_View_Abstract->escape( ??? )   ../FormErrors.php:79
21  0.3465  2618084 call_user_func ( ???, ???, ???, ??? )   ../Abstract.php:804

This is probably because isValid() tries to validate each value in "Multi" separately (!?) and then passes an array of errors to decorator.

Comments

I've done some digging. I know what causes it...

At default, after setting {{required=>true}} the {{Multi}} field has {{Zend_Validator_NotEmpty}} attached to it. When form is validated, {{Zend_Form::isValid()}} function get's called, and with no checkboxes set it loops through fields with:


  foreach ($this->getElements() as $key => $element) {
            $element->setTranslator($translator);
            if (!isset($data[$key])) {
                $valid = $element->isValid(null, $data) && $valid;
            } else {
                $valid = $element->isValid($data[$key], $data) && $valid;
            }
        }

This one is crucial:


            if (!isset($data[$key])) {
                $valid = $element->isValid(null, $data) && $valid;

So the element is validated with {{null}} value. Then it goes to {{Zend_Form_Element::isValid()}} which on line 1325 does this:


if ($this->_hasErrorMessages()) {
      $messages = $this->_getErrorMessages();
      $errors   = $messages;
} else {

And here we are at {{Zend_Form_Element::_getErrorMessages()}} which is:


/**
     * Retrieve error messages and perform translation and value substitution
     *
     * @return array
     */
    protected function _getErrorMessages()
    {
        $translator = $this->getTranslator();
        $messages   = $this->getErrorMessages();
        $value      = $this->getValue();
        foreach ($messages as $key => $message) {
            if (null !== $translator) {
                $message = $translator->translate($message);
            }
            if ($this->isArray() || is_array($value)) {
                $aggregateMessages = array();
                foreach ($value as $val) {
                    $aggregateMessages[] = str_replace('%value%', $val, $message);
                }
                $messages[$key] = $aggregateMessages;
            } else {
                $messages[$key] = str_replace('%value%', $value, $message);
            }
        }
        return $messages;
    }

The error is at :


if ($this->isArray() || is_array($value)) {
                $aggregateMessages = array();
                foreach ($value as $val) {

As the {{Multi}} field always returns true for {{isArray()}} the {{$value}} of {{null}} is used in a {{foreach()}}

This is very close to ZF-5412.

This is exactly the same issue. I already posted a patch and a workaround for this.

Bulk change of all issues last updated before 1st January 2010 as "Won't Fix".

Feel free to re-open and provide a patch if you want to fix this issue.