如何访问Bundle构造函数内部的服务?我正在尝试创建一个系统,在这个系统中,主题捆绑包可以自动向主题服务注册,参见下面的小示例(解决方案越简单越好):
<?php
namespace OrganizationThemeBasicBundle;
use SymfonyComponentHttpKernelBundleBundle;
class ThemeBasicBundle extends Bundle
{
public function __construct() {
$themes = $this->get('organization.themes');
$themes->register(new OrganizationThemeBasicBundleEntityTheme(__DIR__));
}
}
然而,$this->get不起作用,这可能是因为无法保证所有捆绑包都已注册,是否有任何捆绑包后注册"挂钩"可以代替我使用?有什么特殊的方法名称可以添加到所有bundle实例化后执行的bundle类中吗?
服务类如下所示:
<?php
namespace OrganizationThemeBasicBundle;
use OrganizationThemeBasicBundleEntityTheme;
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;
}
}
不能访问服务容器是正常的,因为服务还没有编译。要将标记的服务注入该捆绑包,您需要创建一个新的编译器通行证
要创建编译器传递,它需要实现CompilerPassInterface。
将类放在捆绑包的DependencyInjection/Compiler文件夹中。
use SymfonyComponentDependencyInjectionCompilerCompilerPassInterface;
use SymfonyComponentDependencyInjectionContainerBuilder;
class CustomCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if ($container->has('organization.themes')) {
$container->getDefinition('organization.themes')->addMethodCall('register', array(new OrganizationThemeBasicBundleEntityTheme(__DIR__)));
}
}
}
然后重写bundle定义类的构建方法。
class ThemeBasicBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new CustomCompilerPass());
}
}
一些链接:
http://symfony.com/doc/current/components/dependency_injection/compilation.htmlhttp://symfony.com/doc/current/cookbook/service_container/compiler_passes.htmlhttp://symfony.com/doc/current/components/dependency_injection/tags.html
尝试它可以工作:):
<?php
namespace OrganizationThemeBasicBundle;
use SymfonyComponentHttpKernelBundleBundle;
use SymfonyComponentDependencyInjectionContainerBuilder;
class ThemeBasicBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$themes = $container->get('organization.themes');
$themes->register(new OrganizationThemeBasicBundleEntityTemplate(__DIR__));
}
}