我正在编写一些代码,允许用户阅读网站上的报告,使用 AJAX 调用动态加载所请求的内容,而不是整个 15+MB 的报告。
我正在编写一个模型来访问数据库中的所有报告数据,并且我不想使用事件记录模式。我遵循“模型有一个表,而不是 IS-A 表”的想法,因为该模型将访问 5 个不同的表,并且这些表之间存在一些复杂的 MySQL JOIN。
在 Zend Framework 中遵循什么好的设计模式,例如?
于美国东部时间 2012 年 12 月 5 日中午 12:14 更新
我目前在一家市场研究报告公司工作。在不使用实际函数名称或透露任何有意义的代码细节的情况下,以下是基础知识:
readreportAction() 的作用是:
- 获取报告元数据
- 获取报告“目录”
readsectionAction() 的作用:
- 获取报告文本,仅其中一部分
- 获取嵌入的表格数据
- 获取数据/图像
- 获取脚注
- 格式化报告文本
reportpdfAction() 与 readreportAction() 和 readsectionAction() 执行完全相同的操作,只是同时执行所有操作。我正在尝试构思一种不复制+粘贴此代码/编程逻辑的方法。数据映射器似乎可以解决这个问题。
最佳答案
我会推荐Data Mapper pattern 。
你说的一切都有道理,而且这个模式很适合。您的模型不应该知道或关心它是如何持久化的。相反,映射器会执行它的建议 - 将您的模型映射到数据库。我喜欢这种方法的原因之一是它鼓励人们从对象的角度来思考模型,而不是关系数据库表,就像事件记录模式和表行网关经常发生的那样。
除非非常简单,否则您的对象通常不会反射(reflect)数据库表的结构。这可以让您编写好的对象,然后再担心持久性方面的问题。有时需要更多的手动操作,因为您的映射器需要处理复杂的连接,可能需要编写一些代码或 SQL,但最终结果是它只做您想要的事情,仅此而已。如果您不想利用它们,则不需要任何魔法或约定。
我一直认为这些文章很好地解释了一些可以在 ZF 中很好使用的设计模式:http://survivethedeepend.com/zendframeworkbook/en/1.0/implementing.the.domain.model.entries.and.authors#zfbook.implementing.the.domain.model.entries.and.authors.exploring.the.entry.data.mapper
更新:
那么你的映射器可能会从类似这样的接口(interface)扩展:
<?php
interface Mapper_Interface
{
/**
* Sets the name of the entity object used by the mapper.
*/
public function setObjectClass($class);
/**
* Sets the name of the list class used by the mapper.
*/
public function setObjectListClass($listClass);
/**
* Get the name of the object class used by the mapper.
*
*/
public function getObjectClass();
/**
* Get the name of the object list class used by the mapper.
*
* @return string
*/
public function getObjectListClass();
/**
* Fetch one row.
*
* @param array $where Criteria for the selection.
* @param array [$order = array()] Optionally the order of results
* @return Object_Abstract
* @throws Mapper_Exception
*/
public function fetchRow($where, $order = array());
/**
* Fetch all records. If there is no underlying change in the persisted data this should
* return a consistant result.
*
* @param string|array|Zend_Db_Table_Select $where OPTIONAL An SQL WHERE clause or Zend_Db_Table_Select object.
* @param string|array $order OPTIONAL An SQL ORDER clause.
* @param int $count OPTIONAL An SQL LIMIT count.
* @param int $offset OPTIONAL An SQL LIMIT offset.
* @return Object_List_Abstract
* @throws Mapper_Exception
*/
public function fetchAll($where = null, $order = null, $count = null, $offset = null);
/**
* Deletes one or more object.
*
* @param array|string $where Criteria for row deletion.
* @return integer $affectedRows
* @throws Mapper_Exception
*/
public function delete($where);
/**
* Saves a record. Either updates or inserts, as required.
*
* @param $object Object_Abstract
* @return integer $lastInsertId
* @throws Mapper_Exception
*/
public function save($object);
}
您将与映射器进行交互,如下所示:
$fooObjectMapper = new Foo_Mapper;
$fooObjectList = $fooObjectMapper->fetchAll();
var_dump($fooObjectList->first());
或
$fooObjectMapper = new Foo_Mapper;
$fooObject = $fooObject->fetch(array('id = ?' => 1));
$fooObject->setActive(false);
$fooObjectMapper->save($fooObject);
我通常为任何启用“PDO”的数据库编写映射器摘要。该具体映射器的属性之一是要针对其发出命令的 Zend_Db_Adapter。打造灵活的解决方案,易于在测试中使用模拟数据源。
关于php - Zend 框架模型,Active Record 模式替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13690868/