我在项目中使用symfony的配置组件,我需要在我的yml配置文件的各个部分使用相同的值。
有人知道如何使用配置组件重现symfony configuration.yml的行为吗?
我想导入配置文件:
imports:
- { resource: otherfile.yml }
或声明变量:
myvar: value
othervar: %myvar%
答案 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并访问数组