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.