Salut les mecs,

Je suis en train de développer un projet sur Symfony 5 et je galère sur un truc tout con.

Pour vous expliquer en gros la structure de mon projet: on peut créer des contenus (Articles, Diaporamas, Recettes Groupements, etc.). Chacun de ces contenus a des champs communs contenus dans une entité GlobalContent, (qui contient titre, tags, theme, SEO, etc.) de telle sorte que les entités des contenus ont une relation oneToOne avec l'entité GlobalContent.

Là où ça se complique c'est que les contenus peuvent etre associés à un ou plusieurs groupement(s). Il n'y a que les groupements qui ne peuvent pas être associés à un autre groupement. J'ai donc une relation manyToMany entre GlobalContent et Groupement. Seulement, GlobalContent et Groupement ont également une relation oneToMany.

Dans mon entité GlobalContent j'ai donc:

    /**
     * @ORM\OneToOne(targetEntity="App\Entity\Groupement", mappedBy="global_content", cascade={"persist", "remove"})
     */
    private $groupement;

    /**
    * @ORM\ManyToMany(targetEntity="App\Entity\Groupement", inversedBy="global_contents")
    */
   private $groupements;

   public function getGroupement(): ?Groupement
    {
        return $this->groupement;
    }

    public function setGroupement(?Groupement $groupement): self
    {
        $this->groupement = $groupement;

        return $this;
    }

    /**
     * @return Collection|Groupement[]
     */
    public function getGroupements(): Collection
    {
        return $this->groupements;
    }

    public function addGroupement(Groupement $groupement): self
    {
        if (!$this->groupements->contains($groupement)) {
            $this->groupements[] = $groupement;
        }

        return $this;
    }

    public function removeGroupement(Groupement $groupement): self
    {
        if ($this->groupements->contains($groupement)) {
            $this->groupements->removeElement($groupement);
        }

        return $this;
    }

Et dans mon entité Groupement:

    /**
     * @ORM\OneToOne(targetEntity="App\Entity\GlobalContent", inversedBy="groupement", cascade={"persist", "remove"})
     * @ORM\JoinColumn(nullable=false)
     */
    private $global_content;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\GlobalContent", mappedBy="groupements"))
     */
    private $global_contents;

     public function getGlobalContent(): ?GlobalContent
    {
        return $this->global_content;
    }

    public function setGlobalContent(GlobalContent $global_content): self
    {
        $this->global_content = $global_content;

        return $this;
    }

    /**
     * @return Collection|GlobalContent[]
     */
    public function getGlobalContents(): Collection
    {
        return $this->global_contents;
    }

    public function addGlobalContent(GlobalContent $global_content): self
    {
        if (!$this->global_contents->contains($global_content)) {
            $this->global_contents[] = $global_content;
        }
        return $this;
    }

    public function removeGlobalContent(GlobalContent $global_content): self
    {
        if ($this->global_contents->contains($global_content)) {
            $this->global_contents->removeElement($global_content);
        }
        return $this;
    }

Depuis un article, je peux rajouter ou supprimer un ou plusieurs groupement(s) sans problème.
Depuis un groupement, je peux voir les articles liés dans problème.
Le problème se pose lorsque je veux rajouter/supprimer des articles depuis un groupement.

Le formulaire de creation/modif des groupements est comme ça:

    $builder
            ->add('main_content')
            ->add('main_informations')
            ->add('image')
            ->add('texte')
            // infos complémetaires
            ->add('global_content', GlobalContentType::class)
            // liste des contenus associés (en excluant les groupements)
            ->add('global_contents', EntityType::class,[
                'class'=>GlobalContent::class,
                'placeholder'=>'Contenus associés',
                'label'=>false,
                'required'=>false,
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('f')
                        ->leftJoin('f.groupement', 'groupement')
                        ->andWhere('groupement.id is NULL')
                        ->orderBy('f.main_titre', 'ASC');
                },
                'multiple' => true,
            ])
        ;

Je vous fait grace du code du controller vu que toute les autres modif fonctionne.

Le champ global_contents me remonte bien la liste des contenus, avec les bons contenus associés sélectionnés.

J'ai testé de faire ça a la soumission du formulaire:

    $contenus = $groupement->getGlobalContents();
    dd($contenus->toArray());
    $manager->persist($groupement);
    $manager->flush();

Et ca me remonte bien les contenus que j'ai rentrés dans le formulaire et que je veux voir persister.
Mais rien ne se passe si je fais sans le dd().
Le formulaire est bien envoyé sans erreur, les modification enregistrées mais les contenus associés ne changent pas

Si quelqu'un a une idée, je suis preneur.

2 réponses


cinquiemeDimension
Auteur
Réponse acceptée

Bon, je me suis replongé dedans 4 mois plus tard et j'ai toujours pas trouvé la solution pour faire ça proprement.
Donc j'ai fait ça comme un sagouin:

Bon ce n'est pas partie de la solution, mùais pour clarifier j'ai renommé, dans ma classe GlobalContent, $groupements en $all_groupements (pour ne pas confondre et faire de la merde avec la valeur $groupement au singulier) et pareil pour la classe Groupement et la valeur $global_contents qui est devenue $all_global_contents.

Donc voilà.

Classe GlobalContent, la valeur $all_groupements:

/**
* @ORM\ManyToMany(targetEntity="App\Entity\Groupement", inversedBy="all_global_contents")
* @ORM\JoinTable(name="global_content_groupement")
*/
private $all_groupements;

Classe Groupement, la valeur $all_global_contents:

/**
 * @ORM\ManyToMany(targetEntity="App\Entity\GlobalContent", mappedBy="all_groupements")
 */
private $all_global_contents;

Et dans mon controller GroupementConroller:

Avant le traitement de mon formulaire, je récupère les anciens GlobalContents rattachés

$old_global_contents = $groupement->getAllGlobalContents()->getValues();

et après le traitement du formulaire, je bidouille pour attacher les GlobalContents

//solution de secours pour attacher les GlobalContents
$new_global_contents = $groupement->getAllGlobalContents()->getValues();
// on compare les GlobalContent attachés avant et après le traitement du formulaire et on en déduit des tableau d'ajouts et de suppressions
$adds = array_diff($new_global_contents, $old_global_contents);
$removes = array_diff($old_global_contents, $new_global_contents);
// pour chaque ajout/suppression, on va chercher l'entité GlobalContent et on update de là...
foreach($adds as $added){
    $added->addAllGroupement($groupement);
    $manager->persist($added);
}
foreach($removes as $removed){
    $removed->removeAllGroupement($groupement);
    $manager->persist($removed);
}

C'est pas beau mais ça fonctionne :/

PS: c'est moi ou c'est assez ghetto la façon automatique de sélectionner le code ici ?

Personne pour m'aider ? :'(