3.1.8. Container Builder and Config Classes

The ContainerBuilder also builds fully-configured Container objects using ContainerConfig classes. It works using a two-stage configuration system.

The two stages are "define" and "modify". In the "define" stage, the ContainerConfig object defines constructor parameter values, setter method values, services, and so on. The ContainerBuilder then locks the Container so that these definitions cannot be changed, and begins the "modify" stage. In the "modify" stage, we may get() services from the Container and modify them programmatically if needed.

To build a fully-configured Container using the ContainerBuilder, we do something like the following:

use Aura\Di\ContainerBuilder;

$container_builder = new ContainerBuilder();

// use the builder to create and configure a container
// using an array of ContainerConfig classes
$di = $container_builder->newConfiguredInstance([
    'Aura\Cli\_Config\Common',
    'Aura\Router\_Config\Common',
    'Aura\Web\_Config\Common',
]);

Note: As with the newInstance method of the ContainerBuilder, you will have to pass $container_builder::AUTO_RESOLVE to newConfiguredInstance (as the second parameter) if you want to enable auto-resolution.

A configuration class looks like the following:

namespace Vendor\Package;

use Aura\Di\Container;
use Aura\Di\ContainerConfig;

class Config extends ContainerConfig
{
    public function define(Container $di)
    {
        $di->set('log_service', $di->lazyNew('Logger'));
        $di->params['Logger']['dir'] = '/path/to/logs';
    }

    public function modify(Container $di)
    {
        $log = $di->get('log_service');
        $log->debug('Finished config.');
    }
}

Here are some example ContainerConfig classes from earlier Aura packages:

Alternatively, if you already have a ContainerConfig object created, you can pass it directly to the ContainerBuilder instead of a string class name:

$routerConfig = new Aura\Router\_Config\Common();

// use the builder to create and configure a container
// using an array of ContainerConfig classes
$di = $container_builder->newConfiguredInstance([
    'Aura\Cli\_Config\Common',
    $routerConfig,
    'Aura\Web\_Config\Common',
]);

If you have a package which combines a number of disparate components that each provide a ContainerConfig you could bundle them together using the ConfigCollection class. This class takes an array of ContainerConfigs or ContainerConfig class names and implements ContainerConfigInterface itself.


namespace My\App;

use Aura\Di\ConfigCollection;

use My\Domain;
use My\WebInterface;
use My\DataSource;

class Config extends ConfigCollection
{
    public function __construct()
    {
        parent::__construct(
            [
                Domain\Config::class,
                WebInterface\Config::class,
                DataSource\Config::class,
            ]
        );
    }
}

You can then use the Collection and it will instantiate (if necessary) and call the define and modify methods of each of the other ContainerConfigs.

$di = $container_builder->newConfiguredInstance([\My\App\Config::class])