Получить сущности из однонаправленного отношения многие ко многим с 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..
}