【问题标题】:Zend Framework Data Layer ArchitectureZend Framework 数据层架构
【发布时间】:2012-06-06 03:54:19
【问题描述】:

我正在遵循 Zend 快速入门指南,但对连接到数据库的架构有点困惑。我看到 4 层:

ModelClass
ModelClass_Mapper
ModelClass_DbTable
Actual MySQL Database

我之前使用过一种体系结构,其中有一个文件具有直接映射到数据库的属性,以及一个包含挂钩和数据库操作事件的所有自定义代码的扩展类。

我在哪里可以找到一个很好的解释,说明为什么需要这样的三个文件,而不是仅仅让 ModelClass 继承 DbTable?

【问题讨论】:

    标签: php zend-framework datamapper


    【解决方案1】:

    ZF 快速入门提供了一个似乎与 ZF 1.x 配合得很好的数据映射器模式示例。使用 Zend_Db 不需要您实现 Data Mapper。只需使用 DbTable 模型和 Zend_Db_Table_Abstract 提供的方法,您就可以获得相当不错的功能。

    稍微解释一下:

    Application_Model_Guestbook:将是一个简单的域模型(您与之交互的对象)。

    Application_Model_GuestbookMapper:将是数据映射器,用于将数据库列映射到域模型的属性。

    Application_Model_DbTable_Guestbook:是网关模型,提供数据库和数据库适配器之间的连接。您可以在此处指定数据库表的选项以及与其他表的关系。

    在弄清楚数据映射器如何应用于我的应用程序之前,我对 ZF 和 Models 有了一点经验。当我开始构建依赖于多个数据库表的对象时,我才真正开始了解这些部分是如何组合在一起的。
    '

    您会注意到,许多经验丰富的 ZF 开发人员立即推荐 Doctrine 或其他一些 ORM,对他们来说这可能是正确的选择(并且对于某些人来说似乎是反射性的)。我只是觉得在我至少了解 ORM 的基本功能之前,我不应该开始使用 ORM。

    [编辑]

    基映射器类中的fetchAll()等效方法,将Zend_Db_Table_Abstract的实例传递给__constructor

    public function findAll($order = NULL) {
            $select = $this->_getGateway()->select();
            if (!is_null($order)) {
                $select->order($order);
            }
            $rowset = $this->_getGateway()->fetchAll($select);
            $entities = array();
            foreach ($rowset as $row) {
                //abstract method required in each table mapper, this instantiates the domain model
                $entity = $this->createEntity($row);
                //identiy map allows lazy loading of certain members
                $this->_setMap($row->id, $entity);
                $entities[] = $entity;
            }
            //returns an array of domain models instead
            return $entities;
        }
    

    我的表特定映射器的 createEntity() 方法

    public function createEntity($row) {
    
            $data = array(
                'id'     => $row->id,
                'name'   => $row->name,
                'art'    => $row->art,
                'year'   => $row->year,                
            );
    
            $entity = new Music_Model_Album($data);
            //set artist id to reference map for lazy loading
            $entity->setReferenceId('artist', $row->artist_id);
            return $entity;
        }
    

    祝你好运

    【讨论】:

    • 好吧,我知道 Application_Model_DbTable_Guestbook 非常纤薄,主要包含表名和外键约束等内容,并提供常见的非 sql 依赖方法,如插入、更新、等通过继承。
    • 我仍然对 Application_Model_GuestBookMapper 的使用感到困惑。在示例中,有几个方法 fetchAll()、find(),它们从 db_table 映射到 Guestbook 对象,但这似乎违反了 DRY。这不应该作为 Mapper.Property = "StringNameofDBTableProperty";或一些这样的?重写每个方法的映射似乎非常低效,特别是如果表列名称与对象属性名称相同。
    • 在正常使用中,您将覆盖这些方法,这样您就可以创建域模型的实例,而不仅仅是从数据库中获取结果集。基类通常适用于大多数方法,但可以扩展以处理每个模型执行业务逻辑所需的数据变化。我在答案中添加了一个示例。
    【解决方案2】:

    这里给出了一个非常好的解释:http://martinfowler.com/eaaCatalog/dataMapper.html

    简短的引用:

    Data Mapper 是一层软件,可将内存中的对象与数据库分开。它的职责是在两者之间传输数据,并将它们彼此隔离。使用 Data Mapper,内存中的对象甚至不需要知道是否存在数据库;他们不需要 SQL 接口代码,当然也不需要数据库模式的知识。 (数据库模式总是不知道使用它的对象。)由于它是 Mapper (473) 的一种形式,D​​ata Mapper 本身甚至对领域层都是未知的。

    【讨论】:

      【解决方案3】:

      就个人而言,虽然我喜欢 Zend 框架,但我发现数据层库相当糟糕。我现在使用的是Doctrine 结合Bisna 来整合两者。也许你也应该看看那些?

      【讨论】:

        【解决方案4】:

        Zend_Db_Table 解决方案是 » 表数据网关模式的实现。该解决方案还包括一个实现 » 行数据网关模式的类。

        您可以在Table Data GatewayRow Data Gateway 中查看谁的模式

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-08-18
          • 1970-01-01
          • 1970-01-01
          • 2011-04-27
          • 1970-01-01
          • 2011-04-06
          • 2015-06-17
          • 1970-01-01
          相关资源
          最近更新 更多