TigerZF
🌐Español

36.3. Creación de elementos de formulario usando Zend_Form_Element

Un formulario está compuesto por elementos que típicamente corresponden a entradas de formulario HTML. Zend_Form_Element encapsula elementos de formulario individuales, con las siguientes áreas de responsabilidad:

  • validación (¿son válidos los datos enviados?)

    • captura de los códigos y mensajes de error de validación

  • filtrado (¿cómo se escapa o normaliza el elemento antes de la validación y/o para la salida?)

  • renderizado (¿cómo se muestra el elemento?)

  • metadatos y atributos (¿qué información califica adicionalmente al elemento?)

La clase base, Zend_Form_Element, tiene valores por defecto razonables para muchos casos, pero es mejor extender la clase para elementos de propósito especial de uso común. Además, Zend Framework se distribuye con un número de elementos XHTML estándar; puede leer sobre ellos en el capítulo de Elementos Estándar.

36.3.1. Cargadores de plugins

Zend_Form_Element hace uso de Zend_Loader_PluginLoader para permitir a los desarrolladores especificar ubicaciones de validadores, filtros y decoradores alternativos. Cada uno tiene su propio cargador de plugins asociado, y se usan accesores generales para recuperar y modificar cada uno.

Los siguientes tipos de cargadores se usan con los distintos métodos del cargador de plugins: 'validate', 'filter' y 'decorator'. Los nombres de tipo distinguen entre mayúsculas y minúsculas.

Los métodos usados para interactuar con los cargadores de plugins son los siguientes:

  • setPluginLoader($loader, $type): $loader es el propio objeto del cargador de plugins, mientras $type es uno de los tipos especificados arriba. Esto establece el cargador de plugins para el tipo dado con el nuevo objeto cargador especificado.

  • getPluginLoader($type): recupera el cargador de plugins asociado con $type.

  • addPrefixPath($prefix, $path, $type = null): añade una asociación prefijo/ruta al cargador especificado por $type. Si $type es NULL, intentará añadir la ruta a todos los cargadores, añadiendo "_Validate", "_Filter" y "_Decorator" al prefijo; y añadiendo "Validate/", "Filter/" y "Decorator/" a la ruta. Si tiene todas sus clases de elementos de formulario adicionales bajo una jerarquía común, este es un método de conveniencia para establecer el prefijo base para ellas.

  • addPrefixPaths(array $spec): le permite añadir muchas rutas a la vez a uno o más cargadores de plugins. Espera que cada elemento del array sea un array con las claves 'path', 'prefix', y 'type'.

Los validadores, filtros y decoradores personalizados son una forma fácil de compartir funcionalidad entre formularios y de encapsular funcionalidad personalizada.

Ejemplo 36.1. Etiqueta personalizada

Un caso de uso común para los plugins es proporcionar reemplazos para clases estándar. Por ejemplo, si desea proporcionar una implementación diferente del decorador 'Label' -- por ejemplo, para añadir siempre dos puntos al final -- puede crear su propio decorador 'Label' con su propio prefijo de clase, y luego añadirlo a su ruta de prefijo.

Empecemos con un decorador Label personalizado. Le daremos el prefijo de clase "My_Decorator", y la clase en sí estará en el archivo "My/Decorator/Label.php".

class My_Decorator_Label extends Zend_Form_Decorator_Abstract
{
    protected $_placement = 'PREPEND';

    public function render($content)
    {
        if (null === ($element = $this->getElement())) {
            return $content;
        }
        if (!method_exists($element, 'getLabel')) {
            return $content;
        }

        $label = $element->getLabel() . ':';

        if (null === ($view = $element->getView())) {
            return $this->renderLabel($content, $label);
        }

        $label = $view->formLabel($element->getName(), $label);

        return $this->renderLabel($content, $label);
    }

    public function renderLabel($content, $label)
    {
        $placement = $this->getPlacement();
        $separator = $this->getSeparator();

        switch ($placement) {
            case 'APPEND':
                return $content . $separator . $label;
            case 'PREPEND':
            default:
                return $label . $separator . $content;
        }
    }
}

Ahora podemos indicarle al elemento que use esta ruta de plugin cuando busque decoradores:

$element->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');

