Symfony 4 was released on November 30th.
Update now to the best Symfony ever!

New in Symfony 3.4: Advanced environment variables

Contributed by
Nicolas Grekas
in #23901.

Symfony 4 will promote and leverage environment variables to configure some parts of the applications. In Symfony 3.4 we're working hard to make that fully possible. The last big hurdle was that environment variables are always transformed into strings. That's a big problem when using PHP 7.1 type-hints:

1
2
3
4
public function connect(string hostname, int port)
{
    // ...
}

If the value of the port argument is obtained through an env var, the application won't work because the argument will be a string instead of the expected integer:

1
2
parameters:
    app.connection.port: '%env(DATABASE_PORT)%'

In Symfony 3.4 we improved the processing of environment variables to support type casting. When referencing an env var, you can now set the type you want its value converted to:

1
2
3
parameters:
    # roughly equivalent to "(int) getenv('DATABASE_PORT')"
    app.connection.port: '%env(int:DATABASE_PORT)%'

We included support for the usual bool:, int:, float: and string: casting. But we didn't stop there! We also added some utilities to perform the most common operations related to env vars (and you can combine them all).

The resolve: operator replaces container parameter names by their values:

1
2
3
4
parameters:
    project_dir: '/foo/bar'
    env(DB): 'sqlite://%%project_dir%%/var/data.db'
    db_dsn: '%env(resolve:DB)%'

The file: operator gets the contents of the given file and the json: operator decodes the given contents into a PHP array, so you can combine them to get the secrets stored in some file:

1
2
3
parameters:
    env(SECRETS_FILE): '/etc/secure/example.com/secrets.json'
    app.secrets: '%env(json:file:SECRETS_FILE)%'

The base64: operator decodes the given base64 content and const: allows you to refer to any PHP constant:

1
2
3
4
5
6
parameters:
    env(SOME_VALUE): 'NWE3OWExYzg2NmVmZWY5Y2ExODAwZjk3MWQ2ODlmM2U='
    app.some_value: '%env(base64:SOME_VALUE)%'

    env(NUM_ITEMS): 'App\\Entity\\BlogPost::NUM_ITEMS'
    app.num_items: '%env(constant:NUM_ITEMS)%'

Last but not least, you can define your own operators to manipulate the content of the environment variables before using them. To do so, define a service implementing the new EnvProviderInterface and tag it with container.env_provider.

Comments

The text said that 'const:', but in the example 'constant:' presents. I assume that the first one is correct. ?
Nice !
Yes it's `const`.

Also `container.env_provider` is actually `container.env_var_processor` :)
Is it, or will it be possible to define your own operator?

Like `%env(myDecoder:API_PASSWORD)%`, which will decrypt the environment value into something usable.

class MyDecoder implements EnvironmentOperator {
public function resolve(string $value): string {
// magic stuff for decryption
return $value;
}
}
@Wesley yes, you just need to create a service that implements "EnvProviderInterface" and tag it with "container.env_provider".
Having just seen this presented at SymfonyLive London, I think I like the ability to nest / combine the key words when loading ENV values. Especially so that we can use 'json:file:SECRETS_FILE' or even the option to create a custom one to process data from a file once loaded.
Nice!
What about former yaml arrays like locales: [de,en]? Currently they are strings when using env vars.

but good to hear at all. Now i can cast APP_DEBUG(int) to bool. Cool.
@Maximilian I would write a custom `arrayDecoder` implementing `EnvProviderInterface` for that, I think it would be quite trivial. The catch being that, once you've placed elements in the array, you can cast them as well.
To access `app.secrets` keys (with expression language):
```
bind:
$dbSecret: '@=parameter("app.secrets")["dbSecret"]'
```

Comments are closed.

To ensure that comments stay relevant, they are closed for old posts.