How to parse yaml file from service in symfony2

I want to get an array from a yaml file inside one of my services, and I'm a little confused about how to embed a file for 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

 # /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 a completely wrong approach, if I have to do something else, please let me know!

+5
yaml symfony
source share
4 answers

I will first 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 a large number of packages), so adding a separate line to app / config.yml for each file seemed like a lot of trouble for you for each installation.

In addition, I wanted most configurations to load by default already, so end users didn't even have to worry about setting up most of the time, especially not checking if each configuration file was configured correctly.

If this seems like a similar case for you, read on. If not, just use Chris's solution, that's good too!


Back when I came across the need for this feature, Symfony2 did not provide an easy way to achieve this, so this is how I solved it:

First, I created a local YamlFileLoader class, which was basically a dumbfounded Symfony2 character:

 <?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 the DIC extension for my package (it is usually generated automatically if you allow Symfony2 to create a complete bundle architecture, if not just create the DependencyInjection/<Vendor&BundleName>Extension.php file in your package directory with the 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 / yaml config as a simple service parameter (i.e. %param_name% for services.yml)

+8
source share

I solved it like this:

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% ] 

Class of service

 # /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); } } 
+6
source share

You can use the kernel.root_dir parameter:

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

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

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

0
source share

All Articles