使用Symfony创建配置


Creating configurations in Symfony

几个小时以来,我一直在努力做你能想象到的最简单的事情,但它就是行不通。我已经阅读了大量的stackoverflow问题,阅读了关于配置文件的完整Symfony文档,随着我阅读的每一篇文章或其他信息,它变得越来越难以理解。

详细信息

我创建了自己的Bundle。我们叫它HappyBundle。我已经把这个包放在我公司的文件夹里了。所以我得到了CompanyHappyBundle

我想为这个包做一个专门的配置文件,因为我想让它可重用。

当我测试时,我创建了以下内容:

# src/Company/HappyBundle/Resources/config/config.yml
company_happy:
    import:
        path: /tmp

现在,我想要的是能够在我的控制器中使用这个值。我只是不知道该怎么做。它给了我以下错误:

[Symfony'Component'Config'Exception'FileLoaderLoadException]
There is no extension able to load the configuration for "company_happy" (in /home/user/symfony/src/Company/HappyBundle/Resources/config/config.yml).
Looked for namespace "company_happy", found "framework", "security", "twig", "monolog", "swiftmailer", "assetic", "doctrine", "sensio_framework_extra", "debug", "web_profiler", "sensio_distribution" in /home/user/symfony/src/Company/HappyBundle/Resources/config/config.yml (which is being imported from "/home/user/symfony/app/config/config.yml").

更新

在config. conf文件中。我添加了以下内容:

#app/config/config.yml
imports:
    - { resource: "@CompanyHappyBundle/Resources/config/config.yml" }

我还做了一个Configuration类,因为我在某处读到这是必需的。我真的认为这是大量的工作,使仅仅一个配置文件。

namespace Company'HappyBundle'DependencyInjection;
use Symfony'Component'Config'Definition'Builder'TreeBuilder;
use Symfony'Component'Config'Definition'ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
    /**
     * {@inheritDoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('company_happy');
        $rootNode
            ->children()
            ->arrayNode('import')
                ->children()
                    ->scalarNode('attachments_path')->defaultValue('/tmp')->end()
                    ->scalarNode('method')->defaultValue('ALL')->end()
                    ->booleanNode('move_mail')->defaultValue(true)->end()
                    ->booleanNode('mark_read')->defaultValue(true)->end()
                ->end()
            ->end()
        ;
        return $treeBuilder;
    }
}

我实际上在寻找的是得到这个工作所需的步骤和要求。symfony的问题是它有一百万种方法来做到这一点。文档不只是给出一个工作流程。

有人能帮我一下吗?

我已经解决了我自己的问题,但不是没有麻烦。我对Symfony的配置系统一点也不满意。

步骤1 -创建配置文件

src/<bundle name>/Resources/config/

中创建名为config.yml的文件
yourbundle:
    param_one: value_one
    param_two: value_two
    param_three: value_three
    param_four: value_four
    param_five:
        subparam_one: subvalue_one
        subparam_two: subvalue_two
        subparam_three: subvalue_three
        subparam_four: subvalue_four

步骤2 -导入配置文件

转到app/config/config.yml并添加:

#app/config/config.yml
imports:
    - { resource: "@YourBundle/Resources/config/config.yml" }

步骤三—创建配置类

src/<bundle name>/DependencyInjection/中创建名为Configuration.php的文件

namespace YourBundle'DependencyInjection;
use Symfony'Component'Config'Definition'Builder'TreeBuilder;
use Symfony'Component'Config'Definition'ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
    /**
     * {@inheritDoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('yourbundle');
        $rootNode
            ->children()
                ->scalarNode('param_one')->defaultValue('value_one')->end()
                ->scalarNode('param_two')->defaultValue('value_two')->end()
                ->scalarNode('param_three')->defaultValue('value_three')->end()
                ->scalarNode('param_four')->defaultValue('value_four')->end()
                ->arrayNode('param_five')
                    ->children()
                        ->scalarNode('subparam_one')->defaultValue('subvalue_one')->end()
                        ->scalarNode('subparam_two')->defaultValue('subvalue_two')->end()
                        ->scalarNode('subparam_three')->defaultValue('subvalue_three')->end()
                        ->scalarNode('subparam_four')->defaultValue('subvalue_four')->end()
                    ->end()
            ->end()
        ;
        return $treeBuilder;
    }
}

步骤四—创建扩展

最后但并非最不重要的是,您必须创建一个扩展。在src/<your bundle>/DependencyInjection/

中创建文件<yourbundle>Extension.php
namespace YourBundle'DependencyInjection;
use Symfony'Component'Config'FileLocator;
use Symfony'Component'DependencyInjection'ContainerBuilder;
use Symfony'Component'DependencyInjection'Loader;
use Symfony'Component'HttpKernel'DependencyInjection'Extension;
class YourbundleExtension extends Extension
{
    /**
     * @var ContainerBuilder
     */
    protected $container;
    /**
     * {@inheritDoc}
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $this->container = $container;
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);
        foreach ($config as $key => $value) {
            $this->parseNode('yourbundle.'.$key, $value);
        }
        $container->setParameter('yourbundle', $config);
    }
    /**
     * @param string $name
     * @param mixed  $value
     *
     * @throws 'Exception
     */
    protected function parseNode($name, $value)
    {
        if (is_string($value)) {
            $this->set($name, $value);
            return;
        }
        if (is_integer($value)) {
            $this->set($name, $value);
            return;
        }
        if (is_array($value)) {
            foreach ($value as $newKey => $newValue) {
                $this->parseNode($name.'.'.$newKey, $newValue);
            }
            return;
        }
        if (is_bool($value)) {
            $this->set($name, $value);
            return;
        }
        throw new 'Exception(gettype($value).' not supported');
    }
    /**
     * @param string $key
     * @param mixed  $value
     */
    protected function set($key, $value)
    {
        $this->container->setParameter($key, $value);
    }
}

