Implementing Domain Model and Data Mapper pattern with external data sources
Update:
Ok some update, finally we have decided on the framework (Yii) and have some initial structures. I will paste some of the relavent code to illustrate our current status: (only has read action here)
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
)
);
}
}
Domain Model
class Sponsor extends CModel
{
public $id;
public $db1Result;
public $db2Result;
public function attributeNames()
{
return array(
'id',
'db1Result',
'db2Result',
);
}
}
Data Mapper
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;
}
}
Now I have 2 questions:
Right now the property of Sponsor object is just db1Result and db2Result and I will change it to the actual properties (eg. firstName, lastName, email) so the SponsorMapper::createEntity will be something like this:
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;
}
It seems to me that these kinds of stuff should happen inside the domain object instead mapper; I know I can treat db1Result and db2Result as domain object of their own and create their relations to Sponsor domain object, but I'm not sure if that's the right direction. Should I do it in the mapper?
Initial Question:
We are in the process of designing/creating a RESTFul API project on top of PHP MVC framework. The project's goal is to serve as an adapter between two other "foreign" APIs (one SOAP, the other REST).
I'm thinking the models in this project should roughly work like this:
So we have those models:
Now what I don't like about this design is, the structure is a bit complex and I don't know a good way to place those model files into different places based on their "types" (the User model itself, the builder models, etc).
Am I over-designing this? Is there better patterns I should consider?
There are no "multiple models" in MVC. Model is one of two layers (along with presentation layer), which make up the MVC design pattern. What people usually call "models" are actually domain objects. You might find this relevant.
That said, you are looking at this all the wrong way. What you currently have is variation of active record pattern. Only, instead of database, in this case storage medium is REST API and/or SOAP interface instead of classical SQL storage.
The best option in this case would be to separate the domain object (for example: User
) from the different elements of storage related logic. I personally prefer to implement data mappers for this. Essentially, if you have a domain object, you pass it to the mapper's method, which then either retrieves information from said object and sends it to storage or retrieves the data from storage and applies it to that domain object.
The User
instance does not care whether it was save or not. It has no impact on domain logic.
上一篇: 数据映射器仅适用于CRUD操作?
下一篇: 使用外部数据源实现域模型和数据映射器模式