如何在symfony 3.2中重写容器基类

时间:2018-04-02 18:45:41

标签: symfony

我使用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#getRootDirAppKernel#getCacheDir中的断点。我在Kernel搜索了一些有用的东西。但很难理解为什么它不起作用。我试图清除缓存。

在我看来,我做错了什么。但互联网对重写symfony容器一无所知。这很奇怪。

我想重写容器以允许更改(模拟)配置。目前据我所知,symfony有iced参数包,无法更改。

1 个答案:

答案 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的示例是。

  1. 创建容器:
  2. ```

    命名空间AppBundle \ DependencyInjection;

    类TestContainer扩展\ appTestDebugProjectContainer {

    public $fakeParams = [];
    
    public function getParameter($name) {
        $fake = @$this->fakeParams[$name];
        if ($fake) return $fake;
        return parent::getParameter($name);
    }
    

    }

    ```

    1. 在AppKernel中重写#getContainerClass
    2. ```     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中检查位于(测试环境)的捆绑容器。