Symfony's friendly Configuration Bundle


How to Create Friendly Configuration for a Bundle

Posted by Pedro Resende on 22/02/2015 11:42

This passed few days I've spend some time working on a new bundle, and decided that I wanted to create a specific configuration. Since it's a process that doesn't have much information on, I've decided to write a few lines, can also be considered notes, about how to do it.

I've started to investigate on Symfony's online documentation, however some steps are missing.

To beging I'll assum that you already have a bundle create, let's consider that your bundles's name is TestBundle.

Start by opening the DependencyInjection folder inside your bundle.

You'll notice that there are two files inside:

  • Configuration.php, and
  • TestExtension.php

Start by opening Configuration.php file, inside you should have something like:

<?php

namespace TestBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
 * This is the class that validates and merges configuration from your app/config files
 *
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
 */
class Configuration implements ConfigurationInterface
{
    /**
     * {@inheritdoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('pedro_resende_test');

        return $treeBuilder;
    }
}

Let's start by adding

        $rootNode
            ->children()
                ->arrayNode('twitter')
                    ->children()
                        ->integerNode('client_id')->defaultValue('123')->end()
                        ->scalarNode('client_secret')->defaultValue('123')->end()
                    ->end()
                ->end() // twitter
            ->end()
        ;

 It should look like

<?php

namespace TestBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
 * This is the class that validates and merges configuration from your app/config files
 *
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
 */
class Configuration implements ConfigurationInterface
{
    /**
     * {@inheritdoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('test');

        $rootNode
            ->children()
                ->arrayNode('twitter')
                    ->children()
                        ->integerNode('client_id')->defaultValue('123')->end()
                        ->scalarNode('client_secret')->defaultValue('123')->end()
                    ->end()
                ->end() // twitter
            ->end()
        ;

        return $treeBuilder;
    }
}

Open you terminal window and type

$ php app/console TestBundle

you should get something like 

# Current configuration for "TestBundle"
test:
    twitter:
        client_id: 123
        client_secret: $ecret

This is your bundle default configuration.

Now, it's time to load your configurations, to do that you'll need to open TestExtension.php

Inside, you'll see 

<?php

namespace PedroResende\TestBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

/**
 * 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 PedroResendeTestExtension extends Extension
{
    /**
     * {@inheritdoc}
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader->load('services.yml');
    }
Add, right after $config = $this->...
        foreach ($config as $key => $value) {
            $container->setParameter('test.'.$key, $value);
        }

This will convert your bundle configuration to parameters, in order to get them you'll only need to use

To override the default configurations, add to app/config/config.yml

test:
    twitter:
        client_id: 123
        client_secret: $ecret

And that's it, it's not hard but there's no documentation refering the step of fetching your configuration and passing the values into parameters.