veilletech.fr
18 sept. Feed du jour
#06 SYMFONY Article

Symfony 8.2 : le formulaire dans le DTO

Une classe de formulaire qui ne fait que répéter les propriétés du DTO n'a jamais rien décrit d'autre que le DTO.

Symfony 8.2 permet de déclarer un formulaire directement sur la classe qui porte les données, avec les attributs #[AsFormType] et #[FormField], au lieu d'écrire une classe de type de formulaire séparée. Tout est résolu à la compilation du conteneur, et rien n'est déprécié.

2 min de lectureintermédiairevidéo 1:13
Partager
Sommaire4 sections
  1. Ce qui se passe
  2. Ce que ça change vraiment
  3. Les limites à connaître avant de migrer
  4. À retenir

Ce qui se passe

Un formulaire simple en Symfony demande aujourd'hui deux classes : le DTO qui porte les données, et le type de formulaire qui redécrit les mêmes champs juste à côté. Symfony 8.2 permet de supprimer la seconde, en posant deux attributs sur la première. Contribution de Benjamin Georgeault, PR #60563.

PHP
// src/Dto/UserDto.php
namespace App\Dto;

use Symfony\Component\Form\Attribute\AsFormType;
use Symfony\Component\Form\Attribute\FormField;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;

#[AsFormType(options: ['label' => 'User'])]
class UserDto
{
    // pas de type : il est deviné, comme avec $builder->add()
    #[FormField]
    public ?string $name = null;

    #[FormField(EmailType::class)]
    public ?string $email = null;

    #[FormField(TextareaType::class, ['label' => 'Bio'])]
    public ?string $bio = null;

    // champ « publicName », mappé ici via l'option property_path
    #[FormField(name: 'publicName')]
    public ?string $internalName = null;
}

Le nom de la classe s'utilise ensuite partout où un nom de type de formulaire est attendu :

PHP
$form = $this->createForm(UserDto::class, $userDto);

Ce que ça change vraiment

L'intérêt n'est pas la concision, c'est le moment où l'erreur se voit. Symfony lit ces attributs en compilant le conteneur de services et fabrique un service de type de formulaire ordinaire. Un nom de champ en double échoue donc à la construction du conteneur, pas à la première requête qui affiche le formulaire.

Cela suppose que la classe soit scannée par le conteneur avec l'autoconfiguration. La configuration livrée par défaut couvre src/ — mais elle exclut src/Entity/, ce qui est à garder en tête si vos données vivent là.

Les limites à connaître avant de migrer

PHP
#[FormField(ChoiceType::class, [
    'choice_loader' => new Reference(TagChoiceLoader::class),
])]
public array $tags = [];

À retenir

Rien n'est déprécié. Symfony le dit clairement : les classes de formulaire restent la bonne réponse dès qu'un formulaire demande autre chose qu'une liste de champs. La nouveauté vise les formulaires simples adossés à des DTO — c'est précisément là que la classe séparée n'apportait rien.

Source : New in Symfony 8.2: Attribute-based Forms, Symfony Blog, 17 septembre 2026.