tomphp / config-service-provider
Configure your application and the Dependency Injection Container (DIC) via config arrays or config files.
Installs: 9 107
Dependents: 0
Suggesters: 0
Security: 0
Stars: 19
Watchers: 2
Forks: 3
Open Issues: 3
Requires
- php: ^5.6|^7.0
- beberlei/assert: ^2.6
- tomphp/exception-constructor-tools: ^1.0.0
Requires (Dev)
- friendsofphp/php-cs-fixer: 2.0.0-alpha
- league/container: ^2.0.2
- phpunit/phpunit: ^5.5.4
- pimple/pimple: ^3.0.0
- squizlabs/php_codesniffer: *
- symfony/yaml: ^3.1.4
Suggests
- league/container: Small but powerful dependency injection container http://container.thephpleague.com
- pimple/pimple: A small PHP 5.3 dependency injection container http://pimple.sensiolabs.org
- symfony/yaml: For reading configuration from YAML files
README
This package enables you to configure your application and the Dependency Injection Container (DIC) via config arrays or files. Currently, supported containers are:
Installation
Installation can be done easily using composer:
$ composer require tomphp/container-configurator
Example Usage
<?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');
Reading Files From Disk
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.
Merging
The reader matches files in the order they are specified. As files are read their config is merged in; overwriting any matching keys.
Supported Formats
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.
Application Configuration
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
).
Example
$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" */
Accessing A Whole Sub-Array
Whole sub-arrays are also made available for cases where you want them instead of individual values.
Example
$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" * } */
Configuring Services
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'));
Service Aliases
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', ], ], ], ], ];
Service Factories
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.
Example Config
$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', ], ], ], ], ];
Example Service Factory
<?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; } }
Injecting The Container
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()], ], ], ], ];
Configuring Inflectors
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'] ], ], ], ];
Extra Settings
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 |
Advanced Customisation
Adding A Custom File Reader
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);
Adding A Custom Container Adapter
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);