Alternativamente, podemos hacer eso a nivel de formulario para asegurar que todos los decoradores usen esta ruta:

$form->addElementPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');

Después de añadirla como en el ejemplo anterior, la ruta 'My/Decorator/' se buscará primero para ver si el decorador existe allí cuando añada un decorador. Como resultado, 'My_Decorator_Label' se usará ahora cuando se solicite el decorador 'Label'.


36.3.2. Filtros

A menudo es útil y/o necesario realizar cierta normalización de la entrada antes de la validación. Por ejemplo, puede que desee eliminar todo el HTML, pero ejecutar sus validaciones sobre lo que queda para asegurar que el envío sea válido. O puede que desee recortar los espacios vacíos que rodean la entrada para que un validador StringLength use la longitud correcta de la entrada sin contar los espacios en blanco iniciales o finales. Estas operaciones se pueden realizar usando Zend_Filter. Zend_Form_Element tiene soporte para cadenas de filtros, permitiéndole especificar múltiples filtros secuenciales. El filtrado ocurre tanto durante la validación como cuando recupera el valor del elemento mediante getValue():

$filtered = $element->getValue();

Los filtros pueden añadirse a la cadena de dos maneras:

  • pasando una instancia concreta de filtro

  • proporcionando un nombre corto de filtro

Veamos algunos ejemplos:

// Instancia concreta de filtro:
$element->addFilter(new Zend_Filter_Alnum());

// Nombre corto de filtro:
$element->addFilter('Alnum');
$element->addFilter('alnum');

Los nombres cortos son típicamente el nombre del filtro menos el prefijo. En el caso por defecto, esto significará menos el prefijo 'Zend_Filter_'. La primera letra puede estar en mayúscula o minúscula.

[Note] Uso de clases de filtro personalizadas

Si tiene su propio conjunto de clases de filtro, puede indicarle a Zend_Form_Element sobre estas usando addPrefixPath(). Por ejemplo, si tiene filtros bajo el prefijo 'My_Filter', puede indicarle a Zend_Form_Element sobre esto de la siguiente manera:

$element->addPrefixPath('My_Filter', 'My/Filter/', 'filter');

(Recuerde que el tercer argumento indica sobre qué cargador de plugins se realiza la acción.)

Si en algún momento necesita el valor sin filtrar, use el método getUnfilteredValue():

$unfiltered = $element->getUnfilteredValue();

Para más información sobre filtros, vea la documentación de Zend_Filter.

Los métodos asociados con los filtros incluyen:

  • addFilter($nameOfFilter, array $options = null)

  • addFilters(array $filters)

  • setFilters(array $filters) (sobrescribe todos los filtros)

  • getFilter($name) (recupera un objeto filtro por nombre)

  • getFilters() (recupera todos los filtros)

  • removeFilter($name) (elimina el filtro por nombre)

  • clearFilters() (elimina todos los filtros)

36.3.3. Validadores

Si se suscribe al mantra de seguridad de "filtrar la entrada, escapar la salida", debería usar un validador para filtrar la entrada enviada con su formulario. En Zend_Form, cada elemento incluye su propia cadena de validadores, formada por validadores Zend_Validate_*.

Los validadores pueden añadirse a la cadena de dos maneras:

  • pasando una instancia concreta de validador

  • proporcionando un nombre corto de validador

Veamos algunos ejemplos:

// Instancia concreta de validador:
$element->addValidator(new Zend_Validate_Alnum());

// Nombre corto de validador:
$element->addValidator('Alnum');
$element->addValidator('alnum');

Los nombres cortos son típicamente el nombre del validador menos el prefijo. En el caso por defecto, esto significará menos el prefijo 'Zend_Validate_'. Al igual que con los filtros, la primera letra puede estar en mayúscula o minúscula.

[Note] Uso de clases de validador personalizadas

Si tiene su propio conjunto de clases de validador, puede indicarle a Zend_Form_Element sobre estas usando addPrefixPath(). Por ejemplo, si tiene validadores bajo el prefijo 'My_Validator', puede indicarle a Zend_Form_Element sobre esto de la siguiente manera:

$element->addPrefixPath('My_Validator', 'My/Validator/', 'validate');

(Recuerde que el tercer argumento indica sobre qué cargador de plugins se realiza la acción.)

