编辑1:好像我没有很好地解释自己。 Foo类不一个实体。只是一个通用模型,我希望能够访问实体管理器。
编辑2:我认为我的问题没有答案。基本上,我想要一个可以访问EntityManager的类,而不需要服务管理器调用这个类,这只是因为它可能被一个也没有被服务管理器调用的类调用。换句话说,我试图实现Zend_Registry在ZF1中实现的目标。我必须找到另一种方法来做我想做的事。
我试图在模型中访问Doctrine的实体管理器,方式与在控制器中完成的方式类似:
$this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
ZF2手册(http://framework.zend.com/manual/2.0/en/modules/zend.service-manager.quick-start.html)说:
默认情况下,Zend Framework MVC注册一个初始化程序,它将ServiceManager实例(Zend \ ServiceManager \ ServiceLocatorInterface的一个实现)注入到实现Zend \ ServiceManager \ ServiceLocatorAwareInterface的任何类中。
所以我创建了以下类:
<?php
namespace MyModule\Model;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class Foo implements ServiceLocatorAwareInterface
{
protected $services;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->services = $serviceLocator;
}
public function getServiceLocator()
{
return $this->services;
}
public function test()
{
$em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
}
}
然后,从另一个班级我这样称呼这个班级:
$foo = new \MyModule\Model\Foo();
$foo->test()
会抛出以下错误:
PHP致命错误:在非对象上调用成员函数get()
所以,我想我错过了什么地方,但是什么?哪里?怎么样?也许更容易访问实体管理器?
谢谢!
答案 0 :(得分:1)
从您的问题中,我发现您主要有两个误解,一个是关于您的设计策略(在您的模型上注入EntityManager),另一个是关于如何使用服务管理器(ServiceLocatorAwareInterface)。在我的回答中,我将尝试着重于第二个。
初始化程序是一个php闭包,通过从Service Manager访问的每个实例调用它,然后再将它返回给你。
以下是初始化程序的示例:
// Line 146 - 150 of Zend\Mvc\Service\ServiceManagerConfig class + comments
$serviceManager->addInitializer(function ($instance) use ($serviceManager) {
if ($instance instanceof ServiceManagerAwareInterface) {
$instance->setServiceManager($serviceManager);
}
});
正如您所见,每次要求Service Manager返回实现ServiceManagerAwareInterface接口的实例/对象时,它都会设置/注入Service Manager实例。
顺便提一下,在前面的代码中,您没有正确实现接口,因为您没有定义setServiceManager
方法。但是,这不是你唯一的问题。
首先,如果您希望Service Manager将自己注入模型中,则需要通过工厂调用/构造模型实例(在此过程中它将调用初始化程序),例如,如果您的类具有复杂的依赖关系。
[编辑]
示例:
在你的MyModule
中namespace MyModule;
use Zend\ModuleManager\Feature\ServiceProviderInterface;
use MyModule\Model\Foo;
class Module implements ServiceProviderInterface{
//Previous code
public function getServiceConfig()
{
return array(
'instances' => array(
'myModelClass' => new Foo(),
),
);
}
现在,当您需要Foo实例时,您应该致电服务管理器:
$ serviceManager-&GT;获得( 'myModelClass');
不要忘记定义setServiceManager
方法,否则你没有正确实现ServiceManagerAwareInterface!
答案 1 :(得分:1)
我认为,唯一缺少的是将模型类添加到invokable列表中并通过服务管理器进行检索。
所以基本上将它添加到 module.conf.php :
return array(
'service_manager' => array(
'invokables' => array(
'MyModule\Model\Foo' => 'MyModule\Model\Foo',
),
),
);
并像这样实例化你的模型对象(如果在控制器中):
$foo = $this->getServiceLocator()->get('MyModule\Model\Foo');
$foo->test();