4

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

现在我var_dump('blah');exit;只是为了尝试让一些代码运行......我已经尝试了很多事情,现在我希望这可以工作:

模块.config.php

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

模块.php

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

现在什么都没有发生,这非常令人沮丧......我读了一些关于为每个控制器创建工厂的内容,但我有 33 个,我发现这非常疯狂和愚蠢......?

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

4

3 回答 3

2

这里的问题是“indexController”被定义为可调用和工厂。我认为它首先检查可调用对象,所以当它找到它正在寻找的东西时,它永远不会尝试在工厂中运行代码。只需删除“invokables”数组中的条目。

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

于 2012-09-28T21:49:54.077 回答
1

您可以在任何 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);
        }
    });
}

让需要依赖的控制器实现一个接口并检查控制器是否是该接口的实例然后设置它,而不只是检查该方法是否存在......

于 2012-09-13T20:37:03.200 回答
0

下面是我注入任意类的初始化程序代码。一开始很难掌握——要在实例化时自动注入控制器,你必须在 module.config.php 的“controllers”部分的“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);
            }
       }
   }

}

于 2013-05-21T18:52:05.567 回答