Symfony 2.0, el libro oficial

12.11. Usando un formulario sin clase

Los formularios están casi siempre asociados a un objeto, cuyas propiedades se asocian a los campos del formulario. Esto es exactamente lo que se ha visto hasta ahora en este capítulo con la clase Task.

No obstante, en ocasiones puede que necesites utilizar un formulario sin una clase, y obtener un array de los datos enviados por el usuario. El siguiente ejemplo muestra cómo puedes hacerlo:

// asegúrate de importar el espacio de nombres Request
use Symfony\Component\HttpFoundation\Request;
// ...

public function contactAction(Request $request)
{
    $defaultData = array('message' => 'Type your message here');
    $form = $this->createFormBuilder($defaultData)
        ->add('name', 'text')
        ->add('email', 'email')
        ->add('message', 'textarea')
        ->getForm();

        if ($request->getMethod() == 'POST') {
            $form->bindRequest($request);

            // data es un array con claves 'name', 'email', y 'message'
            $data = $form->getData();
        }

    // ... renderiza el formulario ...
}

Por omisión, los formularios suponen que quieres trabajar con arrays de datos en vez de con objteos. Existen dos maneras de cambiar este comportamiento para asociar los datos a un objeto:

  1. Pasa un objeto al crear el formulario (como primer argumento de createFormBuilder o segundo argumento de createForm);
  2. Declara la opción data_class en tu formulario.

Si no haces ninguna de estas dos cosas, entonces el formulario devolverá los datos como un array. En este ejemplo, como $defaultData no es un objeto (y no se ha establecido la opción data_class), el método $form->getData(), devuelve un array.

Truco También puedes acceder a los valores POST (en este caso name) directamente a través del objeto Request, de la siguiente manera:

$this->get('request')->request->get('name');

No obstante, ten en cuenta que en la mayoría de los casos es mejor utilizar el método getData(), ya que devuelve los datos (generalmente un objeto), después de que el componente de formularios los haya transformado.

12.11.1.  Añadiendo la validación

Lo único que le falta a todos los formularios anteriores es la validación. Por lo general, cuando llamas a $form->isValid(), el objeto es validado aplicando las restricciones que añadiste a esa clase. Pero si el formulario no está asociado a una clase, ¿cómo se pueden definir reglas de validación en el formulario?

La respuesta es configurar las restricciones a mano y añadirlas al formulario. La idea está mejor explicada en el capítulo de validación de este mismo libro, pero a continuación se muestra un ejemplo sencillo:

use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\MinLength;
use Symfony\Component\Validator\Constraints\Collection;

$collectionConstraint = new Collection(array(
    'name' => new MinLength(5),
    'email' => new Email(array('message' => 'Invalid email address')),
));

// crear un formulario sin valore por defecto y pasarle las
// reglas de validación
$form = $this->createFormBuilder(null, array(
    'validation_constraint' => $collectionConstraint,
))->add('email', 'email')
    // ...
;

Ahora, al ejecutar el método $form->bindRequest($request), se aplicarán las reglas de validación a todos los datos enviados por el usuario. Si utilizas una clase de formulario, redefine el método getDefaultOptions para especificar la opción:

namespace Acme\TaskBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\MinLength;
use Symfony\Component\Validator\Constraints\Collection;

class ContactType extends AbstractType
{
    // ...

    public function getDefaultOptions(array $options)
    {
        $collectionConstraint = new Collection(array(
            'name' => new MinLength(5),
            'email' => new Email(
                array('message' => 'Invalid email address')
            ),
        ));

        return array('validation_constraint' => $collectionConstraint);
    }
}

Ahora ya dispones de la flexibilidad de crear formularios con validación y que devuelvan un array de datos en vez de un objeto. Casi siempre es mejor asociar los formularios a objetos, pero para los formularios sencillos este es un método muy práctico.