Php 为什么我能';t在“中定义对象管理器”__“构造”;并在其他方法(操作)中使用它?zf2

Php 为什么我能';t在“中定义对象管理器”__“构造”;并在其他方法(操作)中使用它?zf2,php,orm,constructor,controller,zend-framework2,Php,Orm,Constructor,Controller,Zend Framework2,我开始讨论codereview这个话题,并得到了很好的答案。答案是肯定的 所有的提示看起来都很好,现在我正试图在我的代码中遵循它们 《答案》的作者说,我在所有动作中都使用了对象管理器(大约2次)。他建议在我的控制器的init()方法中执行此操作,并将对象管理器分配给$this->objectManager。我试过这个: 在这种情况下,由于zf2中没有init()方法,我使用了init: public function __construct() { $this->objectMan

我开始讨论codereview这个话题,并得到了很好的答案。答案是肯定的

所有的提示看起来都很好,现在我正试图在我的代码中遵循它们

《答案》的作者说,我在所有动作中都使用了对象管理器(大约2次)。他建议在我的控制器的
init()
方法中执行此操作,并将对象管理器分配给
$this->objectManager
。我试过这个:

在这种情况下,由于zf2中没有
init()
方法,我使用了init:

public function __construct() {
    $this->objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
}
在其他操作中,我使用以下方法:

public function listAction() { 
    $news = $this->objectManager
        ->getRepository('\News\Entity\Item')
        ->findBy(array(), array('created' => 'DESC'));
    // some more code 
}
当我尝试加载页面时,我得到以下信息:

Fatal error: Call to a member function get() on a non-object in F:\Server\domains\zf2-skeleton\module\News\src\News\Controller\NewsController.php on line 12
第12行是
构造中的一行:

$this->objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
在旧版本中,我使用了类似的:

public function indexAction() {
    $objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
    // how I use $objectManager?
    $news = $objectManager
        ->getRepository('\News\Entity\Item')
        ->findBy($options, array('created'=>'DESC'));
    // some more code
}
为什么使用
\u构造的方法不起作用?我做错了什么

github上的文件:

更新 文件
MODULE/src/MODULE/Factory/NewsControllerFactory.php
contents:

<?

namespace News\Factory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use News\Controller\NewsController;



class NewsControllerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        var_dump("bob");
        $objectManager = $serviceLocator->getServiceLocator()->get('Doctrine\ORM\EntityManager');
        return new NewsController($objectManager);
    }
}

这是因为尚未设置服务定位器。当您在构造函数中引用它时,$this->getServiceLocator()仍然返回null

如果要设置objectManager以便在控制器中使用,我建议使用factory。它使测试对象更容易

class NewsControllerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $objectManager = $serviceLocator->getServiceLocator()->get('Doctrine\ORM\EntityManager');
        return new NewsController($objectManager);
    }
}
然后你的控制器会像这样

class NewsController extends AbstractActionController
{
    protected $objectManager;

    public function __construct($objectManager)
    {
        $this->objectManager = $objectManager;
    }
}
以及对module.config.php的必要添加

'controllers' => array(
    'factories'     => array(
        'News\Controller\News' => 'News\Factory\NewsControllerFactory',
    )
)
这应该行得通-

use Zend\Mvc\Controller\AbstractActionController;
use Zend\EventManager\EventManagerInterface;

class IndexController extends AbstractActionController {

    protected $objectManager;

    public function setEventManager(EventManagerInterface $events) {
        parent::setEventManager($events);

        $this->objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
    }
    [......]
}`
然后只需在整个控制器中的任何操作或简单函数中使用
$this->objectManager

public function listAction() { 
    $news = $this->objectManager
        ->getRepository('\News\Entity\Item')
        ->findBy(array(), array('created' => 'DESC'));
    // some more code 
}

看一看,你的问题是相似的。在
setEventManager
中重新设置对象管理器!认真地如果您需要问“为什么要这么长时间”,那么我建议您阅读@SharikovVladislav。DI部分的答案是正确的,这是错误的,因为工厂不属于
服务管理器
配置,它属于
控制器
,像这样->@SharikovVladislav您是否从module.config.php中的可调用列表中删除了
'News\Controller\Item'
?您的控制器配置应该与我链接的要点完全相同-如果我正在阅读您的路由配置和您尝试执行的操作correctly@Crisp哎呀。我的错。我确实没有从inovkables中删除
News\Controller\Item
。现在我这样做了,一切都很好。非常感谢:)NewsControllerFactory很好,描述了它的功能。这实际上是可行的,不知道为什么这个答案会遭到如此多的否定。因为ZF2有一个
依赖注入的概念,其中需要将所需服务的对象传递给想要使用它的类。在这种情况下,控制器确实有一个可直接使用的
服务定位器
,因此在控制器的
构造
中,
对象管理器
可以通过
设置
获取
功能进行管理,或者使用
工厂
方法对控制器进行管理,以便已经注入依赖项。经过长时间的编码,我明白了
工厂
方法是ZF2中更好的方法。控制器似乎没有直接提供服务定位器,除非使用了工厂,还是我错了?除非使用setEventManager()有明显的缺点,否则当创建工厂需要修改三个不同的文件时,我不明白为什么这会如此糟糕。不过,使用工厂可能更像ZF2ish。
控制器
确实可以直接访问
服务管理器
,而且
工厂
更像ZF2ish(非常正确)。但是对于
setEventManager()
的缺点。。。我会找到确切的原因然后回来。