5

我的应用程序由多个名为HelloWorldAdminBundle, HelloWorldUserBundle,的包组成HelloWorldDemoBundle。这会产生一个配置根,如hello_world_demo,hello_world_userhello_world_demo。我希望我的包的配置根是helloworld_demo,helloworld_userhelloworld_admin. 在这一点上我不得不提到,这并不是一个真正的技术问题,而更多的是一个审美问题。

我试图实现一个自定义扩展并将其注册到 Bundle 中:

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

我按照如何为 Bundle 公开语义配置的说明进行操作,但是当我向其中添加项目时,config.yml出现以下错误:

There is no extension able to load the configuration for "helloworld_demo"
4

4 回答 4

3

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

我现在有一个空的但现有的扩展名为 HelloWorldDemoExtension (带有别名hello_world_demo,另外我添加了 DemoExtension (带有别名helloworld_demo)并且它可以工作。

于 2012-09-10T13:33:10.997 回答
3

我通过覆盖解决了这个问题Symfony\Component\HttpKernel\Bundle\Bundle#getContainerExtension()

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

因此,通过覆盖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;
    }
}

而且,当然,不要忘记将其添加到您的扩展类中:

/**
 * The extension alias
 *
 * @return string
 */
public function getAlias()
{
    return 'helloworld_user';
}

警告:我不确定为什么将此检查添加到getContainerExtension()方法中。可能有一个非常正当的理由,并且您在执行上述步骤时可能会遇到问题。但是,到目前为止,我还没有遇到任何问题。

编辑:另请参阅:Symfony2:我不喜欢 Bundles 的一些事情。这篇博客文章提供了与我的答案相同的解决方案。此外,请参阅Symfony 文档的此拉取请求,其中也描述了相同的方法。这让我相信这样做是安全的,而不必担心副作用。

于 2014-08-14T15:38:54.330 回答
0

正如文件所说:

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

  • 扩展必须存储在 DependencyInjection 子命名空间中;
  • 扩展名必须以bundle名命名,并以Extension为后缀(AcmeHelloExtension for AcmeHelloBundle);
  • 扩展应提供 XSD 架构。

我真的不知道你是否需要定义自己的buildgetAlias方法。如果您需要它,那么getAlias方法应该返回与您在根节点中定义的相同的值。所以它应该是helloworld_demo可能而不是hello_world_demo

于 2012-09-10T13:01:30.540 回答
0

从书中“在这种情况下,扩展类还必须实现一个 getAlias() 方法并返回一个以捆绑包命名的唯一别名(例如 acme_hello)。这是必需的,因为类名以 Extension 结尾不符合标准. 此外,只有当用户在至少一个配置文件中指定 acme_hello 别名时,才会调用扩展的 load() 方法。”

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

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

它应该工作

于 2012-09-10T13:22:44.377 回答