所有这些步骤都是为了能够调用特定于你的bundle的配置参数。

如果你们中有人知道任何更容易做到这一点的方法,请随时发表答案或评论。

注意事项:

配置。如果您正在尝试将import定义为数组。似乎symfony不允许在配置的根目录中创建数组元素,这意味着您必须在树的更深处嵌套数组。所以你不能这样做:

company_happy:
    import:
        path: /tmp
    another_import:
        ...

我不确定这正是你想要做的,但是你定义了import作为数组,这让我假设是这样的。

另一方面,你可以这样做:

company_happy:
    imports:
        import:
            path: /tmp
        another_import:
            ...

关于没有扩展名能够加载配置错误:确保您的扩展名文件遵循命名约定。它应该叫做CompanyHappyExtension.php,里面定义了CompanyHappyExtension类。

我已经创建了一个样本CompanyHappyBundle bundle,它在symfony 3上工作得很好(可能也适用于S2)。请随意克隆/下载:)

服务。Yml文件是一个额外的好处,因为您很可能无论如何都需要它。

src/公司/包/HappyBundle/CompanyHappyBundle.php:

<?php
namespace Company'Bundle'HappyBundle;
use Symfony'Component'HttpKernel'Bundle'Bundle;
class CompanyHappyBundle extends Bundle
{
}

src/公司/包/HappyBundle/DependencyInjection CompanyHappyExtension.php

<?php
namespace Company'Bundle'HappyBundle'DependencyInjection;
use Symfony'Component'DependencyInjection'ContainerBuilder;
use Symfony'Component'Config'FileLocator;
use Symfony'Component'HttpKernel'DependencyInjection'Extension;
use Symfony'Component'DependencyInjection'Loader;
use Symfony'Component'DependencyInjection'Extension'ExtensionInterface;

class CompanyHappyExtension extends Extension implements ExtensionInterface
{

    public function load(array $configs, ContainerBuilder $container)
    {
        $loader = new Loader'YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader->load('services.yml');
        $configuration = new Configuration();
        $options = $this->processConfiguration($configuration, $configs);
        // Do something with your options here
    }

}

src/公司/包/HappyBundle/DependencyInjection Configuration.php

<?
namespace Company'Bundle'HappyBundle'DependencyInjection;
use Symfony'Component'Config'Definition'Builder'TreeBuilder;
use Symfony'Component'Config'Definition'ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('company_happy');
        $rootNode
            ->children()
                ->arrayNode('imports')
                    ->prototype('array')
                    ->children()
                        ->scalarNode('path')->defaultValue('/tmp')->end()
                        ->scalarNode('method')->defaultValue('ALL')->end()
                        ->booleanNode('move_mail')->defaultValue(true)->end()
                        ->booleanNode('mark_read')->defaultValue(true)->end()
                    ->end()
                ->end()
            ->end()
        ;
        return $treeBuilder;
    }
}

src/公司/包/HappyBundle/资源/config/config.yml

company_happy:
    imports:
        import:
            path: /tmp

src/公司/包/HappyBundle/资源/config/services.yml

# Define your services here
services:

你差不多完成了,你只需要配置你的Bundle来使用你的配置参数,看看这个答案