【问题标题】:Find YAML by key and change the value按键查找 YAML 并更改值
【发布时间】:2016-06-05 08:27:02
【问题描述】:

我想解析任意 .yml 文件的内容并修改任意键。

让我们获取 security.yml 文件,获取其内容并使用 Yaml::parse,它将返回一个包含其结构的数组数组。

$yml='/config/security.yml';    
$path = $this->get('kernel')->getRootDir().$yml;
$contents= Yaml::parse(file_get_contents($file));

这个输出

array(1) {
  ["security"]=>
  array(5) {
    ["encoders"]=>
    string(8) "Array(1)"
    ["role_hierarchy"]=>
    string(8) "Array(3)"
    ["providers"]=>
    string(8) "Array(2)"
    ["firewalls"]=>
    string(8) "Array(2)"
    ["access_control"]=>
    string(9) "Array(14)"
  }
}

到目前为止一切顺利。现在假设我想更改security.firewalls.main.pattern 的值。我需要更改数组值 $contents['security']['firewalls']['main']['pattern'] 然后 file_put_contents yaml 转储。

我的问题是如何通过任意键动态获取和设置参数值,而不是像上面那样硬编码。 Yaml 解析器无法通过其键获取值。我需要一种方法以某种方式将security.firewalls.main.pattern 转换为数组键。很明显,我之后会删除缓存。

我同时做了一些东西:

   $array = Yaml::parse(file_get_contents($file));  
   $keys=array("security","firewalls","main");
   $val = $this->parseYmlArray($array, $keys);

   public function parseYmlArray($array, $keys)
    {
        $newArr = $array;
        foreach ($keys as $key) {
            $newArr = $newArr[$key];
        }
        return $newArr;
    }

这将返回任何节点,但它需要一个与键深度完全相同的数组。

我最初在考虑是否可以制作一个 ParameterBag 就像容器中的那个一样。问题是我似乎无法找到从深度关联数组到 key->value (例如security.firewalls.main.pattern 及其值)的创建位置。如果我尝试从数组中创建一个 ParameterBag,它不会修改该数组,该包包含完全相同的数组。我正在尝试查找数组在哪里被解析并转换为容器中的那个。

【问题讨论】:

标签: symfony yaml


【解决方案1】:

实际上,我没有看到任何直接更新配置值的替代方法。

但是,您可以通过定义参数来实现。

例如,您可以如下更改您的security.firewalls.main.pattern

parameters:
    firewall_main_pattern: ^/yourpattern
    # ...

firewalls:
    # ...
    main:
        pattern: %firewall_main_pattern%
        # ...

然后,根据需要更新参数:

$this->container->setParameter('firewall_main_pattern', '^/yournewpattern');

希望这能解决您的问题。

更新

在你的parseYmlArray中,你可以使用下面的来改变一个值:

function assignConfigurationValueByPath(&$array, $path, $value) {
    $keys = explode('.', $path);
    while ($key = array_shift($keys)) {
        $arr = &$arr[$key];
    }

    $arr = $value;
}

$array = Yaml::parse(file_get_contents($file));
assignConfigurationValueByPath($array, 'security.firewalls.main.pattern, 'new_value');

现在$array 改为:

array(
    'security' => array(
        // ...
        'firewalls' => array(
             // ...
             'main' => array(
                 // ...
                 'pattern' => 'new_value'
             ),
        ),
    ),
):

【讨论】:

  • 它没有。我正在寻找一种动态而不是手动更改它们的方法。修改后我正在重建缓存。
  • 我如何理解您的问题,您当前正在解析 YAML,手动更改值并重写整个配置文件,并且您正在寻找一种无需硬编码 yaml 解析即可更改参数的方法.这就是为什么我建议您以更清洁的方式进行操作。也许通过谈论避免缓存重建并动态进行更改而不是手动定义来解决您的问题。
  • 使用 setParameter 不会有帮助。实际使用 firewall_main_pattern 的服务实际上被编译成一个缓存的容器定义文件。在编译器传递之外没有实际的方法来修改它们。看一下缓存目录。很多有趣的事情正在发生。
  • 嗯,修改防火墙就是一个例子。目的是修改任何 .yml,而不是特别是这个。编译器通道不允许动态修改。它们需要来自 .yml 文件。
  • 好的,现在很清楚了,谢谢。 @GeorgeIrimiciuc 如果您在没有recompiling the container 的情况下更新配置值(来自任何配置文件),则无法在同一请求中获取最新配置。
猜你喜欢
  • 1970-01-01
  • 2012-09-26
  • 2018-03-18
  • 2016-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
相关资源
最近更新 更多