Runtime environment variables in symfony
Introduction
Environment variables allow developers to extract sensitive credentials from their source code and to use different configuration variables based on their working environment.
When dealing with sensitive options, like database credentials, it is a good practice that you store them outside the Symfony project and make them available through environment variable.
In symfony the file config.yml
is used to options application level and parameters.yml
is used to options in infrastructure level.
It is really bad practice put sensitive options like credentials directly in config.yml file. Usually you put in your repository a template
parameters.yml.dist
with default values (usually values from dev environment) so in your deploy you will do something like this:
You can generate value options in parameters.yml from environment variables o directly you can avoid use parameters.yml file.
Option 1: Use env-map in composer.json to package incenteev/parameterHandler can to create parameters.yml from environment variables
1
2
3
4
5
6
7
8
9
10
{
"extra": {
"incenteev-parameters": {
"env-map": {
"database.user": "DATABASE_USER",
"database.password": "DATABASE_PASSWORD"
}
}
}
}
So in the scripts
section in your composer.json you can see:
1
2
3
4
5
6
7
8
"scripts": {
"post-install-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters"
],
"post-update-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters"
]
},
The script buildParameters
will be called when you execute composer install
or composer update
, this script
will create the file parameters.yml will from template parameters.yml.dist with values from your
environment variables.
Option 2: Do not use parameters.yml file, only use environment variables
In file config.yml
you will have something like this:
1
2
3
4
imports:
- { resource: parameters.yml }
- { resource: services.yml }
# ...
Remove the import of parameters.yml file and create a template to environment variables with standard name .env.dist
Note: Your .env file should not be committed to your application’s source control, since each developer using your application could require a different environment configuration.
So in environment dev, developers can import easily environment variables only executing the command:
1
source .env.dist
Symfony < 3.2
The content file .env.dist
will be something like this:
1
2
export SYMFONY__DATABASE_USER=root
export SYMFONY__DATABASE_PASSWORD=null
Symfony then automatically sets all $_SERVER variables prefixed with SYMFONY__ as parameters in the service container.
You can now reference these parameters wherever you need them.
1
2
3
4
5
6
7
# app/config/config.yml
doctrine:
dbal:
driver: pdo_mysql
dbname: symfony_project
user: '%database.user%'
password: '%database.password%'
Note: In symfony 3.3 deprecated the special SYMFONY__
variables
Symfony >= 3.2
In symfony 3.2 you do not need put prefix SYMFONY__
, it is not make sense because those environment variables
can be used by others applications no necessarily built with symfony.
So the name of variables will be more standard to share with other apps, example:
Content file .env.dist
:
1
2
export DATABASE_USER=root
export DATABASE_PASSWORD=null
To load these environment variables you should execute the next command:
To use the environment variables in your config.yml
file you can put something like this:
1
2
3
4
5
# app/config/config.yml
doctrine:
dbal:
# ...
password: "%env(DATABASE_PASSWORD)%"
Environment “Dev”
To avoid execute in each session the command source .env.dist
or persist environment variables in dev environment we can modify next symfony files:
- bin/console
- web/app_dev.php
bin/console file:
web/app_dev.php file:
To phpunit.xml.dist you can do something similar loading bootstrap file, you can call bootstrap_dev.php and load in your xml phpunit.xml.dist:
Conclusion
Whatever option is valid but I prefer the option 2 because you do not depend of third parts like incenteev\parameterHandler
to
set up in right way options from infrastructure layer and looks a solution more standard.