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://db_user:db_password@127.0.0.1:3306/blog?serverVersion=5.7&charset=utf8mb4"
Sustituyendo db_user
y db_password
por los valores apropiados y blog
es el nombre de la base de datos.
Por ejemplo,
1
DATABASE_URL="mysql://root:sa@127.0.0.1:3306/blog?serverVersion=5.7&charset=utf8mb4"
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.