Quantcast
Channel: Active questions tagged symfony4 - Stack Overflow
Viewing all articles
Browse latest Browse all 3924

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

$
0
0

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


Viewing all articles
Browse latest Browse all 3924

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>