config icon indicating copy to clipboard operation
config copied to clipboard

Support for tokens/parameters?

Open Zyles opened this issue 9 years ago • 7 comments

Did I overlook something or is there support for using tokens with replace like Symfony does in config files.

For example you have a config file:

config.yml:

database:
    host: %hostname%
    user: %username%
    password: %password%

Then you have a file for example parameters.yml

parameters.yml:

database:
    host: example.com
    user: example
    password: password

Then you only need to replace the parameters.yml on each environment and keep one config file complete. Instead of having multiple config files you need to edit if you add or remove values.

Zyles avatar Sep 01 '16 23:09 Zyles

Hi @Zyles, yes, you can do something like this. For example if you have

config.yml

database:
    host: %hostname%
    user: %username%
    password: %password%
api:
    limit: 10

and parameters.yml

database:
    host: example.com
    user: example
    password: password

you can just load them using the multiple files syntax:

$conf = new Config(['config.yml', 'parameters.yml']);

In this example you'll preserve api.limit key and the config will just overwrite all the already defined keys (database.host, database.user and database.password).

DavidePastore avatar Sep 04 '16 11:09 DavidePastore

Yes sure that kind of works. But I also have another use case which is a bit more advanced.

For example two modules from two different developers need access to the same variables. Instead of repeating the same information twice it would be nice if you could reference them inside config files.

Example scenario where two independent modules need access to the database and there is no default setting for that so they both use their own config keys. But the user setting up the config could reference between the files.

Module 1 config:

module1:
    database:
        host: localhost
        user: username
        password: password

Now instead of repeating itself the second module config could reference the first.

Module 2 config:

module2:
    database:
        host: %module1.database.host%
        user: %module1.database.user%
        password: %module1.database.password%

Now most frameworks etc. probably have database connection defined by default. But this could be used for other commonly shared keys.

Zyles avatar Oct 12 '16 07:10 Zyles

@Zyles This has sense. The only problem with this is: how can I handle the case where I have a configuration file with the value of "%module1.database.host%" and I want it as a string?

DavidePastore avatar Oct 12 '16 07:10 DavidePastore

@DavidePastore

Maybe if you enclose it in quotes?

host: "%module1.database.host%"

Zyles avatar Oct 12 '16 18:10 Zyles

SUGGESTION

Sorry guys but is not much better pass the replacements on config costruct?

$config = new Config([
    'default.yml',
    'dev.yml'
],
[
    'db' => [
        'hostname' => 'localhost'
    ]
]);

With dotted array db.hostname you can use in the yml file %db.hostname%.

This make more sense, if you want use yml file instead of simple php array you can parse with yaml the file Yaml::parse('parameters.yml').

nunocodex avatar Oct 12 '16 19:10 nunocodex

@namaless the problem with this solution would be that you can't define paramters inside a configuration file (if this is a requirement at all).

TiMESPLiNTER avatar Nov 05 '16 08:11 TiMESPLiNTER

This should do the trick, I use this often and it's something like how Symfony does it.

$content contains the complete configuration array!

if(isset($content['parameters'])){
    foreach($content['parameters'] as $param){
        foreach($param as $key => $value){
            $parameters[$key] = $value;
        }
    }
}

array_walk_recursive($content, function(&$val, $key) use ($parameters){
    $matches = null;
    preg_match('/\%(.*?)\%/', $val, $matches);
    $param = isset($matches[1]) ? $matches[1] : false;
    if($param){
        if (isset($parameters[$param])) {
           $val = str_replace("%$param%", $parameters[$param], $val);
        }
    }
});

You should place this somewhere you loop through the configuration files. This way all parameters are encapsulated inside a parameters key in the yaml file.

parameters:
    - john:  doe


lastname: %john%  #will result in 'doe'

In case you don't want the parameters to be an array, drop the foreach($content['parameters'] as $param){ and change the foreach($param as $key => $value){ to foreach($content['parameters'] as $key => $value){

If necessary I will create a PR later, but I'm not at my own desktop right now.

leroy0211 avatar Nov 30 '16 13:11 leroy0211