如何在Symfony2中动态设置参数?

如何在Symfony2中动态设置参数?,symfony,service,kernel,listener,before-filter,Symfony,Service,Kernel,Listener,Before Filter,我试图在Symfony2中动态设置一个参数(我无法在parameters.yml文件中静态设置)。我的方法是使用EventListener: namespace Acme\AcmeBundle\EventListener; use Symfony\Component\DependencyInjection\Container; class AcmeListener { private $container; public function __construct(Conta

我试图在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:无法对冻结的参数包调用set()


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

容器参数规则是:

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

如何解决此问题取决于您的需要,前提是容器不被认为具有动态参数

  • 创建自定义的动态“选项”服务并将其注入其他服务中,这样您也可以管理数据库中的参数(如wordpress wp_options),但我不知道有哪个包可以做到这一点。对于现有服务(例如邮寄服务)

  • 参数更改时使缓存无效,以便在重新加载页面时重新生成容器。如果参数频繁更改,则可能会频繁重新加载缓存,如果负载较大,这将成为一个问题

  • 如果选择第二个选项,则需要在将其装入容器之前设置参数,以便:

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

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

    当我想要执行故障切换系统时,我在以
    %base\u url%
    开头的url列表上遇到了问题

    我最终将
    %base\u url%
    替换为
    #base\u 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
    }
    

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

    $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
    }
    
    这是我的控制器功能

       /**
         * @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;
       }
    }