8

我正在用 PHP 编写一个必须写入三个持久层的系统:

  • 一项网络服务
  • 两个数据库(一个mysql一个mssql)

原因是遗留系统,无法更改。

我想使用 DataMapper 模式,并试图建立实现我想要的最佳方式。我有一个如下界面:

<?php
    $service = $factory->getService()->create($entity);
?>

为了简洁起见,下面是一些人为的和精简的代码:

<?php
class Post extends AbstractService
{
    protected $_mapper;

    public function create(Entity $post)
    {
        return $this->_mapper->create($post);
    }
}

class AbstractMapper
{
    protected $_persistence;

    public function create(Entity $entity)
    {
        $data = $this->_prepareForPersistence($entity);
        return $this->_persistence->create($data);
    }   
}
?>

我的问题是,由于存在三个持久层,因此每个持久层也可能需要三个映射器。我想要一个干净的设计模式启发的界面来完成这项工作。

我认为它具有三个选项:

  1. 将三个映射器注入服务并在每个映射器上调用 create
  2. $_mapper 是一个数组/集合,它遍历它们在每个上调用 create
  3. $_mapper 实际上是一个容器对象,它充当进一步的代理并在每个对象上调用 create

这些解决方案中的每一个都让我觉得有些错误,并且希望任何可能适合此的反馈/公认的设计模式。

4

3 回答 3

2

我不得不解决一个类似的问题,但在很多年前的 PEAR DB 时代。在这种特殊情况下,需要跨多个数据库复制数据。

我们没有遇到不同数据库具有不同映射的问题,所以它更简单一些。

我们所做的是对 DB 类进行外观并覆盖 getResult 函数(或任何它被调用的函数)。然后,该函数分析 SQL,如果它是读取的,它会将其发送给一个支持的,如果它是一个写入的,它会将它发送给所有的。

对于一个使用率非常高的网站,这实际上非常有效。

从这个背景来看,我建议完全覆盖所有持久性操作。完成此操作后,实施细节的相关性就会降低,并且可以随时更改。

从这个角度来看,您的任何实现想法似乎都是一种合理的方法。不过,您会想考虑很多事情。

  • 如果其中一个后端抛出错误怎么办?
  • 写入三个数据库服务器对性能有何影响?
  • 是否可以异步完成写入(如果可以,请再次询问第一个问题)

可能还有另一种方法可以解决这个问题。那就是使用存储过程。如果您有一个主数据库服务器,您可以编写一个触发器,该触发器在提交(或大约)时连接到另一个数据库并同步数据。

如果数据更新不需要立即进行,您可以让主数据库记录更改并使用另一个脚本定期“馈送”这些数据到另一个系统。同样,需要考虑错误问题。

希望这可以帮助。

于 2013-02-24T19:28:17.453 回答
1

首先,有点术语:你所说的三层,实际上是三个模块,而不是层。也就是说,在持久层中有三个模块。

现在,这个问题的基本前提是:你必须有三种不同的持久化逻辑,对应三种不同的存储源。这是你无法避免的。因此,问题只是关于如何在此模块上调用写入操作(假设对于读取,您不需要调用所有三个,或者如果您这样做,那是一个单独的问题)。

从您列出的三个选项中,我认为第一个更好。因为,那是三者中最简单的。另外两个,仍然需要分别调用三个模块,以及引入容器或某种数据结构的额外工作。您仍然无法避免在某处调用三个模块。

如果使用第一个选项,那么您显然需要使用接口,为用户/客户端(在本例中为服务)提供统一的抽象。

我的观点是: 1. 它们是您的问题固有的复杂性,您无法进一步简化。2.第一个选项更好,因为另外两个,让事情变得更复杂,而不是简单。

于 2013-02-28T17:39:29.850 回答
0

我认为选项#2是我认为最好的。我会同意的。如果您有 10 多个映射器而不是选项#3 将创建逻辑转移到映射器本身是有意义的,但是由于您有合理数量的映射器,因此只注入它们并迭代它们更有意义。通过添加另一个映射器来扩展功能只需在依赖注入配置中添加 1 行。

于 2013-02-27T22:51:56.897 回答