我有一个应用程序,我使用 PHP 与 Zend 框架和 Doctrine2 作为 ORM。我的问题与控制器最好应该了解多少底层模型和持久层有关。理想情况下,我自己会说这“什么都不是”——控制器不应该知道实体是如何/何时被持久化的。但是我觉得这并不总是最好的解决方案(?)。
我尝试遵循“关注点分离”设计指南。我通过创建一个在我的模型上执行 CRUD 操作的服务层来做到这一点。请参见以下示例:
public function testbuildAction()
{
// create section
$sectionService = new \MyAPP\Model\Service\Acl\SectionService();
$sectionA = $sectionService->createSection('SectionA-NAME');
// create privilege with the above section
$privilegeService = new \MyAPP\Model\Service\Acl\PrivilegeService();
$privilegeA = $privilegeService->createPrivilege(
$sectionA,
\MyAPPFrameWork\Model\Acl\Privilege::PERMISSION_EDIT
);
// create a role with the privilege above. A role must have at least one priv.
$roleService = new \MyAPP\Model\Service\Acl\RoleService();
$role = $roleService->createRole('Role-NAME', $privilegeA);
// this loads a managed User object (managed by EntityManager)
$user = $this->_helper->IdentityLoader();
$user->addRole($role); // add the role to this user
$userService = new \MyAPP\Model\Service\Core\UserService();
$userService->updateUser($user); // persist the updates.
}
如您所见,控制器对持久性一无所知,但要获得此结果,我需要在每次调用服务层的 createXXX() 或 updateXXX() 方法时同时执行 persist() 和 flush()。我宁愿做这样的事情:
public function testbuildAction()
{
// create section
$sectionService = new \MyAPP\Model\Service\Acl\SectionService();
$sectionA = $sectionService->createSection('SectionA-NAME');
// create privilege with the above section
$privilegeService = new \MyAPP\Model\Service\Acl\PrivilegeService();
$privilegeA = $privilegeService->createPrivilege(
$sectionA,
\MyAPPFrameWork\Model\Acl\Privilege::PERMISSION_EDIT
);
// create a role with the privilege above. A role must have at least one priv.
$roleService = new \MyAPP\Model\Service\Acl\RoleService();
$role = $roleService->createRole('Role-NAME', $privilegeA);
// this loads a managed User object (managed by EntityManager)
$user = $this->_helper->IdentityLoader();
$user->addRole($role); // add the role to this user
// persist it all (all service-classes access the same entitymanager).
$roleService->flush(); // everything is persisted
}
但这会导致 Doctrine2 失败,因为它确实以错误的顺序将对象持久保存到数据库中 - 特权在部分之前保留(不知道是否可以指示 Doctrine 以有序的方式执行此操作??)。权限为尚未保留的部分获取错误的 ID。
无论如何,这里的大问题是我是否应该尝试推迟刷新,直到所有对象都被创建并设置好关系。目标是让一个事务完成所有写入数据库 - 因此必须由控制器触发(因为它是唯一知道何时完成对象和关系构建的事务),从而“污染”控制器与持久层?