arnapou / appcfg
Library - Application config system.
Requires
- php: ~8.3.0
- arnapou/ensure: ^2.3
Requires (Dev)
- ext-yaml: *
- friendsofphp/php-cs-fixer: ^3.52
- phpstan/extension-installer: ^1.3
- phpstan/phpstan: ^1.10
- phpstan/phpstan-deprecation-rules: ^1.1
- phpstan/phpstan-phpunit: ^1.3
- phpstan/phpstan-strict-rules: ^1.5
- phpunit/php-code-coverage: ^11.0
- phpunit/phpunit: ^11.0
README
Application config system.
Installation
composer require arnapou/appcfg
packagist 👉️ arnapou/appcfg
Introduction
The global purpose of this lib is to manage a configuration for your applications.
The main features are :
- Allows a mechanism of override: hostname > environment > generic.
- Expression parser of the form
%<processor>(<label>:<value>)%
to manage dependency values inside your configuration, with the possibility to add custom processors. - Dump of the compiled configuration into proper php typed objects, 100% compliant with your static analysis tools.
Parser
Look at the Parser class.
Parsed characters:
%
is the enclosure character, double it%%
to escape if you have a conflict like a string containing%something(
, then escape to%%something(
.()
parentheses are used to gather parts of an expression%env(VAR)%
:
colon is used to separate the label from the value%env(VAR:value)%
Examples:
%<processor>(<label>)%
: expression without value%<processor>(<label>:<value>)%
: main expression%<processor>(<label>:<string>%<processor>(<label>)%<string>)%
: nested is allowed in value part
Unlikely cases where you want to escape the %
:
string | where | escaped | explanation |
---|---|---|---|
%% | everywhere | %%%% | %% is the escaped version of % |
%word( | everywhere | %%word( | doubling the % avoids the parser to think it is an expression |
)% | nested value | %(:))%% | we isolate the ) from the % using the expression %(:<default>)% where <default> is the ) |
Note: the parser is lax about the %
if there is no doubt of its usage.
Example writing foo%bar baz
is valid because it is obviously not an expression.
But writing foo%%bar baz
is also valid because this is the same string with the %
escaped.
Bundled processors:
- DefaultProcessor with name
''
: used to manage default values where labels are paths of other values (i.e.parameter.database.name
). - EnvProcessor with name
'env'
: used to retrieve environment variables with an optional default.
The parsed string is a full immutable object structure like below.
Note that if you cast to string an Expression, you will get back the original raw string.
Processor
A Processor is an interface which can compute a value into a result.
If a value cannot be computed due to dependencies not already processed, you need to return a UnprocessableYet object.
Compiler
A Compiler is an interface which can compile an input array into another.
We provide the StaticCompiler implementation which can parse strings and compile in several passes an array.
This compiler does not explicitly manage cyclic loops but has a max passes security.
Dumper
A Dumper is an interface which can render an input array into php code.
We provide the StaticDumper implementation which produce php typed objects for each associative array of your configuration structure.
This code is 100% compliant with your static analysis tools.
Note: the objects rendered can be mutable or immutable (default).
DataSource / Appcfg
A DataSource is an interface which has the responsibility to manage the source of data in order to be used by Appcfg.
Appcfg is a simple concrete class which is basically an orchestra conductor which can do several classic operations with all the previous objects.
Example
Input data
$data = [
'db' => [
'main' => [
'host' => 'localhost',
'port' => 3306,
'name' => 'project_main',
'password' => 'project_password',
],
'data' => [
'host' => '%(db.main.host)%',
'port' => '%(db.main.port)%',
'name' => 'project_data',
'password' => '%(db.main.password)%',
],
],
'db|prod' => [
'main' => [
'password' => '%env(DB_PASSWORD)%',
],
],
];
💡 If the expression is alone like in
db.data.port
, the referenced type is kept when compiled (int
in the above example).
Compile & render
use Arnapou\Appcfg\Compiler\CompileOptions;
use Arnapou\Appcfg\Compiler\StaticCompiler;
use Arnapou\Appcfg\Dumper\DumpOptions;
use Arnapou\Appcfg\Dumper\StaticDumper;
$compiler = new StaticCompiler();
$compiled = $compiler->compile($data, new CompileOptions('prod'));
$dumper = new StaticDumper();
echo $dumper->dump($compiled, new DumpOptions('MyProject\Config'));
Result
Run command : DB_PASSWORD=123456 php example/readme.php
namespace MyProject;
final readonly class ConfigDbMain
{
public function __construct(
public string $host = 'localhost',
public int $port = 3306,
public string $name = 'project_main',
public string $password = '123456',
) {}
}
final readonly class ConfigDbData
{
public function __construct(
public string $host = 'localhost',
public int $port = 3306,
public string $name = 'project_data',
public string $password = '123456',
) {}
}
final readonly class ConfigDb
{
public function __construct(
public ConfigDbMain $main = new ConfigDbMain(),
public ConfigDbData $data = new ConfigDbData(),
) {}
}
final readonly class Config
{
public function __construct(
public ConfigDb $db = new ConfigDb(),
) {}
}
Changelog versions
Start | Tag, Branch | Php |
---|---|---|
01/01/2024 | 1.x, main | 8.3 |