Symfony integra el componente Form para simplificar la creación y el manejo de formularios. En nuestra aplicación de ejemplo, el único que caso en el que necesitamos utilizarlo es a la hora de permitir a los usuarios publicar un comentario sobre un determinado post.

Sirven para enviar información a una instancia de una clase, validar los datos y guardarlos en la base de datos.

En el caso de que nosotros, como administradores de la aplicación, queramos añadir un nuevo post, se hará desde un panel de administración que generaremos más adelante.

Generación de Formularios

En los anteriores capítulos definimos una entidad llamada Comment para manejar los comentarios de un post. Ahora, vamos a generar el formulario correspondiente a dicha entidad. Para ello, utilizamos el CLI de Symfony, ejecutando el siguiente comando:

php app/console generate:doctrine:form AppBundle:Comment

Si ahora vamos al directorio /src/AppBundle , vemos que se ha creado un directorio Form y, dentro de éste, se encuentra el formulario generado correspondiente a la entidad Comment .

Un formulario de una entidad obtiene su nombre a partir de: NOMBRE_DE_LA_ENTIDAD + Type . En este caso: CommentType .

Esta clase extiende de Symfony\Component\Form\AbstractType , que implementa algunos métodos para el manejo del formulario como, por ejemplo, buildForm o buildView .

Mediante la interfaz FormBuilderInterface , y utilizando el método add() , se añaden al formulario los campos existentes en la entidad que queremos procesar a través del formulario. Como ejemplo, puedes ver que el campo id no se ha añadido por defecto, ya que es un valor autoincremental que el usuario no debe manejar.

Además, nosotros vamos a elminar también el campo de la relación con Post y sustituirlo por uno de tipo submit, para añadir un botón de guardado al formulario.


<?php

/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('content')
        ->add('Publicar comentario', 'submit')
    ;
}

Construcción de Formularios

Ahora que tenemos creada la clase CommentType , vamos a ver cómo generar un objetode tipo Form . Supongamos que uno de nuestros usuarios ha realizado un petición ( Request ) para visualizar el post cuyo nombre es: Symfony es genial .

Como parámetro GET en la url nos habrá llegado el valor correspondiente al campo id :


 http://myblog.com/2/symfony-es-genial

Lo primero es obtener el registro de dicho post en la base de datos. Después, los comentarios asociados a este post que se hayan hecho con anterioridad y, por último, crear una vista del formulario para permirir añadir más comentarios.


<?php

use AppBundle\Entity\Comment;
use AppBundle\Form\CommentType;

/**
 * @Route("/post/{id}/{slug}", name="blog-post")
 */
public function postAction(Request $request, $id){

  $post = $em->getRepository('AppBundle:Post')->find($id);

  // Obtener los comentarios asociados a este post
  $comments = $post->getComments();

  // Generar un objeto formulario de la entidad Comment
  $comment = new Comment();
  $form = $this->createForm(new CommentType(), $comment);

  // Devolver los datos a la vista

  return $this->render('public/post.html.twig', array(
      'post' => $post,
      'comments' => $comments,
      'form' => $form->createView(),
    ));
}

Si nos fijamos en el array de valores devueltos, vemos que el formulario se devuelve a través del método createView() , el cual genera una HTML para mostrarlo directamente en la vista.

Renderización de Formularios

Utilizando el motor de plantillas Twig , mostrar un formulario es algo tan sencillo como:

{{ form(form) }}

Para profundizar en el tema y mostrar formularios en la vista de forma personalizada, visita el siguiente enlace de la documentación oficial de Symfony: Cómo personalizar el renderizado de formularios .

Validación y Procesamiento

A partir de la versión 2.3 del framework, está disponible el método handleRequest() , que permite procesar los formularios de una forma muy cómoda. Vamos a analizar el resultado final del método postAction() visto anteriormente.

<?php

/**
 * @Route("/post/{id}/{slug}", name="blog-post")
 */
public function postAction(Request $request, $id){

    $em = $this->getDoctrine()->getManager();
    $post = $em->getRepository('AppBundle:Post')->find($id);
    $comments = $post->getComments();

    $comment = new Comment();

    $form = $this->createForm(new CommentType(), $comment);
    $form->handleRequest($request);

    if ($form->isValid()) {

        $comment->setPost($post);
        $em->persist($comment);

        $em->flush();
    }

    return $this->render('public/post.html.twig', array(
        'post' => $post,
        'comments' => $comments,
        'form' => $form->createView()
    ));
}

Una vez creado el formulario, se llama al método handleRequest() , pasando como parámetro de objeto Request de la petición, que contiene toda la información enviada desde el cliente.

De esta forma, el método puede detectar si el formulario ha sido enviado o no. Si ha sido enviado, lo procesa y valida.

Más adelante se ha establecido un if statemente cuya condición es $form->isValid() . Si el formulario no es válido, este método devuelve false , con lo que no entraría a ejecutar el código. En caso contrario lo único que queda por hacer es asociar el comentario al post que estamos visualizando, llamar al método persist() para preparar la consulta SQL y, finalmente al método flush() para ejecutarla.

En cualquier caso, el método termina devolviendo el mismo array de valores para volver a generar la página de visualización del post, con todos sus comentarios asociados y con un nuevo formulario de la entidad Comment .

También se podría realizar una redirección a otra ruta, por ejemplo, un listado de los comentarios con mejor valoración, una vez que se valida el formulario y se guarda el registro.

<?php

if ($form->isValid()) {

    $comment->setPost($post);
    $em->persist($comment);

    $em->flush();

    return $this->redirect($this->generateUrl('comments-rate'));
}


Este post ha sido producido gracias a la colaboración de Sopinet Software .