Bonjour tous le monde,

Alors je vous explique :

Dans mon projet j'ai des molécules et des méthodes. Je souhaiterai faire un formulaire qui me permet quand j'ajoute et modifie la moécule je puisse en meme temps gérer les méthodes rattaché à la molécule.

Pour l'ajout du nouvelle molécule pas de soucis, là où ca se complique c'est pour la modification....

J'ai suivi la documentation de symfony : http://symfony.com/doc/master/form/form_collections.html

je vais vous donner mes entités et le controller du formulaire avec le formType.

<?php

namespace Molecules\MoleculesBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Molecules
 *
 * @ORM\Table(name="Molecules")
 * @ORM\Entity(repositoryClass="Molecules\MoleculesBundle\Repository\MoleculesRepository")
 */
class Molecules
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="Nom", type="string", length=255)
     */
    private $nom;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="DateCreation", type="datetime")
     */
    private $dateCreation;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="DateModif", type="datetime")
     */
    private $dateModif;

    /**
     * @ORM\ManyToOne(targetEntity="Molecules\MoleculesBundle\Entity\Familles")
     */
    private $famille;

    /**
     * @ORM\OneToMany(targetEntity="Molecules\MoleculesBundle\Entity\Methodes", mappedBy="molecule", cascade={"persist"})
     */
    private $methodes;

    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set nom
     *
     * @param string $nom
     *
     * @return Molecules
     */
    public function setNom($nom)
    {
        $this->nom = $nom;

        return $this;
    }

    /**
     * Get nom
     *
     * @return string
     */
    public function getNom()
    {
        return $this->nom;
    }

    /**
     * Set dateCreation
     *
     * @param \DateTime $dateCreation
     *
     * @return Molecules
     */
    public function setDateCreation($dateCreation)
    {
        $this->dateCreation = $dateCreation;

        return $this;
    }

    /**
     * Get dateCreation
     *
     * @return \DateTime
     */
    public function getDateCreation()
    {
        return $this->dateCreation;
    }

    /**
     * Set dateModif
     *
     * @param \DateTime $dateModif
     *
     * @return Molecules
     */
    public function setDateModif($dateModif)
    {
        $this->dateModif = $dateModif;

        return $this;
    }

    /**
     * Get dateModif
     *
     * @return \DateTime
     */
    public function getDateModif()
    {
        return $this->dateModif;
    }

    /**
     * Set famille
     *
     * @param \Molecules\MoleculesBundle\Entity\Familles $famille
     *
     * @return Molecules
     */
    public function setFamille(\Molecules\MoleculesBundle\Entity\Familles $famille = null)
    {
        $this->famille = $famille;

        return $this;
    }

    /**
     * Get famille
     *
     * @return \Molecules\MoleculesBundle\Entity\Familles
     */
    public function getFamille()
    {
        return $this->famille;
    }
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->methodes = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Add methode
     *
     * @param \Molecules\MoleculesBundle\Entity\Methodes $methode
     *
     * @return Molecules
     */
    public function addMethode(\Molecules\MoleculesBundle\Entity\Methodes $methode)
    {
        $this->methodes[] = $methode;

        return $this;
    }

    /**
     * Remove methode
     *
     * @param \Molecules\MoleculesBundle\Entity\Methodes $methode
     */
    public function removeMethode(\Molecules\MoleculesBundle\Entity\Methodes $methode)
    {
        $this->methodes->removeElement($methode);
    }

    /**
     * Get methodes
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getMethodes()
    {
        return $this->methodes;
    }
}
<?php

namespace Molecules\MoleculesBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Methodes
 *
 * @ORM\Table(name="Methodes")
 * @ORM\Entity(repositoryClass="Molecules\MoleculesBundle\Repository\MethodesRepository")
 */