Si fallar una validación particular debería impedir que se disparen validadores posteriores, pase el booleano TRUE como segundo parámetro:

$element->addValidator('alnum', true);

Si está usando un nombre de cadena para añadir un validador, y la clase del validador acepta argumentos en el constructor, puede pasar estos como tercer parámetro de addValidator() como un array:

$element->addValidator('StringLength', false, array(6, 20));

Los argumentos pasados de esta manera deben estar en el orden en que se definen en el constructor. El ejemplo anterior instanciará la clase Zend_Validate_StringLenth con sus parámetros $min y $max:

$validator = new Zend_Validate_StringLength(6, 20);
[Note] Proporcionar mensajes de error de validador personalizados

Algunos desarrolladores pueden desear proporcionar mensajes de error personalizados para un validador. El argumento $options del método Zend_Form_Element::addValidator() le permite hacer esto proporcionando la clave 'messages' y asociándola a un array de pares clave/valor para establecer las plantillas de mensajes. Necesitará conocer los códigos de error de los distintos tipos de error de validación para el validador en particular.

Una mejor opción es usar un Zend_Translate_Adapter con su formulario. Los códigos de error se pasan automáticamente al adaptador mediante el decorador Errors por defecto; entonces puede especificar sus propias cadenas de mensajes de error configurando traducciones para los distintos códigos de error de sus validadores.

También puede establecer muchos validadores a la vez, usando addValidators(). El uso básico es pasar un array de arrays, con cada array conteniendo de 1 a 3 valores, coincidiendo con el constructor de addValidator():

$element->addValidators(array(
    array('NotEmpty', true),
    array('alnum'),
    array('stringLength', false, array(6, 20)),
));

Si desea ser más detallado o explícito, puede usar las claves del array 'validator', 'breakChainOnFailure' y 'options':

$element->addValidators(array(
    array(
        'validator'           => 'NotEmpty',
        'breakChainOnFailure' => true),
    array('validator' => 'alnum'),
    array(
        'validator' => 'stringLength',
        'options'   => array(6, 20)),
));

Este uso es bueno para ilustrar cómo podría entonces configurar validadores en un archivo de configuración:

element.validators.notempty.validator = "NotEmpty"
element.validators.notempty.breakChainOnFailure = true
element.validators.alnum.validator = "Alnum"
element.validators.strlen.validator = "StringLength"
element.validators.strlen.options.min = 6
element.validators.strlen.options.max = 20

Note que cada elemento tiene una clave, la necesite o no; esto es una limitación de usar archivos de configuración -- pero también ayuda a hacer explícito cuáles son los argumentos. Solo recuerde que cualquier opción de validador debe especificarse en orden.

Para validar un elemento, pase el valor a isValid():

if ($element->isValid($value)) {
    // válido
} else {
    // inválido
}
[Note] La validación opera sobre valores filtrados

Zend_Form_Element::isValid() filtra los valores a través de la cadena de filtros provista antes de la validación. Vea la sección de Filtros para más información.

[Note] Contexto de validación

Zend_Form_Element::isValid() admite un argumento adicional, $context. Zend_Form::isValid() pasa el array completo de datos que se están procesando a $context al validar un formulario, y Zend_Form_Element::isValid(), a su vez, lo pasa a cada validador. Esto significa que puede escribir validadores que sean conscientes de los datos pasados a otros elementos del formulario. Como ejemplo, considere un formulario de registro estándar que tiene campos tanto para la contraseña como para la confirmación de contraseña; una validación sería que ambos campos coincidan. Un validador de este tipo podría verse como el siguiente:

class My_Validate_PasswordConfirmation extends Zend_Validate_Abstract
{
    const NOT_MATCH = 'notMatch';

    protected $_messageTemplates = array(
        self::NOT_MATCH => 'Password confirmation does not match'
    );

    public function isValid($value, $context = null)
    {
        $value = (string) $value;
        $this->_setValue($value);

        if (is_array($context)) {
            if (isset($context['password_confirm'])
                && ($value == $context['password_confirm']))
            {
                return true;
            }
        } elseif (is_string($context) && ($value == $context)) {
            return true;
        }

        $this->_error(self::NOT_MATCH);
        return false;
    }
}

