Объединение таблиц Doctrine / Symfony: неожиданное поведение

#join #symfony #doctrine #doctrine-orm

#Присоединиться #symfony #доктрина #doctrine-orm

Вопрос:

Я пытаюсь добиться некоторого повышения эффективности, объединив несколько записей из нескольких таблиц в соответствии со статьей: Присоединение к связанным записям. В моей модели у меня есть трекер, который имеет один набор ссылок, который, в свою очередь, имеет несколько ссылок. Теперь в моем контроллере я хочу перебирать эти ссылки через:

 foreach ($tracker->getLinkset()->getLinks() as $link) etc..
  

Более того, код в моем репозитории Tracker выглядит следующим образом:

 public function findWithLinks(Tracker $tracker)
{
      $query = $this->createQueryBuilder('t')
                    ->select('t, ls, l')
                    ->innerJoin('t.linkset', 'ls')
                    ->leftJoin('ls.links', 'l')
                    ->where('t.id = :trackerId')
                    ->setParameters(array(
                          'trackerId' => $tracker->getId()
                    ));

      return $query->getQuery()->getResult();
}
  

Чего я ожидал бы, так это того, что в контроллере, когда я перебираю таблицу foreach, Symfony не выполняет никаких дополнительных вызовов к базе данных, потому что у меня есть трекер с объединенным набором ссылок и объединенными ссылками. Однако для получения набора ссылок и ссылок по отдельности выполняются два дополнительных запроса. Вот сопоставления связанных объектов:

Объект Linkset:

 /**
  * @var Link
  *
  * @ORMManyToMany(targetEntity="Link", mappedBy="linkset")
  */
  private $links;
  

Объект ссылки

 /**
  * @var Linkset
  *
  * @ORMManyToMany(targetEntity="Linkset", inversedBy="link")
  * @ORMJoinTable(name="linkcombo",
  *   joinColumns={
  *     @ORMJoinColumn(name="link_id", referencedColumnName="id", onDelete="CASCADE")
  *   },
  *   inverseJoinColumns={
  *     @ORMJoinColumn(name="linkset_id", referencedColumnName="id", onDelete="CASCADE")
  *   }
  * )
  */
  private $linkset;
  

Ответ №1:

Может быть, вам следует изменить свой оператор «foreach» на что-то вроде этого?

 foreach( $tracker->getLinkset() as $linkset ) {
    foreach( $linkset->getLinks() as $link ) {
        ....
    }
}
  

Я надеюсь, что это поможет!

Редактировать:

Если отношение между «linkset» и «link» является просто отношением manytomany, я бы изменил аннотации так, чтобы они выглядели следующим образом:

Объект linkset:

 /**
 * @ORMManyToMany(targetEntity="Link")
 **/
private $links;
  

Объект ссылки:

 /**
 * @ORMManyToMany(targetEntity="Linkset")
 */
  

Это должно работать при условии, что:

  • Объекты Link и Linkset используют одно и то же пространство имен, в противном случае вам следует изменить targetEntity=»XXX», чтобы оно было полным (т. Е. ВашBundle EntitiesLinkset и вашOtherBundle EntitiesLink
  • Связь между трекером и набором ссылок в порядке (вы это проверили?)

Я уверен, что кто-то более опытный в symfony2 может помочь вам лучше, чем я, я недавно начал использовать symfony

Комментарии:

1. альгимо, спасибо за твой ответ, но, к сожалению, это, похоже, не работает. Это немного сбивает с толку, поскольку статья на веб-сайте Symfony предполагает, что это должно работать. Должно быть, я что-то упускаю из виду! 🙁

2. извините, я не взглянул на ваши объекты, я совершенно ясно видел, что проблема была в foreach. Я отредактирую свой комментарий другим предложением

3. Привет, Альгимо, спасибо за ваш ответ и ваши усилия. Но это тоже не работает. Если я удалю понятие ‘mappedBy=»linkset»‘, то Symfony2 пожалуется, что этот конкретный атрибут отсутствует. Есть другие идеи?