#Symfony — découpler la gestion des formulaires
Symfony est doté d’un excellent composant Form très puissant, qui permet de créer tout type de formulaire. Il est possible de gérer, côté serveur, la soumission et la validité des données du formulaire. Ensuite il reste à coder le traitement à réaliser si le formulaire est valide.
Généralement, cette étape est réalisée dans le controleur Symfony. Et c’est là que la bât blaisse… En effet, un controleur a pour rôle de recevoir une requête et de renvoyer une réponse. Le reste, ce n’est pas à lui de le gérer !
Je vous propose donc d’utiliser ce bundle : https://github.com/Digivia/form-handler pour gérer le traitement de vos formulaires dans une classe dédiée à cet effet.
Ce bundle va vous permettre, depuis votre controleur, d’instancier une classe dédié au traitement du formulaire, un “form handler”.
Ce form handler, comprend une méthode “process”, qui va se charger de recevoir le formulaire et ses données, et va alors effectuer le traitement souhaité : hydrater la base de données, envoyer un mail, ajouter un flash message (session), ou tout ce que vous voulez faire d’autre 😉
Depuis votre controleur, vous allez piloter la réponse à renvoyer au travers de 2 fonctions callables. La première, “onSuccess”, va renvoyer une réponse si le fomulaire a été soumis, et est valide, après que le traitement de la méthode “process” ai été réalisé. Le bundle va automatiquement ajouter à cette réponse le code HTTP 303 (See other). La seconde, “render”, va gérer le cas ou le form n’a pas encore été soumis, et le cas où le form a été soumis mais n’est pas valide (il faut donc le ré-afficher en indiquant les champs en erreur, et ça c’est très bien géré en natif par le composant Form). Dans ce dernier cas, le bundle va automatiquement ajouter un code HTTP 422 (Unprocessable entity) à la réponse.
Dans la pratique, nous allons avoir dans notre controleur, par exemple pour une entité Post :
public function edit(
HandlerFactoryInterface $factory,
Request $request, Post $post
) : Response
{
// On instancie le form handler
$handler = $factory->createHandler(PostFormHandler::class); // On défini l'entité à traiter
$handler->setData($post); // Traitement et renvoi de la réponse via le form handler
return $handler->handle(
$request, // En cas de succès, on renvoi sur la page du post
function (Post $post) use ($request) {
return $this->redirectToRoute(
'post_show',
['id' => $post->getId()]
);
}, // Formulaire non envoyé / non valide : on l'affiche
function (FormView $formView, $data) {
return $this->render('conference/edit.html.twig', [
'form' => $formView,
'post' => $data
]);
}
);
}
Comme vous pouvez le constater, le controleur ne s’occupe que de recevoir une requête, d’effectuer une demande de traitement au form handler, et de renvoyer une réponse…
La partie traitement du formulaire (s’il est valide), quand à elle, va s’effectuer dans le form handler :
<?php
namespace App\Form\Handler;
use App\Form\Type\PostFormType;
use Digivia\FormHandler\Handler\AbstractHandler;
use Doctrine\ORM\EntityManagerInterface;
class PostFormHandler extends AbstractHandler
{
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}
protected function process($data, array $options): void
{
$this->em->persist($data);
$this->em->flush();
}
protected function provideFormTypeClassName(): string
{
// Your form class
return PostFormType::class;
}
}
Le form handler, via sa méthode “provideFormTypeClassName” va s’occuper d’instancier le FormType. Il va, depuis le controleur, créer le form et le soumettre si la requête en a été faite. Cela simplifie grandement les traitements, et permet de bien ranger chaque action à la bonne place.
N’hésitez pas à me faire part de votre avis sur ce bundle, de vos retours, ou demandes d’amélioration 🙂