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 :

Surcharger la classe Form


Sujet :

Symfony PHP

  1. #1
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut Surcharger la classe Form
    Bonjour,

    Je souhaite surcharger la classe Form au sein d'un bundle pour pouvoir ajouter des méthodes à mon formulaire.
    Je sais comment créer un FieldType custom, mais je ne sais pas comment surcharger la classe Form. En effet, le FormBuilder me renvoie toujours une instance de Form.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    <?php
    namespace Snafu\SnafBundle\Form;
     
    use Symfony\Component\Form\Form;
     
    class Myform extends Form
    {
        public function foo()
        {
            return 'hello foo !';
        }
    }
    Comment faire pour créer un formulaire de la classe MyForm ?
    • Avant de poser une question, n'hésitez pas à chercher dans la FAQ et les forums
    • Merci d'utiliser les balises de code (# dans l'éditeur)
    • N'oubliez pas de vous servir des boutons , et

    S.N.A.F.U

  2. #2
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    Je continue de chercher, et je dois bien dire que j'avance dans l'obscurité presque totale.
    Mais finalement, peut-être que mon problème se situe plutôt au niveau du service form.builder ou form.factory

    Comment paramétrer ces deux services ?
    • Avant de poser une question, n'hésitez pas à chercher dans la FAQ et les forums
    • Merci d'utiliser les balises de code (# dans l'éditeur)
    • N'oubliez pas de vous servir des boutons , et

    S.N.A.F.U

  3. #3
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    J'avance, et je patauge...
    Le FormBuilder n'utilise pas de service, mais bien une classe Form codée "en dur".

    Je tente donc un autre truc :

    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
     
    <?php
     
    namespace Snafu\HelpBundle\Form;
     
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilder;
     
    class BasicType extends AbstractType
    {
        public function buildForm(FormBuilder $builder, array $options)
        {
            $builder->add('mon texte', 'text', array('label'=> "mon texte", 'attr' => array('title' => 'foo')));
            $builder->add('email', 'email');
            $builder->add('mon texte2', 'text', array('label'=> "mon texte", 'attr' => array('title' => 'bar')));
            $builder->add('message', 'textarea');
        }
     
        public function getName()
        {
            return 'basic';
        }
     
        public function createBuilder($name, FormFactoryInterface $factory, array $options)
        {
            return new FormBuilder($name, $factory, new EventDispatcher(), $options['data_class']);
        }
     
    }
    Et là le message d'erreur me plante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Fatal error: Declaration of Snafu\HelpBundle\Form\BasicType::createBuilder() must be compatible with that of Symfony\Component\Form\FormTypeInterface::createBuilder() in .../Snafu/HelpBundle/Form/BasicType.php on line 9
    Et là je dis : GNEE ?

    L'interface en question :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
        /**
         * Returns a builder for the current type.
         *
         * The builder is retrieved by going up in the type hierarchy when a type does
         * not provide one.
         *
         * @param string                $name       The name of the builder
         * @param FormFactoryInterface  $factory    The form factory
         * @param array                 $options    The options
         *
         * @return FormBuilder|null A form builder or null when the type does not have a builder
         */
        function createBuilder($name, FormFactoryInterface $factory, array $options);
    Je rate quelque chose, mais quoi ?
    • Avant de poser une question, n'hésitez pas à chercher dans la FAQ et les forums
    • Merci d'utiliser les balises de code (# dans l'éditeur)
    • N'oubliez pas de vous servir des boutons , et

    S.N.A.F.U

  4. #4
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    c'est

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function createBuilder($type, $data = null, array $options = array());

  5. #5
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    Je dois avoir quelque chose dans les yeux, mais je ne vois pas où est écrit cette fonction dans l'interface : j'ai de nouveau téléchargé le framework (au cas où) et j'ai vérifié la méthode Symfony\Component\Form\FormTypeInterface::createBuilder

    Je recolle le source :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
        /**
         * Returns a builder for the current type.
         *
         * The builder is retrieved by going up in the type hierarchy when a type does
         * not provide one.
         *
         * @param string                $name       The name of the builder
         * @param FormFactoryInterface  $factory    The form factory
         * @param array                 $options    The options
         *
         * @return FormBuilder|null A form builder or null when the type does not have a builder
         */
        function createBuilder($name, FormFactoryInterface $factory, array $options);
    Ceci dit, merci Stealth, je vais voir si ça marche dès que je récupère un accès au serveur.
    • Avant de poser une question, n'hésitez pas à chercher dans la FAQ et les forums
    • Merci d'utiliser les balises de code (# dans l'éditeur)
    • N'oubliez pas de vous servir des boutons , et

    S.N.A.F.U

  6. #6
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    Cela ne marche pas.
    La signature donnée par stealth35 ressemble plus à la fonction "createForm" du controller.
    Je ne comprends pas pourquoi l'interface n'est pas respecté.



    Surtout quand je regarde AbstractType qui est la classe mère de mon type :

    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
     
        /**
         * Returns a builder for the current type.
         *
         * The builder is retrieved by going up in the type hierarchy when a type does
         * not provide one.
         *
         * @param string                $name       The name of the builder
         * @param FormFactoryInterface  $factory    The form factory
         * @param array                 $options    The options
         *
         * @return FormBuilder|null A form builder or null when the type does not have a builder
         */
        public function createBuilder($name, FormFactoryInterface $factory, array $options)
        {
            return null;
        }
    • Avant de poser une question, n'hésitez pas à chercher dans la FAQ et les forums
    • Merci d'utiliser les balises de code (# dans l'éditeur)
    • N'oubliez pas de vous servir des boutons , et

    S.N.A.F.U

  7. #7
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut


    Honte sur moi, erreur de namespace. (PHP pourrait être un peu plus causant sur ce problème...)
    Il ne faut pas oublier de déclarer le namespace :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    use Symfony\Component\Form\FormFactoryInterface;
    Je peux continuer mes expérimentations.
    • Avant de poser une question, n'hésitez pas à chercher dans la FAQ et les forums
    • Merci d'utiliser les balises de code (# dans l'éditeur)
    • N'oubliez pas de vous servir des boutons , et

    S.N.A.F.U

  8. #8
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    J'ai réussi pas mal de trucs qui me permettent de mieux comprendre le système de formulaire de SF2, mais je n'arrive pas encore à surcharger ma classe Form.

    Et pourtant je peux énoncer mon problème plus clairement : le controller construit son formulaire via FormFactory::create().

    Cette méthode est assez simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        public function create($type, $data = null, array $options = array())
        {
            return $this->createBuilder($type, $data, $options)->getForm();
        }
    Dans un premier temps, je dois surcharger FormBuilder::getForm(), car cette méthode renvoie une classe Symfony\Component\Form\Form pour obtenir un MyBuilder::getForm() qui renvoie une classe custom MyForm.
    Ca c'est facile. (et il est dommage que le getForm() ne fasse pas appel à un service, cela m'aurait sûrement faciliter la tâche)

    Mais comment faire pour que la factory m'instancie le bon builder ?

    Quelqu'un aurait-il une idée ?
    • Avant de poser une question, n'hésitez pas à chercher dans la FAQ et les forums
    • Merci d'utiliser les balises de code (# dans l'éditeur)
    • N'oubliez pas de vous servir des boutons , et

    S.N.A.F.U

  9. #9
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    j'ai regardé à mon avis faut montrer plus haut et créer ton propre Controller, pas sur que tu puisses en injecter un autre avec le service form.factory

  10. #10
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    J'en ai bien l'impression : j'étais en train de surcharger Controller::createFormBuilder, mais je n'arrive pas à finaliser.

    Mon problème principale vient de la compréhension d'une méthode en particulier : FormFactory::createNamedBuilder

    Si tu as des éclaircissements, je suis preneur !
    • Avant de poser une question, n'hésitez pas à chercher dans la FAQ et les forums
    • Merci d'utiliser les balises de code (# dans l'éditeur)
    • N'oubliez pas de vous servir des boutons , et

    S.N.A.F.U

  11. #11
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    Le Type c'est que pour les champs,
    Faut donc créer ton service, avec ton propre form.factory, ensuite deux solution :
    Soit t’appelles direct le service
    Soit tu crées un nouveau contrôleur qui appelle le service

    EDIT : je vais tester voir si form.type fais aussi les form complets

  12. #12
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    En faisant un form.type direct ça fonctionne. Je regarde si tu peux écraser le type form direct

  13. #13
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    Citation Envoyé par stealth35 Voir le message
    En faisant un form.type direct ça fonctionne. Je regarde si tu peux écraser le type form direct
    Oui, ça fonctionne, parce que Form est un type de champs comme les autres. C'est un peu étrange, mais ça fonctionne. D'ailleurs, le parent de FormType est bien FieldType.

    D'où l'idée que j'ai eu (en faisant du judo, ça aide de se faire mettre sens dessus dessous ), c'est de créer une extension comme pour créer un type de champs custom. Je vais voir jusqu'où cela m'emmène...
    • Avant de poser une question, n'hésitez pas à chercher dans la FAQ et les forums
    • Merci d'utiliser les balises de code (# dans l'éditeur)
    • N'oubliez pas de vous servir des boutons , et

    S.N.A.F.U

  14. #14
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    J'ai réussi, mais c'est crade : trop de boilerplate juste pour ça.

    - création d'un type MyFieldType extends FieldType + définition du service

    - création d'un type MyFormType extends FormType avec MyFieldType comme parent + définition du service

    - création d'un MyBuilder extends FormBuilder qui renvoie MyForm sur la méthode getForm()

    - création des blocks twig nécessaire pour ces types de champs.

    - création d'un BasicType extends AbstractType pour construire le formulaire. Le parent est 'myform', ce qui enclenche la magie de création du formulaire custom.

    Bref, c'est pas satisfaisant du tout. J'espère que la doc sera mise à jour pour savoir comment faire, parce que pour l'instant, c'est un peu obscur...

    Ou bien est-ce Symfony qui est limité sur ce point ?
    • Avant de poser une question, n'hésitez pas à chercher dans la FAQ et les forums
    • Merci d'utiliser les balises de code (# dans l'éditeur)
    • N'oubliez pas de vous servir des boutons , et

    S.N.A.F.U

  15. #15
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    C’était quoi le besoin à la base ?

  16. #16
    Membre expert
    Avatar de s.n.a.f.u
    Homme Profil pro
    Développeur Web
    Inscrit en
    Août 2006
    Messages
    2 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Août 2006
    Messages : 2 760
    Points : 3 545
    Points
    3 545
    Par défaut
    Juste rajouter une méthode toute bête à l'objet formulaire parce que je veux récupérer un attribut sur une source extérieure.

    J'en ai profité pour creuser la surcharge de Form, mais je crois que je vais procéder autrement.

    Par exemple utiliser un CustomFieldType qui se chargera de récupérer le label, si c'est possible.

    Le problème, c'est que la source des labels se trouvent dans un fichier qui porte le nom du formulaire, d'où mon idée de centraliser ça sur le formulaire :
    - construction du formulaire
    - ouverture du fichier de labels
    - itération sur les objets pour leur attribuer un label

    Mais vu le bordel, je pense que je vais faire cela au niveau de l'objet Type. Cela devrait suffire.

    N'empêche : c'est quand même bizarre que le Form ne se surcharge pas plus facilement que ça....
    • Avant de poser une question, n'hésitez pas à chercher dans la FAQ et les forums
    • Merci d'utiliser les balises de code (# dans l'éditeur)
    • N'oubliez pas de vous servir des boutons , et

    S.N.A.F.U

Discussions similaires

  1. Surcharge de classes Struts
    Par blbird dans le forum Struts 1
    Réponses: 8
    Dernier message: 10/11/2006, 13h08
  2. [C#] Comment surcharger la classe DataGrid ?
    Par Dozer71 dans le forum ASP.NET
    Réponses: 8
    Dernier message: 27/07/2006, 13h43
  3. [Struts]control dans la class form
    Par jimi dans le forum Struts 1
    Réponses: 8
    Dernier message: 01/06/2005, 16h50
  4. [MFC] surcharger une classe
    Par exter666 dans le forum MFC
    Réponses: 9
    Dernier message: 16/03/2005, 00h53
  5. Réponses: 12
    Dernier message: 01/07/2004, 11h03

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