Symfony 4 - ManyToMany - FetchData (ORM Fetch или Repository Query) - PullRequest
0 голосов
/ 05 февраля 2020

Я пытаюсь получить данные из отношений ManyToMany. Я нашел много видео / постов / блогов на эту тему, но не могу заставить его работать (или понять). Мне нужна помощь.

ТАК! У меня есть "Формирование" и "Модуль" класс. У каждого «Формирования» может быть много «Модулей» и наоборот.

Ожидаемый результат

Я хочу получить массив «Формирования» (все) / item (byId ) со всеми связанными на нем "Модулями" в атрибуте "-> модули".

Формирование класса

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

Модуль класса

/**
 * @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 - присоединиться

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

Я получаю и [Семантическая ошибка] строка 0, столбец 81 рядом с 'm': Ошибка: Класс MarvinEntreprisesBundle \ Entity \ Formation не имеет ассоциации с именами модулей

Я пытаюсь использовать «Модули», «Модуль», «Формации», «Формирование», «entreprises_formation_module» (имя таблицы объединения))

Попробуйте 2 - QueryBuilder - leftJoin

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

Я получаю ошибку "Псевдоним не был установлен перед вызовом getRootAlias ​​()" .

Попробуйте 3 - Fetch = " EAGER "

Ошибка не получена, я получаю весь элемент" Формирование ", но любой связанный" Модуль "находится в объекте. Кстати, атрибут attribut не установлен (не нуль .... ничего).

В настоящее время я вижу, что у меня нет "getModules ()" в моем классе "Формирование". Если я добавляю его, я получаю ошибку: Возвращаемое значение MarvinEntreprisesBundle \ Entity \ Formation :: getModules ( ) должен быть в позиция Doctrine \ Common \ Collections \ ArrayCollection, ноль возвращено

Какой-то вопрос

Если я написал элемент «Формирование», элемент «Модуль» и директива ссылки "entreprises_formation_module" в базе данных, поэтому не используйте Symfony EntityManager для создания, установите en flu sh в базе данных. Что что-то изменит? (Я еще не создал метод, чтобы сделать это)

Некоторая информация

Если я сделаю "creation-> 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
  }
}

Формирование установлено! Но не принеси. Если add fetch = "EAGER" в классе "Module"

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

Я получаю ошибку Примечание: неопределенный индекс: modules


если i go обратно в коде, я инвертировал «mappedBy» и «inversedBy», Doctrine: схема: обновление дает другой результат

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

В этом случае если я делаю "Module-> find (x)" с fetch = "EAGER", я получаю:

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

ЕГО РАБОТА, но если я вызываю "Formation-> find (1) с fetch =" EAGER "(Формация-> найти (1) - это та же формация, что и в предыдущих модулях-> найти (х)), я получаю:

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

Модули снова обнуляются


В заранее, спасибо за поддержку моей некомпетентности

Ответы [ 2 ]

0 голосов
/ 05 февраля 2020

Я нахожу это!

Формирование класса

/*** <===== 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 и " Формация "никогда не имеет этого атрибута, и вызывает Ошибка: Класс MarvinEntreprisesBundle \ Entity \ Formation не имеет ассоциации с именами модулей

, и теперь я могу сделать просто" return $ this-> findAll () ;» и я получаю полный набор предметов

И я тоже могу использовать код @AppyGG.

Спасибо AppyGG, Спасибо Vyctorya

0 голосов
/ 05 февраля 2020

Чтобы ваши модули были напрямую связаны с выбранным вами объектом, используйте 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

...