Zend验证多选值

时间:2011-07-29 11:05:32

标签: forms zend-framework validation multi-select

表格中有一个多选元素。需要验证其中选择了多少项(最小和最大计数)。

问题在于,当元素可以有多个值时,每个值都会单独验证。

我尝试将isArray设置为false以使用我的自定义验证程序ArraySize验证该值,但出现了新问题:整个数组值传递给InArray验证器和验证失败。所以我必须将registerInArrayValidator设置为false来关闭它。

现在我可以验证所选值的数量值,但无法验证它们与提供的选项的对应关系。

有没有办法解决问题而不再创建一个自定义验证器?

2 个答案:

答案 0 :(得分:0)

注意:我假设这是Zend 1.

我能看到这样做的唯一方法是扩展Multiselect并使用自定义的isValid。这样,您可以看到完整的值数组,而不是一次只能看到一个值。

以下是我的自定义Multiselect类

<?php
/**
 * My_MinMaxMultiselect
 */
class My_MinMaxMultiselect extends Zend_Form_Element_Multiselect
{
    /**
     * Validate element contains the correct number of
     * selected items. Check value against minValue/maxValue
     *
     * @param mixed $value
     * @param mixed $context
     * @return boolean
     */
    public function isValid($value, $context = null)
    {
        // Call Parent first to cause chain and setValue
        $parentValid = parent::isValid($value, $context);

        $valid = true;

        if ((('' === $value) || (null === $value))
            && !$this->isRequired()
            && $this->getAllowEmpty()
        ) {
            return $valid;
        }

        // Get All Values
        $minValue = $this->getMinValue();
        $maxValue = $this->getMaxValue();

        $count = 0;
        if (is_array($value)) {
            $count = count($value);
        }

        if ($minValue && $count < $minValue) {
            $valid = false;
            $this->addError('The number of selected items must be greater than or equal to ' . $minValue);
        }

        if ($maxValue && $count > $maxValue) {
            $valid = false;
            $this->addError('The number of selected items must be less than or equal to ' . $maxValue);
        }

        return ($parentValid && $valid);
    }

    /**
     * Get the Minimum number of selected values
     *
     * @access public
     * @return int
     */
    public function getMinValue()
    {
        return $this->getAttrib('min_value');
    }

    /**
     * Get the Maximum number of selected values
     *
     * @access public
     * @return int
     */
    public function getMaxValue()
    {
        return $this->getAttrib('max_value');
    }

    /**
     * Set the Minimum number of selected Values
     *
     * @param int $minValue
     * @return $this
     * @throws Bad_Exception
     * @throws Zend_Form_Exception
     */
    public function setMinValue($minValue)
    {
        if (is_int($minValue)) {
            if ($minValue > 0) {
                $this->setAttrib('min_value', $minValue);
            }

            return $this;
        } else {
            throw new Bad_Exception ('Invalid value supplied to setMinValue');
        }
    }

    /**
     * Set the Maximum number of selected values
     *
     * @param int $maxValue
     * @return $this
     * @throws Bad_Exception
     * @throws Zend_Form_Exception
     */
    public function setMaxValue($maxValue)
    {
        if (is_int($maxValue)) {
            if ($maxValue > 0) {
                $this->setAttrib('max_value', $maxValue);
            }

            return $this;
        } else {
            throw new Bad_Exception ('Invalid value supplied to setMaxValue');
        }
    }

    /**
     * Retrieve error messages and perform translation and value substitution.
     * Overridden to avoid errors from above being output once per 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);
            }
            if (($this->isArray() || is_array($value))
                && !empty($value)
            ) {
                $aggregateMessages = array();
                foreach ($value as $val) {
                    $aggregateMessages[] = str_replace('%value%', $val, $message);
                }
                // Add additional array unique to avoid the same error for all values
                $messages[$key] = implode($this->getErrorMessageSeparator(), array_unique($aggregateMessages));
            } else {
                $messages[$key] = str_replace('%value%', $value, $message);
            }
        }

        return $messages;
    }
}

要在用户必须精确选择3个选项的表单中使用它:

    $favouriteSports = new MinMaxMultiselect('favourite_sports');
    $favouriteSports
        ->addMultiOptions(array(
            'Football',
            'Cricket',
            'Golf',
            'Squash',
            'Rugby'
        ))
        ->setRequired()
        ->setLabel('Favourite Sports')
        ->setMinValue(3)
        ->setMaxValue(3);

答案 1 :(得分:-1)

虽然你可以在不需要编写自定义验证器的情况下进行挤压,但是当你需要做一些与众不同的事情时,写一个是没有错的。

这听起来像是其中一种情况。