New in Symfony 4.2: Define env vars per environment
Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.
Since the introduction of the DotEnv component in Symfony 3.3, we've been
working hard to improve the experience of using env vars to configure Symfony
apps. In Symfony 4.2, we've added a new
loadForEnv() method to allow you
define different env vars per environment.
Instead of creating a single
.env file at your project's root dir, you can
now create one or more env var files. The values for the env var are looked for
in the following order:
.env.$APP_ENV.local(don't commit this file to the repository) defines environment-specific overrides for your local machine;
.env.$APP_ENV(commit this file to the repository) and defines environment-specific defaults for all developers/machines;
.env.local(don't commit this file to the repository) overrides the main
.envconfig only for your local machine;
.env(commit this file to the repository) and defines the default values for the env vars used in the application.
We're working on a Symfony Flex recipe to bring this new feature into the full Symfony framework (see symfony/recipes #466). There's no need to change anything in your existing applications if you don't want to, but new projects will get the latest recipes versions, with the following changes:
.env(and committed to the shared repository).
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
What is the use case for this that isn't already solved using parameters?
Also, I agree with my friend here: https://twitter.com/storresi/status/1057242707914043392
> Are there any other projects using a similar setup?
Great questions / comments. Actually this new setup was done purposely to follow a standard used by others like Create React App and Rails. So, we're becoming *more* standardized.
But, that's not the *real* reason I'm excited about this. The *real* reason is that it enables us to drastically improve env vars in the test environment via this recipes PR: https://github.com/symfony/recipes/pull/466/files#diff-d611993c75871b5e812244b9a8cf54d4
Currently you need to duplicate your env vars (all of them) in phpunit.xml.dist... even if only a few need to be different in the test environment. In the above recipe PR, the proposal is to introduce a new src/bootstrap.php file that everything uses (phpunit, public/index.php & bin/console) that will load environment variables in a consistent way. By combining that with the ability to have a .env.test file, you can easily tweak your test environment settings. This is big thing that I think needed to be improved.
Other than that recipe PR, for most people, this change won't mean much. As the post mentioned, .env.dist will become .env (and be committed) and .env will become .env.local (and not be committed). But this is just a naming change.
Will the best practices docs be updated to include this?
Great question/point actually! We just had that conversation on the recipe pull request. You CAN actually set environment variables on a per-environment basis by using the special parameters syntax. But, at the very least, it's way less user-friendly than having a .env.dist file for overrides (which will be installed for you when you install phpunit-bridge).
It will make our life easier!
Ah, no - I didn't mean to make it sound like this exactly. Most of the time, it still makes more sense to override environment config in a config file - e.g. services_test.yaml or config/packages/test/*. Or, like how we have 2 different monolog.yaml files for dev vs prod environment. You want these changes committed - they are code. But, for values that are already stored in .env (e.g. DATABASE_DSN), it's just a lot simpler to be able to have a `.env.test` vs knowing to create a config/packages/test/doctrine.yaml file that has the config you need to re-set the database_dsn. That's my main motivation for liking this change.
Good questions! It's helpful to have to me to these discussions!
So we have environments for environment variables
The only reason for rolling this out is so that unittests can be configured easier? Just put the ENV values you need in the phpunit.xml!
I have a setup script that helps to get the project up and running quickly. The setup script sources the .env file or loads real env vars if that file doesn't exist. I'm still not sure how to fix this. The only way I can think of, is to implement the same conditional logic in my setup script that DotEnv uses, to look for and load any relevant "override" files.
Docker Compose looks for .env files by default. https://docs.docker.com/compose/env-file/
It was nice that I didn't have to do anything to make docker properly host my application in development.
IMO this is a significant change that can be obviated with a .env.test file and having w/e test runner source that file and then let Symfony fill in the gaps from the .env file. No changes necessary. (CMIIW)