New in Symfony 3.2: Runtime Environment Variables

Contributed by
Nicolas Grekas
in #19681.

Environment variables are becoming increasingly popular to manage the application configuration. They are one of the main concepts of the twelve-factor app methodology. Their main advantages are that they can be changed between deploys without changing any code and that they don't need to be checked into the code repository.

Symfony has supported environment variables since day one thanks to the special SYMFONY__ variables. However their behavior was rather simple: when the application container was built, the values of those environment variables were dumped into the compiled container. Therefore, if those variables changed during the application execution, the updated values were ignored.

In Symfony 3.2 we added full support for environment variables. The first improvement is that you no longer have to prefix those variables with SYMFONY__ (any variable name will work). The second improvement is that their value is resolved at runtime, so the application will always use the updated value.

In order to use an environment variable in any Symfony configuration file, use the new %env(VARIABLE_NAME)% syntax:

1
2
3
4
5
# app/config/config.yml
doctrine:
    dbal:
        # ...
        password: "%env(DB_PASSWORD)%"

In the previous example, whenever Symfony/Doctrine need the database password, they'll make a call to get the value of the DB_PASSWORD environment variable. To avoid undefined variable errors, you can define default values for these variables using the syntax env(VARIABLE_NAME): VARIABLE_VALUE:

1
2
3
# app/config/parameters.yml
parameters:
    env(DB_PASSWORD): s3cr3t_1234

Comments

Nice feature!

Is there a typo: "they can can be"?
@Victor the typo was fixed. Thanks for noticing it.
So the special SYMFONY__ variables are deprecated now?
Not yet, but there is a proposal to deprecate them: https://github.com/symfony/symfony/pull/20100
Any plans to port this to 2.8 LTS ? Next LTS will be a year from now, it would be great to get this into current LTS.
@Damjan there are no plans to port this to 2.8 because we "can't" do it. Our BC promise [1] and our release process [2] are very clear about this: we can't add new features in old Symfony versions (e.g. 2.8). We can only fix bugs for those old versions. That's why all new features are always created in the "master" branch of the repository.

[1]: http://symfony.com/doc/current/contributing/code/bc.html
[2]: http://symfony.com/doc/current/contributing/community/releases.html
@Damjan You can mimic the similar feature in Symfony 2.8 with the help of incenteev/composer-parameter-handler package. In your composer.json you can map your ENV variables like this.

"incenteev-parameters": {
"file": "app/config/parameters.yml",
"env-map": {
"database_driver": "DATABASE_DRIVER",
......
}
}
}
If the value is resolved at runtime, how can this ever work for example for the "host" parameter in routing as a change cannot trigger a recompilation of the URL matchers and generators? How is this handled in dev and production for situations where parameters are "compiled away" like that?
@Damjan there's no benefit staying on LTS: https://stovepipe.systems/post/symfony-versioning-and-compatibility
Adding on my previous comment #8: I see in the PR discussion that it's "deemed acceptable" that this construct will not work correctly in all situations.

However in my opinion changing the root URL(s) of an application is THE premium use case of all to be defined by the environment, especially in face of the twelve-factor app methodology.

To be honest I think I'm just very skeptical about the whole runtime part. Every change in a Symfony production application requires a cache clear and container recompile, why not a, usually highly dangerous, change in the application's deployment configuration?
Now Symfony perfectly fits with Docker!
@Niels, think about automatically generated database/api credentials that you don't need to deploy your app for. Or possibly even changing the connection of your database to another instance without having to redeploy.
@Javier Yeah, I suspected that.

@Nirmal Thanks, I didn't know that. It will have to do for a while, before we migrate everything to latest.
Great job! This deceptively simple feature will enhance the way DevOps deploys Symfony applications!
Nice feature, thanks Symfony ;)
Very nice, I remove the bad "Incenteev\\ParameterHandler" Yeahhhhh

Let's go to contenerizzzzzz

Comments are closed.

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