php - validacion - Litio y validación de entradas de formularios complejos: ¿cómo?
validar formulario jquery antes de enviar (1)
He hecho bastantes tutoriales de Lithium (enlaces a continuación en caso de que ayuden a alguien más, y también para mostrar que he hecho mi tarea :) y entiendo las partes más básicas de la creación de modelos, vistas, controladores y el uso de MVC para crear un registro DB basado en la entrada del formulario.
Sin embargo, soy nuevo en MVC para webapps y Lithium, y no estoy seguro de cómo debería escribir mi código en situaciones más complicadas. Esta es una pregunta general, pero dos preguntas de validación específicas que tengo son:
- ¿Cómo debo validar los datos de fecha enviados desde el formulario?
- ¿Cómo debo verificar que los dos campos de correo electrónico del usuario tengan el mismo valor?
Estaría muy agradecido por cualquier ayuda con estas preguntas, y ejemplos concretos como este también me ayudarán a comprender cómo hacer una buena codificación MVC en otras situaciones también.
Entrada de fecha: validación de la división de datos en múltiples entradas de formulario
Por razones de UI, el formulario de registro solicita a los usuarios que ingresen su fecha de nacimiento en tres campos:
<?=$this->form->field(''birthday'', array(''type'' => ''select'', ''list'' => array(/*...*/))); ?>
<?=$this->form->field(''birthmonth'', array(''type'' => ''select'', ''list'' => array(/*...*/))); ?>
<?=$this->form->field(''birthyear'', array(''type'' => ''select'', ''list'' => array(/*...*/))); ?>
¿Cuál es la mejor manera de validar este servidor? Creo que debería aprovechar la validación automática, pero no estoy seguro de la mejor manera de hacerlo para un conjunto de variables que no son realmente parte del Modelo. P.ej:
- ¿Debo post-procesar los datos
$this->request->data
enUsersController
? Por ejemplo, modifique$this->request->data
dentro deUsersController
antes de pasarlo aUsers::create
. - ¿Debo extraer los campos de formulario de
$this->request->data
y usar una llamada estática aValidator::isDate
dentro deUsersController
? - ¿Hay alguna manera de escribir una regla de validación en el modelo para combinaciones de variables de formulario que no son parte del modelo?
- ¿debo anular
Users::create
y hacer toda la validación adicional y el postprocesamiento allí?
Todos estos parecen que podrían funcionar, aunque algunos parecen un poco feos y no sé cuáles podrían causarme problemas importantes en el futuro.
[EDIT: estrechamente relacionado con esto es el problema de combinar los tres campos de formulario en un solo campo para ser guardado en el modelo]
Entrada de correo electrónico: verificando dos campos de formulario son idénticos, pero solo se almacena uno
Para el sentido común / práctica común, el formulario de registro solicita a los usuarios que especifiquen su dirección de correo electrónico dos veces:
<?=$this->form->field(''email_address''); ?>
<?=$this->form->field(''verify_email_address''); ?>
¿Cómo puedo escribir una regla de validación automática que verifique que estos dos campos de formulario tengan el mismo valor, pero solo guarda la dirección de correo electrónico en la base de datos?
Parece que es más o menos la misma pregunta que la anterior porque la lista de posibles respuestas que puedo pensar es la misma, así que lo presento como una pregunta, pero realmente agradecería su ayuda con ambas partes, ¡como creo que la solución a esto será sutil y diferente e igualmente esclarecedora!
[EDIT: estrechamente relacionado con esto es el problema de no almacenar verify_email_address en mi modelo y DB]
Algunos antecedentes sobre Lithium
He leído otros, pero estos tres tutoriales me llevaron a donde estoy con los usuarios y a los formularios de inscripción ahora ...
Algunas otras preguntas de StackOverflow sobre temas estrechamente relacionados (pero que no responden y que tampoco son específicos de Lithium)
- Una respuesta a esta pregunta sugiere crear un controlador por separado (y modelo y ...?) - no se siente muy "de litio" para mí, y me preocupa que pueda ser frágil / también con errores.
- Esta maravillosa historia me convenció de que tenía razón en preocuparme por ponerla en el controlador, pero no estoy seguro de cuál sería una buena solución.
- Este en vistas me hace pensar que debería ponerlo en el modelo de alguna manera, pero no sé cuál es la mejor manera de hacerlo en Lithium (ver mi lista con viñetas en la Entrada de fecha anterior)
- Y esta presentación de Scribd me hizo la pregunta que espero responder en la última página ... ¡después de lo cual se detuvo sin responder!
NB: las respuestas estilo CakePHP también están bien. No lo sé, pero es similar y estoy seguro de que puedo traducirlo si es necesario.
Yo recomendaría hacer esto en el Model
lugar de en el Controller
, de esa manera sucede, sin importar de dónde haga el guardado.
Para el problema de campo de fecha, en su modelo, anule el método save()
y maneje la conversión de los múltiples campos en los datos a un campo de fecha antes de llamar a parent::save
para hacer el guardado real. Cualquier manipulación avanzada puede ocurrir allí.
La técnica descrita en su comentario sobre el uso de un campo de formulario oculto para mostrar mensajes de error suena bastante bien.
Para comparar que dos campos de correo electrónico son iguales, recomendaría definir un validador personalizado. Puedes hacer esto en tu bootstrap usando Validator :: add .
use lithium/util/Validator;
use InvalidArgumentException;
Validator::add(''match'', function($value, $format = null, array $options = array()) {
$options += array(
''against'' => '''',
''values'' => array()
);
extract($options);
if (array_key_exists($against, $values)) {
return $values[$against] == $value;
}
return false;
});
Entonces en tu modelo:
public $validates = array(
"email" => array(
"match",
"message" => "Please re-type your email address.",
"against" => "email2"
)
);
Editar : según los comentarios, aquí hay una forma de hacer la validación de reglas personalizadas en un controlador:
public function save() {
$entity = MyModel::create($this->request->data);
$rules = array(
"email" => array(
"match",
"message" => "Please re-type your email address.",
"against" => "email2"
)
);
if (!$entity->validates($rules)) {
return compact(''entity'');
}
// if your model defines a `$_schema` and sets `$_meta = array(''locked'' => true)`
// then any fields not in the schema will not be saved to the db
// here''s another way using the `''whitelist''` param
$blacklist = array(''email2'', ''some'', ''other'', ''fields'');
$whitelist = array_keys($entity->data());
$whitelist = array_diff($whitelist, $blacklist);
if ($entity->save(null, compact(''whitelist''))) {
$this->redirect(
array("Controller::view", "args" => array($entity->_id)),
array(''exit'' => true)
);
}
return compact(''entity'');
}
Una ventaja de establecer los datos en la entidad es que se rellenará automáticamente en su formulario si hay un error de validación.