Php 帮助处理复杂的依赖关系、排序、筛选和访问控制

Php 帮助处理复杂的依赖关系、排序、筛选和访问控制,php,model-view-controller,zend-framework,Php,Model View Controller,Zend Framework,我花了一段时间研究这段代码,试图清理它,但感觉不太对劲。我有一个模型,叫做图书馆。图书馆可以拥有图书,图书馆模型类有一个公共的books属性,它只是一个图书数组。该模型可能如下所示: Application_Model_Library { public $books = null; protected $_id; protected $_name; /* Getters, setters, etc. */ } 我还有一本书的模型。用户可以访问由多对多表定义的

我花了一段时间研究这段代码,试图清理它,但感觉不太对劲。我有一个模型,叫做图书馆。图书馆可以拥有图书,图书馆模型类有一个公共的
books
属性,它只是一个图书数组。该模型可能如下所示:

Application_Model_Library {
    public $books = null;

    protected $_id;
    protected $_name;

    /* Getters, setters, etc. */
}
我还有一本书的模型。用户可以访问由多对多表定义的书籍,
Users\u Books\u 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对象并执行对象的实际获取和初始化

第一个方法还负责注入填充
$\u accessibleBookCount
字段的
联接

获取单个库涉及从前面提到的函数中获取
select
语句,添加
WHERE
子句,以便只选择我想要的库,然后将其输入到方法中以实际实例化库模型对象

一旦我有了一个library对象,取回它的书籍就会由库模型中名为
getBooks
的方法来处理。如果
$books
为空,则该方法将填充它。然后,返回数组。可以访问单个书籍,因为
$books
属性是公共的。获取时,该方法还使用一个
JOIN
来确定用户是否有权访问该书

但是,如果我需要获取所有图书馆的列表,同时列出每个图书馆的书籍,该怎么办?获取库列表需要两个方法调用,但是必须对每个库调用
getBooks
。这会导致大量重复查询


呼。我要感谢任何能够坚持到我的文章末尾的人。我还要提前感谢所有人的帮助。

我看到的在一个查询中获取所有书籍和库的唯一解决方案是实际获取所有书籍并加入libraries表。这可能是一个更好的解决方案,也可能不是,这取决于您对程序中的库和书籍所做的操作

类似这样的内容(在图书模型中):

然后,您可以使用一些PHP魔术来整理库和书籍(创建新对象、数组或任何您想要的内容),例如:

$libraries = array(); 
foreach($books as $book) {
  $libraries[$book->libraryName]["books"][] = $book; 
}

您必须看看它是否值得费心,是否比SQL查询更快/更高效。

一个查询是不必要的。我最担心的是:我在我的库模型上调用fetchAll来获取库列表。但是,我需要每个图书馆的图书清单!因此,我现在必须打电话给每个图书馆的fetchAll以获得这些书。这是1+个(图书馆)查询。目前,我这样做:在库模型中,fetchAll不仅获取库,而且还获取每个要获取的库的所有书籍。然后,我使用您在第二个代码片段中共享的代码将它们排序为它们的合法所有者。你认为这是一个足够好的方法吗?我看到的问题是,你不必总是去拿整批货。有时,您只需要一个简单的库列表。例如,填充“select”表单元素或其他内容。如果您已经覆盖了fetchAll()方法来做更多的工作,那么对于简单的任务来说,这只是不必要的工作量。我可以在库的fetchAll()中包含一个参数,使书籍延迟加载,而不是很好地加载,然后选择一种或另一种方法!我认为没有一个解决方案比另一个好得多。如果您真的想优化,请为每种方法计算脚本执行时间并选择最快的方法。我的意思是,当参数设置为true时,将获取所有书籍并填充库。如果为false,则只获取库;没有书。在后一种情况下,尝试调用库上的
getBooks
,将显式获取该库的图书。
$libraries = array(); 
foreach($books as $book) {
  $libraries[$book->libraryName]["books"][] = $book; 
}