Symfony:无法访问bundle构造函数中的服务

时间:2013-07-29 09:36:12

标签: php symfony bundle symfony-2.3

如何访问Bundle构造函数中的服务?我正在尝试创建一个系统,其中主题包可以使用主题服务自动注册,请参阅下面的小示例(更简单的解决方案更好):

<?php

namespace Organization\Theme\BasicBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class ThemeBasicBundle extends Bundle
{
    public function __construct() {
        $themes = $this->get('organization.themes');
        $themes->register(new Organization\Theme\BasicBundle\Entity\Theme(__DIR__));
    }
}

但是,$ this-&gt; get不起作用,这可能是因为无法保证所有捆绑包已经注册,是否有任何可以使用的邮件包注册“挂钩”?是否有任何特殊的方法名称可以添加到bundle类中,并在实例化所有bundle之后执行?

服务类如下所示:

<?php

namespace Organization\Theme\BasicBundle;

use Organization\Theme\BasicBundle\Entity\Theme;

class ThemeService
{
    private $themes = array();

    public function register(Theme $theme) {
        $name = $theme->getName();

        if (in_array($name, array_keys($this->themes))) {
            throw new Exception('Unable to register theme, another theme with the same name ('.$name.') is already registered.');
        }

        $this->themes[$name] = $theme;
    }

    public function findAll() {
        return $this->themes;
    }

    public function findByName(string $name) {
        $result = null;

        foreach($this->themes as $theme) {
            if ($theme->getName() === $name) {
                $result = $theme;
            }
        }

        return $result;
    }
}

2 个答案:

答案 0 :(得分:3)

您无法访问服务容器是正常的,因为尚未编译服务。 要将标记服务注入到该包中,您需要创建一个新的编译器传递。

要创建编译器传递,它需要实现CompilerPassInterface。

将该类放在bundle的DependencyInjection / Compiler文件夹中。

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

class CustomCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        if ($container->has('organization.themes')) {
            $container->getDefinition('organization.themes')->addMethodCall('register', array(new Organization\Theme\BasicBundle\Entity\Theme(__DIR__)));
        }
    }
}

然后覆盖包定义类的构建方法。

class ThemeBasicBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        $container->addCompilerPass(new CustomCompilerPass());
    }
}

一些链接:

http://symfony.com/doc/current/components/dependency_injection/compilation.html http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html http://symfony.com/doc/current/components/dependency_injection/tags.html

答案 1 :(得分:2)

尝试它可以工作:):

<?php

namespace Organization\Theme\BasicBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class ThemeBasicBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);

        $themes = $container->get('organization.themes');
        $themes->register(new Organization\Theme\BasicBundle\Entity\Template(__DIR__));
    }
}