从Doctrine2和Symfony2获取与多向对话的单向实体

Bel*_*sus 6 many-to-many symfony doctrine-orm

我目前正在开展语言评估项目,使您能够以您想要的语言参加考试并评估您的水平.我使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

只要它是单向关系,我的Question类中就没有'exams'属性.

现在,我想要做的是获取与特定考试相关的所有问题,调用getQuestions()方法,如下所示:

$questions = $exam->getQuestions();
Run Code Online (Sandbox Code Playgroud)

但是这个方法返回一个空数组,即使我的数据库中有数据.如果我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)
              ...
Run Code Online (Sandbox Code Playgroud)

我想我可以在我的QuestionRepository中编写一个findByExam()函数,但在这种情况下我真的不知道如何实现连接.

任何帮助都会很棒!

Nic*_*ich 11

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

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

    return $q->getResult();
 }
Run Code Online (Sandbox Code Playgroud)

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

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

通过将此添加到您的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;
    }

    // ...
Run Code Online (Sandbox Code Playgroud)

之后你可以用......

$question->getExams()
Run Code Online (Sandbox Code Playgroud)

......在你的控制器里.

要自动加入您的相关实体,可以使用doctrine的fetch选项:

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

例:

/**
 * @ManyToMany(targetEntity="Question",inversedBy="exams", cascade={"all"}, fetch="EAGER")
 */
Run Code Online (Sandbox Code Playgroud)

尽管急切加载在性能方面存在缺点,但它可能是您的选择.

使用EAGER获取学说

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

Doctrine文档中阅读更多相关内容.

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

请参阅文档中的Doctrine - 使用关联章节.

提示: 您应该为考试和问题创建界面,并使用它们而不是集合中的原始实体,并添加方法以便于扩展.

  • @Beliasus,您能与我们分享最终解决您问题的方法吗?我有同样的问题,你说"_ [...],我意识到我的问题根本不是来自多对多的关系,而是来自干扰它的其他东西_".什么是"别的东西"?谢谢! (2认同)