Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load external environment parameters in Symfony 3.2 using env() at runtime return unresolved values

I have a parameters file in an application using symfony 3.2 console, config and YAML component , and i try to set external Parameters from environment variable in the Service Container parameters.

I create container builder.

$container = new ContainerBuilder();

Am using file locator to locate resources :

$container = new ContainerBuilder();

Loader resolver to load resources

LoaderResolver();

And using load method :

$this->load('parameters.yml');

parameters.yml file:

parameters:
  database:
    driver: pdo_mysql
    host: 127.0.0.1
    dbname: dbname
    user: env(VAL1)
    password: env(VAL2)
  Local: us-en

After compiling the container and try to check get values from parameters bag :

$container->getParameterBag()->all()

its return me values like this :

env_VAL1_3ec776edc429c1734ed780a29a0af538 , env_VAL2_3ec776edc429c1734ed780a29a0af538

I think the container can't resolve those values from the environment .

Note : i set the environment variable using :

$ export VAL1='SOME TEXT'

Anyone has an idea why ?

like image 263
SMSM Avatar asked Mar 11 '23 07:03

SMSM


2 Answers

So I've spent some time investigating this 'issue' and here is what I found out...

The only way to get env(VAL1) thingy working is to generate the container to PHP file using PHPDumper and then use the generated container. There is no other way to make it working because it only resolves environment in that file.

In the normal Symfony project there is a generated var/cache/dev/appDevDebugProjectContainer.php file. There is method getDynamicParameter which looks like this

 private function getDynamicParameter($name)
    {
        switch ($name) {
            case 'kernel.root_dir': $value = ($this->targetDirs[3].'/app'); break;
            case 'kernel.logs_dir': $value = ($this->targetDirs[2].'/logs'); break;
            case 'user': $value = $this->getEnv('VAL1'); break;
            case 'session.save_path': $value = ($this->targetDirs[3].'/app/../var/sessions/dev'); break;
            case 'router.resource': $value = ($this->targetDirs[3].'/app/config/routing_dev.yml'); break;
            default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
        }
        $this->loadedDynamicParameters[$name] = true;

        return $this->dynamicParameters[$name] = $value;
    }

It is the only place where the env(VAL1) is evaluated.

So for your case the solution is the following.

I used simplified parameters.yml:

parameters:
    user: '%env(VAL1)%'

The export I did:

export VAL1=abc

PHP code:

$container = new ContainerBuilder();

$loader = new YamlFileLoader(
    $container,
    new FileLocator('.')
);

$loader->load('parameters.yml');

$container->compile();

$dumper = new PhpDumper($container);

$content = $dumper->dump(
    [
        'class' => 'DumpedContainer',
        'base_class' => 'Container',
        'file' => 'DumpedContainer.php',
        'debug' => true
    ]
);

// Use this code if you want to write file to the disk
$cache = new ConfigCache('DumpedContainer.php', true);
$cache->write($content, $container->getResources());
require_once $cache->getPath();

// ... otherwise use this code
//$content = str_replace('<?php', '', $content);
//eval($content);

$container = new DumpedContainer();

$user = $container->getParameter('user'); // $user = 'abc'

In the generated code you'll see the following method that do the magic

private function getDynamicParameter($name)
{
    switch ($name) {
        case 'user': $value = $this->getEnv('VAL1'); break;
        default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
    }
    $this->loadedDynamicParameters[$name] = true;

    return $this->dynamicParameters[$name] = $value;
}

This solution works fine but looking at it I wonder if this is really needed in your project? What's wrong with getenv()?

like image 153
Stepashka Avatar answered Apr 25 '23 14:04

Stepashka


Please try:

parameters:
database:
    driver: pdo_mysql
    host: 127.0.0.1
    dbname: dbname
    user: '%env(VAL1)%'
    password: '%env(VAL2)%'
log_path: /logs

I think that's the problem. See this documentation for reference: http://symfony.com/doc/current/configuration/external_parameters.html

like image 34
Alvin Bunk Avatar answered Apr 25 '23 14:04

Alvin Bunk