我已经和这个代码斗争了一段时间,试图清理它,但感觉不对劲。我有一个模型,叫做图书馆。图书馆可以拥有图书,Library Model类有一个公共books
属性,它只是图书的数组。模型可能看起来像这样:
Application_Model_Library {
public $books = null;
protected $_id;
protected $_name;
/* Getters, setters, etc. */
}
我还有一本书的模型。用户可以访问由多对多表users_books_permissions
定义的图书。
库模型存储当前用户可以访问的图书数量,该数量使用图书表上的JOIN
和COUNT(*)
找到。显然,库表本身并不存储这些信息,因此它是一个经过计算的字段。
protected $_accessibleBookCount;
我所有的模型都包含在一个文件中,由(静态)映射器构建
// In the Application_Model_Library class
public static function fetchAll(){
$db = Zend_Registry::get("db");
/* etc */
}
但是,我的分页插件需要访问原始select
语句,以便添加LIMIT
子句。这对于排序和筛选也很有用。为了处理这个问题,获取图书列表实际上需要两个调用。第一个创建并返回一个select
对象。这在我的控制器中根据参数进行了修改,以添加排序、过滤和分页。然后,我的模型中的另一个方法获取select对象,并执行对象的实际获取和初始化。
第一种方法还负责注入填充$_accessibleBookCount
字段的JOIN
。
获取单个库需要从前面提到的函数中获取select
语句,添加WHERE
子句以便只选择我想要的库,然后将其输入到方法中以实际实例化库模型对象。
一旦我有了一个库对象,就可以通过库模型中一个名为getBooks
的方法来处理获取它的图书。如果$books
为null,则该方法填充它。然后,返回数组。由于$books
属性是公共的,因此可以访问个别书籍。在获取时,该方法还使用JOIN
来确定用户是否有权访问该书。
然而,如果我需要获取所有图书馆的列表,并同时列出每个图书馆的书籍,该怎么办?获取库列表需要两个方法调用,但必须对每个库调用getBooks
。这导致了大量的重复查询。
Whew。我要感谢那些能够坚持到我的帖子末尾的人。我还要提前感谢所有人的帮助。
我看到的在一个查询中获取所有书籍和库的唯一解决方案是实际获取所有书籍并与libraries表连接。这可能是一个更好的解决方案,也可能不是,这取决于您对程序中的库和书籍所做的操作。
类似这样的东西(在图书模型中):
$select = $this->select();
$select->setIntegrityCheck(false)
->from(array("b" => "books"))
->join(array("l" => "libraries"),"b.lid = l.id",array("libraryName" => "l.name")) // lid = Library ID in Books table
->order("l.name ASC"); // Order by Library Name
然后,您可以使用一些PHP魔术来整理库和书籍(创建新的对象、数组或任何您想要的东西),例如:
$libraries = array();
foreach($books as $book) {
$libraries[$book->libraryName]["books"][] = $book;
}
您必须看看它是否值得麻烦,是否比SQL查询更快/更高效。