如何从 Symfony2 的服务中解析 yaml 文件

发布于 2024-12-26 13:05:37 字数 1084 浏览 1 评论 0原文

我想从我的一个服务内的 yaml 文件获取一个数组,但我对如何注入要在 services.yml 中使用的文件有点困惑。

# /path/to/app/src/Bundle/Resources/config/services.yml
parameters:
    do_something: Bundle\DoSomething
    yaml.parser.class: Symfony\Component\Yaml\Parser
    yaml.config_file: "/Resources/config/config.yml" # what do I put here to win!

services:
    yaml_parser:
        class: %yaml.parser.class%

    do_parsing:
        class: %do_something%
        arguments: [ @yaml_parser, %yaml.config_file% ]

在我的服务中,我有

# /path/to/app/src/Bundle/DoSomething.php

<?php

namespace Bundle;

use \Symfony\Component\Yaml\Parser;

class DoSemething
{
    protected $parser;
    protected $parsed_yaml_file;

    public function __construct(Parser $parser, $file_path)
    {
       $this->parsed_yaml_file = $parser->parse(file_get_contents(__DIR__ . $file_path));
    }

    public function useParsedFile()
    {
        foreach($parsed_yaml_file as $k => $v)
        {
            // ...  etc etc 
        }
    }
}

这可能是完全错误的方法,如果我应该做其他事情,请告诉我!

I want to get an array from a yaml file inside one of my services, and I am a little confused of how to inject the file to use in my services.yml.

# /path/to/app/src/Bundle/Resources/config/services.yml
parameters:
    do_something: Bundle\DoSomething
    yaml.parser.class: Symfony\Component\Yaml\Parser
    yaml.config_file: "/Resources/config/config.yml" # what do I put here to win!

services:
    yaml_parser:
        class: %yaml.parser.class%

    do_parsing:
        class: %do_something%
        arguments: [ @yaml_parser, %yaml.config_file% ]

In my service I have

# /path/to/app/src/Bundle/DoSomething.php

<?php

namespace Bundle;

use \Symfony\Component\Yaml\Parser;

class DoSemething
{
    protected $parser;
    protected $parsed_yaml_file;

    public function __construct(Parser $parser, $file_path)
    {
       $this->parsed_yaml_file = $parser->parse(file_get_contents(__DIR__ . $file_path));
    }

    public function useParsedFile()
    {
        foreach($parsed_yaml_file as $k => $v)
        {
            // ...  etc etc 
        }
    }
}

This may be the completely wrong approach, if I should be doing something else please let me know!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

×纯※雪 2025-01-02 13:05:37

首先,我将解释为什么我实施了我的解决方案,以便您决定这种情况是否适合您。

我需要一种方法来轻松加载我的捆绑包中的自定义 .yml 文件(对于很多捆绑包),因此为每个文件在 app/config.yml 中添加单独的行对于每个设置来说似乎都很麻烦。

另外,我希望默认情况下已经加载了大部分配置,这样最终用户在大多数情况下甚至不需要担心配置,特别是不需要检查每个配置文件是否设置正确。

如果您遇到类似的情况,请继续阅读。如果没有,就用Kris解决方案,也是一个不错的解决方案!


当我遇到这个功能的需求时,Symfony2 没有提供一种简单的方法来实现这一点,所以我是如何解决这个问题的:

首先我创建了一个本地 YamlFileLoader 类,它基本上是一个简化的 Symfony2 类:

<?php

namespace Acme\DemoBundle\Loader;

use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Config\Loader\FileLoader;

/**
 * YamlFileLoader loads Yaml routing files.
 */
class YamlFileLoader extends FileLoader
{
    /**
     * Loads a Yaml file.
     *
     * @param string $file A Yaml file path
     *
     * @return array
     *
     * @throws \InvalidArgumentException When config can't be parsed
     */
    public function load($file, $type = null)
    {
        $path = $this->locator->locate($file);

        $config = Yaml::parse($path);

        // empty file
        if (null === $config) {
            $config = array();
        }

        // not an array
        if (!is_array($config)) {
            throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $file));
        }

        return $config;
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean True if this class supports the given resource, false otherwise
     *
     * @api
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'yaml' === $type);
    }
}

