0

如何访问 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->get 不起作用,这可能是因为无法保证所有捆绑包都已注册,是否有任何我可以使用的发布捆绑包注册“钩子”?是否有任何特殊的方法名称可以添加到在所有包都被实例化后执行的包类中?

服务类如下所示:

<?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;
    }
}
4

2 回答 2

3

无法访问服务容器是正常的,因为服务还没有编译。要将标记服务注入该捆绑包,您需要创建一个新的编译器通道。

要创建编译器通道,它需要实现 CompilerPassInterface。

将类放在包的 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/组件/dependency_injection/tags.html

于 2013-07-29T10:21:41.067 回答
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__));
    }
}
于 2013-07-29T10:08:38.137 回答