简体   繁体   English

Symfony 2-如何在我自己的Yaml文件加载器中解析%parameter%?

[英]Symfony 2 - how to parse %parameter% in my own Yaml file loader?

I have a Yaml loader that loads additional config items for a "profile" (where one application can use different profiles, eg for different local editions of the same site). 我有一个Yaml加载程序,它为“配置文件”(其中一个应用程序可以使用不同的配置文件,例如,同一站点的不同本地版本)加载其他配置项。

My loader is very simple: 我的加载器非常简单:

# 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
        );
    }
}

The loader is used more or less like this (simplified a bit, because there is caching too): 加载器或多或少是这样使用的(简化了一点,因为也有缓存):

$loaderResolver = new LoaderResolver(array(new YamlProfileLoader($locator)));
$delegatingLoader = new DelegatingLoader($loaderResolver);

foreach ($yamlProfileFiles as $yamlProfileFile) {
    $profileName = basename($yamlProfileFile, '.yml');
    $profiles[$profileName] = $delegatingLoader->load($yamlProfileFile);
}

So is the Yaml file it's parsing: 解析的Yaml文件也是如此:

# profiles/germany.yml

locale: de_DE
hostname: %profiles.germany.host_name%

At the moment, the resulting array contains literally '%profiles.germany.host_name%' for the 'hostname' array key. 目前,生成的数组实际上包含'hostname'数组键的'%profiles.germany.host_name%'

So, how can I parse the % parameters to get the actual parameter values? 那么,如何解析%参数以获得实际参数值?

I've been trawling through the Symfony 2 code and docs (and this SO question and can't find where this is done within the framework itself. I could probably write my own parameter parser - get the parameters from the kernel, search for the %foo% strings and look-up/replace... but if there's a component ready to be used, I prefer to use this. 我一直在浏览Symfony 2代码和文档(以及这个问题 ,无法在框架本身中找到完成的地方。我可能可以编写自己的参数解析器-从内核获取参数,搜索%foo%字符串和查找/替换...但是如果有准备使用的组件,我更喜欢使用它。

To give a bit more background, why I can't just include it into the main config.yml: I want to be able to load app/config/profiles/*.yml , where * is the profile name, and I am using my own Loader to accomplish this. 为了提供更多背景知识,为什么我不能仅仅将其包含在主要的config.yml中:我希望能够加载app/config/profiles/*.yml ,其中*是配置文件名称,我正在使用我自己的加载程序来完成此任务。 If there's a way to wildcard import config files, then that might also work for me. 如果有通配符导入配置文件的方法,那对我也可能有用。

Note: currently using 2.4 but just about ready to upgrade to 2.5 if that helps. 注意:当前使用的是2.4,但如果有帮助,就准备升级到2.5。

I've been trawling through the Symfony 2 code and docs (and this SO question and can't find where this is done within the framework itself. 我一直在研究Symfony 2的代码和文档(以及这个问题),无法在框架本身中找到完成的位置。

Symfony's dependency injection component uses a compiler pass to resolve parameter references during the optimisation phase. Symfony的依赖项注入组件在优化阶段使用编译器传递来解析参数引用。

The Compiler gets the registered compiler passes from its PassConfig instance. 编译器从其PassConfig实例获取注册的编译器通过。 This class configures a few compiler passes by default , which includes the ResolveParameterPlaceHoldersPass . 此类默认配置一些编译器 遍历 ,其中包括ResolveParameterPlaceHoldersPass

During container compilation, the ResolveParameterPlaceHoldersPass uses the Container's ParameterBag to resolve strings containing %parameters% . 在容器编译期间, ResolveParameterPlaceHoldersPass使用容器的ParameterBag 解析包含%parameters% 字符串 The compiler pass then sets that resolved value back into the container. 然后,编译器传递将已解析的值设置回容器中。

So, how can I parse the % parameters to get the actual parameter values? 那么,如何解析%参数以获得实际参数值?

You'd need access to the container in your ProfileLoader (or wherever you see fit). 您需要访问ProfileLoader中的容器(或您认为合适的任何位置)。 Using the container, you can recursively iterate over your parsed yaml config and pass values to the container's parameter bag to be resolved via the resolveValue() method. 使用容器,您可以递归地遍历解析的yaml配置并将值传递到容器的参数包,以通过resolveValue()方法进行解析。


Seems to me like perhaps a cleaner approach would be for you to implement this in your bundle configuration. 在我看来,也许更干净的方法是让您在捆绑包配置中实施此方法。 That way your config will be validated against a defined structure, which can catch configuration errors early. 这样,您的配置将针对已定义的结构进行验证,这可以及早发现配置错误。 See the docs on bundle configuration for more information (that link is for v2.7, but hopefully will apply to your version also). 有关更多信息,请参阅有关捆绑包配置的文档(该链接适用于v2.7,但希望也适用于您的版本)。

I realise this is an old question, but I have spent quite a while figuring this out for my own projects, so I'm posting the answer here for future reference. 我意识到这是一个老问题,但是我花了相当长的时间为自己的项目弄清楚了这个问题,因此我将答案发布在这里以供将来参考。

I tried a lot of options to resolve %parameter% to parameters.yml but no luck at all. 我尝试了很多方法来将%parameter%解析为parameters.yml,但没有任何运气。 All I can think of is parsing %parameter% and fetch it from container, no innovation yet. 我所能想到的就是解析%parameter%并从容器中获取它,尚无创新。

On the other hand I don't have enough information about your environment to see the big picture but I just come up with another idea. 另一方面,我没有关于您的环境的足够信息来了解全局,但是我想出了另一个主意。 It can be quite handy if you declare your profiles in your parameters.yml file and load it as an array in your controller or service via container. 如果您在parameters.yml文件中声明配置文件并通过容器将其作为数组加载到控制器或服务中,则可能非常方便。

app/config/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 

You can have all your profiles as an array in your controller. 您可以将所有配置文件作为数组包含在控制器中。

<?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');
    }
}

With this approach 用这种方法

  • you don't have to code a custom YamlLoader 您不必编写自定义YamlLoader
  • you don't have to worry about importing parameters into other yml files 您不必担心将参数导入到其他yml文件中
  • you can have your profiles as an array anytime you have the $container in your hand 您可以随时将$ container用作阵列的配置文件
  • you don't have to load/cache profile files one by one 您不必一一加载/缓存配置文件
  • you don't have to find a wildcard file loading solution 您不必查找通配符文件加载解决方案

If I got your question correctly, this approach can help you. 如果我正确地提出了您的问题,这种方法可以为您提供帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM