更新:
好的一些更新,最后我们决定了框架(Yii)并有一些初始结构。我将粘贴一些相关代码来说明我们当前的状态: (此处仅读取操作)
Controller
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 域对象的关系,但我不确定这是否是正确的方向。我应该在映射器中执行此操作吗?
- 我需要引入一个缓存层,因为从外部数据库检索数据并不快。引入缓存层的最佳地点/实践在哪里?一种方法是在 Controller 中,因此将缓存层编码为另一个映射器,如果该缓存映射器不返回数据,我们就可以从外部检索数据。但这个解决方案意味着我需要将所有这些逻辑放在 Controller 操作上,也许有更好的方法来放置缓存层?
初始问题:
我们正在 PHP MVC 框架之上设计/创建 RESTFul API 项目。该项目的目标是充当其他两个“外部”API(一个 SOAP,另一个 REST)之间的适配器。
我认为这个项目中的模型应该大致如下工作:
- 假设我们在两个“外国”数据库上都有用户数据集合 在各自的 API 后面,我们在本地创建一个模型“User”
- 假设我们在“User”模型中有一个“GetById”方法,它需要 to:通过 id 从两个外部 API 中获取用户数据,合并并 返回结果。
- 我可能会在“用户”模型中使用构建器模式来 实例化 2 个其他模型(对于每个外部 API),并询问这 2 个模型 模型来获取数据。通过这个结构,我可以让 2 个额外的 模型继承事物需要他们与他们的沟通 API。
所以我们有这些模型:
- 用户
- SOAPBuilder
- RESTBuilder
- 用户SOAP
- 用户REST
现在我不喜欢这个设计的是,结构有点复杂,我不知道有什么好方法可以根据这些模型文件的“类型”(用户模型本身,构建器模型等)。
我是不是设计过度了?我应该考虑更好的模式吗?
最佳答案
MVC 中没有“多个模型”。模型是构成 MVC 设计模式的两层(以及表示层)之一。人们通常所说的“模特”其实是domain objects 。您可能会发现this相关。
也就是说,您看待这件事的方式完全错误。您当前拥有的是 active record 的变体图案。只是,在本例中,存储介质不是数据库,而是 REST API 和/或 SOAP 接口(interface),而不是经典的 SQL 存储。
在这种情况下,最好的选择是将域对象(例如:User
)与存储相关逻辑的不同元素分开。我个人更喜欢实现data mappers为了这。本质上,如果您有一个域对象,则将其传递给映射器的方法,然后该方法从所述对象检索信息并将其发送到存储,或者从存储检索数据并将其应用到该域对象。
User
实例不关心它是否保存。它对域逻辑没有影响。
关于model-view-controller - 使用外部数据源实现域模型和数据映射器模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12015202/