class Methodes
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="Libelle", type="string", length=255)
     */
    private $libelle;

    /**
     * @var string
     *
     * @ORM\Column(name="Value_LQ", type="decimal", precision=10, scale=5, nullable=true)
     */
    private $valueLQ;

    /**
     * @var string
     *
     * @ORM\Column(name="Value_LD", type="decimal", precision=10, scale=5, nullable=true)
     */
    private $valueLD;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="DateCreation", type="datetime")
     */
    private $dateCreation;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="DateModif", type="datetime")
     */
    private $dateModif;

    /**
     * @ORM\ManyToOne(targetEntity="Molecules\MoleculesBundle\Entity\Molecules", inversedBy="methodes", cascade={"persist"})
     */
    private $molecule;

    /**
     * @var string
     * @ORM\Column(name="Unite", type="string", length=10)
     */
    private $unite;

    /**
     * @var string
     * @ORM\Column(name="Commentaire", type="blob", nullable=true)
     */
    private $commentaire;

    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set libelle
     *
     * @param string $libelle
     *
     * @return Methodes
     */
    public function setLibelle($libelle)
    {
        $this->libelle = $libelle;

        return $this;
    }

    /**
     * Get libelle
     *
     * @return string
     */
    public function getLibelle()
    {
        return $this->libelle;
    }

    /**
     * Set valueLQ
     *
     * @param string $valueLQ
     *
     * @return Methodes
     */
    public function setValueLQ($valueLQ)
    {
        $this->valueLQ = $valueLQ;

        return $this;
    }

    /**
     * Get valueLQ
     *
     * @return string
     */
    public function getValueLQ()
    {
        return $this->valueLQ;
    }

    /**
     * Set valueLD
     *
     * @param string $valueLD
     *
     * @return Methodes
     */
    public function setValueLD($valueLD)
    {
        $this->valueLD = $valueLD;

        return $this;
    }

    /**
     * Get valueLD
     *
     * @return string
     */
    public function getValueLD()
    {
        return $this->valueLD;
    }

    /**
     * Set dateCreation
     *
     * @param \DateTime $dateCreation
     *
     * @return Methodes
     */
    public function setDateCreation($dateCreation)
    {
        $this->dateCreation = $dateCreation;

        return $this;
    }

    /**
     * Get dateCreation
     *
     * @return \DateTime
     */
    public function getDateCreation()
    {
        return $this->dateCreation;
    }

    /**
     * Set dateModif
     *
     * @param \DateTime $dateModif
     *
     * @return Methodes
     */
    public function setDateModif($dateModif)
    {
        $this->dateModif = $dateModif;

        return $this;
    }

    /**
     * Get dateModif
     *
     * @return \DateTime
     */
    public function getDateModif()
    {
        return $this->dateModif;
    }

    /**
     * Set unite
     *
     * @param string $unite
     *
     * @return Methodes
     */
    public function setUnite($unite)
    {
        $this->unite = $unite;

        return $this;
    }

    /**
     * Get unite
     *
     * @return string
     */
    public function getUnite()
    {
        return $this->unite;
    }

    /**
     * Set commentaire
     *
     * @param string $commentaire
     *
     * @return Methodes
     */
    public function setCommentaire($commentaire)
    {
        $this->commentaire = $commentaire;

        return $this;
    }

    /**
     * Get commentaire
     *
     * @return string
     */
    public function getCommentaire()
    {
        if($this->commentaire != ""){
            return stream_get_contents($this->commentaire);
        }
    }

    /**
     * Set molecule
     *
     * @param \Molecules\MoleculesBundle\Entity\Molecules $molecule
     *
     * @return Methodes
     */
    public function setMolecule(\Molecules\MoleculesBundle\Entity\Molecules $molecule = null)
    {
        $this->molecule = $molecule;

        return $this;
    }

    /**
     * Get molecule
     *
     * @return \Molecules\MoleculesBundle\Entity\Molecules
     */
    public function getMolecule()
    {
        return $this->molecule;
    }
}
<?php

namespace Molecules\MoleculesBundle\Controller;

use Doctrine\Common\Collections\ArrayCollection;
use Molecules\MoleculesBundle\Entity\Methodes;
use Molecules\MoleculesBundle\Entity\Molecules;
use Molecules\MoleculesBundle\Form\MoleculeType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

class MoleculeController extends Controller
{
    public function indexAction()
    {
        $em = $this->getDoctrine()->getManager();
        $molecules = $em->getRepository("MoleculesBundle:Molecules")->findAll();
        return $this->render('MoleculesBundle:Default:index.html.twig', [
            "molecules" => $molecules
        ]);
    }

