使用外部数据源实现域模型和数据映射器模式

更新:

确定一些更新,最后我们决定了框架(Yii)并且有一些初始结构。 我将粘贴一些相关代码来说明我们的当前状态:(只有阅读动作在这里)

调节器

class SponsorController extends RestController
{
    public function actionRestView($id)
    {
        $sponsorMapper = new SponsorMapper(
            new Db1Adapter(), // Gateway to the external SOAP Webservice
            new Db2Adapter()  // Gateway to the external REST Webservice
        );

        $data = $sponsorMapper->read($id);

        $this->renderJson(
            array(
                'success' => true,
                'message' => 'Record Retrieved Successfully',
                'data' => $data
            )
        );
    }
}

领域模型

class Sponsor extends CModel
{
    public $id;
    public $db1Result;
    public $db2Result;

    public function attributeNames()
    {
        return array(
            'id',
            'db1Result',
            'db2Result',
        );
    }
}

数据映射器

class SponsorMapper extends Mapper
{
    public function __construct(SoapAdapter $db1Adapter,
                                RestAdapter $db2Adapter)
    {
        $this->adapters['soap'] = $db1Adapter;
        $this->adapters['rest'] = $db2Adapter;
    }

    public function read($id)
    {
        $db1Result = $this->adapters['soap']->demoRequest();
        $db2Result = $this->adapters['rest']->demoRequest();

        return $this->createEntity($db1Result, $db2Result);
    }

    protected function createEntity($db1Result, $db2Result)
    {
        $sponsor = new Sponsor();
        $sponsor->db1Result = $db1Result;
        $sponsor->db2Result = $db2Result;

        return $sponsor;
    }
}

现在我有两个问题:

  • 现在,Sponsor对象的属性只是db1Result和db2Result,我将它更改为实际属性(例如firstName,lastName,email),因此SponsorMapper :: createEntity将如下所示:

    protected function createEntity($db1Result, $db2Result)
    {
        $sponsor = new Sponsor();
        $sponsor->firstName = $db1Result->result->first_name;
        $sponsor->lastName = $db1Result->result->last_name;
        $sponsor->email = $db2Result->QueryResult->ItemObject->email;
    
        return $sponsor;
    }
    
  • 在我看来,这些类型的东西应该发生在域对象,而不是映射器; 我知道我可以将db1Result和db2Result视为自己的域对象,并将它们的关系创建为Sponsor域对象,但我不确定这是否是正确的方向。 我应该在制图员那里做吗?

  • 我将需要引入一个缓存层,因为从外部数据库检索数据并不快。 引入缓存层的最佳场所/练习在哪里? 一种方法是在控制器中,将代码缓存层作为另一个映射器,如果这个缓存映射器没有返回数据,那么我们可以用很长的时间来从外部回收东西。 但是这个解决方案意味着我需要将所有这些逻辑放在控制器动作中,也许有更好的方法来放置缓存层?
  • 初始问题:

    我们正在设计/创建一个基于PHP MVC框架的RESTFul API项目。 该项目的目标是作为两个其他“外部”API(一个SOAP,另一个REST)之间的适配器。

    我认为这个项目中的模型应该像这样工作:

  • 假设我们在各自的API背后都有“外部”数据库的用户数据集合,并且在本地我们创建了一个模型“用户”
  • 假设我们在“用户”模型中有一个“GetById”方法,它需要:从两个外部API中通过id获取用户数据,合并并返回结果。
  • 我可能会在“用户”模型中使用一个生成器模式来实例化其他两个模型(针对每个外部API),并要求这两个模型提取数据。 有了这个结构,我可以让2个附加模型继承事物,以便他们与他们的API进行通信。
  • 所以我们有这些模型:

  • 用户
  • SOAPBuilder
  • RESTBuilder
  • UserSOAP
  • UserREST
  • 现在我不喜欢这个设计,这个结构有点复杂,我不知道一个好的方法来把这些模型文件放到不同的地方,根据它们的“类型”(用户模型本身,构建器模型等)。

    我是否过度设计了这个? 我应该考虑更好的模式吗?


    MVC中没有“多个模型”。 模型是构成MVC设计模式的两层中的一层(与表示层一起)。 人们通常所说的“模型”实际上是域对象。 你可能会发现这个相关的。

    这就是说,你看着这一切都是错误的。 你现在有什么是活动记录模式的变化。 只有在这种情况下,存储介质不是数据库,而是REST API和/或SOAP接口,而不是传统的SQL存储。

    在这种情况下,最好的选择是将域对象(例如: User )与存储相关逻辑的不同元素分开。 我个人更喜欢为此实现数据映射器。 实质上,如果您有一个域对象,则将其传递给映射器的方法,然后该方法从所述对象检索信息并将其发送到存储器或从存储器检索数据并将其应用到该域对象。

    User实例不关心它是否保存。 它对域逻辑没有影响。

    链接地址: http://www.djcxy.com/p/9615.html

    上一篇: Implementing Domain Model and Data Mapper pattern with external data sources

    下一篇: PHP Mapper pattern for link tables