Edición de formulario Zend y Zend_Validate_Db_NoRecordExists

Lentamente estoy construyendo mis habilidades con Zend al crear algunos sitios web de utilidad para mi propio uso. He estado usando la validación de formularios y formularios de Zend y hasta ahora he estado feliz de haber entendido la forma en que Zend hace las cosas. Sin embargo, estoy un poco confundido con cómo usar 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.

Por ejemplo, usando esta tabla simple

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

Si simplemente estuviera agregando una nueva fila a la Prueba de tabla, podría agregar un validador al elemento Formulario Zend para el campo Datos como tal:

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

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

Sin embargo, la situación es diferente al editar una fila existente de la tabla Prueba. En ese caso, el validador debe verificar que el valor del elemento cumpla con una de dos condiciones de condiciones mutuamente excluyentes:

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

El usuario tieneNo cambió el valor del elemento. Así el valorhace Actualmente existe en la tabla (y esto está bien).

losDocumentos de validación de Zend habla sobre agregar un parámetro al validador NoRecordExists () con el propósito de excluir registros del proceso de validación. La idea es "validar la tabla buscando cualquier fila coincidente, pero ignorar cualquier acierto donde el campo tenga este valor específico". Tal caso de uso es lo que se necesita para validar el elemento al editar una tabla. El pseudocódigo para hacer esto en 1.9 es así (en realidad, obtuve esto del código fuente 1.9, creo que los documentos actuales pueden estar equivocados):

$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 se va a excluir ($ Value) está vinculado al validador en el momento en que se instancia (también cuando se instancia el formulario). Pero cuando el formulario está editando un registro, ese valor debe vincularse con el contenido del campo $ data cuando el formulario se rellenó inicialmente con datos, es decir, el valor de datos inicialmente leído desde la fila de la tabla de prueba. Pero en los patrones típicos de Zend, se crea una instancia de una forma y se completa en dos pasos separados, lo que impide vincular el valor de exclusión al valor del elemento deseado.

El siguiente código de Zend psuedo marca dónde me gustaría que se produzca el enlace de $ Value al validador NoRecordExists () (y tenga en cuenta que este es un patrón de controlador 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
}

Podría subclasificar Zend_Form y anular el método populate () para hacer una inserción de una sola vez del validador NoRecordExists () en la población de formulario inicial, pero eso me parece un gran truco. Entonces, quería saber qué piensan otras personas 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 para este problema es escribir un validador personalizado y olvidarse de la versión de Zend. Mi formulario tiene la ID del registro como campo oculto, de modo que, dada la tabla y los nombres de las columnas, podría crear algunos SQL para probar la unicidad y excluir la fila con una ID de ese tipo. ¡Por supuesto, esto me hizo pensar en cómo vincularía el formulario a la capa de dB que se supone que oculta el Modelo!

Respuestas a la pregunta(7)

Su respuesta a la pregunta