为什么我不能在__construct"中定义对象管理器并在其他方法(动作)后使用它?zf2


Why I can't define object manager in "__construct" and use it after in other methods (actions)? zf2

我开始了关于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行是__construct中的一行:

$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
}

为什么__construct的方法不起作用?我做错了什么?

github上的文件:

  • 旧的和可怕的控制器代码,但工作一个
  • 新的和漂亮的控制器代码,但不工作:(

更新

文件MODULE/src/MODULE/Factory/NewsControllerFactory.php内容:

<?
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);
    }
}

我试图var_dump();那里的东西,并意识到,createService函数在执行期间不被调用。为什么?

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

如果你想设置objectManager在你的控制器中使用,我建议使用工厂。它使测试对象更容易;

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;
    }
}

和必要的添加到模块.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 
}