2010-02-01 25 views
10

Estoy desarrollando lentamente mis habilidades de Zend construyendo algunos sitios web de utilidad para mi propio uso. He estado usando Formularios Zend y validación de formularios y hasta ahora he estado feliz de haber comprendido la forma de hacer las cosas de Zend. Sin embargo, estoy un poco confundido con el uso de Zend_Validate_Db_NoRecordExists() en el contexto de un formulario de edición y un campo que se asigna a la columna de la base de datos que tiene que ser único.Zend Form Edit y Zend_Validate_Db_NoRecordExists

Por ejemplo el uso de esta tabla simple

TABLE Test 
(
    ID INT AUTO_INCREMENT, 
    Data INT UNIQUE 
); 

Si yo estaba simplemente añadiendo una nueva fila a la prueba de la tabla, que podría añadir un validador para el elemento Formulario Zend para el campo de datos como tal:

$data = new Zend_Form_Element_Text('Data'); 
$data->addValidator(new Zend_Validate_Db_NoRecordExists('Test', 'Data')) 

En la validación de formulario este validador verificará que el contenido del elemento Datos aún no exista en la tabla. Por lo tanto, la inserción en Prueba puede continuar sin violar el calificador UNIQUE de los campos de Datos.

Sin embargo, la situación es diferente cuando se edita una fila existente de la tabla de prueba. En ese caso, el validador tiene que comprobar que el valor del elemento cumple una de las dos condiciones condiciones mutuamente excluyentes:

  1. El usuario ha cambiado el valor del elemento, y el nuevo valor no lo hace actualmente existe en la tabla.

  2. El usuario tiene No ha cambiado el valor del elemento. Por lo tanto, el valor hace actualmente existe en la tabla (y esto está bien).

El Zend Validation Docs hablar de la adición de un parámetro a los NoRecordExists() validador para el propósito de excluir registros desde el proceso de validación. La idea es "validar la tabla buscando las filas que coincidan, pero ignorar las visitas donde el campo a tenga este valor específico". Tal caso de uso es lo que se necesita para validar el elemento al editar una tabla. El pseudo código para hacer esto en 1.9 es igual que (en realidad me dieron esto desde el código 1.9 fuente - Creo que los documentos actuales pueden ser malo):

