12

我正在尝试在 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()。

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

4

3 回答 3

12

容器参数规则是:

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

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

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

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

如果您选择第二个选项,您需要在填充容器之前设置参数,因此您可以:

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

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

于 2014-04-18T17:59:22.573 回答
1

%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
}
于 2014-12-29T13:52:14.243 回答
0

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

这是我的控制器功能。

   /**
     * @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;
   }
}
于 2016-01-26T06:58:17.640 回答