我使用symfony 3.2
。我想重写app/AppKernel#getContainerBaseClass
。实际上我想重写Container
并创建我自己的Symfony\Component\DependencyInjection\Container
。
我发现AppKernel
有#getContainerBaseClass
,据我所知,它返回容器类。我尝试了以下方法:
protected function getContainerBaseClass() {
if ('test' == $this->environment) {
return \AppBundle\DependencyInjection\TestContainer::class;
}
return parent::getContainerBaseClass();
}
它不起作用。我怎么知道它不起作用。首先,我检查容器不是来自自定义容器的行为。其次我在所提到的方法中设置断点并且没有调用它。但是调用了AppKernel#getRootDir
和AppKernel#getCacheDir
中的断点。我在Kernel
搜索了一些有用的东西。但很难理解为什么它不起作用。我试图清除缓存。
在我看来,我做错了什么。但互联网对重写symfony容器一无所知。这很奇怪。
我想重写容器以允许更改(模拟)配置。目前据我所知,symfony有iced参数包,无法更改。
答案 0 :(得分:0)
所以要了解答案是如何工作的,以及它是否适合你 - 很少有评论。
有两个与容器相关的类。首先,容器本身:Symfony\Component\DependencyInjection\Container
。它没有针对每个env进行更改,它包含没有实际数据的动态方法(没有参数,服务,只需要调用它)。第二,捆绑容器。它包含所有参数和服务。它解析了yml文件并从中创建方法/属性。它包含的方法比Symfony\Component\DependencyInjection\Container
多得多。例如,它有#getDefaultParameters
,它返回一个数组中的所有参数。它还有#getTwigService
实际上是twig实例。所以它在php道具和方法中转换yml文件。这个bundle容器类名和命名空间依赖于env。因此,对于测试环境,它是\appTestDebugProjectContainer
。由于它是编译的并且与env不同,因此它位于缓存文件夹中。最后一件事:它从Symfony\Component\DependencyInjection\Container
延伸。
此外,编译容器有一些覆盖Symfony\Component\DependencyInjection\Container
的动态方法(例如#getParameter
)。
所以现在我们可以回到这个问题了。 AppKernel
具有以下与容器相关的方法:
getContainerBaseClass
返回源容器。默认情况下为Symfony\Component\DependencyInjection\Container
。您可以更改它以便它返回您的自定义容器。但实际上没有那么多你可以自定义因为bundle容器重写了很多方法并添加了自己的逻辑。 getContainerClass
返回包容器类名。这是重点。它是实际用于你的环境的容器。你可以扩展它。但首先你应该知道要扩展哪个类。对于我的测试环境,它是appTestDebugProjectContainer
。您可以从以下逻辑中获得满足您需求的课程:
返回$ this-> name.ucfirst($ this-> environment)。($ this-> debug?'Debug':'')。'ProjectContainer';
$this->name
通常是app
。其他事情非常简单。
- initializeContainer
它会完成所有事情并启动容器。我们感兴趣的行是$this->container = new $class();
。我们应该用我们的
$class
var
那么什么是最终解决方案。在某处创建自己的容器并从捆绑的容器名称扩展它。在AppKernel中重写#initializeContainer
。
测试env continer的示例是。
```
命名空间AppBundle \ DependencyInjection;
类TestContainer扩展\ appTestDebugProjectContainer {
public $fakeParams = [];
public function getParameter($name) {
$fake = @$this->fakeParams[$name];
if ($fake) return $fake;
return parent::getParameter($name);
}
}
```
#getContainerClass
:``` class AppKernel扩展了Kernel { // ... protected function initializeContainer() { $ class = $ this-> getContainerClass(); $ cache = new ConfigCache($ this-> getCacheDir()。'/'。$ class。'。php',$ this-> debug); $ fresh = true;
if (!$cache->isFresh()) {
$container = $this->buildContainer();
$container->compile();
$this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
$fresh = false;
}
require_once $cache->getPath();
if ('test' == $this->environment) {
$class = \AppBundle\DependencyInjection\TestContainer::class;
}
$this->container = new $class();
$this->container->set('kernel', $this);
if (!$fresh && $this->container->has('cache_warmer')) {
$this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
}
}
}
```
我只插入了以下几行:
if ('test' == $this->environment) {
$class = \AppBundle\DependencyInjection\TestContainer::class;
}
其他所有内容都是从Kernel#initializeContainer
复制而来。
这适合我。
要了解您可以扩展的内容,您可以在var/cache/test/appTestDebugProjectContainer.php
中检查位于(测试环境)的捆绑容器。