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 :

Embedded forms & bind() [1.x]


Sujet :

Symfony PHP

  1. #1
    Membre Expert Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Par défaut Embedded forms & bind()
    Bonjour,

    Mon problème est le suivant : je génère un formulaire personnalisé dans lequel j'embarque n sous-formulaires correspondant à une classe.

    Après avoir submit mon formulaire, les données contenues dans mon post se présentent de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    post:
      1_1: { quantity: '1', partner_sales_assistant_id: '6', partner_sales_manager_id: '6', dotation_id: '1', partner_id: '1' }
      1_2: { quantity: '1', partner_sales_assistant_id: '8', partner_sales_manager_id: '8', dotation_id: '1', partner_id: '2' }
    Je n'ai donc pas un tableau contenant les données de mes n sous formulaires, mais n tableau contenant les valeurs de chaque sous formulaire.

    J'aimerais pouvoir bind (et save par la même occasion) chacun des sous formulaires avec les tableaux contenus dans mon post.

    Pour cela : j'ai tenté de faire ça de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $this->embeddedForms = new sfForm();
     
    foreach($this->partners as $partner)
    {
      $form = new DotationPartnerForm();
      $this->embeddedForms->embedForm($this->dotation->getId().'_'.$partner->getId(), $form);
    }
    foreach($this->embeddedForms as $name => $form)
    {
      $form->bind($request->getParameter($name));
    }
    Mais une erreur m'est retournée : Call to undefined method sfFormField::bind(). ->ligne 10.
    J'en conclus donc que les éléments de mon embeddedForms ne sont pas des form et ça me contrarie beaucoup mais soit.

    J'avais alors pensé bind le parent ($this->embeddedForms) mais je ne sais pas comment du fait que mon post ne renvoie pas un tableau avec des sous tableaux mais directement tous mes sous tableaux.

    Qu'avez-vous à me suggérer ? Merci.

  2. #2
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Par défaut
    Tout refaire ?

    Bon, on va jeter un oeil

    Je ne suis pas bien sur d'avoir compris la partie du départ, mais tu veux faire des embed sur trois niveau, un form qui contiens des forms qui contiennent des forms ?

    Si non, ta construction de form est loin d'être académique et de faire du form un objet indépendant.

    bind est une méthode de sfForm.

    Pour le reste, il va falloir plus d'information

  3. #3
    Membre Expert Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Par défaut
    Citation Envoyé par Michel Rotta Voir le message
    Tout refaire ?
    NONNNNNNNNNNN !!!!!

    Ok je reformule !

    D'abord il y a deux classes DOTATION, et PARTNER. Et entre : il y a une table DOTATIONPARTNER. Le schema (simplifié) donne ça :

    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
    Dotation:
      columns:
        id:                               { type: integer(11), primary: true, autoincrement: true }
        name:                             { type: string(255) }
     
    Partner:
      columns:
        id:                               { type: integer(11), primary: true, autoincrement: true }
        name:                             { type: string(255) }
      relations:
        Dotations:                        { class: Dotation, refClass: DotationPartner, foreignAlias: Partners }
     
    DotationPartner:
      columns:
        dotation_id:                      { type: integer(11), primary: true }
        partner_id:                       { type: integer(11), primary: true }
        quantity:                         { type: integer(11) }
        partner_sales_assistant_id:       { type: integer(11) }
        partner_sales_manager_id:         { type: integer(11) }
      relations:
        Dotation:                         { foreignAlias: DotationPartners, onDelete: CASCADE }
        Partner:                          { foreignAlias: DotationPartners, onDelete: CASCADE }
        PartnerAssistant:                 { class: Profile, local: partner_sales_assistant_id, foreign: id, foreignAlias: AssistantDotationPartners }
        PartnerManager:                   { class: Profile, local: partner_sales_manager_id, foreign: id, foreignAlias: ManagerDotationPartners }
    Une action de dotation me permet d'afficher un formulaire composé d'autant de sous-formulaire qu'il y a de Partner déja liés, afin de remplir les trois autres champs de ma table intermédiaire. J'arrive donc sur une page avec l'identifiant d'une dotation et c'est sur cette dotation qu'on va travailler et éditer tous les champs pour tous les partenaires associés.

    Je souhaite donc créer un grand formulaire dans lequel il y a n formulaires qui correspondent à cette classe : DotationParner.

    Pour ça j'ai donc créé un formulaire vierge : un simple sfForm(), dans lequel pour chaque partenaire je lui envoie le DotationPartnerForm associé.

    Le reste c'est le principe classique du formulaire, je submit, je renvoie sur la même action et si mon formulaire n'est pas valide je garde les valeurs qui ont été submit et j'affiche les messages d'erreur sur tous mes sous-formulaires.

    Là ou ça coince c'est lorsque je veux bind les résultats postés avec mon form. La j'ai essayé plusieurs techniques toutes moins académiques les unes que les autres (par exemple embarquer un formulaire qui était bound ->impossible) et la dernière en date consistait à imbriquer mon formulaire global (qui imbriquait déja les sous-formulaires) dans un autre form global, pour avoir un seul objet dans mon POST (et non n résultats comme je les ai décris dans mon premier post), lequel je pourrai alors bind sur ce nouveau form global.

    Mais avant d'exploiter cette piste, j'aimerais dans un premier temps savoir quelle serait la manière la plus simple et la plus esthétique de procéder dans mon cas ... si tant est que je me sois expliqué clairement.

  4. #4
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Par défaut
    Si j'ai bien compris, tu essayes de binder un form qui embarque (embed) des form qui embarquent des form... soit trois niveau.

    Des essais que j'ai vu passer ici, ceci ne peut pas fonctionner, les embed se limitent à un niveau de profondeur. Du moins je n'ai vu personne y arriver. Je n'ai personnellement jamais essayé.

    Après, je ne vois pas trop comment traiter la chose élégamment (au niveau du code). Est-il envisageable de mettre tout une ribambelle de form (au sens HTML) en place ? Ce qui limiterai la modification a un enregistrement (pas glop).

    Autre solution, un jeu de form (avec embed de Partner) plus un form pour la Dotation de base. Par contre, il faudra le jouer fin pour la récupération (bind) mais on n'aurais plus le problème de la profondeur. Perso, je partirais par là.

  5. #5
    Membre Expert Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Par défaut
    Hmmmm, je ne vois que deux niveaux : le formulaire global, et les sous-formulaires de la classe DotationPartner qui se trouvent à l'intérieur. D'ailleurs lors du POST, le résultat est sur un seul niveau -> une ligne par sous-formulaire.

    La première solution n'est pas envisageable : on doit pouvoir faire la configuration de tous les éléments des DotationPartner associés à une dotation en une seule fois (sous-entendu : lors de la soumission du formulaire, on doit pouvoir tout sauvegarder en une fois).

    La deuxième ne semble pas correspondre à ce que je veux : le but étant non pas de configurer les partners mais bien les éléments de la table intermédiaire, donc je dois forcément afficher des forms de DotationPartner. De plus, tous les champs - qu'il s'agisse de la dotation ou du partner - sont déjà remplis, et même les relations sont faites. Il n'y a donc que trois champs à remplir et il ne me semble pas adapté d'embarquer les formulaires : ni de partner, ni de dotation.

    Compte tenu de ce que j'arrive à récupérer dans mon post je me sens si près du but ... j'ai l'impression qu'il ne manque que 3 ou 4 lignes de code pour y parvenir. Et j'aimerais juste éviter la solution qui consiste à surcharger la méthode bind pour autoriser les embed qui me semble un peu barbare.

  6. #6
    Membre éprouvé
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2011
    Messages
    124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2011
    Messages : 124
    Par défaut
    De ce que j'ai compris, je cherche à faire la même chose que toi mais je n'ai pas trouvé la solution. Si tu la trouves, pourrais-tu partager ?

  7. #7
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Par défaut
    J'avais compris que tu voulais modifier les Partner depuis le Dotation qui leur est lié.

    Si tu ne veux travaillé que sur les tables Dotation et DotationPartener il ne devrait (presque) pas y avoir de difficultés. La seul limite du système est que l'enregistrement Dotation doit exister avant de pouvoir lui lier des DotationPartner. Il faut donc procéder en deux étapes pour la création d'un enregistrement sur Dotation : Création de l'enregistrement puis ré affichage (en édition ou pas) et création des enfants.

    Après il reste le code donné au début du sujet qui me semble un peu confus et que j'ai du mal à localisé. A priori, la construction du formulaire devrait prendre place dans la méthode configure du form de départ : Dotation.

    Tu as un plugin qui pourrait t'aider la dessus, regarde dans le sujet épinglé de la salle consacrée aux plugins.

  8. #8
    Membre Expert Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Par défaut
    Ça y est ça fonctionne ! \o/

    Je partage le source complet de mon action :

    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
    $dotation = Doctrine_Core::getTable('Dotation')->find($request->getParameter('id'));
    $dotationPartners = $dotation->getPartners();
    $dotationForm = new DotationForm($dotation);
    $dotationForm->useFields(array());
    $partnerCollectionForm = new sfForm();
     
    foreach ($dotationPartners as $i => $partner)
    {
      $dotationPartner = new DotationPartner();
      $dotationPartner->setDotation($dotation);
      $dotationPartner->setPartner($partner);
      $embedForm = new DotationPartnerForm($dotationPartner);
      if (is_null($embedForm->getObject()->getQuantity())) 
      {
        $embedForm->setDefault('quantity', $dotation->getDefaultQty());
      }
      $partnerCollectionForm->embedForm($i, $embedForm);
    }
    $dotationForm->embedForm('partners', $partnerCollectionForm);
     
    if($request->isMethod('post')) 
    {  $dotationForm->bind($request->getParameter($dotationForm->getName()));
      if ($dotationForm->isValid()) {
        die('form is valid, do form proces ...');
      }
    }
     
    $this->dotation = $dotation;
    $this->embeddedForms = $dotationForm;
    $this->partners = $dotationPartners;
    J'étais pas loin mais j'avais fait une mauvaise utilisation des embeddedForms. La subtilité réside dans le fait d'utiliser le formulaire de ma classe dotation comme formulaire parent et d'y ajouter un useField(array()) pour ne voir apparaitre aucun de ses champs, puis embarquer le form de ma table intermédiaire au lieu de créer un nouveau formulaire qui n'était calqué sur rien comme je le faisais avant. Du coup, après submit, on récupère un objet unique dans le post que l'on peut bind au formulaire parent et tous les autres bind se font en cascade.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 17/12/2010, 11h56
  2. Réponses: 0
    Dernier message: 11/12/2010, 12h52
  3. [1.x] Form filter et embedded form
    Par Jeobs dans le forum Symfony
    Réponses: 9
    Dernier message: 17/09/2010, 17h52
  4. [1.x] Création d'objets avec Embeded form
    Par Adesfire dans le forum Symfony
    Réponses: 4
    Dernier message: 08/01/2010, 16h07

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