如果您在控制器中有实体管理器,您将引入“域逻辑”(您的数据库查询)的耦合,它们与应用程序逻辑密不可分(控制器应该只读取请求并返回正确的响应)。这种耦合使得重用和维护代码变得相当困难。
一种解决方案是创建注入控制器的“服务”。服务封装业务逻辑(例如数据库查询)并为控制器提供定义良好的 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;
}
注意 EntityMapper 和 FormElementManager 已注入 - 此处没有 ObjectManager 或 ServiceLocator。
实体映射器
只是对象管理器周围的一个薄层;这允许我们将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();
}
因此,具体服务的示例是:
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);
}
}
列表控制器
然后控制器简单地使用服务(在上面的例子中它是一个“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...
}
哇;比计划的时间长一点,但希望对您有所帮助。