This is a very lean Config component to help you write reusable code. It only offers basic functionality and is meant to be used in libraries and small projects. If you need a Config component for more complex projects, you should take a look at the Symfony Config Component.
- Installation
- Basic Usage
- Config Formats
- Advanced Usage
- Contributing
The best way to use this component is through Composer:
composer require brightnucleus/config
A class that wants to be configurable should accept a ConfigInterface
in its constructor, so that the Config can be injected. The surrounding code then should inject an instance of an object (for example the generic Config
that is provided with this component). This way, the class that accepts the Config can be written in a 100% reusable way, while all project-specific stuff will be injected through the Config.
To check whether the configuration has a certain key, you can use the ConfigInterface::hasKey($key)
method, or, if you are using the ConfigTrait
in your class, you can use the convenience method $this->hasConfigKey($key)
.
To get the configuration value of a certain key, you can use the ConfigInterface::getKey($key)
method, or, if you are using the ConfigTrait
in your class, you can use the convenience method $this->getConfigKey($key)
.
If you use closures in your Config file, you can also use the convenience function $this->getConfigCallable( $key, array $args )
provided by the ConfigTrait
, which will immediately execute the closure by passing it the provided arguments, and return the resultant value instead.
If your keys are nested, you can provide multiple levels of keys in one request. So, whenever you need to provide a key and want to use a nested one, you can either provide a comma-separated list of keys ( $this->getConfigKey( 'level1', 'level2', 'level3' );
) or a string that contains the list of keys separated by a delimiter ( $this->getConfigKey( 'level1/level2/level3' );
).
You can freely mix-and-match these two approaches as you like.
The default delimiters are: /
, \
and .
. You can choose different delimiters by passing an array of delimiters as a fourth argument to the Config
s constructor.
The snippet below shows the basic structure of a config file.
<?php namespace BrightNucleus\Example;
/*
* Example class main settings.
*/
$example = [
'test_key' => 'test_value',
];
return [
'BrightNucleus' => [
'Example' => $example,
],
];
Here is an example setup of how you could feed this configuration into a plugin.
<?php namespace BrightNucleus\Example;
use BrightNucleus\Config\ConfigInterface;
use BrightNucleus\Config\ConfigTrait;
use BrightNucleus\Exception\RuntimeException;
class Example {
use ConfigTrait;
/**
* Instantiate an Example object.
*
* @param ConfigInterface $config Config to parametrize the object.
* @throws RuntimeException If the Config could not be parsed correctly.
*/
public function __construct( ConfigInterface $config ) {
$this->processConfig( $config );
}
/**
* Do something.
*/
public function run() {
$key = 'test_key';
return sprintf(
_( 'The value of the config key "$1%s" is "$2%s".'),
$key,
$this->getConfigKey( $key )
);
}
}
You can combine all of your configurations into 1 single file and only pass "Sub-Configurations" to the individual components using the getSubConfig()
method. This way, you can avoid an additional file access and an additional validation pass for each component.
To create a new instance of a ConfigInterface
, you should use the ConfigFactory
. The basic method ConfigFactory::create()
can take either an array of values, or one or more file names (with absolute paths) as strings.
If you provide a comma-separated list of file names, they are processed consecutively until the first one could be loaded successfully.
There's a convenience function ConfigFactory::createSubConfig()
to immediately fetch a sub-config from a loaded config file. This allows you to quickly bypass the vendor/package prefixes and only pass in the relevant data into the new object.
Here's how you can pass the configuration file into the class:
<?php namespace BrightNucleus\Example;
use BrightNucleus\Config\ConfigFactory;
function init() {
$configFile = __DIR__ . '/config/example_settings.php';
$config = ConfigFactory::createSubConfig($configFile, 'BrightNucleus\Example');
$example = new Example( $config );
// Outputs:
// The value of the config key "test_key" is "test_value".
echo $example->run();
}
The ConfigTrait
provides some convenience functionality that lets you write classes that can receive an injected Config, but fall back to a default configuration file if non was injected.
Here's you can code such a class:
<?php namespace BrightNucleus\Example;
use BrightNucleus\Config\ConfigInterface;
use BrightNucleus\Config\ConfigTrait;
use BrightNucleus\Exception\RuntimeException;
class Example {
use ConfigTrait;
/**
* Instantiate an Example object.
*
* For this constructor, the `$config` argument is optional, and the class will
* load a default configuration if none was injected.
*
* @param ConfigInterface|null $config Optional. Config to parametrize the object.
* @throws RuntimeException If the Config could not be parsed correctly.
*/
public function __construct( ConfigInterface $config = null ) {
// We either process the $config that was injected or fetch a default one.
$this->processConfig( $config ?: $this->fetchDefaultConfig() );
}
/**
* Get the default configuration file name.
*
* This is used to override the default location.
*
* @return string Path & filename to the default configuration file.
*/
protected function getDefaultConfigFile() {
return __DIR__ . '/../config/my_default_config.php';
}
}
You can provide a comma-separated list of file names to the ConfigFactory::merge()
method. They are loaded consecutively and merged into one coherent Config. For each duplicate Config key, the value in the later files will override the value in the earlier files.
For our example, we'll define a new Config file called override_settings.php
, that overrides a key that was already set in the default Config file.
<?php namespace BrightNucleus\Example;
/*
* Example class main settings.
*/
$example = [
'test_key' => 'override_value',
];
return [
'BrightNucleus' => [
'Example' => $example,
],
];
<?php namespace BrightNucleus\Example;
use BrightNucleus\Config\ConfigFactory;
function init() {
$configFile = __DIR__ . '/config/example_settings.php';
$overrideFile = __DIR__ . '/config/override_settings.php';
$config = ConfigFactory::merge($configFile, $overrideFile);
$example = new Example( $config );
// Outputs:
// Both files will be loaded, but values from the second override the first.
// The value of the config key "test_key" is "override_value".
echo $example->run();
}
The Bright Nucleus Config component can be extended to load a multitude of different file formats. The base package includes a very minimal PHPLoader
class. It can load basic PHP files that just return
an array.
Additional packages that add other formats like JSON or YAML are planned and will be released soon.
Custom loaders are lazily instantiated only when needed.
TODO
TODO
TODO
All feedback / bug reports / pull requests are welcome.
This code is released under the MIT license.
For the full copyright and license information, please view the LICENSE
file distributed with this source code.