Contactez-nous

Créer un type de formulaire simple avec `make:form`

Apprenez à générer et configurer une classe de type de formulaire (FormType) dans Symfony en utilisant la commande `make:form` pour définir les champs, types et options de votre formulaire.

Le concept de `FormType` : Définir la structure de votre formulaire en PHP

Dans Symfony, la structure d'un formulaire n'est pas directement écrite en HTML dans un template, mais plutôt définie en PHP à travers une classe spécifique appelée "type de formulaire" (ou `FormType`). Cette approche orientée objet offre plusieurs avantages : la réutilisabilité (un même type de formulaire peut être utilisé à plusieurs endroits), la testabilité, et une meilleure organisation du code. Un `FormType` est responsable de décrire les champs qui composent le formulaire, leurs types (texte, email, case à cocher, liste déroulante, etc.), leurs options de configuration (libellés, valeurs par défaut, contraintes de validation) et comment ils sont liés aux données sous-jacentes (généralement un objet entité ou un tableau).

Chaque type de formulaire est une classe qui implémente l'interface Symfony\Component\Form\FormTypeInterface, bien qu'il soit plus courant d'hériter de la classe Symfony\Component\Form\AbstractType qui fournit une implémentation de base pratique. La méthode principale à implémenter est buildForm(FormBuilderInterface $builder, array $options), où vous utiliserez un objet FormBuilderInterface pour ajouter et configurer les champs de votre formulaire.

Utilisation de la commande `php bin/console make:form`

Symfony, via son composant MakerBundle, propose des commandes pour générer du code récurrent, ce qui accélère le développement. Pour créer un nouveau type de formulaire, la commande php bin/console make:form est votre alliée. Elle génère le squelette d'une classe de type de formulaire, que vous pourrez ensuite personnaliser.

Pour notre gestionnaire de tâches, nous voulons créer un formulaire permettant d'ajouter ou de modifier une tâche. Nommons ce type de formulaire TaskType. Ouvrez votre terminal, naviguez jusqu'à la racine de votre projet Symfony, et exécutez la commande suivante :

php bin/console make:form TaskType

Le MakerBundle vous posera ensuite une question facultative : "The name of the P H P class that the new form will be bound to (e.g. Product)." (Le nom de la classe P H P à laquelle le nouveau formulaire sera lié). Si votre formulaire est destiné à créer ou modifier une entité Doctrine (par exemple, une entité App\Entity\Task), vous pouvez indiquer son nom ici. Cela permettra à Symfony de pré-configurer certaines options et d'inférer les types de champs. Pour notre exemple actuel, où nous travaillons avec des données en dur sous forme de tableau, nous n'avons pas d'entité à lier. Vous pouvez donc simplement appuyer sur "Entrée" pour laisser ce champ vide.

Après l'exécution, la commande vous indiquera qu'un nouveau fichier a été créé : src/Form/TaskType.php. C'est dans ce fichier que nous allons définir la structure de notre formulaire de tâche.

Configuration des champs du formulaire dans la méthode `buildForm`

Ouvrez le fichier src/Form/TaskType.php. Vous y trouverez une classe TaskType qui étend AbstractType, avec deux méthodes principales : buildForm() et configureOptions().

La méthode buildForm(FormBuilderInterface $builder, array $options) est celle où vous définissez les champs de votre formulaire. L'objet $builder est utilisé pour ajouter chaque champ. Pour chaque champ, vous spécifiez :

  1. Son nom (qui sera utilisé comme clé dans les données du formulaire et souvent comme nom d'attribut si lié à une entité).
  2. Son type de champ (par exemple, TextType::class, TextareaType::class, CheckboxType::class, ChoiceType::class, DateType::class, SubmitType::class, etc.). Ces classes de type de champ sont fournies par Symfony et doivent être importées avec une instruction use.
  3. Un tableau optionnel d'options pour configurer le champ (son libellé, s'il est requis, ses attributs HTML, des contraintes de validation, etc.).

Pour notre formulaire de tâche, nous avons besoin au minimum d'un champ pour le titre et d'un champ pour la description. Nous pouvons également ajouter un bouton de soumission directement dans le type de formulaire. Modifions la méthode buildForm comme suit :

namespace App\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType; // Pour les champs texte simples
use Symfony\Component\Form\Extension\Core\Type\TextareaType; // Pour les zones de texte multilignes
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; // Pour les cases à cocher (exemple)
use Symfony\Component\Form\Extension\Core\Type\SubmitType; // Pour les boutons de soumission
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
// Pour les contraintes de validation (si vous les ajoutez ici)
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Length;

class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('title', TextType::class, [
                'label' => 'Titre de la tâche',
                'required' => true, // Le champ est obligatoire
                'attr' => [
                    'placeholder' => 'Ex: Faire les courses',
                    'class' => 'form-control-lg', // Classe CSS pour l'input
                ],
                'constraints' => [ // Exemple de contraintes de validation directement dans le FormType
                    new NotBlank([
                        'message' => 'Veuillez saisir un titre pour la tâche.',
                    ]),
                    new Length(['min' => 3, 'minMessage' => 'Le titre doit comporter au moins {{ limit }} caractères.']),
                ],
            ])
            ->add('description', TextareaType::class, [
                'label' => 'Description détaillée',
                'required' => false, // Le champ est facultatif
                'attr' => [
                    'rows' => 5, // Hauteur de la zone de texte
                    'placeholder' => 'Ajoutez plus de détails sur la tâche (optionnel)...',
                ],
            ])
            // Exemple de champ case à cocher, si on voulait gérer le statut 'completed'
            // ->add('completed', CheckboxType::class, [
            //     'label' => 'Tâche terminée ?',
            //     'required' => false,
            // ])
            ->add('save', SubmitType::class, [
                'label' => 'Enregistrer la tâche',
                'attr' => ['class' => 'btn btn-primary mt-3'], // Classes CSS pour le bouton
            ]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            // 'data_class' => Task::class, // Décommentez si vous liez à une entité Task
            // Par défaut, si data_class n'est pas défini, le formulaire travaille avec des tableaux.
            'csrf_protection' => true, // Active la protection CSRF (activée par défaut)
            'csrf_field_name' => '_token', // Nom du champ CSRF caché
            'csrf_token_id'   => 'task_item', // Identifiant unique pour le token CSRF de ce formulaire
        ]);
    }
}

Dans cet exemple :

  • 'title' est un champ texte (TextType), requis, avec un libellé, un placeholder et des contraintes de validation (NotBlank pour s'assurer qu'il n'est pas vide, Length pour une longueur minimale).
  • 'description' est une zone de texte (TextareaType), non requise, avec un libellé et un placeholder.
  • 'save' est un bouton de soumission (SubmitType) avec un libellé personnalisé.

La méthode configureOptions(OptionsResolver $resolver) permet de définir des options par défaut pour ce type de formulaire. L'option la plus courante est data_class, qui spécifie la classe de l'objet auquel ce formulaire sera lié. Si elle n'est pas définie, le formulaire s'attendra à travailler avec des données sous forme de tableau. Nous avons aussi ajouté des options pour la protection CSRF, qui est une bonne pratique de sécurité et généralement activée par défaut.

Avec cette classe TaskType configurée, vous disposez maintenant d'une définition réutilisable et structurée pour votre formulaire de tâche, prête à être instanciée dans un contrôleur et affichée dans un template Twig.