For a few hours now I\'ve been struggling to do the most simple thing you can imagine and it just won\'t work. I\'ve read tons of stackoverflow questions, read the complete
you're almost done, you just need to configure your Bundle to use your config parameters, take a look at this answer.
A few notices:
In config.yml, you are trying to define import
as array. It seems like symfony doesn't allow creating array elements in the root of your config, meaning that you have to nest arrays deeper down the tree. So you can not do:
company_happy:
import:
path: /tmp
another_import:
...
I am not sure this is exactly what you were trying to do, but you defined import
as array, which makes me assume so.
On the other hand, you can do:
company_happy:
imports:
import:
path: /tmp
another_import:
...
Regarding no extension able to load the configuration error: Make sure your extension file is following naming convetions.It should be called CompanyHappyExtension.php
with CompanyHappyExtension
class defined inside.
I have created a sample CompanyHappyBundle bundle which is working fine on Symofny 3 (probably works on S2 as well). Feel free to clone/download it :)
The services.yml file is an added bonus, as you will most likely need it anyway.
src/Company/Bundle/HappyBundle/CompanyHappyBundle.php:
<?php
namespace Company\Bundle\HappyBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class CompanyHappyBundle extends Bundle
{
}
src/Company/Bundle/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/Company/Bundle/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/Company/Bundle/HappyBundle/Resources/config/config.yml
company_happy:
imports:
import:
path: /tmp
src/Company/Bundle/HappyBundle/Resources/config/services.yml
# Define your services here
services:
I have solved my own issue but not without trouble. I'm not at all pleased with Symfony's configuration system.
Create a file named config.yml
in 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
Go to app/config/config.yml
and add:
#app/config/config.yml
imports:
- { resource: "@YourBundle/Resources/config/config.yml" }
Create a file named Configuration.php
in 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;
}
}
Last but not least, you'll have to create an extension. Create a file <yourbundle>Extension.php
in 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);
}
}
All these steps are required just to be able to call a configuration parameter specific for your bundle.
If any of you know any way to do this easier, feel free to post an answer or comment.