Los validadores se procesan en orden. Cada validador se procesa, a menos que un validador creado con un valor TRUE de $breakChainOnFailure falle su validación. Asegúrese de especificar sus validadores en un orden razonable.

Después de una validación fallida, puede recuperar los códigos de error y los mensajes de la cadena de validadores:

$errors   = $element->getErrors();
$messages = $element->getMessages();

(Nota: los mensajes de error devueltos son un array asociativo de pares código de error / mensaje de error.)

Además de los validadores, puede especificar que un elemento sea obligatorio, usando setRequired($flag). Por defecto, este indicador es FALSE. En combinación con setAllowEmpty($flag) (TRUE por defecto) y setAutoInsertNotEmptyValidator($flag) (TRUE por defecto), el comportamiento de su cadena de validadores puede modificarse de varias maneras:

  • Usando los valores por defecto, validar un Elemento sin pasar un valor, o pasando una cadena vacía para él, omite todos los validadores y valida como TRUE.

  • setAllowEmpty(false) dejando intactos los otros dos indicadores mencionados, validará contra la cadena de validadores que definió para este Elemento, sin importar el valor pasado a isValid().

  • setRequired(true) dejando intactos los otros dos indicadores mencionados, añadirá un validador 'NotEmpty' al principio de la cadena de validadores (si aún no se había establecido ninguno), con el indicador $breakChainOnFailure activado. Este comportamiento otorga al indicador required un significado semántico: si no se pasa ningún valor, invalidamos inmediatamente el envío y notificamos al usuario, y evitamos que otros validadores se ejecuten sobre lo que ya sabemos que son datos inválidos.

    Si no desea este comportamiento, puede desactivarlo pasando un valor FALSE a setAutoInsertNotEmptyValidator($flag); esto evitará que isValid() coloque el validador 'NotEmpty' en la cadena de validadores.

Para más información sobre validadores, vea la documentación de Zend_Validate.

[Note] Uso de Zend_Form_Elements como validadores de propósito general

Zend_Form_Element implementa Zend_Validate_Interface, lo que significa que un elemento también puede usarse como validador en otras cadenas de validación no relacionadas con formularios.

[Note] ¿Cuándo se detecta que un elemento está vacío?

Como se mencionó, el validador 'NotEmpty' se usa para detectar si un elemento está vacío o no. Pero Zend_Validate_NotEmpty, por defecto, no funciona como el método empty() de PHP.

Esto significa que cuando un elemento contiene un entero 0 o una cadena '0', el elemento se considerará no vacío. Si desea tener un comportamiento diferente debe crear su propia instancia de Zend_Validate_NotEmpty. Allí puede definir el comportamiento de este validador. Vea Zend_Validate_NotEmpty para más detalles.

Los métodos asociados con la validación incluyen:

  • setRequired($flag) y isRequired() le permiten establecer y recuperar el estado del indicador 'required'. Cuando se establece como booleano TRUE, este indicador requiere que el elemento esté en los datos procesados por Zend_Form.

  • setAllowEmpty($flag) y getAllowEmpty() le permiten modificar el comportamiento de elementos opcionales (es decir, elementos donde el indicador required es FALSE). Cuando el indicador 'allow empty' es TRUE, los valores vacíos no se pasarán a la cadena de validadores.

  • setAutoInsertNotEmptyValidator($flag) le permite especificar si se antepondrá o no un validador 'NotEmpty' a la cadena de validadores cuando el elemento sea obligatorio. Por defecto, este indicador es TRUE.

  • addValidator($nameOrValidator, $breakChainOnFailure = false, array $options = null)

  • addValidators(array $validators)

  • setValidators(array $validators) (sobrescribe todos los validadores)

  • getValidator($name) (recupera un objeto validador por nombre)

  • getValidators() (recupera todos los validadores)

  • removeValidator($name) (elimina el validador por nombre)

  • clearValidators() (elimina todos los validadores)

36.3.3.1. Mensajes de error personalizados

