【问题标题】:Symfony prependExtensionConfig with data from a serviceSymfony prependExtensionConfig 与来自服务的数据
【发布时间】:2015-05-18 22:23:20
【问题描述】:

我尝试使用我的包中的 prependExtensionConfig 将配置数组添加到不同的包。在 $config 被硬编码之前一切正常。

我的目标是使用 service (例如来自数据库)加载 $config 值,然后将其添加到其他包中。

问题是当时没有加载服务。 我猜这是 symfony2 的一个限制。

有什么想法吗?谢谢

    class MyExtension extends Extension implements PrependExtensionInterface
{

    /**
     * {@inheritDoc}
     */
    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 prepend(ContainerBuilder $container)
    {   

        $config = // load config from a service ...

        $container->prependExtensionConfig('other_bundle', $config);
    }   
}

【问题讨论】:

  • 在加载扩展之前调用 prepend 方法,因此此时不会加载服务。设置参数没有帮助。
  • 你读过我链接的问题吗?我可以再次解释同样的情况。但它会重复链接问题的答案。
  • 谢谢。是的,但如果我理解正确的话 prependExtensionConfig 和 setParameter 是不同的东西。试过了,因为加载顺序不工作。我想这是一个限制,我必须围绕它进行构建。
  • 好的。我稍后会回答你的问题...

标签: symfony config


【解决方案1】:

首先,您需要设置配置以从服务容器的参数部分获取值:

  • 设置config.yml

    # app/config/config.yml
    namespace:
      subnamespace:
        param1: %param1%
        param2: %param2%
    

然后您需要使用数据库中的值填充容器中的%param1%%param2% 参数。为此,您需要声明您的 CompilerPass 并将其添加到容器中。加载整个容器后(在编译时),您将可以访问其中的所有服务。

只需获取实体管理器服务并查询所需的参数并将它们注册到容器中。

  • 定义编译器通道:

    # src/Acme/YourBundle/DependencyInjection/Compiler/ParametersCompilerPass.php
    class ParametersCompilerPass implements CompilerPassInterface
    {
        public function process(ContainerBuilder $container)
        {
            $em = $container->get('doctrine.orm.default_entity_manager');
            $param1 = $em->getRepository('Acme:Params')->find(1);
            $param2 = $em->getRepository('Acme:Params')->find(2);
            $container->setParameter('param1', $param1);
            $container->setParameter('param2', $param2);
        }
    }
    
  • 在包定义类中,您需要将编译器传递添加到您的容器

    # src/Acme/YourBundle/AcmeYourBundle.php
    class AcmeYourBundle extends Bundle
    {
        public function build(ContainerBuilder $container)
        {
            parent::build($container);
    
            $container->addCompilerPass(new ParametersCompilerPass(), PassConfig::TYPE_AFTER_REMOVING);
        }
    }
    

    PassConfig::TYPE_AFTER_REMOVING 意味着这个 CompilerPass 将在所有其他编译器通过之后几乎被处理,此时您已经注入了所有服务。

【讨论】:

  • 嗨迈克尔,再次检查,但我得到的只是[Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException]. You have requested a non-existent parameter "param1"。通过添加一些调试,看起来捆绑配置文件首先加载(并引发异常),然后执行编译器传递(已经太晚了)。我是否遗漏了一些明显的东西?干杯
  • 尝试为这些参数定义“默认”值,并尝试更改编译器传递的优先级以在您的包处理参数之前对其进行处理。
  • 试过了,通过添加 param1 & param2 null 作为默认值,即使在执行编译器传递之后它们仍然为 null。以所有 5 个优先事项执行此操作。
  • 您希望将配置添加到哪个捆绑包中?
猜你喜欢
  • 2013-02-03
  • 1970-01-01
  • 2013-04-14
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 2013-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多