Zend框架数据访问层(DAL)

时间:2012-08-22 15:54:14

标签: php oop zend-framework data-access-layer dao

在Zend Framework中查看有关数据访问的几本教程和书籍,似乎大多数人在他们的模型(Active Record Pattern)甚至控制器中进行数据访问。我非常不同意这一点。因此,我希望有一个数据访问层(DAL),以便我的域层保持可移植性,因为其中没有任何“ZF内容”。我一直在寻找,但还没找到我想要的。抬头:我是ZF的新手。

DAL结构

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

/application/modules/default/dal/

但是,我不确定如何包含此文件夹,以便我可以访问控制器中的类(不使用includes / requires)。如果有人知道如何实现这一点,那将是超级的!当然也欢迎任何其他想法。

我的想法是让我的控制器与数据访问对象(DAO)进行交互。然后DAO使用可以返回控制器的模型。通过这样做,我可以完整地保留我的模型。

实施

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

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

很抱歉这个问题很多。我只需要朝着正确的方向努力。

2 个答案:

答案 0 :(得分:4)

那么,在处理Data Access Layer时你必须​​首先考虑的是,这个层也有子层,找到名为“dal”的文件夹是不常见的在现代框架中(我将Zend Framework和Symfony作为基础)。

其次,关于ActiveRecord,您必须注意,默认情况下,Zend Frameworks 不会实现它。大多数教程都采用最简单的方法来教授新概念。通过简单的示例,业务逻辑的数量是最小的,因此它们不是添加另一层复杂性(数据库和模型的对象之间的映射),而是使用两个基本模式组成domain layer(模型) :Table Data GatewayRow Data Gateway。这对于初学者来说是足够的信息。

  

分析后,您会看到 ActiveRecord 之间存在一些相似之处   和行数据网关模式。主要区别在于   ActiveRecord对象(可持久实体)带有业务逻辑和   行数据网关仅在数据库中表示行。如果你添加   表示数据库行的对象上的业务逻辑,然后它将   成为 ActiveRecord 对象。

此外,遵循Zend Framework 快速入门on the domain model section,您将意识到还有第三个组件,它使用Data Mapper Pattern

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

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);

}

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

  

提示:domain object本身,guestbook   实体,未由DataMapper上的find()方法创建,   相反,我们的想法是对象创建是工厂的任务   并且您必须注入依赖项以实现所谓的   Dependency Inversion Principle (DIP)(SOLID原则的一部分)。但那是   另一个主题,超出了问题的范围。我建议你   访问以下链接http://youtu.be/RlfLCWKxHJ0

映射的东西从这里开始:

$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的目录和namespace guidelines for modules

  

最后提示:我花了很多时间编写自己的数据映射器   终于意识到维持对象映射时的噩梦   您的应用程序随着许多相关实体而增长。 (即帐户   包含对用户对象的引用的对象,包含的用户   角色等等。编写映射内容并不容易   点。所以我强烈推荐你,如果你真的想要真实的话   对象关系映射器,首先研究遗留框架的执行情况   这样的任务,也许使用它。   所以,请花些时间与Doctrine 2进行比较   目前为止最好的之一(IMO)使用 DataMapper模式

就是这样。您仍然可以使用/dal目录存储DataMappers,只需register the namespace,以便自动加载程序可以找到它。

答案 1 :(得分:0)

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

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


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