Как мне разобрать файл yaml из службы в Symfony2 - PullRequest
5 голосов
/ 10 января 2012

Я хочу получить массив из файла 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 
        }
    }
}

Это может быть совершенно неправильный подход, если я должен делать что-то еще, пожалуйста, дайте мне знать!

Ответы [ 4 ]

8 голосов
/ 10 января 2012

Сначала я объясню, почему я реализовал свое решение, чтобы вы решили, подходит ли вам этот случай.

Мне нужен был способ легко загружать пользовательские файлы .yml в мойbundle (для большого количества пакетов), поэтому добавление отдельной строки в app / config.yml для каждого файла выглядело как большая проблема для каждой настройки.

Кроме того, я хотел, чтобы большинство конфигураций уже загружались по умолчанию, чтобы конечному пользователю даже не приходилось беспокоиться о настройке большую часть времени, особенно не проверяя, правильно ли настроен каждый файл конфигурации.

Если для вас это похоже на аналогичный случай, читайте дальше.Если нет, просто используйте решение Kris, это тоже хорошо!


Когда я столкнулся с необходимостью использования этой функции, Symfony2 не предоставил простой способ добиться этого, поэтому вот как я решилit:

Сначала я создал локальный класс 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/<Vendor&BundleName>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%)для services.yml)

6 голосов
/ 25 сентября 2013

Я решил это так:

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);
    }
}
3 голосов
/ 10 января 2012

Вы можете использовать параметр kernel.root_dir:

parameters:
    yaml.config_file: "%kernel.root_dir%/../src/Path/To/MyBundle/Resources/config/config.yml"
0 голосов
/ 03 декабря 2018

Если вы используете Symfony 3.3 или выше, теперь вы также можете использовать новый параметр kernel.project_dir.

Этот параметр указывает на каталог самого высокого уровня, содержащий файл композитора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...