2016-10-09 3 views
1

Angenommen, wir haben zwei Einheiten und einen bidirektionalen Eins-zu-viele Assoziation zwischen ihnen. Auf der umgekehrten Seite kann die Sammlung sehr groß werden, aber meistens wird nur eine bestimmte Teilmenge der Assoziation benötigt, basierend auf einem festen Kriterium.Lehre einer Eins-zu-viele-Verbindung mit nativen und permanenten Filterkriterien

Ich weiß, dass ich extra verzögertes Laden von Sammlungen verwenden kann und Kriterien oder Filter wie in chapter 8 of the Doctrine docs beschrieben. Dies funktioniert jedoch nur, wenn das Unternehmen Manager zugänglich ist, aber ich möchte eine Lösung haben, die auf der Unternehmensebene direkt funktioniert wie in Ashley Dawson's blog diskutiert.

Lassen Sie sich sagt, wir haben das folgende einfache Objektmodell mit Büchern und Kapiteln

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) { /*...*/ } 
} 

Nun sollte Chapters durch ein Attribut erweitert werden important und Books soll eine zweite Sammlung erhalten, dass nur wichtige Geschäfte Kapitel

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

Ist das in irgendeiner Weise möglich? Die nächstgelegene ich bekam, war eine SQL-Ansicht important_chapters auf der Datenbank-Ebene zu erstellen, die die richtigen Zeilen aus der Tabelle wählt chapters und dann eine neue Einheit ImportantChapter auf der Lehre Ebene erstellen. Aber ich mag diese Problemumgehung nicht, weil sie oberflächlich einen dritten Entitätstyp erzeugt. Natürlich könnte man diese Lösung nach vorne schieben und ImportantChapter ein Kind Klasse von Chapter, verwenden Sie Tabelle Vererbung und important als Unterscheidungsspalte verwenden machen. Dies funktioniert jedoch nicht in allen Fällen, insbesondere wenn das Kriterium komplizierter wird als in diesem Spielzeugbeispiel.

Antwort

1

Sie könnten die Lehre Kriterien ohne die Einheit Manager verwenden auch, als Beispiel:

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

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

Hope this Hilfe

+0

Ja, in der Tat. Dann muss ich noch herausfinden, wie man die Kriterienklassen so erweitert, dass sie die zeitlichen und räumlichen Erweiterungen von PostgreSQL unterstützen. Leider ist mein Kriterium nicht so einfach wie im Beispiel. – user2690527

+1

Ich entschied mich, Ihre und meine Lösung zu kombinieren. Da die Docrine-Klasse Criteria nicht die Ausdruckskraft bietet, die ich für die Auswahl benötige, habe ich oben auf der Tabelle eine Ansicht erstellt, die eine zusätzliche Spalte mit einem booleschen Typ hinzufügt – user2690527