2013-05-22 14 views
6

Ich arbeite derzeit an einem Sprachbewertungsprojekt, das es dir ermöglicht, eine Prüfung in der von dir gewünschten Sprache zu machen und dein Niveau zu bewerten. Ich benutze Symfony2 Framework und arbeite auch mit Doctrine2. Mein Problem ist das folgende:Erhalte Entitäten aus einer unidirektionalen Viele-zu-viele-Beziehung mit Doctrine2 und Symfony2

Ich habe zwei Entitäten Prüfung und Frage durch eine Viele-zu-Viele-Beziehung verknüpft (Prüfung ist der Besitzer). Jede Prüfung kann sich auf mehrere Fragen beziehen und jede Frage kann sich auf mehrere Prüfungen beziehen.

Hier ist mein Code:

Exam Einheit

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

Solange es eine unidirektionale Beziehung ist, gibt es keine 'Prüfungen' Attribut in meiner Frage Klasse.

Nun, was ich tun möchte, ist, alle Fragen immer auf eine bestimmte Prüfung im Zusammenhang, den getQuestions() -Methode, wie dies Aufruf:

$questions = $exam->getQuestions(); 

Aber diese Methode ein leeres Array zurück, auch wenn ich habe Daten in meiner Datenbank. Wenn ich die $ Prüfung Variable var_dump, kann ich die Fragen sehen Array leer ist:

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

Ich glaube, ich vielleicht eine findByExam() Funktion in meinem QuestionRepository schreiben könnte, aber ich weiß wirklich nicht, wie das implementieren tritt in diesem Fall ein.

Jede Hilfe wäre großartig!

Antwort

11

Um eine findByExam() -Methode in Ihrem QuestionRepository haben Sie wie folgt vor:

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

    return $q->getResult(); 
} 

Sie könnten auch eine bidirektionale Beziehung nicht unidirektional schaffen!

Jede Prüfung kann mit mehreren Fragen zusammenhängen, und jede Frage kann sich auf mehrere Prüfungen beziehen.

Erstellen Sie eine bidirektionale Beziehung, die durch das Hinzufügen dieser zu Ihrer Frage Einheit:

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

    // ... 

Danach können Sie verwenden ...

$question->getExams() 

... in dem Controller.

automatisch an Ihre verbundenen Unternehmen Lehre der Option verbinden holen kann mit verwendet werden:

  • LAZY (lädt die Beziehungen beim Zugriff)
  • EAGER (Auto verbindet die Beziehungen)
  • EXTRA_LAZY (manueller Abruf)

Beispiel:

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

Obwohl das eifrige Laden einen Nachteil in Bezug auf die Leistung hat, könnte es eine Option für Sie sein.

Lehre Fetch mit EAGER

Jedes Mal, wenn Sie für eine Entität abfragen, die persistent Verbände und diese Verbände hat als EAGER abgebildet, werden sie automatisch zusammen mit der Einheit geladen sein wird abgefragt und ist somit sofort für Ihre Anwendung verfügbar.

Lesen Sie mehr darüber in der Doctrine Documentation.

Eine weitere Option, die Sie überprüfen sollten, wenn Sie mit Beziehungen arbeiten, ist die Kaskade Option.

Siehe Kapitel Doctrine - Working with Associations der Dokumentation.

Tipp: Sie Schnittstellen für die Prüfungen schaffen sollten und Fragen und verwenden sie anstelle der ursprünglichen Einheit in Ihrem Set und Methoden hinzufügen zu ermöglichen, leichter erweitern.

+0

Dank für Ihre große Antwort! Es wird viel helfen. Ich werde daran arbeiten und Sie wissen lassen, ob ich meine Probleme gelöst habe oder andere getroffen habe;) – Beliasus

+0

Ich habe versucht, eine bidirektionale Beziehung anstelle der uni-direktionalen zu erstellen, aber trotzdem kann ich nichts bekommen. Denken Sie, dass es ein Problem im Controller sein kann, bevor Sie eine Prüfung mit den damit verbundenen Fragen in der Datenbank fortsetzen? Ich muss eventuell alle Fragen zur Prüfungsinstanz hinzufügen? Ich meine, wissen Sie, ob die Bindeanforderung in einem Formular die Funktion addQuestion() aufrufen würde oder muss ich das manuell tun? – Beliasus

+0

Nachdem ich stundenlang gesucht hatte, wurde mir klar, dass mein Problem nicht von der vielen zu vielen Beziehung kam, sondern von etwas anderem, das störte. Tatsächlich funktioniert meine getQuestions() - Funktion von der Exam-Entity, und dies ist der beste Weg, um das zu tun, was ich wollte, mit einer unidirektionalen Beziehung. Vielen Dank für Ihre Hilfe, ich habe Ihren Rat für die Add-Funktionen verwendet und auch Doctrine Fetching genauer unter die Lupe genommen. – Beliasus

0

Bidirektionale Relations Doctrine2 ORM mit Zuordnungstabelle exam_questions exam_id mit 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

Verwandte Themen