Symfony: tutorial 11: los formularios

Symfony creación de formularios

Otra de las mejores cosas que tiene Symfony es el manejo y creación de los formularios. Podríamos seguir creando formularios a la antigua, mediante HTML, construyendo poco a poco dichos formularios. Pero si quieres ser realmente productivo construyendo aplicaciones que gestionan mucha información, interactuando con los usuarios, deberías de usar ésta herramienta y aprovechar lo que Symfony nos ofrece.

Es decir, tenemos un componente de Symfony que automatiza gran parte de la creación, y recepción de los datos de formularios. Les puedes añadir fácilmente tokens de seguridad, generar formularios responsivos con Bootstrap de forma automática, generarlos automáticamente a partir de la definición de la base de datos, y un largo muy largo etcétera.

Un poco de teoría sobre formularios

De forma tradicional, los formularios se defininen mediante HTML, CSS y Javascript. Y se reciben los datos en el servidor mediante PHP para nuestro caso.

Mediante el componente symfony/form gran parte de la generación de formularios se hace en el servidor. Es decir, con Symfony deberíamos de tener en PHP la generación del formulario. Este formulario se lo pasamos a la plantilla Twig como un objeto en donde lo pintamos. Si lo hacemos así nos ahorramos el generar todo el HTML, CSS y Javascript que antes teníamos que hacer. Incluso si usamos la plantilla Bootstrap para los formularios haremos que esta generación sea responsiva. Y para rizar el rizo, tenemos un montón de validaciones automáticas de los campos.

Es decir, con Symfony deberíamos de tener en PHP la generación del formulario.

Me repito más que el ajo, podemos seguir trabajando los formularios a la antigua, pero estaríamos sacrificando una de las herramientas de Symfony que más productividad te puede dar a la hora de crear aplicaciones web.

Y además, para la recepción de formularios mediante Symfony, tenemos una serie de funciones que nos harán más fácil la vida. Podemos recibir automáticamente los datos en un objeto si así lo queremos, y hasta comprobar si es válido el formulario, devolviendo los errores definidos mediante las asserts.

Un ejemplo de estudio, para trabajar los formularios

Es más fácil verlo con un ejemplo, que explicar los muchos casos. Imaginemos que creamos una aplicación para gestionar una agenda de contactos. Creamos el proyecto:

composer create-project symfony/skeleton symfony-agenda-contactos
cd symfony-agenda-contactos
composer require --dev maker server
composer require doctrine twig form validator security-csrf annotations

Y creamos una entidad que llamamos Contact:

php bin/console make:entity Contact

Respondiendo a lo que nos pregunta el generador de código de Symfony desde línea de comando, creo los siguientes campos para la entidad Contact:

  • Name: de tipo string de 255 caracteres.
  • Email: de tipo string de 255 caracteres.
  • PhoneNumber: de tipo string de 255 caracteres.
  • Observations: de tipo text.

Con todo esto se nos generarán los ficheros src/Entity/Contact.php y src/Repository/ContactRepository.php con todo el código fuente. Lo siguiente que propongo es usar el generador de CRUDs, ya que una de las cosas que crea es el formulario, junto con el controlador y todas las acciones de guardado. Ejecutamos:

php bin/console make:crud Contact

Y se nos generarán automáticamente los siguientes ficheros:

created: src/Controller/ContactController.php
created: src/Form/ContactType.php
created: templates/contact/_delete_form.html.twig
created: templates/contact/_form.html.twig
created: templates/contact/edit.html.twig
created: templates/contact/index.html.twig
created: templates/contact/new.html.twig
created: templates/contact/show.html.twig

Ahora podemos arrancar la nueva agenda de contactos para probarla haciendo:

php bin/console server:start

Tenemos que crear la base de datos para poder usar esta agenda así que configuramos nuestro fichero .env del proyecto, le ponemos conexión a la BD y luego hacemos hacemos esto:

php bin/console doctrine:database:create
php bin/console doctrine:schema:create

Ahora ya podemos conectar al servidor local en: http://127.0.0.1:8000/contact Y podremos probar nuestra nueva agenda de contactos. Podremos crear nuevos contactos, listarlos, editarlos o borrarlos, que son las cuatro acciones CRUD.

Poniendo bonitos los formularios, haciéndolos responsivos

Como éste post va sobre formularios, vamos a centrarnos sólo en la pantalla de creación de nuevo contacto. Lo ideal sería hacer un layout molón para toda la aplicación web, definir cabeceras, pies, menús, etc.. Así que sólo usaremos esta ruta: http://127.0.0.1:8000/contact/new

Le vamos a añadir Bootstrap, jQuery y vemos qué tal queda.. Para esto editamos el fichero templates/base.html.twig y lo dejamos así:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>

</head>
<body class="container">
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>

Marco en negrita lo que he modificado. Lo siguiente es editar la configuración de Twig, para que renderice los formularios usando el tema de Bootstrap. Para esto editamos el fichero config/packages/twig.yaml y le ponemos la siguiente línea marcada en negrita:

twig:
form_themes: ['bootstrap_4_layout.html.twig']

Si todo ha ido bien, ya tenemos que ver por pantalla el siguiente formulario en la dirección http://127.0.0.1:8000/contact/new

Ya tenemos un CRUD completo responsivo, en pocos minutos, en una aplicación web para gestionar nuestra agenda de contactos. Notarás que hay muchos detalles que mejorar, pero también notarás que en unos minutos nos hemos ahorrado, probablemente horas, de haberlo hecho todo esto con HTML, CSS, Javascript y PHP a pelo.