然后我更新了 DIC 扩展对于我的包(如果你让 Symfony2 创建完整的包架构,它通常会自动生成,如果不只是创建一个包目录中的 DependencyInjection/Extension.php 文件包含以下内容:

<?php

namespace Acme\DemoBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

use Acme\DemoBundle\Loader\YamlFileLoader;

/**
 * This is the class that loads and manages your bundle configuration
 *
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
 */
class AcmeDemoExtension extends Extension
{
    /**
     * {@inheritDoc}
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));

        $loader->load('services.xml');

        // until here everything is default config (for your DIC services)

        $ymlLoader = new YamlFileLoader(new FileLocator(__DIR__.'/../Resources/config'));
        $container->setParameter('param_name', $ymlLoader->load('yaml_file_name'))); // load yml file contents as an array
    }
}

现在您可以将 yaml 配置作为简单服务参数访问/传递(即 %param_name%< /code> services.yml)

First I'll explain why I implemented my solution for you to decide if this case is right for you.

I needed a way to easily load custom .yml files in my bundle (for lots of bundles) so adding a separate line to app/config.yml for every file seemed like a lot of hassle for every setup.

Also I wanted most of the configs to be already loaded by default so end-user wouldn't even need to worry about configuring most of the time, especially not checking that every config file is setup correctly.

If this seems like a similar case for you, read on. If not, just use Kris solution, is a good one too!


Back when I encountered a need for this feature, Symfony2 didnt't provide a simple way to achieve this, so here how I solved it:

First I created a local YamlFileLoader class which was basically a dumbed down Symfony2 one:

<?php

namespace Acme\DemoBundle\Loader;

use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Config\Loader\FileLoader;

/**
 * YamlFileLoader loads Yaml routing files.
 */
class YamlFileLoader extends FileLoader
{
    /**
     * Loads a Yaml file.
     *
     * @param string $file A Yaml file path
     *
     * @return array
     *
     * @throws \InvalidArgumentException When config can't be parsed
     */
    public function load($file, $type = null)
    {
        $path = $this->locator->locate($file);

        $config = Yaml::parse($path);

        // empty file
        if (null === $config) {
            $config = array();
        }

        // not an array
        if (!is_array($config)) {
            throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $file));
        }

        return $config;
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean True if this class supports the given resource, false otherwise
     *
     * @api
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'yaml' === $type);
    }
}

Then I updated DIC Extension for my bundle (it's usually generated automatically if you let Symfony2 create full bundle architecture, if not just create a DependencyInjection/<Vendor&BundleName>Extension.php file in your bundle directory with following content:

<?php

namespace Acme\DemoBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

use Acme\DemoBundle\Loader\YamlFileLoader;

/**
 * This is the class that loads and manages your bundle configuration
 *
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
 */
class AcmeDemoExtension extends Extension
{
    /**
     * {@inheritDoc}
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));

        $loader->load('services.xml');

        // until here everything is default config (for your DIC services)

        $ymlLoader = new YamlFileLoader(new FileLocator(__DIR__.'/../Resources/config'));
        $container->setParameter('param_name', $ymlLoader->load('yaml_file_name'))); // load yml file contents as an array
    }
}

And now you can access/pass your yaml config as simple service parameter (i.e. %param_name% for services.yml)

暗地喜欢 2025-01-02 13:05:37

我这样解决了:

Services.yml

#/path/to/app/src/Bundle/Resources/config/services.yml

parameters:
    example.class: Path\To\Bundle\Service\Class
    example.yaml_config_file: "%kernel.root_dir%/../src/Path/To/Bundle/Resources/config/config.yml"

services:
    example_service:
        class: %example.class%
        arguments: [%example.yaml_config_file% ]

服务类

# /path/to/app/src/Bundle/Service/Example.php

<?php

namespace Bundle\Service;

use \Symfony\Component\Yaml\Yaml;

class Example
{
    private $parsed_yaml_file;

    public function __construct($yaml_config_file)
    {
       $this->parsed_yaml_file = Yaml::parse($yaml_config_file);
    }
}

I solved it this way:

Services.yml

#/path/to/app/src/Bundle/Resources/config/services.yml

parameters:
    example.class: Path\To\Bundle\Service\Class
    example.yaml_config_file: "%kernel.root_dir%/../src/Path/To/Bundle/Resources/config/config.yml"

services:
    example_service:
        class: %example.class%
        arguments: [%example.yaml_config_file% ]

Service class

# /path/to/app/src/Bundle/Service/Example.php

<?php

namespace Bundle\Service;

use \Symfony\Component\Yaml\Yaml;

class Example
{
    private $parsed_yaml_file;

    public function __construct($yaml_config_file)
    {
       $this->parsed_yaml_file = Yaml::parse($yaml_config_file);
    }
}
谁人与我共长歌 2025-01-02 13:05:37

您可以使用 kernel.root_dir 参数:

parameters:
    yaml.config_file: "%kernel.root_dir%/../src/Path/To/MyBundle/Resources/config/config.yml"

You can use the kernel.root_dir parameter:

parameters:
    yaml.config_file: "%kernel.root_dir%/../src/Path/To/MyBundle/Resources/config/config.yml"
等风也等你 2025-01-02 13:05:37

如果您使用的是 Symfony 3.3 或更高版本,您现在还可以使用新的 kernel.project_dir 参数。

该参数指向包含 Composer 文件的最高级别目录。

If you're using Symfony 3.3 or higher, you can now also use the new kernel.project_dir parameter.

This parameter points to the highest level directory containing a composer file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文