В течение нескольких часов я изо всех сил старался сделать самую простую вещь, которую вы можете себе представить, и она просто не сработает. Я прочитал множество вопросов о 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; } }
И последнее, но не менее важное: вам нужно создать расширение. Создайте файл <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 для использования ваших параметров конфигурации, взгляните на этот ответ .