Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zend Form Validator : Element A or Element B

I have two fields in my Zend Form, and i want to apply the validation rule that ensures the user enters either one of the these two fields.

    $companyname = new Zend_Form_Element_Text('companyname');
    $companyname->setLabel('Company Name');
    $companyname->setDecorators($decors);
    $this->addElement($companyname);

    $companyother = new Zend_Form_Element_Text('companyother');
    $companyother->setLabel('Company Other');
    $companyother->setDecorators($decors);
    $this->addElement($companyother);

How can i add a validator that will look at both fields?

like image 577
emeraldjava Avatar asked Mar 06 '10 18:03

emeraldjava


2 Answers

See the 'Note: Validation Context' on at this page. Zend_Form passes the context along to every Zend_Form_Element::isValid call as the second parameter. So simply write your own validator that analyzes the context.

EDIT:
Alright, I thought I'ld take a shot at this myself. It's not tested, nor is it a means to all ends, but it will give you a basic idea.

class My_Validator_OneFieldShouldBePresent extend Zend_Validator_Abstract
{
    const NOT_PRESENT = 'notPresent';

    protected $_messageTemplates = array(
        self::NOT_PRESENT => 'Field %field% is not present'
    );

    protected $_messageVariables = array(
        'field' => '_field'
    );

    protected $_field;

    protected $_listOfFields;

    public function __construct( array $listOfFields )
    {
        $this->_listOfFields = $listOfFields;
    }

    public function isValid( $value, $context = null )
    {
        if( !is_array( $context ) )
        {
            $this->_error( self::NOT_PRESENT );

            return false;
        }

        foreach( $this->_listOfFields as $field )
        {
            if( isset( $context[ $field ] ) )
            {
                return true;
            }
        }

        $this->_field = $field;
        $this->_error( self::NOT_PRESENT );

        return false;
    }
}

Usage:

$oneOfTheseFieldsShouldBePresent = array( 'companyname', 'companyother' );

$companyname = new Zend_Form_Element_Text('companyname');
$companyname->setLabel('Company Name');
$companyname->setDecorators($decors);
$companyname->addValidator( new My_Validator_OneFieldShouldBePresent( $oneOfTheseFieldsShouldBePresent ) );
$this->addElement($companyname);

$companyother = new Zend_Form_Element_Text('companyother');
$companyother->setLabel('Company Other');
$companyother->setDecorators($decors);
$companyname->addValidator( new My_Validator_OneFieldShouldBePresent( $oneOfTheseFieldsShouldBePresent ) );
$this->addElement($companyother);
like image 149
Decent Dabbler Avatar answered Nov 08 '22 11:11

Decent Dabbler


The solution provided by @fireeyedboy is handy but not working for this exact issue.

Zend_Validate_Abstract is using the context, which cannot be passed as variable to isValid(). This way when using the isValid() method (no matter if the original or overwritten one) the empty fields are not passed over and validated (unless you have setRequired(true) or setAllowEmpty(false), which we don't want). So in the case when you leave both two fields (companyname and companyother) empty, no action will take place. The only solution I am aware of is extending the Zend_Validate class to allow empty fields being validated.

Please let me know if you know better solution as I am struggling with similar problem too.

like image 23
gogh Avatar answered Nov 08 '22 12:11

gogh