2.0 ¿Qué aprenderemos?
- A conectar con una base de datos
- A generar entidades y repositorios
- A generar formularios
- A guardar los datos del formulario en la base de datos
- A realizar validaciones en los campos
- A personalizar los campos de los formularios
2.1 Base de datos
En esta parte del curso vamos a crear el formulario para que se puedan enviar mensajes.

2.1.1 Conexión con la base de datos
Para crear la base de datos, hemos de modificar el archivo .env introduciendo los datos de conexión apropiados. En el caso de MySql es la siguiente:
1
DATABASE_URL=mysql://root:sa@127.0.0.1:3306/blog
Para crearla se usa el comando:
1
php bin/console doctrine:database:create
2.1.2 Creación de la entidad Contact
El primer paso para trabajar con la Base de Datos es definir la entidad en la que debemos almacenar los datos. En principio, una entidad equivale a una tabla en la base de datos. Para crearla usamos el siguiente comando:
1
php bin/console make:entity
Nos pedirá los nombres y atributos de los campos de la entidad:
Ahora ya sólo nos queda crear la tabla asociada en la base de datos mediante los siguientes comandos:
1
php bin/console make:migration
Y por último aplicar la migración:
1
php bin/console doctrine:migrations:migrate
2.1.3 Clases Contact y ContactRepository
Al ejecutar el comando php bin/console make:entity Symfony ha creados dos archivos. Uno llamado App\Entity\Contact.php que almacena la definición de la entidad-tabla y otro llamado App\Repository\ContactRepository.php que es la clase encargada de realizar las tareas de base de datos relacionadas con la entidad Contact.
2.2 Formulario
Una vez hemos definido la entidad que va a almacenar los datos introducidos, vamos a crear el formulario. Symfony posee un comando que, automáticamente, crea un formulario a partir de la entidad subyacente.
1
php bin/console make:form ContactForm Contact
El código generado en Form\ContactFormType.php es el siguiente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
namespace App\Form;
use App\Entity\Contact;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ContactFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('firstName')
->add('lastName')
->add('email')
->add('subject')
->add('message');
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Contact::class,
]);
}
}
Y falta añadirle el botón submit
1
2
3
4
5
...
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
...
->add('message')
->add('Send', SubmitType::class, array('label' => 'Send'));
Ya solo queda renderizarlos. Para ello, ve a la plantilla page/contact.html.twig y localiza el formulario. Sustitúyelo por el siguiente código:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{{ form_start(form, {'attr': {'class':'form-horizontal'}}) }}
{{ form_errors(form) }}
<div class="form-group">
<div class="col-xs-6">
{{ form_row(form.firstName, {'attr': {'class':'form-control'}}) }}
</div>
<div class="col-xs-6">
{{ form_row(form.lastName, {'attr': {'class':'form-control'}}) }}
</div>
</div>
<div class="form-group">
<div class="col-xs-12">
{{ form_row(form.email, {'attr': {'class':'form-control'}}) }}
</div>
</div>
<div class="form-group">
<div class="col-xs-12">
{{ form_row(form.subject, {'attr': {'class':'form-control'}}) }}
</div>
</div>
<div class="form-group">
<div class="col-xs-12">
{{ form_row(form.message, {'attr': {'class':'form-control'}}) }}
{{ form_row(form.Send, {'attr': {'class':'pull-right btn btn-lg sr-button'}}) }}
</div>
</div>
{{ form_end(form) }}
Hemos cambiado el tag
1
<form>
por
1
2
{{ form_start(form, {'attr': {'class':'form-horizontal'}}) }}
{{ form_errors(form) }}
y
1
</form>
por
1
{{ form_end(form) }}
Además, cada uno de los campos los hemos cambiado por su etiqueta twig equivalente. Por ejemplo
1
2
<label class="label-control">First Name</label>
<input class="form-control" type="text">
por
1
{{ form_row(form.firstName, {'attr': {'class':'form-control'}}) }}
2.2.1 Personalizar campos
Ahora mismo el campo Email es de tipo text. Vamos a modificar el formulario para que renderice un campo de tipo email. Modifica la clase ContactFormType :
1
2
3
4
...
use Symfony\Component\Form\Extension\Core\Type\EmailType;
...
->add('email', EmailType::class)
Ya sólo nos queda añadir el formulario en el controlador:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
use Doctrine\Persistence\ManagerRegistry;
use App\Entity\Contact;
...
#[Route('/contact', name: 'contact')]
public function contact(ManagerRegistry $doctrine, Request $request): Response
{
$contact = new Contact();
$form = $this->createForm(ContactFormType::class, $contact);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$contacto = $form->getData();
$entityManager = $doctrine->getManager();
$entityManager->persist($contacto);
$entityManager->flush();
return $this->redirectToRoute('index', []);
}
return $this->render('page/contact.html.twig', array(
'form' => $form->createView()
));
}

2.2.2 Validar campos
En este momento hay campos en la parte del cliente que tienen el atributo required por lo que no se puede enviar el formulario si no se han rellenado. Pero esta restricción se puede saltar con las herramientas del desarrollador del navegador.
Por ejemplo, vamos a eliminar el atributo required del campo First Name mediante la herramienta Firebug de Firefox.


Ahora al enviar el formulario se producirá el siguiente error:

Esto es así porque el campo first_name no puede ser nulo.
Para que esto no pase, vamos a modificar la entidad Contact para añadirle aserciones. Por ejemplo vamos a obligar a que el campo firstName no pueda estar vacío:
1
2
3
4
5
6
...
use Symfony\Component\Validator\Constraints as Assert;
...
#[ORM\Column(length: 255)]
#[Assert\NotBlank(message: "Field `First Name` is mandatory")]
private $firstName;
De esta forma ahora se mostrará un mensaje de error al no enviar dicho dato. Realiza el mismo cambio para el resto de campos obligatorios.
Para el email también podemos obligarlo a que tenga un correo válido:
1
2
3
4
#[ORM\Column(length: 255)]
#[Assert\NotBlank(message: "Field `email` is mandatory")]
#[Assert\Email(message:"{{ value }} is not a valid email")]
private $email;
2.2.3 Reto - Página thankyou
Ahora mismo cuando se envía un Mensaje, se redirecciona al usuario a la ruta index. Modifica el controlador contact para que redirija a la ruta thankyou. Puedes usar un Jumbotron de Bootstrap para el diseño.

Deberás crear una nueva ruta, un controlador y una plantilla.