Получить сущности из однонаправленного отношения многие ко многим с Doctrine2 и Symfony2

В настоящее время я работаю над проектом, оценка языка, что позволяет сдать экзамен на знание языка и оценить свой уровень. Я использую Symfony2 framework и работаю с Doctrine2. Моя проблема заключается в следующем:

у меня есть два объекта экзамен и вопрос, связанные отношением "многие ко многим" (экзамен является владельцем). Каждый экзамен может быть связан с несколькими вопросами, и каждый вопрос может быть связан с несколькими экзаменами.

вот мой код:

экзамен сущность

/**
 * Exam
 *
 * @ORMTable(name="cids_exam")
 * @ORMEntity(repositoryClass="LAAdminBundleEntityExamRepository")
 */
class Exam
{
    ...

    /**
    * @ORMManyToMany(targetEntity="LAAdminBundleEntityQuestion", cascade={"persist"})
    * @ORMJoinTable(name="cids_exam_question")
    */
    private $questions;

    ...


    /**
     * Constructor
     */
    public function __construct()
    {
        $this->questions = new DoctrineCommonCollectionsArrayCollection();
    }

    /**
     * Add questions
     *
     * @param LAAdminBundleEntityQuestion $questions
     * @return Exam
     */
    public function addQuestion(LAAdminBundleEntityQuestion $questions)
    {
        $this->questions[] = $questions;

        return $this;
    }

    /**
     * Remove questions
     *
     * @param LAAdminBundleEntityQuestion $questions
     */
    public function removeQuestion(LAAdminBundleEntityQuestion $questions)
    {
        $this->questions->removeElement($questions);
    }

    /**
     * Get questions
     *
     * @return DoctrineCommonCollectionsCollection 
     */
    public function getQuestions()
    {
        return $this->questions;
    }
}

пока это однонаправленное отношение, в моем классе вопросов нет атрибута "экзамены".

Теперь, что я хочу сделать, это получить все вопросы, связанные с конкретным экзаменом, вызывая метод getQuestions (), например:

$questions = $exam->getQuestions();

но этот метод возвращает пустой массив, даже если у меня есть данные в моей базе данных. Если я var_dump переменная $exam, я вижу, что массив вопросов пусто:

object(LAAdminBundleEntityExam)[47]
  private 'id' => int 5
  ...
  private 'questions' => 
    object(DoctrineORMPersistentCollection)[248]
      private 'snapshot' => 
        array (size=0)
          empty
      private 'owner' => null
      private 'association' => null
      private 'em' => null
      private 'backRefFieldName' => null
      private 'typeClass' => null
      private 'isDirty' => boolean false
      private 'initialized' => boolean false
      private 'coll' => 
        object(DoctrineCommonCollectionsArrayCollection)[249]
          private '_elements' => 
            array (size=0)
              ...

Я думаю, что мог бы написать функцию findByExam() в моем QuestionRepository, но я действительно не знаю, как реализовать соединения в этом случае.

любая помощь будет здорово!

2 ответов


чтобы иметь метод findByExam () в QuestionRepository сделайте следующее:

 public function findByExam($exam)
 {
    $q = $this->createQueryBuilder('q')
        ->where('q.exam = :exam')
        ->setParameter('exam', $exam)
        ->getQuery();

    return $q->getResult();
 }

вы также можете создать двунаправленные отношения не однонаправленные !

каждый экзамен может быть связан с несколькими вопросами, и каждый вопрос может иметь отношение к нескольким экзаменам.

создайте двунаправленное отношение, добавив это в свой вопрос:

use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Vendor\YourExamBundle\Entity\ExamInterface;

class Question 
{
    protected $exams;

    public function __construct()
    {
       $this->exams = new ArrayCollection();
    }

    public function getExams()
    {
       return $this->exams;
    }

    public function addExam(ExamInterface $exam)
    {
        if !($this->exams->contains($exam)) {
            $this->exams->add($exam);
        }
        return $this;
    }

    public function setExams(Collection $exams)
    {
        $this->exams = $exams;

        return $this;
    }

    // ...

после этого вы можете использовать...

$question->getExams()

... в контроллере.

чтобы автоматически присоединиться к опции выборки связанных сущностей доктрины можно использовать с:

  • LAZY (загружает отношения при доступе )
  • нетерпеливый (авто-присоединяется к отношениям )
  • EXTRA_LAZY (ручная выборка )

пример:

/**
 * @ManyToMany(targetEntity="Question",inversedBy="exams", cascade={"all"}, fetch="EAGER")
 */

хотя предвыборка имеет недостаток с точки зрения производительности, это может быть вариантом для вы.

учение принести с нетерпением

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

подробнее об этом читайте в разделе Доктрина Документации.

другой вариант вы должны проверить при работе с отношениями это каскад.

посмотреть учение-работа с ассоциациями глава документации.

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


двунаправленные отношения с использованием Doctrine2 ORM с таблицей ассоциаций exam_questions question_id exam_id

<?php

class Exams

 ....OTHER PROPERTIES...

 /**
  * Owning Side
  *
  * @ManyToMany(targetEntity="Questions", inversedBy="exams")
  * @JoinTable(name="exam_questions",
  *      joinColumns={@JoinColumn(name="exam_id", referencedColumnName="id")},
  *      inverseJoinColumns={@JoinColumn(name="question_id", referencedColumnName="id")}
  *      )
  */
 private $questions;

 ..OTHER CODES..

 }


 class Questions{


 ..OTHER CODES..

 /**
  * Inverse Side
  *
  * @ManyToMany(targetEntity="Exams", mappedBy="questions")
  */
 private $exams;

 ..OTHER CODES..

 }

http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#annref-manytomany