Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/244.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php ServiceLocatorAwareInterface在运行模块测试时会混淆DI容器_Php_Dependency Injection_Zend Framework2 - Fatal编程技术网

Php ServiceLocatorAwareInterface在运行模块测试时会混淆DI容器

Php ServiceLocatorAwareInterface在运行模块测试时会混淆DI容器,php,dependency-injection,zend-framework2,Php,Dependency Injection,Zend Framework2,我有一个新模块,我正在为它编写测试。 该模块包含一个实现ServiceLocatorAwareInterface的类,因为它需要使用DI容器创建其他对象。在skeleton应用程序中运行时,一切正常,但在运行模块测试时,我得到以下结果: Zend\Di\Exception\RuntimeException:Zend\ServiceManager\ServiceLocatorInterface类型为“NULL”的实例化器无效 稍微研究一下,我发现DI容器试图创建一个“ServiceLocatorA

我有一个新模块,我正在为它编写测试。 该模块包含一个实现ServiceLocatorAwareInterface的类,因为它需要使用DI容器创建其他对象。在skeleton应用程序中运行时,一切正常,但在运行模块测试时,我得到以下结果:

Zend\Di\Exception\RuntimeException:Zend\ServiceManager\ServiceLocatorInterface类型为“NULL”的实例化器无效

稍微研究一下,我发现DI容器试图创建一个“ServiceLocatorAwareInterface”类型的新对象,这当然是错误的

在测试引导中再深入一点,我发现添加以下行可以解决问题,因为DI现在知道该接口实例化什么类

$di->instanceManager()->addTypePreference('Zend\ServiceManager\ServiceLocatorInterface', new \Zend\ServiceManager\ServiceManager());
我不确定这是否是该问题的最佳解决方案,因为从我身边经过的ServiceManager是一个虚拟的解决方案


有人有其他想法吗?

在这种情况下,您可以做以下几点

在模块单元测试的引导过程中,创建一个虚拟应用程序,该应用程序配置为仅加载正在测试的模块的配置

...//other code before this for autoloading stuff

// DON'T RUN THE application in your tests, just init it
$application = Zend\Mvc\Application::init(include 'config/test.application.config.for.module.php');

$fullyConfigedManager = $application->getServiceManager();

TestCases::setServiceManager( $fullyConfigedManager );

应用程序增强后,可以直接从应用程序中提取ServiceManager。此服务管理器应使用模块中的任何工厂、可调用项和配置进行完全配置。

是的,您正朝着正确的方向前进。(见附件)

现在没有多少人使用DI来支持ServiceManager(包括我自己),但是如果DI的配置与ZF2 betas期间的配置类似,那么您应该能够在DI配置中添加“首选项”部分,如下所示:

'di' => array(
    'instance' => array(
        'preferences' => array(
            'My_Interface' => 'My_Implementation_Or_Alias',
        ) 
    )
)
此配置块可以替换对
$di->instanceManager()->addTypePreference()


通过查看当前文档并模仿该示例,您可以使用ZF2官方版本成功定义DI配置,如下所示:

$di = new Zend\Di\Di;
$di->configure(new Zend\Di\Config(array(
    'instance' => array(
        'preferences' => array(
            'My_Interface' => 'My_Implementation_Or_Alias',
        ) 
    )
)));

这就完成了任务,但是创建一个完整的应用程序对象是没有用的。相反,我通过手动创建一个包含DI的SM来修复它。这里的例子:是的,我注意到带工厂的SM是在Beta之后创建对象的首选方式。也许我以后会修改代码。DI是一个如此新颖的想法,看到它消失真是太遗憾了。如果您确实希望长期保持DI配置,github上的Ocramius是一个有用的源代码()。他是DI的忠实粉丝。我认为PHP中DI的主要问题是它必须在每个请求上重新处理,并且是过程密集型的,对吗?我只是在猜。当然你可以设置缓存,但是对于我们这些只想获取Zend的人来说,设置起来并不容易。我认为和服务经理一起去是个好主意。它让事情变得更明确,更不“神奇”。是的。DI使用内省,这是昂贵的;对于生产环境,DI配置应“编译”为静态配置。有了DI,有些事情“就行了”,但与增加的复杂性相比,好处很小。SM肯定更适合初学者。