Issues

ZF-3882: InArray validator for nested arrays

Description

The current InArray implementation does not support nested arrays. Which makes it unusable for selects with optgroups (for example). Have such functionality will enable this functionality.

Comments

This is a huge downfall. It's creating a usability issue with my form. I can extend it; however, this should be a default feature. Is it too late to be added to 1.6? Perhaps for 1.6.1?

Just like to point out that I found two work-arounds for this. The first is the easiest and that is if you are retrieving valid items from a database, then whenever you iterate through to create the optgroup items, add the valid values to a new array and pass it in as a parameter to the InArray validator.

The other option is to override the InArray validator and add another method. I called it calculateValids() and here is it's construct:


class My_Validators_InArray extends Zend_Validate_Abstract
{
    CONST NOT_IN_ARRAY = 'notInArray';
    
    protected $_messageTemplates = array(
        self::NOT_IN_ARRAY => '\'%value%\' was not found in the haystack',
    );
    
    protected $_haystack;
    
    protected $_strict;
    
    public function __construct(array $haystack, $strict=false)
    {
        $this->setHaystack($haystack)
            ->setStrict($strict);
    }
    
    public function calculateValids($array)
    {
        $valids = array();
        foreach($array as $key=>$value)
        {
            if(is_array($value))
                $valids = array_merge($valids, $this->calculateValids($value));
            else
                $valids[] = $key;
        }
        return $valids;
    }
    
    public function getHaystack()
    {
        return $this->_haystack;
    }
    
    public function setHaystack(array $haystack)
    {
        $this->_haystack = $this->calculateValids($haystack);
        
        return $this;
    }
    
    public function getStrict()
    {
        return $this->_strict;
    }
    
    public function setStrict($strict)
    {
        $this->_strict = $strict;
        return $this;
    }
    
    public function isValid($value)
    {
        $this->_setValue($value);
        if(!in_array($value, $this->_haystack, $this->_strict))
        {
            $this->_error();
            return false;
        }
        return true;
    }
}

Not the prettiest; however, it works :) Hopefully this can make it in to the next release or minor release.

I looked into the code of Zend_Form_Element_Multi, because I wanted to implement my own isValid method on a province select element. To my surprise, I found that validation of optgroups is supported. It works very well. The problem in my case was that I add added the multioptions in the render method, which is far to late for the validator to work (the validator will have no options at its disposal at all!).

After I implemented the getMultiOptions method to return a fixed set of provinces, validation worked just fine. So I wonder if this issue should not be marked as resolved?

Under code review since 27.06.2009 (Incubator r16316)

Feature implemented with ZF1.10. See option 'recursive'.