我有一个Yaml加载器,为一个"配置文件"加载额外的配置项(其中一个应用程序可以使用不同的配置文件,例如同一站点的不同本地版本)。
我的加载器非常简单:
# YamlProfileLoader.php
use Symfony'Component'Config'Loader'FileLoader;
use Symfony'Component'Yaml'Yaml;
class YamlProfileLoader extends FileLoader
{
public function load($resource, $type = null)
{
$configValues = Yaml::parse($resource);
return $configValues;
}
public function supports($resource, $type = null)
{
return is_string($resource) && 'yml' === pathinfo(
$resource,
PATHINFO_EXTENSION
);
}
}
加载器大致是这样使用的(简化了一点,因为也有缓存):
$loaderResolver = new LoaderResolver(array(new YamlProfileLoader($locator)));
$delegatingLoader = new DelegatingLoader($loaderResolver);
foreach ($yamlProfileFiles as $yamlProfileFile) {
$profileName = basename($yamlProfileFile, '.yml');
$profiles[$profileName] = $delegatingLoader->load($yamlProfileFile);
}
解析的Yaml文件也是如此:
# profiles/germany.yml
locale: de_DE
hostname: %profiles.germany.host_name%
目前,结果数组实际上包含'hostname'
数组键的'%profiles.germany.host_name%'
。
那么,我如何解析%参数以获得实际的参数值呢?
我一直在浏览Symfony 2的代码和文档(以及这个SO问题),但找不到框架本身在哪里完成的。我可能会编写自己的参数解析器-从内核中获取参数,搜索%foo%字符串并查找/替换…但如果有一个组件准备使用,我更喜欢使用这个。
给出更多的背景,为什么我不能把它包含在主配置中。我希望能够加载app/config/profiles/*.yml
,其中*
是配置文件名称,我使用自己的加载器来完成此操作。如果有一种方法可以通配符导入配置文件,那么这可能也适用于我。
注意:目前使用2.4,但如果有帮助,准备升级到2.5。
我一直在浏览Symfony 2的代码和文档(以及这个SO问题),但找不到框架本身在哪里完成的。
Symfony的依赖注入组件在优化阶段使用编译器传递来解析参数引用。
编译器从它的PassConfig实例中获取注册的编译器传递。这个类默认配置了几个编译器传递,其中包括ResolveParameterPlaceHoldersPass。
在容器编译过程中,ResolveParameterPlaceHoldersPass
使用容器的ParameterBag来解析包含%parameters%
的字符串。然后,编译器传递将解析后的值设置回容器中。
那么,我如何解析%参数以获得实际的参数值呢?
您需要访问您的ProfileLoader(或任何您认为合适的地方)中的容器。使用容器,您可以递归地遍历已解析的yaml配置,并将值传递给容器的参数包,以便通过resolveValue()方法进行解析。
在我看来,也许更简洁的方法是在你的bundle配置中实现它。这样,您的配置将根据已定义的结构进行验证,从而可以及早发现配置错误。有关更多信息,请参阅有关bundle配置的文档(该链接适用于v2.7,但希望也适用于您的版本)。
我知道这是一个老问题,但我已经花了相当长的时间为我自己的项目弄清楚这个问题,所以我把答案贴在这里供将来参考。
我尝试了很多选项来将%parameter%解析为parameters。我知道,但一点也不走运。我所能想到的就是解析%参数%并从容器中获取它,还没有创新。
另一方面,我没有足够的信息来了解你的环境,但我只是想到了另一个想法。如果在参数中声明概要文件,这将非常方便。Yml文件,并通过容器将其作为数组加载到控制器或服务中。
app/config/parameters.yml
parameters:
profiles:
germany:
locale: de_DE
host_name: http://de.example.com
uk:
locale: en_EN
host_name: http://uk.example.com
turkey:
locale: tr_TR
host_name: http://tr.example.com
你可以把你所有的配置文件作为一个数组放在你的控制器中。
<?php
namespace Acme'DemoBundle'Controller;
use Symfony'Bundle'FrameworkBundle'Controller'Controller;
class DefaultController extends Controller
{
public function indexAction()
{
$profiles = $this->container->getParameter('profiles');
var_dump($profiles);
return $this->render('AcmeDemoBundle:Default:index.html.twig');
}
}
使用这种方法
- 你不需要编写自定义的YamlLoader
- 您不必担心将参数导入到其他yml文件
- 你可以把你的配置文件作为一个数组,只要你有$container在你的手
- 你不需要逐个加载/缓存配置文件
- 你不需要找到一个通配符文件加载解决方案
如果我对你的问题理解正确,这个方法可以帮助你。