El controlador, la recepción del formulario

Ahora viene mucha de la magia de Symfony en todo esto de los formularios. En este ejemplo hemos usado una entidad como base del formulario. De esta forma que ya hemos visto toda la parte de programación de cliente. Vamos ahora con la parte de programación de servidor.

Abriendo el controlador que hemos generado automáticamente, nos sirve de guia para crear cualquier otro manejo de formularios. Siempre se hace igual, o parecido. Vamos a la función de esta pantalla, que es la de la función new, para crear un nuevo contacto en la agenda. Abrimos el fichero src/Controller/ContactController.php y veremos esto:

    /**
* @Route("/new", name="contact_new", methods={"GET","POST"})
*/
public function new(Request $request): Response
{
// Recibe los datos del formulario
// y los carga en un objeto de tipo Contact.
$contact = new Contact();
$form = $this->createForm(ContactType::class, $contact);
$form->handleRequest($request);


if ($form->isSubmitted() && $form->isValid()) {
// Si el formulario se ha enviado y es válido
// guarda los datos del contacto en la BD.
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($contact);
$entityManager->flush();

// Redirige al listado de contactos.
  return $this->redirectToRoute('contact_index');
}

// Te lleva al formulario de nuevo contacto.
return $this->render('contact/new.html.twig', [
'contact' => $contact,
'form' => $form->createView(),
]);
}
Marco en negrita lo que es la recepción del formulario en PHP. Esas tres líneas te generan un objeto de tipo Contact con todos sus datos tal y como los hemos definido.

La definición del formulario

Lo siguiente para ver cómo funcionan los formularios son las clases que los definen. En esta versión de Symfony tendremos nuestros formularios bajo el directorio src/Form/ y todos tendrán la nomenclatura NombreFormularioType.php. Siguiendo el post del ejemplo si abrimos el fichero src/Form/ContactType.php veremos esto:

<?php

namespace App\Form;

use App\Entity\Contact;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ContactType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('email')
->add('phoneNumber')
->add('observations')
;
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Contact::class,
]);
}
}

Las dos líneas que he marcado en negrita son las que hacen que este formulario cargue o llene una entidad de Doctrine. Sí, así de sencillo. Más bien dicho así de sencillo no, porque esto es el principio. En la función buildForm es donde tenemos la mayoría de las configuraciones que harán muchas cosas en el pintado del formulario.

Configurando los campos de formulario

Esto se puede hacer de dos formas, en la definición del formulario en PHP y/o en la plantilla de Twig. Por ejemplo podríamos definir un campo de la forma:

            ->add('nombreCampo', ChoiceType::class, [
'label' => 'Etiqueta del campo',
'choices' => [
'Opción 1' => 'valor1',
'Opción 2' => 'valor2',
],
'help' => 'Esto es el texto que sale debajo de la caja.',
])

Marco en negrita la ayuda, que es un pequeño gran detalle nuevo que la verdad que ayuda mucho y en Symfony 2 y 3 no lo tuvimos.

En el Twig, curioseando un poco más la generación del formulario en las plantillas, podríamos ver un formulario definido como el siguiente:

{{ form(form) }}

Sí, con sólo una línea en el Twig, quedaría pintado todo el formulario en la plantilla. Pero si quisiéramos desglosarlo un poco más, podríamos tener un formulario más definido como el siguiente:

{{ form_start(form, {'attr':{'onsubmit': 'saveWithSearchedLocation()'}}) }}
{{ form_row(form.imageFile) }}
{{ form_row(form.publicPhoneNumber, {'attr': {'value' : app.user.publicPhoneNumber}}) }}
{{ form_end(form) }}

Ésto se podría desglosar más aún, de forma que cada row podríamos desglosarla en el Twig usando las siguientes funciones:

{{ form_label(form.publicPhoneNumber) }}
{{ form_errors(form.publicPhoneNumber) }}
{{ form_widget(form.publicPhoneNumber) }}
{{ form_help(form.publicPhoneNumber }}

Los formularios de Symfony son una de las herramientas más potentes, para ser muy productivos en el desarrollo web, que he visto. Así que mejor me remito a la documentación oficial para escudriñar cada campo, y dejo aquí esto como una breve introducción.

Terminando

Ya me estoy extendiendo demasiado en este post, de nuevo. Así que para no aburrirte más, si es que has llegado hasta aquí, me queda citar dos cosas muy interesantes: los asserts y un par de componentes que mejoran los formularios enormemente.

Los asserts son una serie de validaciones que le pones en las entidad asociada a un formulario. Las pones como comentarios en annotations del fichero de la entidad. Es muy potente porque configuras esto y Symfony se encarga también de hacer la validación y mostrar los errores en el frontend al usuario. ¡Una maravilla! Con esto te ahorras también horas y horas.

Los dos componentes que tengo en mente para los que hayan llegado hasta aquí abajo, y tengan ganas de curiosear un poco, son el CKEditor y el VichUploader. Con el CKEditor puedes tener un campo de formulario que sea un área de texto en forma de editor WYSIWYG. El VichUploader es para hacer un campo de formulario que sea un fichero para subir al servidor.

Recapitulando, con el componente de formularios (y algunas vitaminas en forma de módulos extra) te puedes ahorrar horas y horas de árduo trabajo, además de que serás mucho más productivo creando webs con formularios.

Otro día más, aquí que lo dejo y en breve me voy al sobre.. ¡Un saludo!

Compartir..

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

3 × 2 =