IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

Gestion des formulaires : faut-il créer des FormHandler pour alléger nos contrôleurs ?


Sujet :

Symfony PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2019
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2019
    Messages : 67
    Par défaut Gestion des formulaires : faut-il créer des FormHandler pour alléger nos contrôleurs ?
    Bonjour à tous,

    J'ai pu lire sur d'anciens tutoriels / documentation, qu'il était possible de créer des FormHandler afin de déléguer le traitement des formulaires sur Symfony.

    J'ai moi-même mis en place cette technique sur certains projets, mon but principal étant d'alléger le ou les controllers au maximum...
    Cependant j'aimerai l'avis de personnes avisées concernant cette méthode, est-ce une bonne pratique ou non sur la dernière version de Symfony ?

    Je me pose la question car je ne vois rien à ce sujet sur la documentation récente.
    En fait je me retrouve parfois avec des actions de controleurs, qui doivent gérer 3 ou 4 formulaires sur la même vue... On se retrouve donc rapidement avec des dizaines de lignes c'est pourquoi l'idée d'un FormHandler me séduit

    Je me permets de vous poster un petit exemple simplifié pour illustrer mes propos.

    App\Controller\ContactController
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    /**
         * @Route("/contact/{contact_id}", name="edit_contact")
         */
        public function editContact(Request $request)
        {
            $form = $this->createForm(ContactType::class, new Contact(), array(
                'action' => $this->generateUrl('admin_client_contact', array('contact_id' => $contact->getId()))
            ));
     
            $entityManager = $this->getDoctrine()->getManager();
            $contactHandler = new ContactHandler($form, $request, $entityManager);
     
            if ($contactHandler->process()) {
                return $this->redirectToRoute('liste_contacts');
            }
     
            return $this->render('contact.html.twig', [
                'form' => $contactHandler->getForm()->createView()
            ]);
        }
    App\FormHandler\ContactHandler
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     
    class ContactHandler
    {
        protected $request;
        protected $form;
        protected $mailer;
     
        /**
         * @param Form $form
         * @param Request $request
         * @param EntityManagerInterface $entityManager
         *
         */
        public function __construct(Form $form, Request $request, EntityManagerInterface $entityManager)
        {
            $this->form = $form;
            $this->request = $request;
            $this->entityManager = $entityManager;
        }
     
        /**
         * Process form
         *
         * @return boolean
         */
        public function process()
        {
            $this->form->handleRequest($this->request);
     
            if ($this->form->isSubmitted() && $this->form->isValid()) {
                $this->onSuccess();
                return true;
            }
     
            return false;
        }
     
        /**
         * Get form
         *
         * @return
         */
        public function getForm()
        {
            return $this->form;
        }
     
        /**
         * Persist on success
         */
        protected function onSuccess()
        {
            $this->entityManager->persist($this->form->getData()).
            $this->entityManager->flush();
        }
    }
    Aujourd'hui je me retrouve avec ce problème, car je souhaite gérer 4 ou 5 formulaires pour certains quasi-identiques sur la même vue...

    Tous les avis seront les bienvenus !

    Merci d'avance,
    PhiMau

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Mai 2008
    Messages
    1 576
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 1 576
    Par défaut
    Je ne me souviens pas avoir vu précisément cette technique des formhandlers dans la doc de symfony; mais tout ce qui permet de retirer du contrôleur tout ce qui n'a pas directement lié à une Request ou une Response est une bonne idée.

  3. #3
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2019
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2019
    Messages : 67
    Par défaut
    Merci pour cette réponse, donc le code exemple que j'ai montré ne vous choque pas ? (le fait que le "form->handlerequest" se fasse en dehors du controleur, etc..)
    Effectivement j'ai peut être vu ça sur un tuto et non sur une DOC officielle...

    Si d'autres personnes veulent également témoigner de leurs habitudes concernant la gestion de formulaires multiples, je suis preneur

  4. #4
    Membre éprouvé
    Homme Profil pro
    Developpeur
    Inscrit en
    Juillet 2014
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Juillet 2014
    Messages : 102
    Par défaut
    Un grand oui personnel pour cette pratique.
    Moins il y a de code dans le controller mieux c'est pour moi.

  5. #5
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2019
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2019
    Messages : 67
    Par défaut
    Je me sens moins seul grâce à vos avis

    Je posterai plus tard le code de mon Controller et de mon FormHandler pour montrer à quoi ça ressemble.
    On sait jamais, si quelqu'un veut me faire une petite revue de code gratos

    En fait j'ai une vue qui permet à l'utilisateur d'ouvrir plusieurs fenêtres modals :
    - Un modal pour uploader une vidéo locale (fichier depuis son PC)
    - Un modal pour poster une vidéo distante (URL d'une vidéo distante)
    - Un modal pour poster une vidéo youtube

    Ce qui nous fait 3 formulaires différents mais très similaires, et qui au final vont persister dans la même table Video...
    Sans parler des autres modals / formulaires qui permettent d'upload de l'image ou du PDF.

    D'où la crainte d'encombrer mon contrôleur avec tout ça !

    Bref merci à vous deux !
    Bonne soirée

  6. #6
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2019
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2019
    Messages : 67
    Par défaut
    Bonjour,

    Je me permets d'up ce topic avec une autre question concernant ce principe de traitement de formulaire dans un service au lieu d'un contrôleur...

    J'ai modifié un peu mon code dans le but que mon service "FormHandler" gère tout :
    - création du formulaire
    - traitement
    - sauvegarde de l'entité

    Du coup j'injecte certains composants dans mon service comme le FormFactory, mais aussi Router (obligé car j'appelle la méthode "generateUrl" pour assigner l'action du formulaire).
    J'appelle aussi TokenStorage car j'ai besoin d'effectuer un "getUser" au moment de persister l'entité...

    Ma question est simple, est-ce que ça reste une bonne pratique ? Ou bien ces actions devraient être réservées au contrôleur ?
    Sachant que j'ai quand même laissé la redirection dans le contrôleur.

    Voici le code pour illustrer mes propos :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
     
    class InterventionPhotoHandler
    {
        private $requestStack;
        private $form;
        private $photosDirectory;
        private $currentUser;
        private $fileUploader;
        private $imageProcessing;
        private $formFactory;
        private $router;
     
        /**
         * Initialize the handler with the form and the request
         */
        public function __construct
        (
            RequestStack $requestStack,
            EntityManagerInterface $entityManager,
            ContainerInterface $container,
            TokenStorageInterface $tokenStorageInterface,
            FileUploader $fileUploader,
            ImageProcessing $imageProcessing,
            FormFactoryInterface $formFactory,
            RouterInterface $router
        )
        {
            $this->requestStack = $requestStack;
            $this->entityManager = $entityManager;
            $this->photosDirectory = $container->getParameter('photos_directory');
            $this->currentUser = $tokenStorageInterface->getToken()->getUser();
            $this->fileUploader = $fileUploader;
            $this->imageProcessing = $imageProcessing;
            $this->formFactory = $formFactory;
            $this->router = $router;
        }
     
        public function init(Intervention $intervention)
        {
            $interventionPhoto = new InterventionPhoto();
            $interventionPhoto->setIntervention($intervention);
     
            $form = $this->formFactory->create(InterventionPhotoType::class, $interventionPhoto, [
                'action' => $this->router->generate('admin_' . $intervention->getType() . '_edit', array("intervention_id" => $intervention->getId())),
                'method' => 'POST',
                'photo_types' => $photo_types
            ]);
     
            $this->form = $form;
     
            return $this->form;
        }
     
        /**
         * Process form
         *
         * @return boolean
         */
        public function process()
        {
            $this->form->handleRequest($this->requestStack->getCurrentRequest());
     
            if ($this->form->isSubmitted() && $this->form->isValid()) {
                $this->onSuccess();
                return true;
            }
     
            return false;
        }
     
        public function setForm(Form $form)
        {
            $this->form = $form;
        }
     
        /**
         * Get form
         *
         * @return
         */
        public function getForm()
        {
            return $this->form;
        }
     
        /**
         * Persist on success
         */
        protected function onSuccess()
        {
            $interventionPhoto = $this->form->getData();
            /** @var Symfony\Component\HttpFoundation\File\UploadedFile $file */
            $file = $this->form->getData()->getFichier();
     
            $targetDirectory = $this->photosDirectory;
            $thumbTargetDirectory = $targetDirectory . '/thumbs';
     
            $fileName = $this->fileUploader->upload($file, $targetDirectory);
     
            if (!$fileName)
                return false;
     
            copy($targetDirectory . '/' . $fileName, $thumbTargetDirectory . '/' . $fileName);
            $this->imageProcessing->resizeImage($targetDirectory . '/' . $fileName, 1920);
            $this->imageProcessing->resizeImage($thumbTargetDirectory . '/' . $fileName, 250);
     
            $interventionPhoto->setNom($fileName);
            $interventionPhoto->setFichier($fileName);
            $interventionPhoto->setUser($this->currentUser);
     
            // Sauvegarde dans la base de données
            $this->entityManager->persist($interventionPhoto);
            $this->entityManager->flush();
        }
    }
    Et voici le seul code restant dans l'action de mon contrôleur qui s'en retrouve allégé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    $form = $contactHandler->init($contact);
     
            if ($contactHandler->process()) {
                // Action facultative lorsque le formulaire est envoyé...
                return $this->redirectToRoute('admin_client_contacts', array('client_id' => $contact->getClientId()));
            }
     
            return $this->render('admin/client_contact/contact.html.twig', [
                'contact' => $contact,
                'client' => $contact->getClient(),
                'form' => $form->createView()
            ]);
    Merci d'avance pour vos conseils !

Discussions similaires

  1. Gestion des erreurs pour runtime
    Par cbleas dans le forum Runtime
    Réponses: 1
    Dernier message: 09/12/2006, 14h18
  2. Réponses: 6
    Dernier message: 09/06/2006, 12h17
  3. Question des gestions des genres pour livre, BD...
    Par Oberown dans le forum Schéma
    Réponses: 3
    Dernier message: 16/09/2004, 16h58
  4. Gestion des modifications pour un enregistrement
    Par Pascal Jankowski dans le forum Bases de données
    Réponses: 3
    Dernier message: 10/03/2004, 14h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo