2

查看有关 Zend Framework 中数据访问的几本教程和书籍,似乎大多数人在他们的模型(活动记录模式)甚至控制器中进行数据访问。我强烈不同意这一点。因此,我想要一个数据访问层(DAL),这样我的域层就可以通过没有任何“ZF 的东西”来保持可移植性。我四处寻找,但并没有真正找到我想要的东西。注意:我是采埃孚的新手。

DAL结构

所以,第一个问题是在哪里放置数据访问层。虽然它当然可以放在library文件夹中并向自动加载器添加命名空间,但这似乎不合逻辑,因为它特定于我的应用程序(因此该applications文件夹是合适的)。我正在使用模块化结构。我正在考虑使用以下结构:

/application/modules/default/dal/

但是,我不确定如何包含此文件夹,以便我可以访问控制器中的类(不使用包含/需要)。如果有人知道如何做到这一点,那就太棒了!当然也欢迎任何其他想法。

这个想法是让我的控制器与数据访问对象 (DAO) 交互。然后 DAO 使用可以返回给控制器的模型。通过这样做,我可以保持我的模型完好无损。

执行

在其他语言中,我之前已经为每个模型实现了 DAO,例如DAL_User. 这导致了大量的 DAO 类。有没有更聪明的方法来做到这一点(使用单个类似乎并不容易使用外键)?

我也很感激有关如何在 ZF 中实现我的 DAO 类的建议。我没有花太多时间阅读所有可用于数据库交互的组件,因此非常欢迎任何想法。我怀疑有比可用的标准 PDO 更智能的东西(不过,它可能在内部使用 PDO)。名字下降就足够了。

很抱歉有很多问题。我只需要朝着正确的方向前进。

4

2 回答 2

4

好吧,在处理 . 时首先要考虑的Data Access Layer是,这一层也有子层,在现代框架中找到名为“dal”的文件夹是不寻常的(我以 Zend Framework 和 Symfony 为基础) )。

其次,关于ActiveRecord,您必须知道默认情况下 Zend Frameworks没有实现它。大多数教程采用最简单的方法来教授新概念。用简单的例子,业务逻辑的数量是最小的,所以不是增加另一层复杂性(数据库和模型对象之间的映射),而是domain layer用两个基本模式组成(模型):表数据网关行数据网关。对于初学者来说,这是足够的信息。

分析之后,您会发现ActiveRecordRow Data Gateway模式之间存在一些相似之处。主要区别在于 ActiveRecord 对象(可持久实体)承载业务逻辑,而 Row Data Gateway仅代表数据库中的一行。如果您在表示数据库行的对象上添加业务逻辑,那么它将成为ActiveRecord对象。

此外,在 Zend Framework快速入门之后,在域模型部分,您将意识到还有第三个组件,它使用数据映射器模式

因此,如果您的主要目的DAL是在业务对象(模型)和您的存储之间映射数据,则此任务的责任委托给 Data Mappers,如下所示:

class Application_Model_GuestbookMapper
{

    public function save(Application_Model_Guestbook $guestbook);

    public function find($id);

    public function fetchAll();

}

这些方法将与域对象交互Database Abstraction Layer并用数据填充域对象。沿着这条线的东西:

public function find($id, Application_Model_Guestbook $guestbook)
{

    $result = $this->getDbTable()->find($id);

    if (0 == count($result)) {

        return;

    }

    $row = $result->current();

    $guestbook->setId($row->id)

              ->setEmail($row->email)

              ->setComment($row->comment)

              ->setCreated($row->created);

}

如您所见,与Zend_Db_Table实例Data Mappers交互,该实例使用表数据网关模式。另一方面,返回Zend_Db_Table_Row的实例,它实现了行数据网关模式(它是一个表示数据库行的对象)。$this->getDbTable->find()

提示: 实体domain object本身不是由 DataMapper 上的 find() 方法创建的,其思想是对象创建是工厂的任务, 必须注入依赖才能实现所谓的 依赖倒置原则(DIP)(SOLID 原则的一部分)。但这是另一个主题,超出了问题的范围。我建议您访问以下链接http://youtu.be/RlfLCWKxHJ0guestbook

映射的东西从这里开始:

$guestbook->setId($row->id)
          ->setEmail($row->email)
          ->setComment($row->comment)
          ->setCreated($row->created);

到目前为止,我想我已经回答了你的主要问题,你的结构如下:

application/models/DbTable/Guestbook.php
application/models/Guestbook.php
application/models/GuestbookMapper.php

因此,就像 ZF 快速入门中一样:

class GuestbookController extends Zend_Controller_Action
{

    public function indexAction()

    {
        $guestbook = new Application_Model_GuestbookMapper();

        $this->view->entries = $guestbook->fetchAll();

    }

}

也许您想为数据映射器创建一个单独的文件夹。只是改变:

application/models/GuestbookMapper.php

application/models/DataMapper/GuestbookMapper.php

班级名称将是

class Application_Model_DataMapper_GuestbookMapper

我已经看到您想将您的domain model objects模块分成模块。也有可能,您只需要遵循 ZF 的modules 目录和命名空间指南即可。

最后提示:我花了很多时间编写自己的数据映射器,最终意识到当您的应用程序与大量相关实体一起增长时,维护对象映射是一场噩梦。(即包含对用户对象的引用的帐户对象、包含角色的用户等)此时编写映射的东西并不容易。因此,如果您真的想要一个真正的对象关系映射器,我强烈建议您首先研究遗留框架如何执行此类任务并可能使用它。因此,花点时间学习Doctrine 2,这是迄今为止使用DataMapper 模式的最佳方法之一(IMO) 。

That's it. You still can use your /dal directory for storing the DataMappers, just register the namespace, so that the auto loader can find it.

于 2012-08-23T06:40:25.403 回答
0

在我看来,每个模型都应该有一个网关抽象(不仅仅是数据库访问)。一个 DAO 是不够的。如果您需要在某个时候从云端获取数据怎么办?这很快就会成为现实。如果您将网关逻辑抽象为通用的东西,然后使用数据库实现它,您可以两全其美。

如果您愿意,特定网关接口的实现可以使用通用数据映射器。我在一家小公司工作,并且总是使用 PDO 创建我的实现。这让我可以足够接近数据库来处理我可能需要但能够支持非常抽象的接口的任何有趣的 SQL 位。


我根本没有使用 Zend 框架。我不知道他们是否有可以帮助您实现网关接口的数据映射器工具。

于 2012-08-22T17:14:13.607 回答