2012-01-10 61 views
5

我想從我的一個服務中的yaml文件中獲取數組,並且我對如何注入要在我的服務中使用的文件有點困惑。陽明海運。如何從Symfony2中的服務中解析yaml文件

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

這可能是完全錯誤的做法,我是否應該做別的事情,請讓我知道!

回答

8

首先,我將解釋爲什麼我實現我的解決方案爲您來決定,如果這種情況下是適合你的。

我需要一種方法來輕鬆地加載自定義.yml文件在我的包中(對於很多捆綁包),所以爲每個文件添加一個單獨的行到app/config.yml對於每個安裝似乎都很麻煩。

此外,我希望大部分配置已經默認加載,所以最終用戶甚至不需要擔心配置大部分時間,特別是不檢查每個配置文件的設置是否正確。

如果這對你來說似乎是一個類似的情況,請繼續閱讀。如果沒有,只需使用Kris解決方案,也是一個不錯的選擇!


回來時,我遇到了一個需要此功能,Symfony2的didnt't提供了一種簡單的方式來實現這一點,所以在這裏我如何解決它:

首先,我創建了一個本地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)

+0

感謝深入的回答,非常有幫助。 – 2012-01-11 10:41:16

3

可以使用kernel.root_dir參數:

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

我解決這樣說:

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