Making a Zend_Form_Element_Multiselect Required

Written by James Mansson on March 17, 2014 Categories: Zend Framework 1

I recently encountered a problem with the Zend Framework, when attempting to make a form field of type Zend_Form_Element_Multiselect required. When the field failed validation, because no value had been selected, the application displayed the warning “Invalid argument supplied for foreach…”. Investigation of the Zend Framework code revealed that the issue was caused by a flaw in the _getErrorMessages function of Zend_Form_Element.

I was able to get round the problem as follows. I created a replacement class for Zend_Form_Element_Multiselect with the code of the _getErrorMessages function corrected. The implementation of the class can be found below.

<?php
/** Zend_Form_Element_Multiselect */
require_once 'Zend/Form/Element/Multiselect.php';

class Application_Form_Element_Multiselect extends Zend_Form_Element_Multiselect
{
    /**
     * Retrieve error messages and perform translation and value substitution
     *
     * This has been modified from the implementation in Zend_Form_Element
     * as if $value is NULL, this will generate a warning when calling foreach on $value.
     *
     * @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);
            }
            // Removed condition $this->isArray() as $value could be NULL
            if (is_array($value)) {
                $aggregateMessages = array();
                foreach ($value as $val) {
                    $aggregateMessages[] = str_replace('%value%', $val, $message);
                }
                if (count($aggregateMessages)) {
                    $messages[$key] = implode($this->getErrorMessageSeparator(), $aggregateMessages);
                }
            } else {
                $messages[$key] = str_replace('%value%', $value, $message);
            }
        }
        return $messages;
    }
}

The code has been changed by replacing:

if ($this->isArray() || is_array($value)) {

with

if (is_array($value)) {

This is because the variable $value could, in the case of a multi-select, be NULL, even if $this->isArray() is true. This is a consequence of how “no selections” is indicated for a multi-select.

No Comments on Making a Zend_Form_Element_Multiselect Required

Leave a Reply

Your email address will not be published. Required fields are marked *