2012-01-10 25 views
5

Quiero obtener una matriz de un archivo yaml dentro de uno de mis servicios, y estoy un poco confundido acerca de cómo inyectar el archivo para utilizarlo en mis servicios. yml.Cómo analizar un archivo yaml desde un servicio en Symfony2

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

En mi servicio tengo

# /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 
     } 
    } 
} 

Este puede ser el enfoque totalmente erróneo, si yo debería hacer algo más por favor hágamelo saber!

Respuesta

8

En primer lugar voy a explicar por qué he implementado mi solución para que usted pueda decidir si este caso es adecuado para usted.

Necesitaba una forma de cargar fácilmente archivos .yml personalizados en mi paquete (para muchos paquetes) por lo que agregar una línea separada a la aplicación/config.yml para cada archivo parecía una gran molestia para cada configuración.

También quería que la mayoría de las configuraciones ya estuvieran cargadas de manera predeterminada, así el usuario final ni siquiera tendría que preocuparse por configurar la mayoría del tiempo, especialmente sin verificar que cada archivo de configuración esté configurado correctamente.

Si esto le parece un caso similar, siga leyendo. Si no, solo usa la solución de Kris, ¡también es una buena!


Antes, cuando me encontré con la necesidad de esta característica, Symfony2 didnt't proporciona una forma sencilla de lograr esto, así que aquí cómo lo resolví:

Primero creó una clase YamlFileLoader local, que era básicamente un callados Symfony2 uno:

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

Entonces puse al día DIC Extensión para mi paquete (por lo general es generada automáticamente si se deja Symfony2 crear la arquitectura paquete completo, si no sólo crear un archivo en el directorio de DependencyInjection/<Vendor&BundleName>Extension.php paquete con Follo contenido de ala:

<?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 
    } 
} 

Y ahora se puede acceder a/config yaml pasar su parámetro de servicio tan simple (es decir, %param_name% para services.yml)

+0

Gracias por la respuesta en profundidad, muy útil. –

3

Puede utilizar el parámetro kernel.root_dir:

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

He resuelto de esta manera:

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

clase de servicio

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