Php Symfony2:自定义配置根目录

Php Symfony2:自定义配置根目录,php,symfony,Php,Symfony,我的应用程序由多个bundle组成,这些bundle的名称类似于HelloWorldAdminBundle,HelloWorldUserBundle,HelloWorldDemoBundle。这将产生一个配置根目录,如hello\u world\u demo、hello\u world\u user和hello\u world\u demo。我希望捆绑包的配置根是helloworld\u demo,helloworld\u user和helloworld\u admin。在这一点上,我必须提到,

我的应用程序由多个bundle组成,这些bundle的名称类似于
HelloWorldAdminBundle
HelloWorldUserBundle
HelloWorldDemoBundle
。这将产生一个配置根目录,如
hello\u world\u demo
hello\u world\u user
hello\u world\u demo
。我希望捆绑包的配置根是
helloworld\u demo
helloworld\u user
helloworld\u admin
。在这一点上,我必须提到,这不是一个真正的技术问题,而是一个美学问题

我已尝试实现自定义扩展并将其注册到捆绑包中:

public function build(ContainerBuilder $container)
{
    parent::build($container);

    $container->registerExtension(new HelloworldDemoExtension());
}
延长期限:

...
class HelloworldDemoExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader->load('services.yml');
    }

    public function getAlias()
    {
        return 'hello_world_demo';
    }
}
最后是配置:

...
class Configuration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('helloworld_demo');
        ...
        return $treeBuilder;
    }
}
我按照说明进行操作,但是,当我向
config.yml
添加一个项目时,出现以下错误:

There is no extension able to load the configuration for "helloworld_demo"
正如上面所说:

创建扩展时,请遵循以下简单约定:

  • 扩展必须存储在DependencyInjection子命名空间中
  • 扩展名必须以包名命名,并以扩展名作为后缀(AcmeHelloExtension代表AcmeHelloBundle)
  • 扩展应该提供一个XSD模式
我不知道您是否需要定义自己的
build
getAlias
方法。若您需要它,那个么
getAlias
方法应该返回和您在根节点中定义的相同的值。所以它应该是helloworld\u demo,而不是书中的hello\u world\u demo “在这种情况下,扩展类还必须实现getAlias()方法,并返回以捆绑包命名的唯一别名(例如acme_hello)。这是必需的,因为类名以扩展结尾不符合标准。 此外,仅当用户在至少一个配置文件中指定acme_hello别名时,才会调用扩展名的load()方法。”

因此,此别名是根配置名称。将代码更改为

public function getAlias()
{
    return 'helloworld_demo';
}

而且它应该会起作用

我找到了解决问题的办法。它的工作原理与我在问题中描述的完全相同,但是,必须存在一个默认扩展名(带有捆绑包的名称)


我现在有一个名为HelloWorldDemoExtension的空扩展名(别名为
hello\u world\u demo
),而且我还添加了DemoExtension(别名为
helloworld\u demo
),它可以工作。

我通过重写解决了这个问题

此方法自动创建并返回
ExtensionInterface
的实例,还检查扩展的别名(根据答案,可以通过在扩展类中实现
getAlias
来指定)是否符合命名约定

因此,通过重写bundle类中的
getContainerExtension()
方法,只需返回扩展类的实例,就可以绕过检查和
LogicException

这是您的bundle类的外观:

<?php

namespace HelloWorld\Bundle\UserBundle;

use HelloWorld\Bundle\UserBundle\DependencyInjection\HelloWorldUserExtension;
use Symfony\Component\HttpKernel\Bundle\Bundle;

class HelloWorldUserBundle extends Bundle
{
    public function getContainerExtension()
    {
        if (null === $this->extension) {
            $this->extension = new HelloWorldUserExtension();
        }

        return $this->extension;
    }
}
警告:我不确定为什么要将此检查添加到
getContainerExtension()
方法中。这可能是一个非常合理的原因,您在执行上述步骤时可能会遇到问题。但是,到目前为止,我还没有遇到任何问题


编辑:另请参阅:。这篇博客文章提供了与我的答案相同的解决方案。另外,请参阅Symfony的文档,其中也描述了相同的方法。这使我相信这样做是安全的,而无需预期副作用。

否。就我对文档的理解而言,
getAlias
方法是我们的由Symfony编辑以将扩展与捆绑包关联。由于扩展名不再提供捆绑包的任何提示,因此使用别名。编辑:这在语义配置文档页面的底部进行了解释:关于第一部分。我知道这些约定,为了美观,我想打破它们。
 [LogicException]捆绑包的默认扩展名的扩展别名必须是捆绑包名称的下划线版本(“hello\u world\u demo”而不是“helloworld\u demo”)
mmm…因此,我想剩下的唯一解决方案是将您的捆绑包重命名为HelloworldDemoBundle,等等…这很难看,但我想如果您真的想打破symfony的惯例,那就是最好的方法。最干净的方法必须是正确命名您的捆绑包:-)@AlainTiemblo正确命名捆绑包并不总是可行的-
CMSIP2LocationBundle
/**
 * The extension alias
 *
 * @return string
 */
public function getAlias()
{
    return 'helloworld_user';
}