Zend Framework 2 + Doctrine:在模型中获取实体管理器

时间:2013-01-23 09:00:25

标签: doctrine-orm zend-framework2

编辑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()

所以,我想我错过了什么地方,但是什么?哪里?怎么样?也许更容易访问实体管理器?

谢谢!

2 个答案:

答案 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();