我想在我的代码中创建一个“类似API”的层,有效地阻止数据库访问更高级别的代码。例如,我可能有以下功能:
class MyApi {
private $my_user_id;
function getContacts() {
$contacts = $em->getRepository('Contacts')->findByOwner($this->my_user_id);
$em->clear();
return $contacts;
}
function getGroups() {
$groups = $em->getRepository('Groups')->findByOwner($this->my_user_id);
//hydrate each group's contacts list
foreach ($groups as $group) {
$group->getContacts();
}
$em->clear();
return $groups;
}
}
我正在使用$ em-> clear()在返回EntityManger之前从EntityManger中分离实体,因此我的视图不会意外地修改托管实体。但是,当我想比较两个顺序API函数返回的实体时,我遇到了问题。理想情况下,我希望视图/控制器包含:
$my_contacts = $myapi->getContacts();
$my_groups = $myapi->getGroups();
foreach($my_groups as $group) {
foreach ($my_contacts as $contact) {
if ($group->getContacts()->contains($contact)) {
echo "{$group->getName()} contains {$contact->getName()}!<br/>";
} else {
echo "{$group->getName()} does not contain {$contact->getName()}!<br/>";
}
}
}
但是,由于我在getContacts API调用结束时从EntityManager中分离了所有联系人,因此$group->getContacts()
返回的对象与<{>返回的对象不同的 PHP对象。 1}},因此$api->getContacts()
函数无法正常工作。
我是否有任何“defanging”我的实体的选项,使它们有效地只读,而不会放弃EntityManager提供的好处? (例如,表示相同数据库条目的所有托管实体都是同一个对象,能够在从API传回相关对象后进一步保持水合等)。
答案 0 :(得分:1)
为什么您会担心您的视图会进行更改以提交回数据库?如果您的观点不了解EM(并且他们不应该),那么他们对实体所做的任何更改都将在请求结束时消失。
我能想到的唯一另一个选择是将结果保存为数组,当它们注定要被提供给视图脚本时。但这放弃了许多方便的功能。
答案 1 :(得分:0)
也许这有点晚了,但是对于那些仍然需要在这个问题上回答的人来说这很有用......
我认为这里缺少一个领域驱动设计原则:Command Query Separation 在每个对象上,您只能使用两种方法:
doSomething() {
//this kind of method can change the internal state
}
getSomething() {
//this kind of method NEVER changes internal state
}
牢记适当的MVC,观点应该只需要get-methods,它们永远不会改变一个东西 如果仅考虑CQS和MVC,则不必分离您的实体,也不需要担心。