ZendフレームワークとDoctrine2をORMとして使用するPHPを使用するアプリケーションがあります。私の質問は、コントローラーが基礎となるモデルと永続層についてどれだけ知っておくべきかに関するものです。理想的には、これは自分自身では「何もない」と言えます。コントローラーは、エンティティが永続化される方法とタイミングについて何も知らないはずです。しかし、これが常に最善の解決策であるとは限らないと思います(?)。
私は「関心の分離」の設計ガイドラインに従おうとしました。これは、モデルで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に順序付けられた方法でこれを実行するように指示できる場合はdunno ??)。特権は、まだ永続化されていないセクションのIDを誤って取得します。
とにかく、ここでの大きな問題は、すべてのオブジェクトが作成され、リレーションが設定されるまで、フラッシュを延期する必要があるかどうかです。目標は、データベースへのすべての書き込みを行う1つのトランザクションを持つことです。これは、コントローラーによってトリガーされる必要があります(これは、オブジェクトとリレーションの構築が行われることを知っている唯一のトランザクションであるため)。これにより、コントローラーを「汚染」します。永続性レイヤー?