Symfony 8.2 Nouveauté Publié le

Décrire un formulaire par attributs

Les champs d'un formulaire se déclarent sur le DTO, juste à côté des contraintes de validation : plus de classe de formulaire pour les cas simples.

Notions abordées : FormulaireDTO

Nouveau dans Symfony 8.2 (en développement). Un formulaire simple demandait jusqu'ici une classe à part — ou un createFormBuilder() au milieu du contrôleur — alors que ses champs suivent de près les propriétés du DTO, où les contraintes de validation sont déjà déclarées par attributs. #[AsFormType] et #[FormField] réunissent les deux.

Avant

$form = $this->createFormBuilder($message)
    ->add('nom')
    ->add('email', EmailType::class)
    ->add('message', TextareaType::class, ['label' => 'Votre message'])
    ->getForm();

Depuis Symfony 8.2

#[AsFormType]
class MessageContact
{
    #[FormField]
    #[Assert\NotBlank]
    public ?string $nom = null;

    #[FormField(EmailType::class)]
    #[Assert\NotBlank]
    #[Assert\Email]
    public ?string $email = null;
}
$form = $this->createForm(MessageContact::class, $message);

La classe marquée #[AsFormType] s'utilise partout où Symfony attend un nom de type de formulaire. Ses propriétés marquées #[FormField] en deviennent les champs, dans l'ordre où elles sont écrites : le type est deviné faute d'être précisé, et le deuxième argument porte les options du champ. Le conteneur lit ces attributs à la compilation : une erreur, comme deux champs de même nom, se voit au vidage du cache et non en pleine requête.

Les attributs décrivent des champs, rien de plus. Un formulaire qui a besoin d'événements, de transformateurs de données ou de champs dynamiques garde sa classe de formulaire — ou reçoit une extension de type.

À faire

Réécrivez le formulaire de contact : les trois champs se déclarent sur MessageContact, et ContactController se contente de demander le formulaire de ce type. La page /contact doit se comporter comme avant, libellé « Votre message » compris.

D'où vient la fonctionnalité : la pull request d'origine.