Symfony 1.4, la guía definitiva

10.6. Usos alternativos de los formularios

10.6.1. Clases de formulario

Después de incluir todas las opciones, validadores y parámetros, el formulario de contacto creado en la clase de la acción parece un poco enmarañado:

// en modules/mimodulo/actions/actions.class.php
// Definir el formulario
$this->form = new sfForm();
$this->form->setNameFormat('contacto[%s]');
$this->form->setIdFormat('mi_formulario_%s');

$this->form->setWidgets(array(
  'nombre'  => new sfWidgetFormInputText(),
  'email'   => new sfWidgetFormInput(array('default' => '[email protected]')),
  'asunto'  => new sfWidgetFormChoice(array('choices' => array('Asunto A', 'Asunto B', 'Asunto C'))),
  'mensaje' => new sfWidgetFormTextarea(),
));
$this->form->setValidators(array(
  'nombre'  => new sfValidatorString(),
  'email'   => new sfValidatorEmail(),
  'asunto'  => new sfValidatorString(),
  'mensaje' => new sfValidatorString(array('min_length' => 4))
));

Una buena práctica consiste en crear una clase de formulario con todo el código anterior e instanciarla en todas las acciones que necesiten un formulario de este tipo. A continuación se muestra cómo crear una clase para el formulario de contacto:

// en lib/form/ContactoForm.class.php
class ContactoForm extends sfForm
{
  protected static $asuntos = array('Asunto A', 'Asunto B', 'Asunto C');

  public function configure()
  {
    $this->setNameFormat('contacto[%s]');
    $this->setIdFormat('mi_formulario_%s');
    $this->setWidgets(array(
      'nombre'  => new sfWidgetFormInputText(),
      'email'   => new sfWidgetFormInput(array('default' => '[email protected]')),
      'asunto'  => new sfWidgetFormChoice(array('choices' => array('Asunto A', 'Asunto B', 'Asunto C'))),
      'mensaje' => new sfWidgetFormTextarea(),
    ));
    $this->setValidators(array(
      'nombre'  => new sfValidatorString(),
      'email'   => new sfValidatorEmail(),
      'asunto'  => new sfValidatorString(),
      'mensaje' => new sfValidatorString(array('min_length' => 4))
    ));
    $this->setDefaults(array(
      'email' => '[email protected]'
    ));
  }
}

Ahora en la acción se pueden crear formularios de contacto fácilmente:

// en modules/mimodulo/actions/actions.class.php
// Definir el formulario
$this->form = new ContactoForm();

10.6.2. Modificar un objeto de formulario

Cuando utilizas clases de formulario, sus propiedades se definen fuera de la acción. Esto hace que sea difícil asignar valores por defecto de forma dinámica. Por eso las clases de formulario admiten como primer parámetro un array de valores por defecto:

// en modules/mimodulo/actions/actions.class.php
// Definir el formulario
$this->form = new ContactoForm(array('email' => '[email protected]'));

También se pueden redefinir los widgets y validadores de cada campo mediante los métodos setWidget() o setValidator(). No obstante, como los widgets y los validadores son objetos, Symfony define una API para manipularlos.

However, widgets and validators are objects in symfony, and offer a clean API to modify their properties:

// en modules/mimodulo/actions/actions.class.php
// Definir el formulario
$this->form = new ContactoForm();

// Permitir seleccionar varios idiomas
$form->getWidget('idioma')->setOption('multiple', true);

// Añadir un widget para elegir el sexo
$form->setWidget('sexo', new sfWidgetFormChoice(array('expanded' => true, 'choices' => array('h' => 'Hombre', 'm' => 'Mujer')), array('class' => 'miclase')));

// Modificar los atributos HTML del widget 'asunto'
$form->getWidget('asunto')->setAttribute('disabled', 'disabled');

// Eliminar el campo 'asunto'
unset($form['asunto'])

// No se puede eliminar sólo un widget. Al eliminarlo, Symfony también elimina todos sus validadores

// Cambiar el error 'min_length' del validador 'mensaje'
$form->getValidator('mensaje')->setMessage('min_length', 'Este mensaje es muy corto');

// Convertir el campo 'nombre' en opcional
$form->getValidator('nombre')->setOption('required', false);