A veces, puede querer especificar uno o más mensajes de error específicos para usar en lugar de los mensajes de error generados por los validadores adjuntos a su elemento. Además, a veces puede querer marcar el elemento como inválido usted mismo. A partir de la versión 1.6.0, esta funcionalidad es posible mediante los siguientes métodos.

  • addErrorMessage($message): añade un mensaje de error para mostrar en los errores de validación del formulario. Puede llamar a esto más de una vez, y los nuevos mensajes se añaden a la pila.

  • addErrorMessages(array $messages): añade múltiples mensajes de error para mostrar en los errores de validación del formulario.

  • setErrorMessages(array $messages): añade múltiples mensajes de error para mostrar en los errores de validación del formulario, sobrescribiendo todos los mensajes de error establecidos previamente.

  • getErrorMessages(): recupera la lista de mensajes de error personalizados que se han definido.

  • clearErrorMessages(): elimina todos los mensajes de error personalizados que se han definido.

  • markAsError(): marca el elemento como que ha fallado la validación.

  • hasErrors(): determina si el elemento ha fallado la validación o ha sido marcado como inválido.

  • addError($message): añade un mensaje a la pila de mensajes de error personalizados y marca el elemento como inválido.

  • addErrors(array $messages): añade varios mensajes a la pila de mensajes de error personalizados y marca el elemento como inválido.

  • setErrors(array $messages): sobrescribe la pila de mensajes de error personalizados con los mensajes proporcionados y marca el elemento como inválido.

Todos los errores establecidos de esta manera pueden traducirse. Además, puede insertar el marcador de posición "%value%" para representar el valor del elemento; este valor actual del elemento se sustituirá cuando se recuperen los mensajes de error.

36.3.4. Decoradores

Uno de los puntos más dolorosos para muchos desarrolladores web es la creación de los propios formularios XHTML. Para cada elemento, el desarrollador necesita crear el marcado para el propio elemento (típicamente una etiqueta) y marcado especial para mostrar los mensajes de error de validación. Cuantos más elementos haya en la página, menos trivial se vuelve esta tarea.

Zend_Form_Element intenta resolver este problema mediante el uso de "decoradores". Los decoradores son simplemente clases que tienen acceso al elemento y un método para renderizar contenido. Para más información sobre cómo funcionan los decoradores, por favor vea la sección sobre Zend_Form_Decorator.

Los decoradores por defecto usados por Zend_Form_Element son:

  • ViewHelper: especifica un helper de vista para usar para renderizar el elemento. El atributo del elemento 'helper' puede usarse para especificar qué helper de vista usar. Por defecto, Zend_Form_Element especifica el helper de vista 'formText', pero las subclases individuales especifican helpers diferentes.

  • Errors: añade mensajes de error al elemento usando Zend_View_Helper_FormErrors. Si no hay ninguno presente, no se añade nada.

  • Description: añade la descripción del elemento. Si no hay ninguna presente, no se añade nada. Por defecto, la descripción se renderiza en una etiqueta <p> con una clase 'description'.

  • HtmlTag: envuelve el elemento y los errores en una etiqueta HTML <dd>.

  • Label: antepone una etiqueta al elemento usando Zend_View_Helper_FormLabel, y la envuelve en una etiqueta <dt>. Si no se proporciona ninguna etiqueta, solo se renderiza la etiqueta de término de definición.

[Note] Los decoradores por defecto no necesitan cargarse

Por defecto, los decoradores por defecto se cargan durante la inicialización del objeto. Puede desactivar esto pasando la opción 'disableLoadDefaultDecorators' al constructor:

$element = new Zend_Form_Element('foo',
                                 array('disableLoadDefaultDecorators' =>
                                      true)
                                );

Esta opción puede combinarse con cualquier otra opción que pase, tanto como opciones de array o en un objeto Zend_Config.

Dado que el orden en que se registran los decoradores importa -el primer decorador registrado se ejecuta primero-, necesitará asegurarse de registrar sus decoradores en un orden apropiado, o asegurarse de establecer las opciones de posicionamiento de forma razonable. Para dar un ejemplo, aquí está el código que registra los decoradores por defecto:

$this->addDecorators(array(
    array('ViewHelper'),
    array('Errors'),
    array('Description', array('tag' => 'p', 'class' => 'description')),
    array('HtmlTag', array('tag' => 'dd')),
    array('Label', array('tag' => 'dt')),
));

