David Patterson
David Patterson

Reputation: 1920

How do I implement Configuration and AppExtension classes for the app in Symfony 4?

This is for Symfony 4.

I need to implement application (not bundle), configuration parameters using DependencyInjection\Configuration and DependencyInjection\AppExtension.

I created both classes as I would for a bundle. The namespace for each is App\DependencyInjection.

The file and class names are Configuration and AppExtension, respectively and are located in src/DependencyInjection/.

The Configuration currently just defines two scalar nodes for simplicity.

// src/DependencyInjection/Configuration.php

namespace App\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( 'app' );
    $rootNode
      ->addDefaultsIfNotSet()
      ->children()
        ->scalarNode( 'a1' )
          ->defaultValue( 'I am the default value for a1' )
        ->end()
        ->scalarNode( 'a2' )
          ->defaultValue( 'I am the default value for a2' )
        ->end()
      ->end();
    return $treeBuilder;
  }    
} 

The AppExtension class implements two methods: __construct() and load().
The __construct() method simply echos its method name.
The load() method currently does a die( __METHOD__ ); just to ensure that I know if it's called. It isn't.

// src/DependencyInjection/AppExtension.php

namespace App\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;

class AppExtension extends Extension
{
  public function __construct()
  {
    echo __METHOD__ . "()\n";
  }

  public function load( array $configs, ContainerBuilder $container )
  {
    die( __METHOD__ );
  }
}

I also created a config file:

# config/app.yml
app:
  a1: 'A one'
  a2: 'A two'

The answer to this question indicates that I need to include a call to $container->registerExtension() in the configureContainer() method of my src/kernel.php file so I added that.

protected function configureContainer( ContainerBuilder $container, LoaderInterface $loader )
{
  $container->registerExtension( new AppExtension() );
  ...
}

When I run the console cache:clear command, the constructor for AppExtension is called, but the load() method never is.

Running the console debug:config app command results in this error:

No extensions with configuration available for "app".

What am I missing?
TIA

Upvotes: 4

Views: 1750

Answers (2)

Mr.B
Mr.B

Reputation: 21

In the initial post there was just one line missing to get it work without creating an extra bundle:

src/DependencyInjection .
-- AppExtension .
-- AppConfiguration

In src/Kernel.php:

protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
{
    //...

    $container->registerExtension(new AppExtension());
    $container->loadFromExtension('app'); //this was missing in initial question

    //...
}

Upvotes: 2

David Patterson
David Patterson

Reputation: 1920

So. I have a solution.
It takes three things beyond the normal Configuration and AppExtension classes in src/DependencyInjection/

Implement an empty App\AppBundle class that extends Bundle and place it in src/

// src/AppBundle.php
namespace App;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class AppBundle extends Bundle {}

Add an entry for the bundle to the array returned by config/bundles.php

<?php
// config/bundles.php
return [
    ...
    App\AppBundle::class => ['all' => true],
]

Place your configuration parameters in config/packages/app.yaml

# config/packages/app.yaml
app:
  a1: 'A1 from app.yaml'
  a2: 'A2 from app.yaml'

  array_one:
    a:  { attr1: 'attribute one', attr2: 'two' }
    b:  { attr1: 'attribute one', attr2: 'two' }

This is actually working for me.
By the way, doing it this way, you do not need to register the extension in Kernel.php.

Upvotes: 1

Related Questions