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

Model view controller 使用外部数据源实现域模型和数据映射器模式,model-view-controller,design-patterns,frameworks,datamapper,domain-model,Model View Controller,Design Patterns,Frameworks,Datamapper,Domain Model,更新: 好的,进行一些更新,最后我们决定了框架(Yii)并有一些初始结构。我将粘贴一些相关代码来说明我们的当前状态: (此处仅包含读取操作) 控制器 class SponsorController extends RestController { public function actionRestView($id) { $sponsorMapper = new SponsorMapper( new Db1Adapter(), // Gat

更新:

好的,进行一些更新,最后我们决定了框架(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 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
            )
        );
    }
}
现在我有两个问题:

  • 现在发起人对象的属性只是db2Result和db2Result,我将把它更改为实际属性(例如firstName、lastName、email),因此发起人映射器::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;
    }
    
  • 在我看来,这类事情应该发生在域对象内部,而不是映射器;我知道我可以将db2Result和db2Result视为它们自己的域对象,并创建它们与发起域对象的关系,但我不确定这是否是正确的方向。我应该在地图绘制程序中进行吗

  • 我需要引入一个缓存层,因为从外部数据库检索数据并不快。哪里是引入缓存层的最佳位置/实践?一种方法是在控制器中,将缓存层编码为另一个映射器,如果这个缓存映射器不返回数据,那么我们可以从外部检索数据。但这个解决方案意味着我需要将所有这些逻辑放在控制器操作上,也许有更好的方法放置缓存层
  • 初始问题:

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

    我认为这个项目中的模型应该大致如下:

    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;
    }
    
    • 假设我们在两个“外部”数据库上都有一组用户数据 在各自的API之后,我们在本地创建一个模型“用户”
    • 假设我们在“用户”模型中有一个“GetById”方法,它需要 to:从两个国外API中按id获取用户数据,并合并和 返回结果
    • 我可能会在“用户”模型中使用构建器模式来 实例化另外2个模型(针对每个外国API),并询问这2个 获取数据的模型。有了这个结构,我可以让2个额外的 继承事物的模型需要它们与自己的对象进行通信 API
    • 所以我们有这些模型:

    • 使用者
    • 肥皂制造者
    • RESTBuilder
    • 用户SOAP
    • 用户休息
    现在我不喜欢这个设计,因为它的结构有点复杂,我不知道有什么好方法可以根据它们的“类型”(用户模型本身、构建器模型等)将这些模型文件放置到不同的位置

    我是不是设计过度了?是否有更好的模式需要考虑?

    < P>在MVC中没有“多模型”。模型是构成MVC设计模式的两个层(以及表示层)之一。人们通常称之为“模型”的实际上是。你可能会发现相关的

    也就是说,你对这件事的看法完全错误。你现在拥有的是变化的模式。只是,在这种情况下,存储介质不是数据库,而是RESTAPI和/或SOAP接口,而不是传统的SQL存储

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

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

    MVC中没有“多模型”。模型是构成MVC设计模式的两个层(以及表示层)之一。人们通常称之为“模型”的实际上是。你可能会发现相关的

    也就是说,你对这件事的看法完全错误。你现在拥有的是变化的模式。只是,在这种情况下,存储介质不是数据库,而是RESTAPI和/或SOAP接口,而不是传统的SQL存储

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


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

    你应该总是喜欢组合而不是继承。你应该总是喜欢组合而不是继承。谢谢tereško的回答。如果我理解正确,您建议将域对象(用户)传递给映射器(UserSOAP、UserREST),并让映射器根据请求操作/更新域对象。(我的任务是将映射器封装到域对象中)我的问题是,它有什么好处?在我看来,这并不会真正改变大部分代码的去向,也不会真正改变复杂性。@Vincent,主要的好处是您可以单独测试这些代码。此外,通过这种方式,您可以清楚地看到添加缓存系统的好处。这样,如果您有一个可以从SOAP保存和检索数据的映射器和一个可以从REST保存和检索数据的映射器,那么您就可以设计一个可以在SOAP中从REST和ave检索数据的系统。您会发现一个非常简单的API示例。这整件事都和你有关。展示一些代码可能会得到更好的答案。到目前为止,我一直在猜测你在被误用的时髦词“模型”下究竟隐藏了什么样的架构