Symfony 4 - ManyToMany - FetchData(ORM 获取或存储库查询)

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

我尝试从多对多关系中获取数据。我发现了很多关于这个主题的 videos/posts/blogs,但我无法让它工作(或理解)。我需要帮助。

太棒了!我有 "Formation" 和 "Module" class。每个 "Formation" 可以有很多 "Module" 反之亦然。

预期结果

我想获得 "Formation" array(all)/item(byId) 以及所有 "Modules" link 在“->modules”属性中编辑它。

Class阵型

/***
 * @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 模块

/**
 * @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;
}

尝试 1 - QueryBuilder - 加入

$this->createQueryBuilder('f')
        ->join('f.modules', 'm')
        ->select('f, m')
        ->getQuery()
        ->getResult();

我得到 [语义错误] 第 0 行,'m' 附近的第 81 列:错误:Class MarvinEntreprisesBundle\Entity\Formation 没有名为模块的关联

我尝试使用 "Modules"、"Module"、"Formations"、"Formation"、"entreprises_formation_module"(连接名称 table")

尝试 2 - QueryBuilder - leftJoin

 $this->getEntityManager()
        ->createQueryBuilder()
        ->leftJoin(Module::class, 'm')
        ->andWhere('m.id = :id')
        ->setParameter('id', $formation->getId());

我得到一个错误 "No alias was set before invoking getRootAlias()".

尝试 3 - 获取="EAGER"

没有收到错误,我得到了所有 "Formation" 项,但任何 "Module" linked 都在对象中。顺便说一下,模块属性没有设置(不是空的....什么都没有)。

此时,我发现我的 "Formation" class 上没有 "getModules()"。如果我添加它,我会收到错误消息: Return MarvinEntreprisesBundle\Entity\Formation::getModules() 的值必须是 Doctrine\Common\Collections\ArrayCollection 的实例,返回 null

一些问题

如果我在数据库中写入了 "Formation" 项、"Module" 项和 "entreprises_formation_module" link 直接项,那么不要使用 Symfony EntityManager 进行创建,设置 en刷新数据库..那改变了什么? (我还没有创建这样做的方法)

一些信息

如果我做一个 "formation->find()" 我得到

MarvinEntreprisesBundle\Entity\Formation {#1602
  -id: 3
  -enable: false
  -publish: false
  -dateToPublish: null
  -status: "draft"
  -modules: null
}

模块已设置但为空


如果我做一个 "module->find(x)" 我得到

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
  }
}

队形已定!但不取。如果在 "Module" class

添加 fetch="EAGER"
     @ORM\ManyToMany(targetEntity="MarvinEntreprisesBundle\Entity\Formation", mappedBy="modules", fetch="EAGER")

我收到错误 通知:未定义的索引:模块


如果我回到代码中,我会反转 "mappedBy" 和 "inversedBy",Doctrine:Schema:Update 会给我不同的结果

    //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

但是

  //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;

在这种情况下,如果我使用 fetch="EAGER" 执行 "Module->find(x)" 我得到:

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
}
}

它的工作,但如果我用 fetch="EAGER" 调用“Formation->find(1)”(Formation->find(1) 与我在之前的 Modules->find(x) 中得到的相同),我得到:

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

模块再次为空


提前谢谢大家支持我的无能

要让您的模块直接链接到您获取的对象,请在您的存储库中使用 leftJoin :

// FormationRepository.php

public function getFormationWithModules(){
    $q = $this->createQueryBuilder('f')
         ->leftJoin('f.modules', 'modules') <<<===
         ->addSelect('modules') <<== EDIT : Add addSelect row
         ->andWhere('modules.id = :id')
         ->setParameter('id', $formation->getId());

    return $q->getQuery()->getResults();
}

leftJoin 只会获取链接在您的 formation.modules

中的项目

我找到了!

Class编队

/*** <===== THIS ! =====
 * @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;

永远不会设置属性模块,因为注释的开头有三个 *。

所以ORM和"Formation"从来没有这个属性,导致错误:Class MarvinEntreprisesBundle\Entity\Formation has no association named modules

现在我可以做一个简单的 "return $this->findAll();" 并且我得到了我的项目完全提取

而且我也可以使用@AppyGG 代码。

谢谢 AppyGG,谢谢 Vyctorya