Symfony2 - Access kernel from a compiler pass

2019-04-29 10:23发布

Is there a way to access the kernel from inside a compiler pass? I've tried this:

    ...
    public function process(ContainerBuilder $container)
    {
        $kernel = $container->get('kernel');
    }
    ...

This throws an error. Is there another way to do it?

2条回答
来,给爷笑一个
2楼-- · 2019-04-29 11:08

As far as I can tell, Kernel isn't available anywhere in a CompilerPass, by default.

But you can add it in by doing this:

In your AppKernel, pass $this to the bundle the compiler pass is in.

  • Add a constructor to your Bundle object, which accepts the Kernel as a parameter and stores it as a property.
  • In your Bundle::build() function, pass the Kernel to your CompilerPass instance.
  • In your CompilerPass, at a constructor to accept the Kernel as a parameter and store it as a property.
  • Then you can use $this->kernel in your compiler pass.

// app/AppKernel.php
new My\Bundle($this);

// My\Bundle\MyBundle.php
use Symfony\Component\HttpKernel\KernelInterface;

class MyBundle extends Bundle {
protected $kernel;

public function __construct(KernelInterface $kernel)
{
  $this->kernel = $kernel;
}

public function build(ContainerBuilder $container)
{
    parent::build($container);
    $container->addCompilerPass(new MyCompilerPass($this->kernel));
}

// My\Bundle\DependencyInjection\MyCompilerPass.php
use Symfony\Component\HttpKernel\KernelInterface;

class MyCompilerPass implements CompilerPassInterface
protected $kernel;

public function __construct(KernelInterface $kernel)
{
   $this->kernel = $kernel;
}

public function process(ContainerBuilder $container)
{
    // Do something with $this->kernel
}
查看更多
Deceive 欺骗
3楼-- · 2019-04-29 11:13

What samanime recommends works if you need to whole kernel.

If you are just interested in some values the kernel contains, it might be sufficient to just use the parameters set by symfony.

Here is a list of available ones:

Array
(
    [0] => kernel.root_dir
    [1] => kernel.environment
    [2] => kernel.debug
    [3] => kernel.name
    [4] => kernel.cache_dir
    [5] => kernel.logs_dir
    [6] => kernel.bundles
    [7] => kernel.charset
    [8] => kernel.container_class
    [9] => kernel.secret
    [10] => kernel.http_method_override
    [11] => kernel.trusted_hosts
    [12] => kernel.trusted_proxies
    [13] => kernel.default_locale
)

For instance, the kernel.bundles contains a list of all registered bundles in the format [bundle => class].

PS: I fetched this list using the following compiler pass:

<?php
namespace Acme\InfoBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class InfoCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        print_r(array_values(array_filter(
            array_keys($container->getParameterBag()->all()), 
            function ($e) {
                return strpos($e, 'kernel') === 0;
            }
        )));
        die;
    }
}
查看更多
登录 后发表回答