【问题标题】:How can I dynamically set a parameter in Symfony2?如何在 Symfony2 中动态设置参数?
【发布时间】:2014-06-03 03:03:54
【问题描述】:

我正在尝试在 Symfony2 中动态设置一个参数(我无法在我的 parameters.yml 文件中静态设置该参数)。我的方法是使用EventListener

namespace Acme\AcmeBundle\EventListener;

use Symfony\Component\DependencyInjection\Container;

class AcmeListener
{
    private $container;

    public function __construct(Container $container)
    {
        $this->container = $container;
    }

    public function onKernelRequest()
    {
        // Dynamically fetch $bar
        $bar = fetch('foobar');

        // Set parameter
        $this->container->setParameter('foo', $bar);
    }
}

我在config.yml 中的服务定义如下:

service:
    kernel.listener.acme_listener:
        class: Acme\AcmeBundle\EventListener\AcmeListener
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
        arguments: [ '@service_container' ]

问题是,我得到一个异常:

LogicException:无法在冻结的 ParameterBag 上调用 set()。

我该如何解决这个异常,或者您是否看到了另一种动态设置参数的方法?

【问题讨论】:

    标签: symfony service listener before-filter symfony-http-kernel


    【解决方案1】:

    容器参数规则是:

    只能在容器编译前设置参数

    在不认为容器具有动态参数的前提下,如何解决问题取决于您的需求。

    1. 为您创建自定义动态“选项”服务并将其注入其他服务,这样您还可以管理数据库中的参数(如 wordpress wp_options),但我不知道执行此操作的包。对于现有服务(例如邮件)you can use configurators

    2. 当参数更改here an easy method 时使缓存无效,因此当您重新加载页面时,容器会被重建。如果参数频繁更改,则可能会频繁重新加载缓存,如果负载很大,这将成为一个问题。

    如果选择第二个选项,则需要在填充到容器之前设置参数,这样可以:

    • 在清除缓存前,当参数发生变化时,在 app/config/config.yml 中加载的自定义 yaml 文件中导出,这样您就可以从其他服务中获取数据
    • 在bundle扩展here the cookbook中加载参数,这样你就无法访问其他服务获取数据,扩展只能访问containerbuilder

    不过,我建议使用选项 1(选项服务和配置器),因为(我重复一遍)容器不被认为具有动态参数,但它提供了使用来自任何来源的数据的自定义动态服务配置器的能力。

    【讨论】:

      【解决方案2】:

      当我想做一个故障转移系统时,我在以%base_url% 开头的 URL 列表中遇到了问题。

      我终于用#base_url# 替换了%base_url%,并在服务中进行了手动占位符解析。

      $tries = array (
              $this->container->getParameter('base_url'),
              $this->container->getParameter('base_url_failover'),
      );
      
      foreach ($tries as $try)
      {
          $url = str_replace('#base_url#', $try, $unresolvedUrl);
      
          // whatever
      }
      

      【讨论】:

        【解决方案3】:

        我认为我们可以将参数作为简单的类函数添加到服务中。

        这是我的控制器功能。

           /**
             * @Route("/products/checkService")
             * @Template()
             */
            public function checkServiceAction() {            
                $paypal = $this->get('Paypal');
                return new Response($paypal->chkVal('dsdd'));
            }
        

        这是我的服务

        <?php
        
        namespace Eagle\ShopBundle\Services;
        
        use Symfony\Component\HttpFoundation\Response;
        
        class Paypal {      
            public function __construct($var) {
                $this->paypalCongig = $var;
            }
        
            public function getVal() {
                return $this->paypalCongig;
           }
        
            public function chkVal($var) {
                return $var;
           }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-16
          • 1970-01-01
          • 2023-03-22
          • 2012-02-23
          • 2021-07-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多