更新:
好的一些更新,最后我们决定了框架(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 后面的两个“外部”数据库上都有一组用户数据,并且我们在本地创建了一个模型“用户”
- 假设我们在“User”模型中有一个“GetById”方法,它需要:通过 id 从两个外部 API 中获取用户数据,组合并返回结果。
- 我可能会在“用户”模型中使用构建器模式来实例化 2 个其他模型(针对每个外部 API),并要求这 2 个模型获取数据。有了这个结构,我可以让另外两个模型继承它们与 API 通信所需的东西。
所以我们有这些模型:
- 用户
- SOAP 生成器
- REST 构建器
- 用户SOAP
- 用户REST
现在我不喜欢这个设计的是,结构有点复杂,我不知道根据它们的“类型”(用户模型本身,构建器模型)将这些模型文件放置到不同位置的好方法, ETC)。
我是否过度设计了这个?我应该考虑更好的模式吗?