我目前正在开展语言评估项目,使您能够以您想要的语言参加考试并评估您的水平。我使用Symfony2框架并与Doctrine2一起使用。我的问题是以下问题:
我有两个实体考试和问题由多对多关系链接(考试是所有者)。每个考试都可以与几个问题相关,每个问题都可以与几个考试相关。
这是我的代码:
考试实体
/**
* 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;
}
}
只要它是单向关系,我的问题类中就没有'考试'属性。
现在,我要做的是获取与特定考试相关的所有问题,调用getQuestions()方法,如下所示:
$questions = $exam->getQuestions();
但是这个方法返回一个空数组,即使我的数据库中有数据。如果我var_dump $ exam变量,我可以看到问题数组是空的:
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)
...
我想我可以在我的QuestionRepository中编写一个findByExam()函数,但在这种情况下我真的不知道如何实现连接。
任何帮助都会很棒!
答案 0 :(得分:11)
要在QuestionRepository中使用findByExam()方法,请执行以下操作:
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()
...在您的控制器中。
要自动加入相关实体,可以使用doctrine的fetch选项:
示例:
/**
* @ManyToMany(targetEntity="Question",inversedBy="exams", cascade={"all"}, fetch="EAGER")
*/
虽然急切加载在性能方面存在缺点,但它可能是您的选择。
使用EAGER进行学说提取
每当您查询具有持久关联的实体时 这些关联被映射为EAGER,它们将自动成为 与被查询的实体一起加载,因此立即加载 适用于您的应用程序。
在Doctrine Documentation中了解更多相关信息。
使用关系时应检查的另一个选项是级联选项。
请参阅文档的Doctrine - Working with Associations章节。
提示强> 您应该为考试和问题创建界面,并使用它们而不是集合中的原始实体,并添加方法以便于扩展。
答案 1 :(得分:0)
使用Doctrine2 ORM与关联表exam_questions的双向关系 exam_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..
}