Les formulaires sous Symfony 6

La création et le traitement des formulaires HTML sont difficiles et répétitifs. Vous devez vous occuper du rendu des champs de formulaire HTML, de la validation des données soumises, du mappage des données du formulaire en objets et bien plus encore. Symfony inclut une puissante fonctionnalité de formulaire qui fournit toutes ces caractéristiques et bien plus encore pour des scénarios vraiment complexes.

Installation

Dans les applications utilisant Symfony Flex, exécutez cette commande pour installer la fonctionnalité de formulaire avant de l’utiliser :

composer require symfony/form

Utilisation

Le flux de travail recommandé pour travailler avec les formulaires Symfony est le suivant :

Construire le formulaire dans un contrôleur Symfony ou en utilisant une classe de formulaire dédiée ;
Rendre le formulaire dans un modèle pour que l’utilisateur puisse le modifier et le soumettre ;
Traiter le formulaire pour valider les données soumises, les transformer en données PHP et en faire quelque chose (par exemple, les conserver dans une base de données).

Chacune de ces étapes est expliquée en détail dans les sections suivantes. Pour rendre les exemples plus faciles à suivre, ils supposent tous que vous construisez une petite application de liste Todo qui affiche des « tâches ».

Les utilisateurs créent et modifient les tâches à l’aide de formulaires Symfony. Chaque tâche est une instance de la classe Task suivante :

// src/Entity/Task.php
namespace App\Entity;

class Task
{
    protected $task;
    protected $dueDate;

    public function getTask(): string
    {
        return $this->task;
    }

    public function setTask(string $task): void
    {
        $this->task = $task;
    }

    public function getDueDate(): ?\DateTime
    {
        return $this->dueDate;
    }

    public function setDueDate(?\DateTime $dueDate): void
    {
        $this->dueDate = $dueDate;
    }
}

Cette classe est un « plain-old-PHP-object » car, jusqu’à présent, elle n’a rien à voir avec Symfony ou toute autre bibliothèque. C’est un objet PHP normal qui résout directement un problème dans votre application (c’est-à-dire le besoin de représenter une tâche dans votre application). Mais vous pouvez également modifier les entités Doctrine de la même manière.

Types de formulaire

Avant de créer votre premier formulaire Symfony, il est important de comprendre le concept de « type de formulaire ». Dans d’autres projets, il est courant de faire la différence entre « formulaires » et « champs de formulaire ». Dans Symfony, tous sont des « types de formulaire » :

  1. un seul champ de formulaire est un « type de formulaire » (par exemple TextType) ;
  2. un groupe de plusieurs champs HTML utilisés pour saisir une adresse postale est un « type de formulaire » (par exemple PostalAddressType) ;
  3. un complet avec plusieurs champs pour modifier un profil d’utilisateur est un « type de formulaire » (par exemple, UserProfileType).
  4. Cela peut être déroutant au début, mais cela vous semblera assez vite naturel. En outre, cela simplifie le code et rend la « composition » et l' »intégration » des champs de formulaire beaucoup plus faciles à mettre en œuvre.

Il existe des dizaines de types de formulaires fournis par Symfony et vous pouvez également créer vos propres types de formulaires.

Construire des formulaires

Symfony fournit un objet « form builder » qui vous permet de décrire les champs du formulaire en utilisant une interface fluide. Plus tard, ce constructeur crée l’objet de formulaire réel utilisé pour rendre et traiter le contenu.

Création de formulaires dans les contrôleurs

Si votre contrôleur s’étend à partir de AbstractController, utilisez l’aide createFormBuilder() :

// src/Controller/TaskController.php
namespace App\Controller;

use App\Entity\Task;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class TaskController extends AbstractController
{
    public function new(Request $request): Response
    {
        // creates a task object and initializes some data for this example
        $task = new Task();
        $task->setTask('Write a blog post');
        $task->setDueDate(new \DateTime('tomorrow'));

        $form = $this->createFormBuilder($task)
            ->add('task', TextType::class)
            ->add('dueDate', DateType::class)
            ->add('save', SubmitType::class, ['label' => 'Create Task'])
            ->getForm();

        // ...
    }
}

Si votre contrôleur ne s’étend pas à AbstractController, vous devrez récupérer les services dans votre contrôleur et utiliser la méthode createBuilder() du service form.factory.

Dans cet exemple, vous avez ajouté deux champs à votre formulaire – task et dueDate – correspondant aux propriétés task et dueDate de la classe Task. Vous avez également attribué à chacun un type de formulaire (par exemple TextType et DateType), représenté par son nom de classe entièrement qualifié. Enfin, vous avez ajouté un bouton de soumission avec une étiquette personnalisée pour soumettre le formulaire au serveur.

Création de classes de formulaire

Symfony recommande de mettre le moins de logique possible dans les contrôleurs. C’est pourquoi il est préférable de déplacer les formulaires complexes vers des classes dédiées plutôt que de les définir dans les actions du contrôleur. De plus, les formulaires définis dans des classes peuvent être réutilisés dans plusieurs actions et services.

Les classes de formulaires sont des types de formulaires qui implémentent FormTypeInterface. Cependant, il est préférable d’étendre à partir de AbstractType, qui implémente déjà l’interface et fournit quelques utilitaires :

// src/Form/Type/TaskType.php
namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('task', TextType::class)
            ->add('dueDate', DateType::class)
            ->add('save', SubmitType::class)
        ;
    }
}

Astuce : Installez le MakerBundle dans votre projet pour générer des classes de formulaires en utilisant les commandes make:form et make:registration-form.