    public function formAddMoleculeAction(Request $request)
    {
        $form = $this->createForm(MoleculeType::class);
        $form->handleRequest($request);

        if($form->isSubmitted()){
            $em = $this->getDoctrine()->getManager();

            $datas = $form->getData();

            $molecule = new Molecules();
            $molecule->setNom($datas["Nom"]);
            $molecule->setDateCreation(new \DateTime());
            $molecule->setDateModif(new \DateTime());

            $em->persist($molecule);

            foreach ($datas["methodes"] as $methodeData){
                $methode = new Methodes();
                $methode->setLibelle($methodeData["Libelle"]);
                $methode->setMolecule($molecule);
                $methode->setValueLQ($methodeData["Value_LQ"]);
                $methode->setValueLD($methodeData["Value_LD"]);
                $methode->setUnite($methodeData["Unite"]);
                $methode->setCommentaire($methodeData["Commentaire"]);
                $methode->setDateCreation(new \DateTime());
                $methode->setDateModif(new \DateTime());

                $em->persist($methode);
            }
            $em->flush();
            $this->addFlash("success", "La molécule a bien été enregistrée.");
        }

        return $this->render("@Molecules/Default/formAdd.html.twig", [
            "form" => $form->createView()
        ]);
    }

    public function formUpdateAction($id, Request $request)
    {
        $em = $this->getDoctrine()->getManager();
        $molecule = $em->getRepository("MoleculesBundle:Molecules")->find($id);

        $originalMethodes = new ArrayCollection();
        foreach ($molecule->getMethodes() as $methode){
            $originalMethodes->add($methode);
        }
        $form = $this->createForm(MoleculeType::class, $molecule, [
            "submit_button_label" => "Modifier"
        ]);

        $form->handleRequest($request);
        // TODO[deshiloh] Faire la routine de suppression des méthodes http://symfony.com/doc/master/form/form_collections.html
        if($form->isSubmitted() && $form->isValid()){

            foreach ($datas->getMethodes() as $methodeForm){
                if($originalMethodes->contains($methodeForm)){
                    $em->flush();
                }else {
                    if(count($originalMethodes) < count($datas->getMethodes())){
                        $methodeForm->setMolecule($molecule);
                        $methodeForm->setDateCreation(new \DateTime());
                        $methodeForm->setDateModif(new \DateTime());
                        $em->persist($methodeForm);
                    }else {
                        $em->remove($methodeForm);
                    }
                }
            }
            $em->flush();
            /*dump($datas->getMethodes());
            die();*/
            /*foreach ($originalMethodes as $methode){
                if($datas->getMethodes()->contains($methode) === false){
                    $em->remove($methode);
                }
            }*/

            /*foreach ($datas->getMethodes() as $newMethode){
                if($originalMethodes->contains($newMethode) === false){
                    $newMethode->setMolecule($molecule);
                    $newMethode->setDateCreation(new \DateTime());
                    $newMethode->setDateModif(new \DateTime());

                    $em->persist($newMethode);
                }
            }
            $em->flush();*/
            $this->addFlash("success", "La molécule a bien été modifiée.");
        }

        return $this->render("@Molecules/Default/formAdd.html.twig", [
           "form" => $form->createView(),
        ]);
    }
}
<?php
/**
 * Created by PhpStorm.
 * User: deshiloh
 * Date: 05/07/2017
 * Time: 10:50
 */

namespace Molecules\MoleculesBundle\Form;

use Molecules\MoleculesBundle\Entity\Molecules;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class MoleculeType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add("Nom", TextType::class)
            ->add("methodes", CollectionType::class, [
                "entry_type" => MethodeType::class,
                "allow_add" => true,
                "allow_delete" => true,
                "label" => false,
                'by_reference' => false,
            ])
            ->add("submit", SubmitType::class, [
                "label" => $options["submit_button_label"],
                "attr" => [
                    "class" => "btn-primary pull-right"
                ]
            ])
            ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            "data_class" => Molecules::class,
            "submit_button_label" => "Ajouter"
        ]);
    }
}

A savoir que quand ma molécule existante n'as pas de méthodes ça fonctionne, mon problème est quand j'ai au moins une méthode dans la molécule.

Imaginons que j'ai 3 méthodes déjà d'enregistrer, si j'en rajoute une 4ème le formulaire me retourne 3 méthodes. Je me retrouve donc avec mon tableau de méthode du formulaire égal à celui que je récupère avec doctrine sur la molécule.

Merci d'avance pour l'aide.

Cordialement.

1 réponse