2010-03-06 10 views
13

Tengo dos campos en mi Zend Form, y deseo aplicar la regla de validación que garantiza que el usuario ingrese cualquiera de estos dos campos.Zend Form Validator: Elemento A o Elemento 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); 

¿Cómo puedo agregar un validador que se vea en ambos campos?

Respuesta

12

Consulte la 'Nota: Contexto de validación' en este page. Zend_Form pasa el contexto a lo largo de cada llamada Zend_Form_Element :: isValid como el segundo parámetro. Así que simplemente escriba su propio validador que analiza el contexto.

EDIT:
bien, pensé I'ld tomar un tiro en esto por mí mismo. No está probado, ni es un medio para todos los fines, pero te dará una idea básica.

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

Uso:

$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

No he encontrado una solución así, pero es perfectamente válida para +1.

Extendería Your_Form::isValid() para incluir una verificación manual de los valores de esos dos elementos.

Si todos los campos pasan sus propios validadores individuales, esta validación probablemente pertenece en el formulario como un todo y tal podría colocarse en la validación del formulario en lugar de los campos. ¿Estás de acuerdo con esta línea de pensamiento?

0

Estoy de acuerdo con @chelmertz que una característica como esta no existe.

Lo que no estoy de acuerdo es ampliar Your_Form::isValid(). En cambio, me write a custom Validator que acepta los valores de ambos elementos del formulario que tienen que tener un valor. De esta forma podría reutilizarlo en elementos de forma arbitraria. Esto es algo similar al Validador idéntico.

1

La solución proporcionada por @fireeyedboy es conveniente, pero no funciona para este problema exacto.

Zend_Validate_Abstract está utilizando el contexto, que no se puede pasar como variable a isValid(). De esta forma, al utilizar el método isValid() (sin importar si es el original o sobreescrito), los campos vacíos no se pasan por alto ni se validan (a menos que tenga setRequired(true) o setAllowEmpty(false), que no queremos). Por lo tanto, en el caso de que deje ambos campos (companyname y companyother) vacíos, no se realizará ninguna acción. La única solución que conozco es ampliar la clase Zend_Validate para permitir que se validen campos vacíos.

Háganme saber si conoce una mejor solución, ya que también estoy luchando con un problema similar.

Cuestiones relacionadas