6

私は現在、希望する言語で試験を受け、レベルを評価できる言語評価プロジェクトに取り組んでいます。私は Symfony2 フレームワークを使用し、Doctrine2 も使用しています。私の問題は次のとおりです。

多対多の関係 (Exam が所有者) によってリンクされた 2 つのエンティティ Exam と Question があります。各試験は複数の問題に関連付けることができ、各問題は複数の試験に関連付けることができます。

これが私のコードです:

試験体

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

一方向の関係である限り、私の Question クラスには「exams」属性はありません。

ここで、次のように getQuestions() メソッドを呼び出して、特定の試験に関連するすべての問題を取得したいと考えています。

$questions = $exam->getQuestions();

しかし、データベースにデータがある場合でも、このメソッドは空の配列を返します。$exam 変数を var_dump すると、質問配列が空であることがわかります。

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() 関数を記述できると思いますが、この場合の結合の実装方法がよくわかりません。

どんな助けでも素晴らしいでしょう!

4

2 に答える 2

11

QuestionRepository で findByExam() メソッドを使用するには、次の手順を実行します。

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

    return $q->getResult();
 }

一方向ではなく、双方向の関係を作成することもできます。

各試験は複数の問題に関連付けることができ、各問題は複数の試験に関連付けることができます。

これを 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;
    }

    // ...

その後、使用できます...

$question->getExams()

...コントローラーで。

関連するエンティティに自動的に参加するには、doctrine の fetch オプションを次のように使用できます。

  • LAZY (アクセス時にリレーションをロードします)
  • EAGER (リレーションを自動結合)
  • EXTRA_LAZY (手動フェッチ)

例:

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

熱心な読み込みにはパフォーマンスの面でマイナス面がありますが、オプションになる可能性があります。

EAGER を使用した Doctrine Fetch

永続的な関連付けを持つエンティティをクエリし、これらの関連付けが EAGER としてマップされている場合は常に、関連付けがクエリ対象のエンティティと共に自動的に読み込まれるため、アプリケーションですぐに使用できます。

詳しくはDoctrine Documentationを読んでください。

リレーションを操作するときに確認する必要があるもう 1 つのオプションは、カスケードオプションです。

ドキュメントのDoctrine - Working with Associationsの章を参照してください。

ヒント: 試験と問題のインターフェイスを作成し、セット内の元のエンティティの代わりにそれらを使用し、メソッドを追加して拡張を容易にする必要があります。

于 2013-05-22T11:12:13.983 に答える