El contenido inicial se crea con el decorador 'ViewHelper', el cual crea el propio elemento de formulario. A continuación, el decorador 'Errors' recupera los mensajes de error del elemento, y, si hay alguno presente, los pasa al helper de vista 'FormErrors' para renderizar. Si hay una descripción presente, el decorador 'Description' añadirá un párrafo de clase 'description' que contiene el texto descriptivo al contenido agregado. El siguiente decorador, 'HtmlTag', envuelve el elemento, los errores y la descripción en una etiqueta HTML <dd>. Finalmente, el último decorador, 'label', recupera la etiqueta del elemento y la pasa al helper de vista 'FormLabel', envolviéndola en una etiqueta HTML <dt>; el valor se antepone al contenido por defecto. El resultado final se ve básicamente así:

<dt><label for="foo" class="optional">Foo</label></dt>
<dd>
    <input type="text" name="foo" id="foo" value="123" />
    <ul class="errors">
        <li>"123" is not an alphanumeric value</li>
    </ul>
    <p class="description">
        This is some descriptive text regarding the element.
    </p>
</dd>

Para más información sobre decoradores, lea la sección Zend_Form_Decorator.

[Note] Uso de múltiples decoradores del mismo tipo

Internamente, Zend_Form_Element usa la clase de un decorador como mecanismo de búsqueda al recuperar decoradores. Como resultado, no puede registrar múltiples decoradores del mismo tipo; los decoradores subsiguientes simplemente sobrescribirán los que existían antes.

Para solucionar esto, puede usar alias. En lugar de pasar un decorador o nombre de decorador como primer argumento a addDecorator(), pase un array con un único elemento, donde el alias apunta al objeto o nombre de decorador:

// Alias a 'FooBar':
$element->addDecorator(array('FooBar' => 'HtmlTag'),
                       array('tag' => 'div'));

// Y recuperarlo después:
$decorator = $element->getDecorator('FooBar');

En los métodos addDecorators() y setDecorators(), necesitará pasar la opción 'decorator' en el array que representa al decorador:

// Añadir dos decoradores 'HtmlTag', dando alias a uno como 'FooBar':
$element->addDecorators(
    array('HtmlTag', array('tag' => 'div')),
    array(
        'decorator' => array('FooBar' => 'HtmlTag'),
        'options' => array('tag' => 'dd')
    ),
);

// Y recuperarlo después:
$htmlTag = $element->getDecorator('HtmlTag');
$fooBar  = $element->getDecorator('FooBar');

Los métodos asociados con decoradores incluyen:

  • addDecorator($nameOrDecorator, array $options = null)

  • addDecorators(array $decorators)

  • setDecorators(array $decorators) (sobrescribe todos los decoradores)

  • getDecorator($name) (recupera un objeto decorador por nombre)

  • getDecorators() (recupera todos los decoradores)

  • removeDecorator($name) (elimina el decorador por nombre)

  • clearDecorators() (elimina todos los decoradores)

Zend_Form_Element también usa sobrecarga para permitir renderizar decoradores específicos. __call() interceptará los métodos que empiecen con el texto 'render' y usará el resto del nombre del método para buscar un decorador; si se encuentra, renderizará entonces ese decorador único. Cualquier argumento pasado a la llamada al método se usará como contenido para pasar al método render() del decorador. Como ejemplo:

// Renderizar solo el decorador ViewHelper:
echo $element->renderViewHelper();

// Renderizar solo el decorador HtmlTag, pasando contenido:
echo $element->renderHtmlTag("This is the html tag content");

Si el decorador no existe, se lanza una excepción.

36.3.5. Metadatos y atributos

