ZF2-控制器中的ServiceManager依赖关系


ZF2 - ServiceManager dependencies into Controllers

我正试图将我的测试版DI代码转换为ZF2的发布版本。现在我一开始就崩溃了,似乎没有任何关于将东西注入控制器的文档,这让我认为在控制器中存在依赖关系是不正常的?

现在我只是在做一个var_dump('blah');exit;,只是为了尝试运行一些代码。。。我已经尝试了很多东西,现在我希望它能起作用:

module.config.php

'controllers' => array(
    'invokables' => array(
        'indexController' => 'Application'Controller'IndexController',
    )
)

Module.php

public function getControllerConfig() {
    return array(
        'factories' => array(
            'indexController'    => function(ControllerManager $cm) {
                var_dump('blah');exit;
            },
        ),
    );
}

现在什么都没发生,非常令人沮丧。。。我读到一些关于为每个控制器创建工厂的文章,但我有33个,我觉得这很疯狂和愚蠢?

我试图注入的是像userMapper这样的东西,用于抓取/保存用户。因此registerAction使用userMapper在数据库中创建一个用户,当您尝试登录时,它会使用userMapper来检查那里是否有用户等。

这里的问题是"indexController"被定义为可调用和工厂。我认为它首先检查可调用程序,所以当它找到它要查找的内容时,它从不尝试在工厂中运行代码。只需删除"invokables"数组中的条目。

我刚刚写了一篇关于这个主题的帖子。不用为每个控制器创建一个单独的工厂类,而是可以使用闭包来完成。如果依赖项是可调用的,或者可以使用选项数组轻松配置,那就更容易了,只需要一个列出可以注入的类的数组。退房http://zendblog.shinymayhem.com/2013/09/using-servicemanager-as-inversion-of.html

您可以在任何Module.php 中轻松地这样做

public function onBootstrap('Zend'EventManager'EventInterface $e)
{
    $serviceManager = $e->getApplication()->getServiceManager();
    $myDependency = /*something*/;
    $controllerLoader = $serviceManager->get('ControllerLoader');
    $controllerLoader->addInitializer(function ($controller) use ($myDependency) {
        if (method_exists($instance, 'injectMyDependency')) {
            $controller->injectMyDependency($myDependency);
        }
    });
}

一个更干净的方法是让需要依赖关系的控制器实现一个接口,检查控制器是否是该接口的实例,然后设置它,而不仅仅是检查该方法是否存在。。。

下面是我要注入任意类的Initializer代码。一开始有点难理解——要在实例化时自动注入控制器,必须在module.config.php的"controllers"部分的"initializer"部分中定义initializer,而不是在"service_manager"部分中。基本上是为了创建通用的"感知接口",这将对控制器和其他部分有效——相应的初始化器密钥应该同时出现在这两个部分中。。。

// module/SkeletonClassmapGenerator/Item/ImplementedItem/ImplementedItemInitializer.php
namespace SkeletonClassmapGenerator'Item'ImplementedItem;
use Zend'ServiceManager'InitializerInterface;
use SkeletonClassmapGenerator'Provider'GenericInitializerTrait;
class ImplementedItemInitializer implements InitializerInterface
{
    static protected $T_NAMESPACE = __NAMESPACE__;
    static protected $T_CLASS = __CLASS__;
    use GenericInitializerTrait; 
}

然后对于特性(显然在所有初始化项之间共享)。。。

// module/SkeletonClassmapGenerator/Provider/GenericInitializerTrait.php
namespace SkeletonClassmapGenerator'Provider;
use Zend'ServiceManager'ServiceLocatorInterface;
trait GenericInitializerTrait
{
    public function initialize($instance, ServiceLocatorInterface $serviceLocator)
    {       
       if (isset(static::$T_CLASS)&&(isset(static::$T_NAMESPACE))){
       $classname = explode('''', static::$T_CLASS);        
       $class = end($classname);
       preg_match('/(['w]*)Initializer$/i', $class,$matches);
       $basename = $matches[1];
        if(is_subclass_of($instance,static::$T_NAMESPACE.''''.$basename.'AwareInterface')) {
            $sl = (method_exists($serviceLocator,'getServiceLocator'))?
            $serviceLocator->getServiceLocator():$serviceLocator;
             $dependency  = $sl->get(static::$T_NAMESPACE.''''.$basename.'Interface');  // I use 'Interface' as postfix for Service Manager invokable names           
             $instance->{'set'.$basename}($dependency);
            }
       }
   }

}