如何在Symfony中显示表单错误



我想了解如何显示来自表单的错误。目前,当我验证项目中的任何表单时,都不会出现任何内容。

如何在Symfony中显示表单错误?

谢谢你的帮助。

你可以从看到我的代码

  • register.html.twit文件,其中显示了帮助用户注册的用户表单
  • UserController.php文件,您可以在其中查看验证用户表单时会发生什么
  • 还有User.phpUserType.php

register.html.trick

{% 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 AppControllerFront;
use AppEntityUser;
use AppFormUserType;
use DoctrineORMEntityManagerInterface;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentRoutingAnnotationRoute;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentPasswordHasherHasherUserPasswordHasherInterface;
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 AppEntity;
use AppRepositoryUserRepository;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineCommonCollectionsCollection;
use DoctrineDBALTypesTypes;
use DoctrineORMMapping as ORM;
use SymfonyComponentSecurityCoreUserPasswordAuthenticatedUserInterface;
use SymfonyComponentSecurityCoreUserUserInterface;
#[ORMEntity(repositoryClass: UserRepository::class)]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORMId]
#[ORMGeneratedValue]
#[ORMColumn]
private ?int $id;
#[ORMColumn(length: 180, unique: true)]
#[AssertNotBlank(message:'Tu as oublié d'entrer ton adresse e-mail.')]
#[AssertEmail(message: 'Entre une adresse e-mail valide.')]
private ?string $email = null;
/**
* @var string The hashed password
*/
#[ORMColumn]
#[AssertNotBlank(message:'Tu as oublié de créer un mot de passe.')]
#[AssertLength(min: 6, minMessage: 'Crée un mot de passe de 6 caractères minimum.')]
private ?string $password = null;
#[ORMColumn(length: 255)]
#[AssertNotBlank(message:'Tu as oublié de sélectionner ton genre.')]
private ?string $gender = null;
#[ORMColumn(length: 255)]
#[AssertNotBlank(message:'Tu as oublié d'entrer ton prénom.')]
#[AssertLength(min: 2, minMessage: 'Écris un prénom valide.')]
private ?string $firstname = null;
#[ORMColumn(length: 255)]
#[AssertNotBlank(message:'Tu as oublié d'entrer ton nom de famille.')]
#[AssertLength(min: 2, minMessage: 'Écris un nom de famille valide.')]
private ?string $lastname = null;
#[ORMColumn(type: Types::DATE_MUTABLE)]
#[AssertNotBlank(message:'Tu as oublié de sélectionner ta date de naissance.')]
private ?DateTimeInterface $birthdate = null;
#[ORMColumn(length: 255)]
#[AssertNotBlank(message:'Tu as oublié de nous dire ce que tu fais.')]
#[AssertLength(min: 2, minMessage: 'Écris une occupation valide.')]
private ?string $occupation = null;
#[ORMManyToOne(inversedBy: 'users')]
#[AssertNotBlank(message:'Tu as oublié de nous sélectionner le pays d'où tu viens.')]
private ?Country $nationality = null;
#[ORMManyToOne(inversedBy: 'users')]
#[AssertNotBlank(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 AppForm;
use AppEntityUser;
use AppEntityCountry;
use AppEntityLanguage;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyBridgeDoctrineFormTypeEntityType;
use SymfonyComponentOptionsResolverOptionsResolver;
use SymfonyComponentFormExtensionCoreTypeTextType;
use SymfonyComponentFormExtensionCoreTypeChoiceType;
use SymfonyComponentFormExtensionCoreTypeSubmitType;
use SymfonyComponentFormExtensionCoreTypeBirthdayType;
use SymfonyComponentFormExtensionCoreTypePasswordType;
use SymfonyComponentFormExtensionCoreTypeRepeatedType;
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'
]);
}
}

--这个问题仍然悬而未决。——