$data = new Zend_Form_Element_Text('Data'); 
$data->addValidator(new Zend_Validate_Db_NoRecordExists('Test', 'Data', 
        array ('field'=>'Data', 'Value'=> $Value)); 

El problema es que el valor que ha de excluirse ($ Value) está vinculado al validador en el momento en que se crea la instancia (también cuando se crea una instancia del formulario). Pero cuando el formulario está editando un registro, ese valor debe vincularse al contenido del campo $ data cuando el formulario se rellenó inicialmente con datos, es decir, el valor de Datos inicialmente leído de la fila de la tabla de Prueba. Pero en los patrones típicos de Zend, se crea una instancia de una forma y se rellena en dos pasos separados que excluyen el enlace del valor de exclusión con el valor del elemento deseado.

Los siguientes Zend marcas de código pseudo donde te gustaría la unión de $ Valor a las NoRecordExists() validador que se produzca (y tenga en cuenta que este es un patrón controlador de Zend común):

$form = new Form() 
if (is Post) { 
    $formData = GetPostData() 
    if ($form->isValid($formData)) { 
     Update Table with $formData 
     Redirect out of here 
    } else { 
     $form->populate($formData) 
    } 
} else { 
    $RowData = Get Data from Table 
    $form->populate($RowData)  <=== This is where I want ('value' => $Value) bound 
} 

pude sub -clase Zend_Form y anula el método populate() para hacer una inserción de una sola vez del validador NoRecordExists() en la población de formularios inicial, pero eso me parece un gran truco. Entonces, quería saber qué piensan los demás y ¿hay algún patrón ya escrito que resuelva este problema?

Editar 2009-02-04

He estado pensando que la única solución decente a este problema es escribir un validador personalizado y olvidarse de la versión de Zend. Mi formulario tiene el ID de registro como campo oculto, por lo que, dados los nombres de tabla y columna, podría crear algunos SQL para probar la exclusividad y excluir la fila con una ID de tal. Por supuesto, esto me hizo pensar en cómo estaría atando el formulario a la capa de dB que se supone que oculta el Modelo.

Respuesta

1

Después de revisar la abrumadora respuesta que he decidido que voy con un validador personalizado

0

Puede llamar al $form->getElement('input')->removeValidator('Zend_Validator_Db_NoRecordExists'); en lugar de proporcionar la exclusión.

+0

@The Guy - que parecerían frustrar el propósito de asegurar que los datos es único antes de hacer la actualización dB durante el ciclo de edición. Siento que también tiene el efecto de contaminar el controlador con algo que pertenece a la forma. –

+0

Sí, estoy de acuerdo, es un poco hackish. En realidad, no estoy muy contento con la forma en que Zend_Form está funcionando en este momento. Aunque aún utilizo una antigua implementación de estilo ZF 1.6: P –

+0

Tipo - Empecé con 1.9 en diciembre, así que todavía estoy aprendiendo cosas - pero cosas como esta me hacen "¿mmm?" –

6

Así es como se hace:

  1. que su formulario, añadir este validador (por ejemplo, correo electrónico campo):

 

$email->addValidator('Db_NoRecordExists', true, array('table' => 'user', 'field' => 'email')); 
  1. No agregue mensaje de error personalizado para este puesto después de eso no funcionó para mí, por ejemplo:

 

$email->getValidator('Db_NoRecordExists')->setMessage('This email is already registered.'); 

 

  1. en su controlador añadir esto:

 

/* Don't check for Db_NoRecordExists if editing the same field */ 

    $form->getElement('email') 
      ->addValidator('Db_NoRecordExists', 
           false, 
           array('table' => 'user', 
             'field' => 'email', 
             'exclude' => array ('field' => 'id', 'value' => $this->request->get('id')))); 

And after this you do verifications, e.g.: 

    if ($this->getRequest()->isPost()) 
      { 
       if($form->isValid($this->getRequest()->getPost())) 
       { 

    .... 

Eso es todo!

1
private $_id; 

public function setId($id=null) 
{ 
    $this->_id=$id;  
} 

public function init() 
{ 
    ..... 
    if(isset($this->_id)){ 
     $email->addValidator('Db_NoRecordExists', false, array('table' => 'user', 'field' => 'email','exclude' => array ('field' => 'id', 'value' => $this->_id))); 
     $email->getValidator('Db_NoRecordExists')->setMessage('This email is already registered.');  
    } 

Ahora u puede utilizar:

$form = new Form_Test(array('id'=>$id)); 
0

acabo de probado este ejemplo para email address singularidad y funciona perfectamente con las materias siguientes:

1] En mi formulario:

// Add an email element 
    $this->addElement('text', 'email', array(
     'label'  => 'Email :', 
     'required' => true, 
     'filters' => array('StringTrim'), 
     'validators' => array(
      'EmailAddress', 
     ) 
    )); 

Aquí hay algo especial que necesitaba para añadir unique email address a trabajar:

$email = new Zend_Form_Element_Text('email'); 
    $email->addValidator('Db_NoRecordExists', true, array('table' => 'guestbook', 'field' => 'email')); 

2] En mi controlador:

$form->getElement('email') 
    ->addValidator('Db_NoRecordExists', 
         false, 
         array('table' => 'guestbook', 
           'field' => 'email', 
           'exclude' => array ('field' => 'id', 'value' => $request->get('id')))); 

if ($this->getRequest()->isPost()) { 
     if ($form->isValid($request->getPost())) { 

espero que le ayuda a la gente!

Gracias

4

Esto también funcionará:

$this->addElement('text', 'email', array(
     'label'  => 'Your email address:', 
     'required' => true, 
     'filters' => array('StringTrim'), 
     'validators' => array(
      'EmailAddress', 
      array('Db_NoRecordExists', true, array(
        'table' => 'guestbook', 
        'field' => 'email', 
        'messages' => array(
         'recordFound' => 'Email already taken' 
        ) 
       ) 
      ) 
     ) 
    ));