Zend_Form_Element maneja una variedad de atributos y metadatos de elementos. Los atributos básicos incluyen:

  • name: el nombre del elemento. Usa los accesores setName() y getName().

  • label: la etiqueta del elemento. Usa los accesores setLabel() y getLabel().

  • order: el índice en el que un elemento debe aparecer en el formulario. Usa los accesores setOrder() y getOrder().

  • value: el valor actual del elemento. Usa los accesores setValue() y getValue().

  • description: una descripción del elemento; a menudo se usa para proporcionar información contextual mediante tooltip o javascript describiendo el propósito del elemento. Usa los accesores setDescription() y getDescription().

  • required: indicador que señala si el elemento es obligatorio al realizar la validación del formulario. Usa los accesores setRequired() y isRequired(). Este indicador es FALSE por defecto.

  • allowEmpty: indicador que señala si un elemento no obligatorio (opcional) debe intentar validar valores vacíos. Si se establece en TRUE y el indicador required es FALSE, los valores vacíos no se pasan a la cadena de validadores y se presumen TRUE. Usa los accesores setAllowEmpty() y getAllowEmpty(). Este indicador es TRUE por defecto.

  • autoInsertNotEmptyValidator: indicador que señala si se debe insertar o no un validador 'NotEmpty' cuando el elemento es obligatorio. Por defecto, este indicador es TRUE. Establezca el indicador con setAutoInsertNotEmptyValidator($flag) y determine el valor con autoInsertNotEmptyValidator().

Los elementos de formulario pueden requerir metadatos adicionales. Para elementos de formulario XHTML, por ejemplo, puede que desee especificar atributos como la clase o el id. Para facilitar esto hay un conjunto de accesores:

  • setAttrib($name, $value): añade un atributo

  • setAttribs(array $attribs): similar a addAttribs(), pero sobrescribe

  • getAttrib($name): recupera un único valor de atributo

  • getAttribs(): recupera todos los atributos como pares clave/valor

Sin embargo, la mayoría de las veces puede simplemente acceder a ellos como propiedades del objeto, ya que Zend_Form_Element utiliza sobrecarga para facilitar el acceso a ellos:

// Equivalente a $element->setAttrib('class', 'text'):
$element->class = 'text;

Por defecto, todos los atributos se pasan al helper de vista usado por el elemento durante el renderizado, y se renderizan como atributos HTML de la etiqueta del elemento.

36.3.6. Elementos estándar

Zend_Form se distribuye con un número de elementos estándar; por favor lea el capítulo de Elementos Estándar para más detalles.

36.3.7. Métodos de Zend_Form_Element

Zend_Form_Element tiene muchísimos métodos. A continuación se presenta un resumen rápido de sus firmas, agrupados por tipo:

  • Configuración:

    • setOptions(array $options)

    • setConfig(Zend_Config $config)

  • I18n:

    • setTranslator(Zend_Translate_Adapter $translator = null)

    • getTranslator()

    • setDisableTranslator($flag)

    • translatorIsDisabled()

  • Propiedades:

    • setName($name)

    • getName()

    • setValue($value)

    • getValue()

    • getUnfilteredValue()

    • setLabel($label)

    • getLabel()

    • setDescription($description)

    • getDescription()

    • setOrder($order)

    • getOrder()

    • setRequired($flag)

    • isRequired()

    • setAllowEmpty($flag)

    • getAllowEmpty()

    • setAutoInsertNotEmptyValidator($flag)

    • autoInsertNotEmptyValidator()

    • setIgnore($flag)

    • getIgnore()

    • getType()

    • setAttrib($name, $value)

    • setAttribs(array $attribs)

    • getAttrib($name)

    • getAttribs()

  • Cargadores de plugins y rutas:

    • setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type)

    • getPluginLoader($type)

    • addPrefixPath($prefix, $path, $type = null)

    • addPrefixPaths(array $spec)

  • Validación:

    • addValidator($validator, $breakChainOnFailure = false, $options = array())

    • addValidators(array $validators)

    • setValidators(array $validators)

    • getValidator($name)

    • getValidators()

    • removeValidator($name)

    • clearValidators()

    • isValid($value, $context = null)

    • getErrors()

    • getMessages()

  • Filtros:

    • addFilter($filter, $options = array())

    • addFilters(array $filters)

    • setFilters(array $filters)

    • getFilter($name)

    • getFilters()

    • removeFilter($name)

    • clearFilters()

  • Renderizado:

    • setView(Zend_View_Interface $view = null)

    • getView()

    • addDecorator($decorator, $options = null)

    • addDecorators(array $decorators)

    • setDecorators(array $decorators)

    • getDecorator($name)

    • getDecorators()

    • removeDecorator($name)

    • clearDecorators()

    • render(Zend_View_Interface $view = null)

36.3.8. Configuración

