如何在symfony yaml配置组件中使用变量和导入文件

时间:2015-03-10 18:17:38

标签: php symfony configuration yaml

我在项目中使用symfony的配置组件,我需要在我的yml配置文件的各个部分使用相同的值。

有人知道如何使用配置组件重现symfony configuration.yml的行为吗?

我想导入配置文件:

imports:
  - { resource: otherfile.yml }

或声明变量:

myvar: value
othervar: %myvar%

3 个答案:

答案 0 :(得分:3)

Symfony Config组件没有内置此功能。在配置文件中定义和解析导入和参数是DependencyInjection组件的一部分,即其FileLoader类(Symfony \ Component \ DependencyInjection \ Loader \ FileLoader)。

如果您不想将整个DependencyInjection组件添加为依赖项,那么最好的方法是简单地扩展Config组件自己的FileLoader类,覆盖load()方法,读入配置,查找“导入” “子元素并在其中引用的文件路径上调用”$ this-> import()“。 然后读取“参数”键下的所有内容,遍历所有配置键,并将所有先前找到的参数替换为其值。

示例:

public function load($resource, $type = null)
{
  // ...
  // Load your config data as usual. It's assumed that
  // the configuration is now a multidimensional array
  // named $content
  // Load the imports:
  if (isset($content['imports'])) {
      foreach ($content['imports'] as $import) {
          $extraContent = $this->import($import['resource']);
          $content = array_replace_recursive($extraContent, $content);
      }
  }
  // Store the parameters:
  if (isset($content['parameters'])) {
      foreach ($content['parameters'] as $param) {
          foreach ($param as $key => $value) {
              $this->_parameters[$key] = $value;
          }
      }
  }
  // iterate over all configuration keys and substitute
  // placeholders with parameter values:
  array_walk_recursive(
      $content,
      function(&$val, $key) {
          $matches = null;
          preg_match('/\%(.*?)\%/', $val, $matches);
          $param = isset($matches[1]) ? $matches[1] : false;
          if ($param) {
              if (isset($this->_parameters[$param])) {
                  $val = str_replace("%$param%", $this->_parameters[$param], $val);
              }
          }
      }
  );    
  // And you're done. From here on, proceed as usual
  // (like, validate content against a ConfigurationInterface
  // implementation
  // ...
}

警告:示例代码非常简略,不包含错误检查,并且未在此简短形式中进行测试 - 但它确实包含了所有必要的步骤,我希望它可以指向正确的方向。

还建议查看Symfony \ Component \ DependencyInjection \ Loader \ FileLoader类,看看它是如何完成的(忽略所有资源注册的东西)。

答案 1 :(得分:2)

Markus Wolff的一点点代码:

class FileLoader extends \Symfony\Component\Config\Loader\FileLoader
{
    private $_parameters;

    public function addParameter($k, $v)
    {
        $this->_parameters[$k] = $v;
    }

    public function load($resource, $type = null)
    {
        $resource = $this->getLocator()->locate($resource, null, true);
        $content = \Symfony\Component\Yaml\Yaml::parse(file_get_contents($resource));

        if (isset($content['imports'])) {
            foreach ($content['imports'] as $import) {
                $extraContent = $this->import($import['resource']);
                $content = array_replace_recursive($extraContent, $content);
            }
        }

        if (isset($content['parameters'])) {
            foreach ($content['parameters'] as $key => $value) {
                $this->_parameters[$key] = $value;
            }
        }

        array_walk_recursive(
            $content,
            function (&$val) {
                $matches = null;
                preg_match_all('/\%(.*?)\%/', $val, $matches, PREG_SET_ORDER, 0);
                if ($matches) {
                    foreach ($matches as $match) {
                        if ($param = isset($match[1]) ? $match[1] : false) {
                            if (isset($this->_parameters[$param])) {
                                $val = str_replace("%$param%", $this->_parameters[$param], $val);
                            }
                        }
                    }
                }
            }
        );

        return $content;
    }

    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION);
    }
}

答案 2 :(得分:0)

好的,这里有一些未经测试的代码:

<?php
// parse yaml to an array
$parser = new \Symfony\Component\Yaml\Parser();
$configs = $parser->parse(\file_get_contents('config.yml'));

// your config tree
$configuration = new Configuration();

// processor reading the config from the array according to the Configuration NodeTree
$processor = new Processor();
$result = $processor->processConfiguration($configuration, $configs);

// you can be 100% sure, that your $result array has the attributes you set in Configuration

处理器应该为您验证配置并抛出异常。但您也可以直接解析YAML并访问数组