2011-01-03 33 views
2

私はPHP Webアプリケーションで作業していますが、ORM機能にDoctrine 2.0を使用したいと考えています。しかし、特定の種類のクエリに重大な問題があります。doctrine 2 - 同期していないデータベース/エンティティを処理する方法

FooとBar Entitiesを含む単純なドメインモデルを考えてみましょう。 Fooエンティティには多くのバーが含まれ、バーにはアクティブとマークされることがあります。

/** @Entity */ 
class Foo 
{ 
    /** @OneToMany(targetEntity="Bar", mappedBy="foo") */ 
    protected $bars; 

    /** Returns Bars marked as active. */ 
    public function getActiveBars() 
    { 
     // XXX What goes here? 
    } 
} 

/** @Entity */ 
class Bar 
{ 
    /** @ManyToOne(targetEntity="Foo", inversedBy="bar") */ 
    protected $foo; 

    /** @Column(type="boolean") */ 
    protected $active; 

    /** ...setter omitted for clarity... */ 
} 

私の質問は:どのようなコードはgetActiveBars方法で配置する必要がありますか?


次のコードは正常に動作しますが、多くの非アクティブバーオブジェクトがデータベース内に存在するときのパフォーマンスが問題になります。 Barコレクションを反復処理すると、実行されるデータベースに対して大きなクエリが発生します。

なgetActiveBar内 SELECT b FROM Bar l WHERE b.active = true AND b.foo = :foo(としてDQLクエリを実行する
function getActiveBars() 
{ 
    $ret = array(); 
    foreach($this->bars as $bar) { 
     if ($bar->isActive()) $ret[] = $bar; 
    } 
    return $ret; 
} 

)が解決策になるようだ、しかし、このようなクエリは、のEntityManager#フラッシュ(前に作られた棒に未処理の変更を検出しません)DQLが実行されているので(と呼ばれていますデータベースに対して)。

答えて

3

おそらく世界の終わりではありません。 Foo :: barsがロードされ、変更され、データベースにコミットされていない場合、唯一のオプションは反復することです。

Foo :: barsがロードされていない場合は、確かに変更されていないので、データベースに問い合わせることもできます。

(バーは、ロードされた変更、およびバックコミットされた場合は最後に、バーのコレクションのサイズがフェッチまたは反復することは、おそらく、より良いでしょうかどうかを決定します)

私は好奇心旺盛になり、そのために方法がありますされますコレクションであるメンバがロードされたかどうかを知るためのエンティティ。 (:あなたの例では、バー、フー)、ないinstanceof ArrayCollectionテストに合格するdocumentation

は、プロキシさのArrayCollectionがあることを暗示しているようです。だから、あなたは、スマートのような取得しようとするかもしれません:

 class Foo { 
     public function getActiveBars(){ 
     if ($this->bars instanceof \Doctrine\Common\Collection\ArrayCollection){ 
      //get active bars by iterating over $this->bars 
     }else{ 
      //get active bars by DQL, and avoid loading $this->bars (for now). 
     } 
     } 
    } 
+0

バージョン2.3以来、Doctrineは[クライテリアAPI](http://www.doctrine-project.org/api/common/2.3/class-Doctrine.Commonを持っています。 Collections.Criteria.html)は、コレクションが既にロードされているかどうかによって、DQLまたは配列検索を使用してArrayCollectionをフィルタリングします。 [参考文献](http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html#filtering-collections)を確認してください。 – GeorgeK

関連する問題