This package enables you to configure your application and the Dependency Injection Container (DIC) via config arrays or files. Currently, supported containers are:
Installation can be done easily using composer:
$ composer require tomphp/container-configurator
<?php
use League\Container\Container; // or Pimple\Container
use TomPHP\ContainerConfigurator\Configurator;
$config = [
'db' => [
'name' => 'example_db',
'username' => 'dbuser',
'password' => 'dbpass',
],
'di' => [
'services' => [
'database_connection' => [
'class' => DatabaseConnection::class,
'arguments' => [
'config.db.name',
'config.db.username',
'config.db.password',
],
],
],
],
];
$container = new Container();
Configurator::apply()->configFromArray($config)->to($container);
$db = $container->get('database_connection');Instead of providing the config as an array, you can also provide a list of
file pattern matches to the fromFiles function.
Configurator::apply()
->configFromFile('config_dir/config.global.php')
->configFromFiles('json_dir/*.json')
->configFromFiles('config_dir/*.local.php')
->to($container);configFromFile(string $filename) reads config in from a single file.
configFromFiles(string $pattern) reads config from multiple files using
globbing patterns.
The reader matches files in the order they are specified. As files are read their config is merged in; overwriting any matching keys.
Currently .php and .json files are supported out of the box. PHP
config files must return a PHP array.
.yaml and .yml files can be read when the package symfony/yaml is
available. Run
composer require symfony/yaml
to install it.
All values in the config array are made accessible via the DIC with the keys
separated by a separator (default: .) and prefixed with constant string (default:
config).
$config = [
'db' => [
'name' => 'example_db',
'username' => 'dbuser',
'password' => 'dbpass',
],
];
$container = new Container();
Configurator::apply()->configFromArray($config)->to($container);
var_dump($container->get('config.db.name'));
/*
* OUTPUT:
* string(10) "example_db"
*/Whole sub-arrays are also made available for cases where you want them instead of individual values.
$config = [
'db' => [
'name' => 'example_db',
'username' => 'dbuser',
'password' => 'dbpass',
],
];
$container = new Container();
Configurator::apply()->configFromArray($config)->to($container);
var_dump($container->get('config.db'));
/*
* OUTPUT:
* array(3) {
* ["name"]=>
* string(10) "example_db"
* ["username"]=>
* string(6) "dbuser"
* ["password"]=>
* string(6) "dbpass"
* }
*/Another feature is the ability to add services to your container via the
config. By default, this is done by adding a services key under a di key in
the config in the following format:
$config = [
'di' => [
'services' => [
'logger' => [
'class' => Logger::class,
'singleton' => true,
'arguments' => [
StdoutLogger::class,
],
'methods' => [
'setLogLevel' => [ 'info' ],
],
],
StdoutLogger::class => [],
],
],
];
$container = new Container();
Configurator::apply()->configFromArray($config)->to($container);
$logger = $container->get('logger'));You can create an alias to another service by using the service keyword
instead of class:
$config = [
'database' => [ /* ... */ ],
'di' => [
'services' => [
DatabaseConnection::class => [
'service' => MySQLDatabaseConnection::class,
],
MySQLDatabaseConnection::class => [
'arguments' => [
'config.database.host',
'config.database.username',
'config.database.password',
'config.database.dbname',
],
],
],
],
];If you require some addition additional logic when creating a service, you can define a Service Factory. A service factory is simply an invokable class which can take a list of arguments and returns the service instance.
Services are added to the container by using the factory key instead of the
class key.
$appConfig = [
'db' => [
'host' => 'localhost',
'database' => 'example_db',
'username' => 'example_user',
'password' => 'example_password',
],
'di' => [
'services' => [
'database' => [
'factory' => MySQLPDOFactory::class,
'singleton' => true,
'arguments' => [
'config.db.host',
'config.db.database',
'config.db.username',
'config.db.password',
],
],
],
],
];<?php
class MySQLPDOFactory
{
public function __invoke($host, $database, $username, $password)
{
$dsn = "mysql:host=$host;dbname=$database";
$pdo = new PDO($dsn, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
}
}In the rare case that you want to inject the container in as a dependency to
one of your services, you can use Configurator::container() as the name
of the injected dependency. This will only work in PHP config files, it's not
available with YAML or JSON.
$config = [
'di' => [
'services' => [
ContainerAwareService::class => [
'arguments' => [Configurator::container()],
],
],
],
];It is also possible to set up
Inflectors by adding an
inflectors key to the di section of the config.
$appConfig = [
'di' => [
'inflectors' => [
LoggerAwareInterface::class => [
'setLogger' => ['Some\Logger']
],
],
],
];The behaviour of the Configurator can be adjusted by using the
withSetting(string $name, $value method:
Configurator::apply()
->configFromFiles('*.cfg.php'),
->withSetting(Configurator::SETTING_PREFIX, 'settings')
->withSetting(Configurator::SETTING_SEPARATOR, '/')
->to($container);Available settings are:
| Name | Description | Default |
|---|---|---|
| SETTING_PREFIX | Sets prefix name for config value keys. | config |
| SETTING_SEPARATOR | Sets the separator for config key. | . |
| SETTING_SERVICES_KEY | Where the config for the services is. | di.services |
| SETTING_INFLECTORS_KEY | Where the config for the inflectors is. | di.inflectors |
| SETTING_DEFAULT_SINGLETON_SERVICES | Sets whether services are singleton by default. | false |
You can create your own custom file reader by implementing the
TomPHP\ContainerConfigurator\FileReader\FileReader interface. Once you have
created it, you can use the
withFileReader(string $extension, string $readerClassName) method to enable
the it.
IMPORTANT: withFileReader() must be called before calling
configFromFile() or configFromFiles()!
Configurator::apply()
->withFileReader('.xml', MyCustomXMLFileReader::class)
->configFromFile('config.xml'),
->to($container);You can create your own container adapter so that you can configure other
containers. This is done by implementing the
TomPHP\ContainerConfigurator\FileReader\ContainerAdapter interface. Once you
have created your adapter, you can use the
withContainerAdapter(string $containerName, string $adapterName) method to
enable the it:
Configurator::apply()
->withContainerAdapter(MyContainer::class, MyContainerAdapter::class)
->configFromArray($appConfig),
->to($container);