Symfony 4 – ManyToMany – FetchData (ORM Fetch or Repository Query)

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 DoctrineCommonCollectionsCollection|Module[]
 * @ORMManyToMany(targetEntity="MarvinEntreprisesBundleEntityModule", inversedBy="formations")
 * @ORMJoinTable(
 *      name="entreprises_formation_module",
 *      joinColumns={
 *          @ORMJoinColumn(name="formation_id", referencedColumnName="id")
 *      },
 *      inverseJoinColumns={
 *          @ORMJoinColumn(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 DoctrineCommonCollectionsCollection|Formation[]
 * @ORMManyToMany(targetEntity="MarvinEntreprisesBundleEntityFormation", 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 MarvinEntreprisesBundleEntityFormation 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 MarvinEntreprisesBundleEntityFormation::getModules() must be an instance of DoctrineCommonCollectionsArrayCollection, 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

MarvinEntreprisesBundleEntityFormation {#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

MarvinEntreprisesBundleEntityModule {#1650
  -id: 2
  -enable: false
  -publish: false
  -dateToPublish: null
  -status: "draft"
  -moduleDescriptions: DoctrineORMPersistentCollection {#1370
    -snapshot: []
    -owner: MarvinEntreprisesBundleEntityModule {#1650}
    -association: array:15 [ …15]
    -em: DoctrineORMEntityManager {#1329 …11}
    -backRefFieldName: "module"
    -typeClass: DoctrineORMMappingClassMetadata {#1647 …}
    -isDirty: false
    #collection: DoctrineCommonCollectionsArrayCollection {#1676
      -elements: []
    }
    #initialized: false
  }
  -formations: DoctrineORMPersistentCollection {#1619
    -snapshot: []
    -owner: MarvinEntreprisesBundleEntityModule {#1650}
    -association: array:16 [ …16]
    -em: DoctrineORMEntityManager {#1329 …11}
    -backRefFieldName: "modules"
    -typeClass: DoctrineORMMappingClassMetadata {#1430 …}
    -isDirty: false
     #collection: DoctrineCommonCollectionsArrayCollection {#1617
      - elements: []
    }
    #initialized: false
  }
}

Formation is set ! But not fetch. If a add fetch=”EAGER” at “Module” class

     @ORMManyToMany(targetEntity="MarvinEntreprisesBundleEntityFormation", 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
    @ORMManyToMany(targetEntity="MarvinEntreprisesBundleEntityFormation", mappedBy="modules", fetch="EAGER")

    //Class Formation
    @ORMManyToMany(targetEntity="MarvinEntreprisesBundleEntityModule", inversedBy="formations", fetch="EAGER")

    //Doctrine:schema:update --dump-sql ==> create nothing

BUT

  //Class Module
    @ORMManyToMany(targetEntity="MarvinEntreprisesBundleEntityFormation", inversedBy="modules", fetch="EAGER")

    //Class Formation
    @ORMManyToMany(targetEntity="MarvinEntreprisesBundleEntityModule", 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 :

MarvinEntreprisesBundleEntityModule {
 -id: 2
 -enable: false
 -publish: false
 -dateToPublish: null
 -status: "draft"
 -moduleDescriptions: DoctrineORMPersistentCollection {#895
   -snapshot: array:1 [ …1]
   -owner: MarvinEntreprisesBundleEntityModule {#900}
   -association: array:15 [ …15]
   -em: DoctrineORMEntityManager {#527 …11}
   -backRefFieldName: "module"
   -typeClass: DoctrineORMMappingClassMetadata {#788 …}
   -isDirty: false
   #collection: DoctrineCommonCollectionsArrayCollection {#897
     -elements: array:1 [
       0 => MarvinEntreprisesBundleEntityModuleDescription {#872
         -id: 2
         -titre: "Stress, souffrance et mal-être au travail"
         -module: MarvinEntreprisesBundleEntityModule {#900}
         -language: "FR"
       }
     ]
   }
   #initialized: true
 }
 -formations: DoctrineORMPersistentCollection {#898
   -snapshot: array:1 [ …1]
   -owner: MarvinEntreprisesBundleEntityModule {#900}
   -association: array:19 [ …19]
   -em: DoctrineORMEntityManager {#527 …11}
   -backRefFieldName: "modules"
   -typeClass: DoctrineORMMappingClassMetadata {#631 …}
   -isDirty: false
   #collection: DoctrineCommonCollectionsArrayCollection {#865
     -elements: array:1 [
       0 => MarvinEntreprisesBundleEntityFormation {#843
         -id: 1
         -enable: false
         -publish: false
         -dateToPublish: null
         -formationDescriptions: DoctrineORMPersistentCollection {#867
           -snapshot: array:1 [ …1]
           -owner: MarvinEntreprisesBundleEntityFormation {#843}
           -association: array:15 [ …15]
           -em: DoctrineORMEntityManager {#527 …11}
           -backRefFieldName: "formation"
           -typeClass: DoctrineORMMappingClassMetadata {#834 …}
           -isDirty: false
           #collection: DoctrineCommonCollectionsArrayCollection {#866
             -elements: array:1 [
               0 => MarvinEntreprisesBundleEntityFormationDescription
              -id: 1
              -titre: "Gestion des pressions sociales"
              -formation: MarvinEntreprisesBundleEntityFormation {#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 :

MarvinEntreprisesBundleEntityFormation {
  -id: 1
  -enable: false
  -publish: false
  -dateToPublish: null
  -formationDescriptions: DoctrineORMPersistentCollection {#1647
    -snapshot: array:1 [ …1]
    -owner: MarvinEntreprisesBundleEntityFormation {#1700}
    -association: array:15 [ …15]
    -em: DoctrineORMEntityManager {#1330 …11}
    -backRefFieldName: "formation"
    -typeClass: DoctrineORMMappingClassMetadata {#1588 …}
    -isDirty: false
    #collection: DoctrineCommonCollectionsArrayCollection {#1698
      -elements: array:1 [
        0 => MarvinEntreprisesBundleEntityFormationDescription {#1664
          -id: 1
          -titre: "Gestion des pressions sociales"
          -formation: MarvinEntreprisesBundleEntityFormation {#1700}
          -language: "FR"
        }
      ]
    }
    #initialized: true
  }
  -status: "draft"
  -modules: null

Modules null again


In advance, thank you for supporting my incompetence

Source: Symfony Questions

Was this helpful?

0 / 0

Leave a Reply 0

Your email address will not be published. Required fields are marked *