6

I'm currently working on a language assessment project which enables you to take an exam in the language you want and evaluate your level. I use Symfony2 framework and work with Doctrine2 as well. My issue is the following one:

I have two entities Exam and Question linked by a Many-To-Many relation (Exam being the owner). Each exam can be related to several questions, and each question can be related to several exams.

Here is my code:

Exam entity

/**
 * Exam
 *
 * @ORM\Table(name="cids_exam")
 * @ORM\Entity(repositoryClass="LA\AdminBundle\Entity\ExamRepository")
 */
class Exam
{
    ...

    /**
    * @ORM\ManyToMany(targetEntity="LA\AdminBundle\Entity\Question", cascade={"persist"})
    * @ORM\JoinTable(name="cids_exam_question")
    */
    private $questions;

    ...


    /**
     * Constructor
     */
    public function __construct()
    {
        $this->questions = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Add questions
     *
     * @param \LA\AdminBundle\Entity\Question $questions
     * @return Exam
     */
    public function addQuestion(\LA\AdminBundle\Entity\Question $questions)
    {
        $this->questions[] = $questions;

        return $this;
    }

    /**
     * Remove questions
     *
     * @param \LA\AdminBundle\Entity\Question $questions
     */
    public function removeQuestion(\LA\AdminBundle\Entity\Question $questions)
    {
        $this->questions->removeElement($questions);
    }

    /**
     * Get questions
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getQuestions()
    {
        return $this->questions;
    }
}

As long as it is a unidirectional relation, there is no 'exams' attribute in my Question class.

Now, what I want to do is getting all the questions related to a specific exam, calling the getQuestions() method, like this:

$questions = $exam->getQuestions();

But this method returns an empty array, even if I have data in my database. If I var_dump the $exam variable, I can see the questions array is empty:

object(LA\AdminBundle\Entity\Exam)[47]
  private 'id' => int 5
  ...
  private 'questions' => 
    object(Doctrine\ORM\PersistentCollection)[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(Doctrine\Common\Collections\ArrayCollection)[249]
          private '_elements' => 
            array (size=0)
              ...

I think I could maybe write a findByExam() function in my QuestionRepository, but I don't really know how to implement the joins in this case.

Any help would be great!

4

2 回答 2

11

要在 QuestionRepository 中有 findByExam() 方法,请执行以下操作:

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

    return $q->getResult();
 }

您还可以创建双向关系而不是单向关系!

每个考试可以与几个问题相关,每个问题可以与几个考试相关。

通过将其添加到您的 Question 实体来创建双向关系:

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()

...在您的控制器中。

要自动加入您的相关实体,学说的 fetch 选项可用于:

  • LAZY(访问时加载关系)
  • EAGER(自动加入关系)
  • EXTRA_LAZY(手动获取)

例子:

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

尽管急切加载在性能方面有缺点,但它可能是您的一个选择。

使用 EAGER 获取教义

每当您查询具有持久关联的实体并且这些关联被映射为 EAGER 时,它们将自动与被查询的实体一起加载,因此您的应用程序可以立即使用它们。

在Doctrine 文档中阅读更多关于它的信息。

使用关系时应该检查的另一个选项是级联选项。

请参阅文档的Doctrine - Working with Associations章节。

提示: 您应该为考试和问题创建接口,并使用它们而不是您集合中的原始实体,并添加方法以允许更轻松地扩展。

于 2013-05-22T11:12:13.983 回答
0

使用 Doctrine2 ORM 和关联表的双向关系exam_questionsexam_id question_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

于 2016-01-27T23:44:30.067 回答