Get entities from a one-to-many relationship with many with Doctrine2 and Symfony2

I am currently working on a language assessment project that allows you to take an exam in your preferred language and evaluate your level. I use the Symfony2 framework and work with Doctrine2. My problem is this:

I have two Exam and Question objects related to the Many-to-Many relationship (The exam is the owner). Each exam may be associated with several questions, and each question may be associated with several exams.

Here is my code:

Exam subject

/** * 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; } } 

While this is a one-way relationship, there is no exams attribute in my Question class.

Now, what I want to do is get all the questions related to a particular exam by calling the getQuestions () method, for example:

 $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 see that the array of questions 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 write the findByExam () function in my QuestionRepositor, but I really don't know how to implement joins in this case.

Any help would be great!

+6
source share
2 answers

To find the findByExam () method in your QuestionRepository, follow these steps:

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

You can also create a bi-directional relationship, not one-way!

Each exam can be associated with several questions, and each question can be associated with several exams.

Create a bidirectional link by adding this to your Question object:

 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; } // ... 

Subsequently, you can use ...

 $question->getExams() 

... in your controller.

To automatically join related objects, the doctrine selection option can be used with:

  • LAZY (loads relationships on access)
  • EAGER (automatically merges relationships)
  • EXTRA_LAZY (manual selection)

Example:

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

Although the downloaded download has a performance penalty, this may be an option for you.

Doctrine Fetch with EAGER

Whenever you request an entity that has constant associations and these associations are displayed as EAGER, they will automatically be loaded with the requested entity and thus immediately available to your application.

Read more about this in the Doctrine Documentation .

Another option you should check when working with relationships is the cascade parameter.

See the chapter Doctrine - Working with Associations in the documentation.

Tip: You should create interfaces for exams and questions and use them instead of the source object in your collection and add methods to simplify the extension.

+11
source

Bidirectional relationships using Doctrine2 ORM with association table 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.. } 

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

0
source

Source: https://habr.com/ru/post/945572/


All Articles