0

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

所以,我想我在某个地方遗漏了一些东西,但是什么?在哪里?如何?也许有一个更容易访问实体管理器?

谢谢!

4

2 回答 2

1

我认为,您唯一缺少的是将模型类添加到可调用列表中并通过服务管理器检索它。

所以基本上把它添加到你的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();
于 2013-02-19T09:06:58.400 回答
1

从您的问题中,我看到您主要有两个误解,一个是关于您的设计策略(在您的模型上注入 EntityManager),另一个是关于服务管理器(ServiceLocatorAwareInterface)的工作方式。在我的回答中,我将尝试专注于第二个。

Initializers 是 php 闭包,在从服务管理器访问的每个实例上调用,然后再将其返回给您。

下面是一个初始化器的例子:

// 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方法。但是,这不是您唯一的问题。首先,如果您希望服务管理器将自己注入您的模型中,您需要通过工厂调用/构造模型实例(在此过程中它将调用初始化程序),例如,如果您的类具有复杂的依赖关系。

[编辑]

例子:

在你的 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 实例时,您应该调用 Service Manager:

$serviceManager->get('myModelClass');

不要忘记定义setServiceManager方法,否则你没有正确实现 ServiceManagerAwareInterface!

于 2013-01-23T10:14:09.540 回答