Php 为什么我能';t在“中定义对象管理器”__“构造”;并在其他方法(操作)中使用它?zf2
我开始讨论codereview这个话题,并得到了很好的答案。答案是肯定的 所有的提示看起来都很好,现在我正试图在我的代码中遵循它们 《答案》的作者说,我在所有动作中都使用了对象管理器(大约2次)。他建议在我的控制器的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
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()
的缺点。。。我会找到确切的原因然后回来。