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);