编辑:我找到了显示错误消息的方法。但这个问题仍然存在:密码不会显示错误信息。我不明白为什么。

尝试测试"名字";例如,在表单中只键入2个字符,最小长度为3,则会出现表单错误还是没有?

use SymfonyComponentValidatorConstraints as Assert;
#[ORMColumn(length: 255)]
#[AssertNotBlank]
#[AssertLength(min: 3)]
private ?string $firstname = null;
/**
* @AssertNotBlank(
*     message="Mot de passe ne doit pas être vide."
* )
* @AssertLength(
*     min="6",
*     max="32",
*     minMessage="Mot de passe doit avoir au minimum ({{ limit }}) caractères.",
*     maxMessage="Mot de passe doit avoir au maximum ({{ limit }}) caractères."
* )
* @AssertLength(max=4096)
*/
private $plainPassword;
public function getPlainPassword(): ?string
{
return $this->plainPassword;
}
public function setPlainPassword(?string $password): self
{
$this->plainPassword = $password;
return $this;
}

表单类型:

use SymfonyComponentValidatorConstraintsLength;
use SymfonyComponentValidatorConstraintsNotBlank;
->add('plainPassword', RepeatedType::class, array(
'type' => PasswordType::class,
'first_options'  => array(
'label' => 'Mot de passe (6 caractères au minimum)',
'constraints' => [
new NotBlank([
'message' => 'Mot de passe ne doit pas être vide',
]),
new Length([
'min' => 6,
'minMessage' => 'Mot de passe doit avoir au minimum {{ limit }} caractères',
'max' => 4096,
]),
],
),
'second_options' => array('label' => 'Confirmation'),
'invalid_message' => 'Les deux mots de passe ne sont pas identiques'
))

控制器:

use SymfonyComponentPasswordHasherHasherUserPasswordHasherInterface;
private UserPasswordHasherInterface $passwordHasher;
public function __construct(UserPasswordHasherInterface $passwordHasher)
{
$this->passwordHasher = $passwordHasher;
}
if ($form->isSubmitted() && $form->isValid()) {
$user->addRole('ROLE_AAAAAA');
$user->setPassword(
$this->passwordHasher->hashPassword($user, $form->get('plainPassword')->getData()));
// ...........
}

树枝形式:

{% if not userform.vars.valid %}
<div class="alert alert-danger">
{{ form_errors(userform) }}
{% for children in userform.children %}
{% if not children.vars.valid %}
{{ form_errors(children) }}
{% endif %}
{% for child in children %}
{% if not child.vars.valid %}
{{ form_errors(child) }}
{% endif %}
{% endfor %}
{% endfor %}
</div>
{% endif %}

<div class="col-md-6">
{{ form_row(form.plainPassword.first) }}
</div>
<div class="col-md-6">
{{ form_row(form.plainPassword.second) }}
</div>

_我认为User类有问题,您没有为表单设置任何验证:https://symfony.com/doc/current/forms.html#validating-形成

验证是通过向类中添加一组称为(验证(约束的规则来完成的。您可以将它们添加到实体类或表单类中。

尝试向类中添加一些规则(#[Assert\NotBlank](,如果不合适,表单将抛出错误。

_此外,您需要将User类中字段的默认值(=null(删除到需要填充的变量中(至少您需要删除不能为null的ID(。

_在每个字段的表单中,您将"error_bubbling"设置为true:https://symfony.com/doc/current/reference/forms/types/text.html#error-气泡

如果为true,则此字段的任何错误都将传递给父字段或窗体。例如,如果在普通字段上设置为true,那么该字段的所有错误都将附加到主窗体,而不是特定字段。

如果你想控制每个字段,我认为你需要删除这个选项,那么symfony会在每个字段上附加错误。或者,您可以允许此选项,但随后您需要更新Alertdiv中的代码,以不呈现每个字段,而是呈现父字段或窗体。

相关内容

  • 没有找到相关文章

最新更新