Создание конфигураций в 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.yml я добавил следующее:

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

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

 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.

Шаг первый. Создайте свой файл конфигурации.

Создайте файл с именем config.yml в src/<bundle name>/Resources/config/

 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 

Шаг второй – импорт вашего файла конфигурации

Перейдите в app/config/config.yml и добавьте:

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

Шаг третий. Создайте класс конфигурации.

Создайте файл с именем Configuration.php в src/<bundle name>/DependencyInjection/

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

Шаг 4 – Создание расширения

И последнее, но не менее важное: вам нужно создать расширение. Создайте файл <yourbundle>Extension.php в src/<your bundle>/DependencyInjection/

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

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

Если кто-либо из вас знает какой-либо способ сделать это проще, не стесняйтесь публиковать ответ или комментарий.

Несколько уведомлений:

В config.yml вы пытаетесь определить import as array. Похоже, что symfony не позволяет создавать элементы массива в корне вашей конфигурации, что означает, что вам нужно вложить массивы глубже по дереву. Таким образом, вы не можете:

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

Я не уверен, что это именно то, что вы пытались сделать, но вы определили import как массив, что заставляет меня предположить это.

С другой стороны, вы можете:

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

Относительно никакого расширения, способного загрузить ошибку конфигурации : Убедитесь, что ваш файл расширения соответствует именованию convetions.It следует называть CompanyHappyExtension.php с классом CompanyHappyExtension определенным внутри.

Я создал образец пакета CompanyHappyBundle, который отлично работает на Symofny 3 (возможно, работает и на S2). Не стесняйтесь клонировать / скачать его 🙂

Файл services.yml является дополнительным бонусом, так как вам это, скорее всего, понадобится.

ЦСИ / Компания / Bundle / HappyBundle / CompanyHappyBundle.php:

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

ЦСИ / Компания / Bundle / HappyBundle / внедрение зависимости / 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 } } 

ЦСИ / Компания / Bundle / HappyBundle / внедрение зависимости / 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; } } 

ЦСИ / Компания / Bundle / HappyBundle / Ресурсы / конфигурации / config.yml

 company_happy: imports: import: path: /tmp 

ЦСИ / Компания / Bundle / HappyBundle / Ресурсы / конфигурации / services.yml

 # Define your services here services: 

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