Валидатор формы Zend: элемент A или элемент B

У меня есть два поля в моей форме Zend, и я хочу применить правило проверки, которое гарантирует, что пользователь входит в одно из этих двух полей.

    $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);

Как я могу добавить валидатор, который будет смотреть на оба поля?

Ответы

Ответ 1

См. "Примечание: Контекст проверки" на этой странице . Zend_Form передает контекст каждому вызову Zend_Form_Element:: isValid в качестве второго параметра. Поэтому просто напишите свой собственный валидатор, который анализирует контекст.

EDIT:
Хорошо, я подумал, что сам это сделаю. Он не тестировался и не является средством для всех целей, но он даст вам базовую идею.

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;
    }
}

Использование:

$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);

Ответ 2

Решение, предоставляемое @fireeyedboy, удобно, но не работает для этой точной проблемы.

Zend_Validate_Abstract использует контекст, который не может быть передан как переменная в isValid(). Таким образом, при использовании метода isValid() (независимо от исходного или перезаписанного) пустые поля не передаются и не проверяются (если у вас нет setRequired(true) или setAllowEmpty(false), чего мы не хотим). Поэтому в случае, когда вы оставляете оба поля (companyname и companyother) пустыми, никаких действий не будет. Единственное решение, о котором я знаю, - это расширение класса Zend_Validate, позволяющее проверять пустые поля.

Пожалуйста, дайте мне знать, если вы знаете лучшее решение, поскольку я тоже борюсь с подобной проблемой.

Ответ 3

Я не сталкивался с таким решением, но он отлично действует так +1.

Я бы продолжил Your_Form::isValid(), чтобы включить ручную проверку значений этих двух элементов.

Если все поля передают свои собственные отдельные валидаторы, эта проверка, вероятно, принадлежит форме as-a-whole и поэтому может быть помещена на проверку формы вместо полей. Согласны ли вы с этим мышлением?

Ответ 4

Я согласен с @chelmertz, что такой функции не существует.

То, что я не согласен, распространяется Your_Form::isValid(). Вместо этого я написал пользовательский Validator, который принимает значения обоих элементов формы, которые должны иметь значение. Таким образом, я мог бы использовать его на произвольных элементах формы. Это несколько похоже на Identical Validator.