1

更新:

好的一些更新,最后我们决定了框架(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;
    }
}

现在我有两个问题:

  1. 现在 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 域对象的关系,但我不确定这是否是正确的方向。我应该在映射器中做吗?

  1. 我需要引入一个缓存层,因为从外部数据库检索数据并不快。引入缓存层的最佳地点/实践在哪里?一种方法是在控制器中,因此将缓存层代码作为另一个映射器,如果这个缓存映射器不返回数据,我们可以走很长的路从外部检索东西。但是这个解决方案意味着我需要将所有这些逻辑放在控制器动作中,也许有更好的方法来放置缓存层?

最初的问题:

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

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

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

    1. 用户
    2. SOAP 生成器
    3. REST 构建器
    4. 用户SOAP
    5. 用户REST

现在我不喜欢这个设计的是,结构有点复杂,我不知道根据它们的“类型”(用户模型本身,构建器模型)将这些模型文件放置到不同位置的好方法, ETC)。

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

4

1 回答 1

1

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

就是说,您正在以错误的方式看待这一切。您目前拥有的是活动记录模式的变化。只是,在这种情况下,存储介质不是数据库,而是 REST API 和/或 SOAP 接口,而不是经典的 SQL 存储。

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

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

于 2012-08-18T04:25:37.527 回答