Esta guía de inicio rápido cubre los fundamentos de la creación,
validación y renderizado de formularios con Zend_Form.
Crear un objeto de formulario es muy sencillo: simplemente instancie
Zend_Form:
$form = new Zend_Form;
Para casos de uso avanzados, quizá desee crear una
subclase de Zend_Form, pero para formularios simples, puede
crear un formulario de forma programática utilizando un objeto
Zend_Form.
Si desea especificar la acción y el método del formulario (siempre es buena
idea), puede hacerlo con los accesores setAction() y
setMethod():
$form->setAction('/resource/process')
->setMethod('post');
El código anterior establece la acción del formulario a la URL parcial
"/resource/process" y el método del formulario a HTTP
POST. Esto se reflejará durante el renderizado final.
Puede establecer atributos HTML adicionales para la
etiqueta <form> utilizando los métodos setAttrib()
o setAttribs(). Por ejemplo, si desea establecer el
id, establezca el atributo "id":
$form->setAttrib('id', 'login');
Un formulario no es nada sin sus elementos. Zend_Form
incluye algunos elementos por defecto que se renderizan como XHTML mediante
ayudantes (helpers) de Zend_View. Estos son los siguientes:
button
checkbox (o varios checkboxes a la vez con multiCheckbox)
hidden
image
password
radio
reset
select (tanto el tipo normal como el de selección múltiple)
submit
text
textarea
Tiene dos opciones para añadir elementos a un formulario: puede
instanciar elementos concretos y pasar esos objetos, o puede
pasar simplemente el tipo de elemento y dejar que Zend_Form
instancie un objeto del tipo correcto por usted.
Algunos ejemplos:
// Instantiating an element and passing to the form object:
$form->addElement(new Zend_Form_Element_Text('username'));
// Passing a form element type to the form object:
$form->addElement('text', 'username');
Por defecto, estos no tienen ningún validador ni filtro. Esto significa que
deberá configurar sus elementos con al menos validadores,
y potencialmente filtros. Puede hacer esto (a) antes de pasar
el elemento al formulario, (b) mediante opciones de configuración pasadas
al crear un elemento a través de Zend_Form, o (c) obteniendo
el elemento del objeto formulario y configurándolo después
de eso.
Veamos primero cómo crear validadores para una instancia
concreta de elemento. Puede pasar objetos Zend_Validate_*,
o el nombre de un validador a utilizar:
$username = new Zend_Form_Element_Text('username');
// Passing a Zend_Validate_* object:
$username->addValidator(new Zend_Validate_Alnum());
// Passing a validator name:
$username->addValidator('alnum');
Al usar esta segunda opción, puede pasar argumentos del constructor en un array como el tercer parámetro si el validador puede aceptarlos:
// Pass a pattern
$username->addValidator('regex', false, array('/^[a-z]/i'));
(El segundo parámetro se utiliza para indicar si el fallo de
este validador debe impedir o no que se ejecuten validadores posteriores; por
defecto, es FALSE.)
También puede querer especificar un elemento como requerido. Esto puede hacerse mediante un accesor o pasando una opción al crear el elemento. En el primer caso:
// Make this element required: $username->setRequired(true);
Cuando un elemento es requerido, se añade un validador 'NotEmpty' al principio de la cadena de validadores, asegurando que el elemento tenga un valor cuando sea requerido.
Los filtros se registran básicamente de la misma manera que los validadores. Con fines ilustrativos, añadamos un filtro para convertir a minúsculas el valor final:
$username->addFilter('StringtoLower');
La configuración final del elemento podría verse así:
$username->addValidator('alnum')
->addValidator('regex', false, array('/^[a-z]/'))
->setRequired(true)
->addFilter('StringToLower');
// or, more compactly:
$username->addValidators(array('alnum',
array('regex', false, '/^[a-z]/i')
))
->setRequired(true)
->addFilters(array('StringToLower'));
Por simple que sea, repetir esto para cada elemento de un formulario
puede resultar un poco tedioso. Probemos la opción (b) mencionada anteriormente. Cuando
creamos un nuevo elemento usando Zend_Form::addElement() como
fábrica, podemos pasar opcionalmente opciones de configuración. Estas
pueden incluir validadores y filtros. Para hacer todo lo
anterior de forma implícita, pruebe lo siguiente:
$form->addElement('text', 'username', array(
'validators' => array(
'alnum',
array('regex', false, '/^[a-z]/i')
),
'required' => true,
'filters' => array('StringToLower'),
));
![]() |
Nota |
|---|---|
Si observa que configura elementos usando las mismas opciones en
muchos lugares, quizá quiera considerar crear su propia
subclase de |
Renderizar un formulario es sencillo. La mayoría de los elementos utilizan un
ayudante (helper) de Zend_View para renderizarse a sí mismos, y por tanto necesitan un
objeto de vista para renderizar. Aparte de eso, tiene dos
opciones: usar el método render() del formulario, o simplemente hacer un echo de él.
// Explicitly calling render(), and passing an optional view object: echo $form->render($view); // Assuming a view object has been previously set via setView(): echo $form;
Por defecto, Zend_Form y
Zend_Form_Element intentarán utilizar el objeto de vista
inicializado en el ViewRenderer, lo que significa que no
necesitará establecer la vista manualmente cuando use el MVC de Zend Framework.
Para renderizar un formulario en una vista, simplemente debe hacer lo siguiente:
<?php echo $this->form ?>
Internamente, Zend_Form utiliza "decoradores" para llevar a cabo
el renderizado. Estos decoradores pueden reemplazar contenido, añadir contenido al final, o
añadir contenido al principio, y pueden inspeccionar completamente el elemento pasado
a ellos. Como resultado, puede combinar múltiples decoradores para
lograr efectos personalizados. Por defecto, Zend_Form_Element
de hecho combina cuatro decoradores para lograr su salida; la configuración
se ve algo así:
$element->addDecorators(array(
'ViewHelper',
'Errors',
array('HtmlTag', array('tag' => 'dd')),
array('Label', array('tag' => 'dt')),
));
(Donde <HELPERNAME> es el nombre de un ayudante de vista a utilizar, y varía según el elemento.)
Lo anterior crea una salida como la siguiente:
<dt><label for="username" class="required">Username</dt>
<dd>
<input type="text" name="username" value="123-abc" />
<ul class="errors">
<li>'123-abc' has not only alphabetic and digit characters</li>
<li>'123-abc' does not match against pattern '/^[a-z]/i'</li>
</ul>
</dd>
(Aunque no con el mismo formato.)
Puede cambiar los decoradores utilizados por un elemento si desea obtener una salida diferente; consulte la sección sobre decoradores para más información.
El propio formulario simplemente recorre los elementos, y los envuelve
en un HTML <form>. La acción y el método
que proporcionó al configurar el formulario se pasan a la
etiqueta <form>, al igual que cualquier atributo que haya establecido mediante
setAttribs() y similares.
Los elementos se recorren en el orden en que fueron registrados, o, si su elemento contiene un atributo de orden, se utilizará ese orden. Puede establecer el orden de un elemento usando:
$element->setOrder(10);
O, al crear un elemento, pasándolo como opción:
$form->addElement('text', 'username', array('order' => 10));
Después de enviar un formulario, deberá comprobar si
pasa las validaciones. Cada elemento se comprueba contra los datos
proporcionados; si una clave que coincide con el nombre del elemento no está presente, y
el elemento está marcado como requerido, las validaciones se ejecutan con un valor
NULL.
¿De dónde vienen los datos? Puede usar $_POST o
$_GET, o cualquier otra fuente de datos que tenga a mano
(peticiones de servicios web, por ejemplo):
if ($form->isValid($_POST)) {
// success!
} else {
// failure!
}
Con peticiones AJAX, a veces puede permitirse validar
un único elemento, o grupos de elementos.
isValidPartial() validará un formulario parcial. A diferencia de
isValid(), sin embargo, si una clave en particular no está
presente, no ejecutará validaciones para ese elemento en particular:
if ($form->isValidPartial($_POST)) {
// elements present all passed validations
} else {
// one or more elements tested failed validations
}
Se puede usar un método adicional, processAjax(), para
validar formularios parciales. A diferencia de isValidPartial(),
devuelve una cadena en formato JSON que contiene mensajes de error en caso de
fallo.
Suponiendo que sus validaciones han pasado, ahora puede obtener los valores filtrados:
$values = $form->getValues();
Si necesita los valores sin filtrar en algún momento, use:
$unfiltered = $form->getUnfilteredValues();
Si, por el contrario, necesita todos los valores válidos y filtrados de un formulario parcialmente válido, puede llamar a:
$values = $form->getValidValues($_POST);
¿Su formulario tuvo validaciones fallidas al enviarlo? En la mayoría de los casos, puede simplemente volver a renderizar el formulario, y los errores se mostrarán al usar los decoradores por defecto:
if (!$form->isValid($_POST)) {
echo $form;
// or assign to the view object and render a view...
$this->view->form = $form;
return $this->render('form');
}
Si desea inspeccionar los errores, dispone de dos métodos.
getErrors() devuelve un array asociativo de
nombres de elemento / códigos (donde codes es un array de códigos de error).
getMessages() devuelve un array asociativo de
nombres de elemento / mensajes (donde messages es un array asociativo de pares
código de error / mensaje de error). Si un elemento dado no tiene ningún
error, no se incluirá en el array.
Construyamos un formulario de acceso simple. Necesitará elementos que representen:
username
password
submit
Para nuestros propósitos, supongamos que un nombre de usuario válido debe contener solo caracteres alfanuméricos, comenzar con una letra, tener una longitud mínima de 6, y máxima de 20; se normalizarán a minúsculas. Las contraseñas deben tener un mínimo de 6 caracteres. Simplemente descartaremos el valor de submit cuando terminemos, para que pueda quedar sin validar.
Usaremos el poder de las opciones de configuración de Zend_Form
para construir el formulario:
$form = new Zend_Form();
$form->setAction('/user/login')
->setMethod('post');
// Create and configure username element:
$username = $form->createElement('text', 'username');
$username->addValidator('alnum')
->addValidator('regex', false, array('/^[a-z]+/'))
->addValidator('stringLength', false, array(6, 20))
->setRequired(true)
->addFilter('StringToLower');
// Create and configure password element:
$password = $form->createElement('password', 'password');
$password->addValidator('StringLength', false, array(6))
->setRequired(true);
// Add elements to form:
$form->addElement($username)
->addElement($password)
// use addElement() as a factory to create 'Login' button:
->addElement('submit', 'login', array('label' => 'Login'));
A continuación, crearemos un controlador para gestionar esto:
class UserController extends Zend_Controller_Action
{
public function getForm()
{
// create form as above
return $form;
}
public function indexAction()
{
// render user/form.phtml
$this->view->form = $this->getForm();
$this->render('form');
}
public function loginAction()
{
if (!$this->getRequest()->isPost()) {
return $this->_forward('index');
}
$form = $this->getForm();
if (!$form->isValid($_POST)) {
// Failed validation; redisplay form
$this->view->form = $form;
return $this->render('form');
}
$values = $form->getValues();
// now try and authenticate....
}
}
Y un script de vista para mostrar el formulario:
<h2>Please login:</h2> <?php echo $this->form ?>
Como notará en el código del controlador, aún hay más trabajo por hacer:
aunque el envío pueda ser válido, es posible que todavía necesite realizar cierta autenticación
usando Zend_Auth u otro mecanismo de autorización.
Todas las clases de Zend_Form son configurables mediante
Zend_Config; puede pasar un objeto
Zend_Config al constructor o pasarlo
con setConfig(). Veamos cómo podríamos crear el
formulario anterior utilizando un archivo INI. Primero, sigamos las
recomendaciones, y coloquemos nuestras configuraciones en secciones
que reflejen la ubicación de publicación, y centrémonos en la sección
'development'. A continuación, configuraremos una sección para el controlador dado
('user'), y una clave para el formulario ('login'):
[development] ; general form metainformation user.login.action = "/user/login" user.login.method = "post" ; username element user.login.elements.username.type = "text" user.login.elements.username.options.validators.alnum.validator = "alnum" user.login.elements.username.options.validators.regex.validator = "regex" user.login.elements.username.options.validators.regex.options.pattern = "/^[a-z]/i" user.login.elements.username.options.validators.strlen.validator = "StringLength" user.login.elements.username.options.validators.strlen.options.min = "6" user.login.elements.username.options.validators.strlen.options.max = "20" user.login.elements.username.options.required = true user.login.elements.username.options.filters.lower.filter = "StringToLower" ; password element user.login.elements.password.type = "password" user.login.elements.password.options.validators.strlen.validator = "StringLength" user.login.elements.password.options.validators.strlen.options.min = "6" user.login.elements.password.options.required = true ; submit element user.login.elements.submit.type = "submit"
Luego pasaría esto al constructor del formulario:
$config = new Zend_Config_Ini($configFile, 'development'); $form = new Zend_Form($config->user->login);
y todo el formulario quedará definido.
![[Note]](images/note.png)