我最近一直在研究一系列项目,将Doctrine 1.2集成到Zend Framework 1.11中,它非常有趣。
我在服务层中实现的最常用方法之一是根据作为参数传递的一组条件返回我的域模型集合的方法。
我一直用这样的接口创建它们:
//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
对象并检查任何现有的连接,条件等。这是因为两个完全不同的标准并非不可能可能需要相同的条件集或相同的连接集。在这种情况下,第二标准可以简单地重新使用现有的连接和/或相应地进行调整。此外,不难想象标准的一组条件与另一条件互不相容的情况,在这种情况下应该保证抛出异常。
所以我的问题是:
有没有办法检查Doctrine_Query
并获取有关哪些组件已加入的信息,或已应用的任何条件?