Zend Form Validator : Element A or Element B
Asked Answered
D

4

13

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?

Dispensable answered 6/3, 2010 at 18:42 Comment(0)
P
12

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);
Phosphatase answered 9/3, 2010 at 19:14 Comment(0)
A
1

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.

Asphalt answered 16/4, 2012 at 7:49 Comment(0)
S
0

I haven't come across such a solution, but it's perfectly valid so +1.

I would extend Your_Form::isValid() to include a manual check for the values of those two elements.

If all fields pass their own individual validators, this validation probably belongs on the form as-a-whole and such it could be placed on the validation of the form instead of the fields. Do you agree with this line of thinking?

Samba answered 6/3, 2010 at 19:10 Comment(0)
W
0

I agree with @chelmertz that a feature like this does not exists.

What I don't agree is extending Your_Form::isValid(). Instead, I'd write a custom Validator that accepts the values of both form elements that have to have a value. This way I could reuse it on arbitrary form elements. This is somewhat similar to the Identical Validator.

Waiver answered 6/3, 2010 at 21:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.