I try to fetch data from a ManyToMany relations. I found a lot of videos/posts/blogs on the subject, but I can't make it work (or understand). I need help.
SO ! I've "Formation" and "Module" class. Each "Formation" can have many "Module" and the opposite too.
Expected result
I want to get "Formation" array(all)/item(byId) with all "Modules" linked at it in "->modules" attribut.
Class Formation
/***
* @var \Doctrine\Common\Collections\Collection|Module[]
* @ORM\ManyToMany(targetEntity="MarvinEntreprisesBundle\Entity\Module", inversedBy="formations")
* @ORM\JoinTable(
* name="entreprises_formation_module",
* joinColumns={
* @ORM\JoinColumn(name="formation_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="module_id", referencedColumnName="id")
* }
* )
*/
private $modules;
public function addModules(Module $module): self
{
if (!$this->modules->contains($module)) {
$this->modules[] = $module;
}
return $this;
}
public function removeModules(Module $module): self
{
if ($this->modules->contains($module)) {
$this->modules->removeElement($module);
}
return $this;
}
Class Module
/**
* @var \Doctrine\Common\Collections\Collection|Formation[]
* @ORM\ManyToMany(targetEntity="MarvinEntreprisesBundle\Entity\Formation", mappedBy="modules")
*/
private $formations;
public function addFormation(Formation $formation): self
{
if (!$this->formations->contains($formation)) {
$this->formations[] = $formation;
$article->addTag($this);
}
return $this;
}
public function removeFormation(Formation $formation): self
{
if ($this->formations->contains($formation)) {
$this->formations->removeElement($formation);
$formation->removeTag($this);
}
return $this;
}
Try 1 - QueryBuilder - join
$this->createQueryBuilder('f')
->join('f.modules', 'm')
->select('f, m')
->getQuery()
->getResult();
I get and [Semantical Error] line 0, col 81 near 'm': Error: Class MarvinEntreprisesBundle\Entity\Formation has no association named modules
I try to use "Modules", "Module", "Formations", "Formation", "entreprises_formation_module"(name of join table")
Try 2 - QueryBuilder - leftJoin
$this->getEntityManager()
->createQueryBuilder()
->leftJoin(Module::class, 'm')
->andWhere('m.id = :id')
->setParameter('id', $formation->getId());
I get an error "No alias was set before invoking getRootAlias()".
Try 3 - Fetch="EAGER"
No error received, i get all "Formation" item but any "Module" linked is in object. By the way, modules attribut is not set (not null.... nothing).
At this time, i see i've not "getModules()" on my "Formation" class. If i add it i get an error : Return value of MarvinEntreprisesBundle\Entity\Formation::getModules() must be an instance of Doctrine\Common\Collections\ArrayCollection, null returned
Some question
If i've write "Formation" item, "Module" item and the "entreprises_formation_module" link direclty in database, so not use a Symfony EntityManager for create, set en flush in database.. That change somthing ? (I have not yet created the method to do it)
Some info
If i make a "formation->find()" i get
MarvinEntreprisesBundle\Entity\Formation {#1602
-id: 3
-enable: false
-publish: false
-dateToPublish: null
-status: "draft"
-modules: null
}
Modules is set but empty
If i make a "module->find(x)" i get
MarvinEntreprisesBundle\Entity\Module {#1650
-id: 2
-enable: false
-publish: false
-dateToPublish: null
-status: "draft"
-moduleDescriptions: Doctrine\ORM\PersistentCollection {#1370
-snapshot: []
-owner: MarvinEntreprisesBundle\Entity\Module {#1650}
-association: array:15 [ …15]
-em: Doctrine\ORM\EntityManager {#1329 …11}
-backRefFieldName: "module"
-typeClass: Doctrine\ORM\Mapping\ClassMetadata {#1647 …}
-isDirty: false
#collection: Doctrine\Common\Collections\ArrayCollection {#1676
-elements: []
}
#initialized: false
}
-formations: Doctrine\ORM\PersistentCollection {#1619
-snapshot: []
-owner: MarvinEntreprisesBundle\Entity\Module {#1650}
-association: array:16 [ …16]
-em: Doctrine\ORM\EntityManager {#1329 …11}
-backRefFieldName: "modules"
-typeClass: Doctrine\ORM\Mapping\ClassMetadata {#1430 …}
-isDirty: false
#collection: Doctrine\Common\Collections\ArrayCollection {#1617
- elements: []
}
#initialized: false
}
}
Formation is set ! But not fetch. If a add fetch="EAGER" at "Module" class
@ORM\ManyToMany(targetEntity="MarvinEntreprisesBundle\Entity\Formation", mappedBy="modules", fetch="EAGER")
I get error Notice: Undefined index: modules
if i go back in the code, i inverse "mappedBy" and "inversedBy", Doctrine:Schema:Update give me diffrent result
//Class Module
@ORM\ManyToMany(targetEntity="MarvinEntreprisesBundle\Entity\Formation", mappedBy="modules", fetch="EAGER")
//Class Formation
@ORM\ManyToMany(targetEntity="MarvinEntreprisesBundle\Entity\Module", inversedBy="formations", fetch="EAGER")
//Doctrine:schema:update --dump-sql ==> create nothing
BUT
//Class Module
@ORM\ManyToMany(targetEntity="MarvinEntreprisesBundle\Entity\Formation", inversedBy="modules", fetch="EAGER")
//Class Formation
@ORM\ManyToMany(targetEntity="MarvinEntreprisesBundle\Entity\Module", mappedBy="formations", fetch="EAGER")
//Doctrine:schema:update --dump-sql create
CREATE TABLE module_formation (module_id INT NOT NULL, formation_id INT NOT NULL, INDEX IDX_1A213E77AFC2B591 (module_id), INDEX IDX_1A213E775200282E (formation_id), PRIMARY KEY(module_id, formation_id)) DEFAULT CHARACTER SET UTF8 COLLATE `UTF8_unicode_ci` ENGINE = InnoDB;
In this case, if i do "Module->find(x)" with fetch="EAGER" i get :
MarvinEntreprisesBundle\Entity\Module {
-id: 2
-enable: false
-publish: false
-dateToPublish: null
-status: "draft"
-moduleDescriptions: Doctrine\ORM\PersistentCollection {#895
-snapshot: array:1 [ …1]
-owner: MarvinEntreprisesBundle\Entity\Module {#900}
-association: array:15 [ …15]
-em: Doctrine\ORM\EntityManager {#527 …11}
-backRefFieldName: "module"
-typeClass: Doctrine\ORM\Mapping\ClassMetadata {#788 …}
-isDirty: false
#collection: Doctrine\Common\Collections\ArrayCollection {#897
-elements: array:1 [
0 => MarvinEntreprisesBundle\Entity\ModuleDescription {#872
-id: 2
-titre: "Stress, souffrance et mal-être au travail"
-module: MarvinEntreprisesBundle\Entity\Module {#900}
-language: "FR"
}
]
}
#initialized: true
}
-formations: Doctrine\ORM\PersistentCollection {#898
-snapshot: array:1 [ …1]
-owner: MarvinEntreprisesBundle\Entity\Module {#900}
-association: array:19 [ …19]
-em: Doctrine\ORM\EntityManager {#527 …11}
-backRefFieldName: "modules"
-typeClass: Doctrine\ORM\Mapping\ClassMetadata {#631 …}
-isDirty: false
#collection: Doctrine\Common\Collections\ArrayCollection {#865
-elements: array:1 [
0 => MarvinEntreprisesBundle\Entity\Formation {#843
-id: 1
-enable: false
-publish: false
-dateToPublish: null
-formationDescriptions: Doctrine\ORM\PersistentCollection {#867
-snapshot: array:1 [ …1]
-owner: MarvinEntreprisesBundle\Entity\Formation {#843}
-association: array:15 [ …15]
-em: Doctrine\ORM\EntityManager {#527 …11}
-backRefFieldName: "formation"
-typeClass: Doctrine\ORM\Mapping\ClassMetadata {#834 …}
-isDirty: false
#collection: Doctrine\Common\Collections\ArrayCollection {#866
-elements: array:1 [
0 => MarvinEntreprisesBundle\Entity\FormationDescription
-id: 1
-titre: "Gestion des pressions sociales"
-formation: MarvinEntreprisesBundle\Entity\Formation {#843}
-language: "FR"
}
]
}
#initialized: true
}
-status: "draft"
-modules: null
}
]
}
#initialized: true
}
}
ITS WORK, but if i call "Formation->find(1) with fetch="EAGER" (Formation->find(1) is same formation i get in previous Modules->find(x)), i get :
MarvinEntreprisesBundle\Entity\Formation {
-id: 1
-enable: false
-publish: false
-dateToPublish: null
-formationDescriptions: Doctrine\ORM\PersistentCollection {#1647
-snapshot: array:1 [ …1]
-owner: MarvinEntreprisesBundle\Entity\Formation {#1700}
-association: array:15 [ …15]
-em: Doctrine\ORM\EntityManager {#1330 …11}
-backRefFieldName: "formation"
-typeClass: Doctrine\ORM\Mapping\ClassMetadata {#1588 …}
-isDirty: false
#collection: Doctrine\Common\Collections\ArrayCollection {#1698
-elements: array:1 [
0 => MarvinEntreprisesBundle\Entity\FormationDescription {#1664
-id: 1
-titre: "Gestion des pressions sociales"
-formation: MarvinEntreprisesBundle\Entity\Formation {#1700}
-language: "FR"
}
]
}
#initialized: true
}
-status: "draft"
-modules: null
Modules null again
In advance, thank you for supporting my incompetence