El constructor de Zend_Form_Element acepta ya sea un array de opciones o un objeto Zend_Config que contiene opciones, y también puede configurarse usando setOptions() o setConfig(). En términos generales, las claves se nombran de la siguiente manera:

  • Si 'set' + clave corresponde a un método de Zend_Form_Element, entonces el valor proporcionado se pasará a ese método.

  • De lo contrario, el valor se usará para establecer un atributo.

Las excepciones a la regla incluyen lo siguiente:

  • prefixPath se pasará a addPrefixPaths()

  • Los siguientes setters no pueden establecerse de esta manera:

    • setAttrib (aunque setAttribs funciona)

    • setConfig

    • setOptions

    • setPluginLoader

    • setTranslator

    • setView

Como ejemplo, aquí hay un archivo de configuración que pasa configuración para cada tipo de dato configurable:

[element]
name = "foo"
value = "foobar"
label = "Foo:"
order = 10
required = true
allowEmpty = false
autoInsertNotEmptyValidator = true
description = "Foo elements are for examples"
ignore = false
attribs.id = "foo"
attribs.class = "element"
; For radio button elements
escape = true
listsep = "<br />\n"
; sets 'onclick' attribute
onclick = "autoComplete(this, '/form/autocomplete/element')"
prefixPaths.decorator.prefix = "My_Decorator"
prefixPaths.decorator.path = "My/Decorator/"
disableTranslator = 0
validators.required.validator = "NotEmpty"
validators.required.breakChainOnFailure = true
validators.alpha.validator = "alpha"
validators.regex.validator = "regex"
validators.regex.options.pattern = "/^[A-F].*/$"
filters.ucase.filter = "StringToUpper"
decorators.element.decorator = "ViewHelper"
decorators.element.options.helper = "FormText"
decorators.label.decorator = "Label"

36.3.9. Elementos personalizados

Puede crear sus propios elementos personalizados simplemente extendiendo la clase Zend_Form_Element. Las razones comunes para hacer esto incluyen:

  • Elementos que comparten validadores y/o filtros comunes

  • Elementos que tienen funcionalidad de decorador personalizada

Hay dos métodos que se usan típicamente para extender un elemento: init(), que puede usarse para añadir lógica de inicialización personalizada a su elemento, y loadDefaultDecorators(), que puede usarse para establecer una lista de decoradores por defecto usados por su elemento.

Como ejemplo, digamos que todos los elementos de texto en un formulario que está creando necesitan filtrarse con StringTrim, validarse con una expresión regular común, y que desea usar un decorador personalizado que ha creado para mostrarlos, 'My_Decorator_TextItem'. Además, tiene una serie de atributos estándar, incluyendo 'size', 'maxLength' y 'class' que desea especificar. Podría definir un elemento para lograr esto de la siguiente manera:

class My_Element_Text extends Zend_Form_Element
{
    public function init()
    {
        $this->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator')
             ->addFilters('StringTrim')
             ->addValidator('Regex', false, array('/^[a-z0-9]{6,}$/i'))
             ->addDecorator('TextItem')
             ->setAttrib('size', 30)
             ->setAttrib('maxLength', 45)
             ->setAttrib('class', 'text');
    }
}

Luego podría informar a su objeto formulario sobre la ruta de prefijo para tales elementos, y empezar a crear elementos:

$form->addPrefixPath('My_Element', 'My/Element/', 'element')
     ->addElement('text', 'foo');

El elemento 'foo' ahora será de tipo My_Element_Text, y exhibirá el comportamiento que ha delineado.

Otro método que puede querer sobrescribir al extender Zend_Form_Element es el método loadDefaultDecorators(). Este método carga condicionalmente un conjunto de decoradores por defecto para su elemento; puede que desee sustituir sus propios decoradores en su clase que extiende:

class My_Element_Text extends Zend_Form_Element
{
    public function loadDefaultDecorators()
    {
        $this->addDecorator('ViewHelper')
             ->addDecorator('DisplayError')
             ->addDecorator('Label')
             ->addDecorator('HtmlTag',
                            array('tag' => 'div', 'class' => 'element'));
    }
}

Hay muchas formas de personalizar elementos. Lea la documentación de la API de Zend_Form_Element para conocer todos los métodos disponibles.