I wish to understand how to display errors that come from forms. For now, when I validate any form on my project, I don't have anything appearing.
How to display form errors in Symfony ?
Thank you for your help.
You can see my code from :
- register.html.twig file where my userform helping users to register is shown.
- UserController.php file where you can see what happens when userform is validated.
- Also User.php and UserType.php.
register.html.twig
{% extends 'base.html.twig' %}
{% block title %}Incris-toi !{% endblock %}
{% block main %}
{{ form_start(userform) }}
<div class="alert alert-danger text-center" role="alert">
{% set formErrors = userform.vars.errors.form.getErrors(true) %}
{% if formErrors|length %}
<div class="alert alert-danger text-center" role="alert">
{% if userform.vars.value.email == null or userform.vars.value.email != 'email' or userform.vars.value.email != 'unique' %}
{{ form_errors(userform.email) }}
{% elseif userform.vars.value.password|length < 6 %}
{{ form_errors(userform.password) }}
{% elseif userform.vars.value.gender == null or (userform.vars.value.gender != 'male' and userform.vars.value.gender != 'female' and userform.vars.value.gender != 'non-binary') %}
{{ form_errors(userform.gender) }}
{% elseif userform.vars.value.firstname|length < 2 %}
{{ form_errors(userform.firstname) }}
{% elseif userform.vars.value.lastname|length < 2 %}
{{ form_errors(userform.lastname) }}
{% elseif userform.vars.value.birthdate == null %}
{{ form_errors(userform.birthdate) }}
{% elseif userform.vars.value.occupation|length < 2 %}
{{ form_errors(userform.occupation) }}
{% elseif userform.vars.value.nationality == null %}
{{ form_errors(userform.nationality) }}
{% elseif userform.vars.value.nativelanguage == null %}
{{ form_errors(userform.nativelanguage) }}
{% endif %}
</div>
{% endif %}
</div>
{{ form_widget(userform.email) }}
{{ form_widget(userform.password) }}
{{ form_widget(userform.gender) }}
{{ form_widget(userform.firstname) }}
{{ form_widget(userform.lastname) }}
{{ form_widget(userform.birthdate) }}
{{ form_widget(userform.occupation) }}
{{ form_widget(userform.nationality) }}
{{ form_widget(userform.nativelanguage) }}
{{ form_widget(userform.save) }}
{{ form_end(userform) }}
UserController.php
<?php
namespace App\Controller\Front;
use App\Entity\User;
use App\Form\UserType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
class UserController extends AbstractController
{
#[Route('/register', name: 'register', methods: ['GET', 'POST'])]
public function createUser(
Request $request,
EntityManagerInterface $entityManagerInterface,
UserPasswordHasherInterface $userPasswordHasherInterface
){
$user = new User();
$userform = $this->createForm(UserType::class, $user);
$userform->handleRequest($request);
if ($userform->isSubmitted() && $userform->isValid()) {
$user->setRoles(["ROLE_USER"]);
$plainPassword = $userform->get('password')->getData();
$hashedPassword = $userPasswordHasherInterface->hashPassword($user, $plainPassword);
$user->setPassword($hashedPassword);
$entityManagerInterface->persist($user);
$entityManagerInterface->flush();
return $this->redirectToRoute('home');
}
return $this->renderForm('front/register.html.twig', [
'userform' => $userform,
]);
}
User.php
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
#[ORM\Entity(repositoryClass: UserRepository::class)]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id;
#[ORM\Column(length: 180, unique: true)]
#[Assert\NotBlank(message:'Tu as oublié d\'entrer ton adresse e-mail.')]
#[Assert\Email(message: 'Entre une adresse e-mail valide.')]
private ?string $email = null;
/**
* @var string The hashed password
*/
#[ORM\Column]
#[Assert\NotBlank(message:'Tu as oublié de créer un mot de passe.')]
#[Assert\Length(min: 6, minMessage: 'Crée un mot de passe de 6 caractères minimum.')]
private ?string $password = null;
#[ORM\Column(length: 255)]
#[Assert\NotBlank(message:'Tu as oublié de sélectionner ton genre.')]
private ?string $gender = null;
#[ORM\Column(length: 255)]
#[Assert\NotBlank(message:'Tu as oublié d\'entrer ton prénom.')]
#[Assert\Length(min: 2, minMessage: 'Écris un prénom valide.')]
private ?string $firstname = null;
#[ORM\Column(length: 255)]
#[Assert\NotBlank(message:'Tu as oublié d\'entrer ton nom de famille.')]
#[Assert\Length(min: 2, minMessage: 'Écris un nom de famille valide.')]
private ?string $lastname = null;
#[ORM\Column(type: Types::DATE_MUTABLE)]
#[Assert\NotBlank(message:'Tu as oublié de sélectionner ta date de naissance.')]
private ?\DateTimeInterface $birthdate = null;
#[ORM\Column(length: 255)]
#[Assert\NotBlank(message:'Tu as oublié de nous dire ce que tu fais.')]
#[Assert\Length(min: 2, minMessage: 'Écris une occupation valide.')]
private ?string $occupation = null;
#[ORM\ManyToOne(inversedBy: 'users')]
#[Assert\NotBlank(message:'Tu as oublié de nous sélectionner le pays d\'où tu viens.')]
private ?Country $nationality = null;
#[ORM\ManyToOne(inversedBy: 'users')]
#[Assert\NotBlank(message:'Tu as oublié de nous sélectionner ta langue maternelle.')]
private ?Language $nativelanguage = null;
public function __construct()
{
$this->events = new ArrayCollection();
$this->participations = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->email;
}
/**
* @see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getGender(): ?string
{
return $this->gender;
}
public function setGender(string $gender): self
{
$this->gender = $gender;
return $this;
}
public function getFirstname(): ?string
{
return $this->firstname;
}
public function setFirstname(string $firstname): self
{
$this->firstname = $firstname;
return $this;
}
public function getLastname(): ?string
{
return $this->lastname;
}
public function setLastname(string $lastname): self
{
$this->lastname = $lastname;
return $this;
}
public function getBirthdate(): ?\DateTimeInterface
{
return $this->birthdate;
}
public function setBirthdate(?\DateTimeInterface $birthdate): self
{
$this->birthdate = $birthdate;
return $this;
}
public function getOccupation(): ?string
{
return $this->occupation;
}
public function setOccupation(string $occupation): self
{
$this->occupation = $occupation;
return $this;
}
public function getNationality(): ?Country
{
return $this->nationality;
}
public function setNationality(?Country $nationality): self
{
$this->nationality = $nationality;
return $this;
}
public function getNativelanguage(): ?Language
{
return $this->nativelanguage;
}
public function setNativelanguage(?Language $nativelanguage): self
{
$this->nativelanguage = $nativelanguage;
return $this;
}
}
UserType.php
<?php
namespace App\Form;
use App\Entity\User;
use App\Entity\Country;
use App\Entity\Language;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\BirthdayType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('gender', ChoiceType::class, [
'choices' => [
'Je suis ...' => '',
'un homme' => 'male',
'une femme' =>'female',
'non-binaire' => 'non-binary'
]
])
->add('lastname')
->add('firstname')
->add('birthdate', BirthdayType::class, [
'placeholder' => [
'year' => 'Année', 'month' => 'Mois', 'day' => 'Jour',
],
'choice_translation_domain' => true
])
->add('occupation')
->add('nationality', EntityType::class, [
'class' => Country::class,
'choice_label' => 'name',
'placeholder' => 'Je choisis un pays'
])
->add('nativelanguage', EntityType::class, [
'class' => Language::class,
'choice_label' => 'name',
'placeholder' => 'Je sélectionne ma langue maternelle'
])
->add('email')
->add('password', PasswordType::class, [
'mapped' => false
])
->add('password', RepeatedType::class, [
'type' => PasswordType::class,
'invalid_message' => 'Les deux mots de passe doivent être identiques.',
'options' => ['attr' => ['class' => 'password-field']],
'required' => true,
'first_options' => ['label' => 'Password'],
'second_options' => ['label' => 'Repeat Password']
])
->add('save', SubmitType::class, [
'attr' => ['class' => 'save'],
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => User::class,
'translation_domain' => 'forms'
]);
}
}
-- This question is still open. --
EDIT : I have found the way to display error messages. But this problem persists : password doesn't show its error message. I don't understand why.
UserandUserTypefiles.