Configuring components

The application and its components are configured using a collection of files called configuration fragments. These fragments are used to synthesize the configuration of one or more components. When the same fragments are used to synthesize different configurations, these configurations are qualified as derived. Fragments are synthesized using callback functions called synthesizers. What's great about synthesized configurations is that they are tailored to exactly for the need of their components, and that they can be cached cancelling the cost of the synthesis.

Configuration fragments

A configuration fragment is a PHP file returning an array. Multiple fragments are used to synthesize a configuration, or derived configuration. They are usually located in config directories and are usually named after the config they are used to synthesize.

The following code is an example of a app config fragment, which is used to configure the core of the application:

<?php

namespace ICanBoogie;

return [

    AppConfig::CACHE_CATALOGS => false,
    AppConfig::CACHE_CONFIGS => false,
    AppConfig::CACHE_MODULES => false,

    AppConfig::STORAGE_FOR_CONFIGS => Hooks::class . '::create_storage_for_configs',
    AppConfig::STORAGE_FOR_VARS => Hooks::class . '::create_storage_for_vars',

    AppConfig::ERROR_HANDLER => Debug::class. '::error_handler',
    AppConfig::EXCEPTION_HANDLER => Debug::class. '::exception_handler',

    AppConfig::SESSION => [

        SessionOptions::OPTION_NAME => 'ICanBoogie'

    ]

];

Synthesizing a configuration

The synthesize() method of the Config instance is used to synthesize a configuration.

The following example demonstrates how a closure can be used to synthesize multiple fragments:

<?php

use function ICanBoogie\array_merge_recursive;

/* @var $config \ICanBoogie\Config */

$app_config = $config->synthesize('app', function(array $fragments) {

    return array_merge_recursive(...$fragments);

});

Magic constructors

The synthesize() methods supports the magic constructors merge and recursive merge which respectively use the array_merge() and ICanBoogie\array_merge_recursive() functions. Thus, the following code examples are equivalent:

<?php

use function ICanBoogie\array_merge_recursive;

/* @var $config \ICanBoogie\Config */

$app_config = $config->synthesize('app', function(array $fragments) {

    return array_merge_recursive(...$fragments);

});
<?php

/* @var $config \ICanBoogie\Config */

$app_config = $config->synthesize('app', 'merge recursive');

Configuration synthesizers

Synthesizers can be defined for each configuration, they are used when the config collection is used as an array:

<?php

use ICanBoogie\Config;

/* @var array $paths */

$synthesizers = [ 'app' => 'merge recursive' ];
$config = new Config($paths, $synthesizers);
$app_config = $config['app'];

Derived configurations

It is possible to synthesize a configuration from the same fragments as another configuration, such a configuration is qualified as derived.

For instance, connections, models, and facets, for the icanboogie/bind-activerecord package are defined in activerecord fragments, the synthesizer for the activerecord_connections configuration filters the fragments data to extract what is relevant.

The following example demonstrates how to obtain the activerecord_connections configuration using the synthesize() method:

<?php

use ICanBoogie\Binding\ActiveRecord\Hooks;

/* @var $config \ICanBoogie\Config */

$events_config = $config->synthesize(
    'activerecord_connections', 
    Hooks::class . '::synthesize_connections_config',
    'activerecord'
);

The following example demonstrates how to define the synthesizer of the activerecord_connections configuration:

<?php

use ICanBoogie\Binding\ActiveRecord\Hooks;
use ICanBoogie\Config;

/* @var $paths array */

$config = new Config($paths, [

    'activerecord_connections' => [ 

        Hooks::class . '::synthesize_connections_config', 'activerecord' 

    ]

]);

Declaring synthesizers

Configuration synthesizers are declared using the extra section of the composer.json file.

The following example demonstrates how the synthesizers can be declared for an activerecord_connections and an activerecord_models configuration. Notice how the # sign is used to separate the callable and the configuration fragment name:

{
    "extra": {
        "icanboogie": {
            "config-constructor": {
                "activerecord_connections": "ICanBoogie\\Binding\\ActiveRecord\\Hooks::synthesize_connections_config#activerecord",
                "activerecord_models": "ICanBoogie\\Binding\\ActiveRecord\\Hooks::synthesize_models_config#activerecord"
            }
        }
    }
}

Caching synthesized configurations

Caching synthesized configurations removes the cost of synthesizing configurations by reusing the result of a previous synthesis. To enable caching, you just need to provide an instance implementing Storage.

<?php

use ICanBoogie\Config;
use ICanBoogie\Storage\Storage;

/* @var $paths array */
/* @var $synthesizers array */
/* @var Storage $cache */

$config = new Config($paths, $synthesizers, $cache);

Events

Cache must be cleared

The clear_cache event of class ClearCacheEvent is fired when the various caches of the application must be cleared. Event hooks may use this event to clear their own cache. For instance, ICanBoogie clears its configurations cache when this event is fired.