2010-03-06 3 views
13

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

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

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

ответ

12

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

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

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

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

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

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

0

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

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

1

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

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

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

Смежные вопросы