Symfony 2.4, el libro oficial

12.7. Creando clases de formulario

En las secciones anteriores, los formularios se creaban y utilizaban directamente desde el controlador. Sin embargo, se recomienda como una buena práctica definir los formularios en sus propias clases PHP independientes de los controladores. De esta forma puedes reutilizar el mismo formulario en diferentes partes de la aplicación. Para ello, crea en primer lugar una nueva clase con toda la lógica necesaria para crear el formulario:

// src/Acme/TaskBundle/Form/Type/TaskType.php
namespace Acme\TaskBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('task');
            ->add('dueDate', null, array('widget' => 'single_text'))
            ->add('save', 'submit');
    }

    public function getName()
    {
        return 'task';
    }
}

Esta nueva clase contiene todas las indicaciones necesarias para crear el formulario (observa que el método getName() devuelve un identificador único para este tipo de formulario). Ahora ya puedes utilizar esta clase para construir rápidamente un formulario en el controlador:

// src/Acme/TaskBundle/Controller/DefaultController.php

// añade esta nueva declaración al principio de la clase
use Acme\TaskBundle\Form\Type\TaskType;

public function newAction()
{
    $task = ...;
    $form = $this->createForm(new TaskType(), $task);

    // ...
}

Cuando la lógica del formulario reside en su propia clase, esto significa que puedes reutilizar fácilmente el formulario en cualquier parte del proyecto. Esta es la mejor manera de crear formularios, pero hacerlo así o de la otra forma depende exclusivamente de ti.

Truco Cuando un formulario gestiona un objeto, se establece una relación con todas las propiedades del objeto. De esta forma, si el formulario contiene un campo que no corresponde con ninguna propiedad del objeto, se produce una excepción.

Si necesitas añadir campos adicionales en el formulario (por ejemplo para incluir la típica casilla de "Estoy de acuerdo con estos términos y condiciones") que no se van a asociar con ninguna propiedad del objeto, debes establecer la opción mapped a false:

use Symfony\Component\Form\FormBuilderInterface;

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('task');
        ->add('dueDate', null, array('mapped' => false))
        ->add('save', 'submit');
}

Además, si el formulario contiene campos que no se incluyen en los datos enviados por el usuario, a esos campos se les asigna el valor null.

Los datos de cada campo se pueden acceder en un controlador con el método getData():

$form->get('dueDate')->getData();