shu*_*van 2 architecture doctrine-orm zend-framework2
使用Doctrine ObjectManager的最佳方法是什么?我将它注入module.config.php的控制器
'Telecom\Controller\Users' => function($sm){
$ctr = new Telecom\Controller\UsersController();
$ctr->setEntityManager(
$sm->getServiceLocator()
->get('Doctrine\ORM\EntityManager')
);
return $ctr;
},
Run Code Online (Sandbox Code Playgroud)
然后我在我的控制器中使用它如下
$this->getEntityManager()->persist($entity);
$this->getEntityManager()->flush();
Run Code Online (Sandbox Code Playgroud)
但是Marco Pivetta(Doctrine团队,zf2撰稿人)教导"如果你在控制器中注入objectmanager,你将会有一个糟糕的架构" http://marco-pivetta.com/doctrine-orm-zf2-tutorial/#/39/11.
所以请帮助我,使用Entity Manager的最佳架构方式是什么.我应该使用像我自己的服务这样的另一层来处理实体经理吗?
如果控制器中有实体管理器,则引入"域逻辑"(数据库查询)的耦合,它们与应用程序逻辑不可分离(控制器应该只读取请求并返回正确的响应).这种耦合使得重用和维护代码变得相当困难.
一种解决方案是创建注入控制器的"服务".服务封装业务逻辑(例如数据库查询)并为控制器提供定义良好的API.好的一面是,业务逻辑应该随时改变(它总是会改变); 您只需要更改所述服务的实现,控制器将继续运行.
ZF2非常灵活,有很多方法可以完成相同的任务.我个人做了以下事情:
服务
服务并不意味着只封装一个实体; 它们应该封装执行该特定任务所需的所有实体.这完全取决于服务尝试做什么.例如,更复杂的服务可能需要其他服务.
在我的实现中,我有一个抽象类,AbstractEntityService这个类被扩展用于所有需要持久性的服务(需要数据库的任何东西).
这里的课程很长,但是关键位是下面的.
abstract class AbstractEntityService
extends Service\AbstractService
implements EntityMapperAwareInterface, FormProviderInterface
{
public function __construct(
EntityMapper $entityMapper,
FormElementManager $formElementManager)
{
$this->entityMapper = $entityMapper;
$this->formElementManager = $formElementManager;
$this->getEventManager()->addIdentifiers(array(__CLASS__));
parent::__construct();
}
public function getForm($name)
{
return $this->formElementManager->get($name);
}
public function create(Entity\EntityInterface $entity)
{
$this->triggerEvent(static::EVENT_CREATE, array('entity' => $entity));
$entity = $this->entityMapper->insert($entity);
$this->triggerEvent(static::EVENT_CREATE_POST, array('entity' => $entity));
return $entity;
}
Run Code Online (Sandbox Code Playgroud)
注意EntityMapper并FormElementManager注入 - 否ObjectManager或ServiceLocator此处.
EntityMapper
只是对象管理器周围的薄层; 这使我们能够换出EntityManager的DocumentManager,如果我们从做MySQL对MongoDB的例子.
interface MapperInterface
{
public function getObjectManager();
public function setObjectManager(ObjectManager $objectManager);
public function getRepository($className);
public function insert(EntityInterface $entity);
public function save(EntityInterface $entity);
public function delete(EntityInterface $entity);
public function flush();
}
Run Code Online (Sandbox Code Playgroud)
所以具体服务的一个例子是:
class ListService extends AbstractEntityService
{
public function __construct(
EntityMapper $entityMapper,
FormElementManager $formElementManager,
ListRepository $listRepository
){
parent::__construct($entityMapper, $formElementManager);
$this->listRepository = $listRepository;
}
protected function init(EventManagerInterface $eventManager){
parent::init($eventManager);
$eventManager->attach(static::EVENT_CREATE, array($this, 'createList'));
}
public function createList(EventInterface $event)
{
$list = $event->getParam('entity');
if (! $list instanceof Entity\ValueList) return;
$name = $list->getName();
if (empty($name)) {
$name = $this->formatName($list->getTitle());
$list->setName($name);
}
}
Run Code Online (Sandbox Code Playgroud)
ListController
然后控制器只使用该服务(在上面的例子中它是一个"ListService")
class ListController extends AbstractActionController {
public function __construct(
ListService $listService
){
$this->listService = $listService;
}
public function createAction(){
// validate request/form data...
$form = $this->listService->getListCreateForm();
$list = $this->listService->create($form->getData());
// return view...
}
Run Code Online (Sandbox Code Playgroud)
哇; 有点长于计划,但希望它有所帮助.
| 归档时间: |
|
| 查看次数: |
1960 次 |
| 最近记录: |