Doctrine与本机和永久过滤条件的一对多关联

时间:2016-10-09 14:12:16

标签: orm doctrine-orm

假设我们有两个实体并且它们之间存在双向一对多关联。在反面,集合可以变得非常庞大,但大多数时候只需要基于固定标准的关联的某个特定子集。

我知道我可以按照chapter 8 of the Doctrine docs中的说明使用延迟加载的集合和条件或过滤器。但是,这仅在实体管理器可访问时才有效,但我希望有一个直接适用于实体级别的解决方案,如Ashley Dawson's blog中所述。

让我们说,我们有以下简单的对象模型,包括书籍和章节

class Book {
  /**
   * @ORM\OneToMany( targetEntity = "Chapter", mappedBy = "book" )
   * @var ArrayCollection
   */
  protected $chapters;

  /**
   * @return Chapter[]
   */
  public function getChapters() { /*...*/ }

  /**
   * @param Chapter $chapter
   */
  public function addChapter( Chapter $chapter ) { /*...*/ }

  /**
   * @param Chapter $chapter
   */
  public function removeChapter( Chapter $chapter ) { /*...*/ }
}

class Chapter {
  /**
   * @ORM\ManyToOne( targetEntity = "Book", inversedBy = "chapters" )
   * @ORM\JoinColumn( name = "book_id", referencedColumnName="id" )
   * @var Book|null
   */
  protected $book;

  /**
   * @return Book|null
   */
  public function getBook() { /*...*/ }

  /**
   * @param Book|null $newBook
   */
  public function setBook( Book $newBook = null ) { /*...*/ }
}

现在,Chapters应该通过属性important进行扩充,Books应该获得仅存储重要章节的第二个集合

class Book {
  // ... as above ...

  /**
   * @ORM\OneToMany( targetEntity = "Chapter", mappedBy = "book" )
   * **HERE WE NEED TO SPECIFY SOME CRITERION FOR chapter.important = true**
   * @var ArrayCollection
   */
  protected $importantChapters;

  /**
   * @return Chapter[]
   */
  public function getImportantChapters() {
    return $this->importantChapters->toArray();
  }
}

class Chapter {
  // ... as above ...

  /**
   * @Column( type="boolean")
   * @var boolean
   */
  protected $important;
}

这有可能吗?我得到的最接近的是在数据库级别创建一个SQL视图important_chapters,从表chapters中选择正确的行,然后在Doctrine级别创建一个新的实体ImportantChapter。但我不喜欢这种解决方法,因为它表面上创建了第三种类型的实体。当然,可以推进该解决方案并使ImportantChapter成为Chapter的子类,使用表继承并使用important作为鉴别器列。但这并不适用于所有情况,特别是如果标准变得比这个玩具示例更复杂。

1 个答案:

答案 0 :(得分:1)

您也可以在没有实体管理器的情况下使用Doctrine Criteria,例如:

  /**
   * @return Chapter[]
   */
  public function getImportantChapters() {
    $criteria = Criteria::create();
    $criteria->where(Criteria::expr()->eq('important', true));

    return $this->chapters->matching($criteria);
  }

希望这个帮助