最近、Doctrine 1.2 を Zend Framework 1.11 に統合するプロジェクトに取り組んでいますが、とても楽しかったです。
サービス層に実装した最も一般的なメソッドの 1 つは、引数として渡される一連の基準に従ってドメイン モデルのコレクションを返すメソッドです。
私は次のようなインターフェースでそれらを作成してきました:
//All books
$books = $service->getBooks();
//Books under certain categories and authored which matches the search term 'Hitchens'
$books = $service->getBooks(array(
'category' => array(1,2,3,4),
'author' => array('like' => '%Hitchens%', 'diedBefore' => Zend_Date::now()),
'orderBy' => 'bookTitle',
'limit' => 10
));
そして、実装は次のようになります。
public function getBooks(array $options = null)
{
$query = Doctrine_Query::create()->from('LibSys_Model_Book as book');
if($options !== null){
if(isset($options['author']){
//Manipulate Doctrine_Query object here....
}
//More 'ifs' and manipulations to the Doctrine_Query object...(additional criterias, orderBy clauses, limits, offsets, etc.)
}
}
そして、より多くの基準の必要性が高まるにつれて、実装はより厄介になります。言うまでもなく、あらゆる場所で多くのコードが再利用されており、コードの更新は非常に退屈な作業です。
配列セグメントの代わりにオブジェクトとして条件を渡すことができれば、次のようなビジター パターンを利用できれば、はるかに優れていると考えていました。
$authorCriteria = new LibSys_Criteria_Author();
$authorCriteria->like('%Hitchens%');
$authorCriteria->diedBefore(Zend_Date::now());
$books = $service->getBooks(array(
$authorCriteria,
new LibSys_Criteria_Category(array(1,2,3,4))
));
次のような一般的なインターフェイスLibSys_Criteria_Category
をLibSys_Criteria_Author
実装します。
interface LibSys_Doctrine_Criteria_Interface
{
public function applyCriteria(Doctrine_Query $query);
}
したがって、提供された一連の基準オブジェクトをループDoctrine_Query
処理し、必要に応じて順番に操作しながらオブジェクトを渡すだけです。
public function getBooks(array $criteria = null)
{
$query = Doctrine_Query::create()->from('LibSys_Model_Book as book');
if($criteria !== null){
foreach($criteria as $criterion){
if($criterion instanceof LibSys_Doctrine_Criteria_Interface){
$criterion->applyCriteria($query);
}
}
}
}
このようにすると、サービスが使いやすくなるだけでなく、サービスが拡張可能になり、基準オブジェクトが再利用可能になり、すべてが維持しやすくなります。
ただし、これを確実に機能させるには、Doctrine_Query
オブジェクトを検査し、既存の結合、条件などを確認できる必要があります。これは、2 つのまったく異なる基準が同じ条件セットまたは同じセットを必要とする可能性があるためです。結合のセット。その場合、2 番目の基準は、既存の結合を単純に再利用したり、それに応じて調整したりできます。また、基準の一連の条件が相互に互換性がない場合を想像するのは難しくありません。その場合、例外をスローする必要があります。
だから私の質問は:
を調べて、Doctrine_Query
どのコンポーネントが結合されているか、または既に適用されている条件のセットに関する情報を取得する方法はありますか?