Comment fonctionnent les fichiers d’environnements Symfony ?
Si vous êtes arrivés sur cet article c’est que soit vous ignorez ce qu’est ce fameux .env soit vous souhaitez en savoir plus. Soyons simples et efficaces, il s’agit d’un fichier utilisé par Symfony (vous en trouverez également dans d'autres systèmes comme node.js par exemple) contenant une liste de clés/valeurs utilisées généralement dans la configuration du framework.
Alors pourquoi ne pas l'intégrer directement dans la configuration? Déjà parce que c’est plus simple de tout regrouper. Non, pas que l’on soit fainéant mais bon, on aime se faciliter la vie, mais principalement car notre configuration va changer selon l'environnement où on l'exécute.
Si votre projet se trouve sur votre machine en local, sur un serveur de test ou sur le serveur final, l’ensemble de votre code sera bien identique. Par contre, la configuration ne sera bien évidemment pas la même. Ne serait-ce que pour les accès aux bases de données.
Donc en simplifiant très fortement: il s’agit d’un fichier regroupant la configuration d’un projet en un seul et même fichier afin d’en faciliter le déploiement.
Et ça se présente comment?
Le plus simplement du monde : une simple association clés/valeurs pouvant être de type string, integer, boolean.
FIRSTNAME=”Kevin”
(Notez que le firstname en majuscule tient plus de la bonne pratique qu’autre chose)
Les environnements
Il faut tout d’abord différencier les différents environnements de base:
- production : correspondant comme son nom l’indique au serveur de production
- dev : qui est utilisé lors du développement avec généralement le debugger actif pour faciliter nos existences
- test : uniquement lors de la réalisation de test automatisé
Bien évidemment, rien ne vous oblige à utiliser ces trois environnements là mais… il faut bien penser que des tests sur la db de prod c’est quand même pas terrible…
Ok, donc le fichier .env correspond à la prod, c’est bien ça? Pas du tout, il s’agit là d’une fausse croyance. Les gens ont tendance à utiliser le .env comme fichier de prod car par défaut, il est le seul fichier d’environnement à être commité. Mais c’est une erreur et ce justement car il est commité ! Si l’on suit les bonnes pratiques, on ne veut pas que nos accès db, nos clés API,... se retrouvent en clair sur notre git.
Mais du coup il y a quoi dans le .env ?
Et bien on pourrait le comparer à un fichier “modèle” servant de base pour les différents environnements. Pour ceux qui connaissent, on pourrait parler de fichier déshydraté.
Si l’on suit cette pratique, il ressemblerait, par exemple, à ceci:
DATABASE_HOST=
DATABASE_NAME=”lenomdemadb”
DATABASE_USER=
DATABASE_PASSWORD=
API_KEY=
Ici nous donnons le nom de la db car on pourrait s’imaginer que peu importe l’environnement, elle a le même nom. Mais pas l’host, le user et le password qui varient.
Nous allons ensuite créer un fichier “.env.local” dédié à notre environnement local.
DATABASE_HOST=”127.0.0.1”
DATABASE_USER=”kevin”
DATABASE_PASSWORD=”SuperPassword1234!”
API_KEY=”Azertyuiop123456789!”
Ce fichier ne sera pas commit car il n’est, en théorie, fonctionnel que sur la machine où il est utilisé.
Précision: lorsque je parle d’environnement local, il s’agit de là où se trouve votre code. Que ce soit sur votre machine ou sur votre serveur. Vous aurez donc un fichier .env.local sur votre machine lors du dev et un fichier .env.local sur votre serveur pour la prod.
Gestion de l’héritage
Les plus attentifs vont me dire: “Mais il manque le name”.
Et bien non car Symfony applique un système d’override se basant sur le fichier .env.
Si j'exécute mon code, Symfony va donc prendre les valeurs du fichier .env et ajouter les valeurs du fichier .env.local. Et pour les valeurs existantes, les écraser.
Les valeurs combinées donneront donc:
DATABASE_HOST=”127.0.0.1”
DATABASE_NAME=”lenomdemadb”
DATABASE_USER=”kevin”
DATABASE_PASSWORD=”SuperPassword1234!”
API_KEY=”Azertyuiop123456789!”
Je pense que vous commencez à comprendre les avantages de ces .env mais ce n’est pas tout. En plus du .env et du .env.local, vous pouvez aussi ajouter des fichiers pour les environnements de dev et de test ayant chacun leur propre .local...
Ce qui au final nous donne donc un total de 6 fichiers et une hiérarchie pas forcément simple à comprendre.
Heureusement, Symfony va répondre à notre question via la commande que voici:
symfony console debug:dotenv
Nous savons désormais l’ordre utilisé par Symfony.
Petit aparté sur le .env.local.php, il s’agit d’un fichier qui permet de forcer l’utilisation d’un environnement précis via la commande suivante: $ composer dump-env dev
Récupérer et utiliser les variables d’environnement…
…dans la configuration
Prenons votre fichier doctrine.yaml où vous souhaitez récupérer les informations de connexion à la db:
doctrine:
dbal:
host: '%env(resolve:DATABASE_HOST)%'
dbname: '%env(resolve:DATABASE_NAME)%'
user: '%env(resolve:DATABASE_USER)%'
password: '%env(resolve:DATABASE_PASSWORD)%'
…dans un controller
Deux possibilités s’offrent à vous.
La plus simple étant de simplement récupérer la valeur comme une variable d’environnement classique de php
$apiKey = $_ENV[‘API_KEY];
La seconde consiste à l’ajouter dans le fichier services.yaml
parameters:
API_KEY: '%env(API_KEY)%'
Pour ensuite la récupérer dans le controller:
$apiKey = $this->getParameter('API_KEY');
…dans un service
Ici aussi, deux méthodes.
La première se déroule uniquement dans votre class:
class MyService
{
protected $parameterBag;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->parameterBag = $parameterBag;
}
public function getKey(){
return $this->parameterBag->get('API_KEY');
}
}
La seconde demande une config supplémentaire dans le fichier services.yaml
services:
App\Service\MyService:
arguments:
$apiKey: "%env(API_KEY)%"
Ce qui permet une récupération directement dans le __construct du service.
class MyService
{
protected $apiKey;
public function __construct($apiKey)
{
$this->apiKey = $apiKey;
}
public function getKey(){
return $this->apiKey;
}
}
…dans TWIG
Une nouvelle fois, cela se passera dans la config en modifiant cette fois le fichier twig.yaml
twig:
globals:
API_KEY: "%env(API_KEY)%"
Dans votre fichier twig, il vous suffit de l’insérer comme n’importe quelle variable twig.
{{ API_KEY }}
Désormais, vous saurez comment gérer les différents niveaux de variables liés aux différents environnements et comment les récupérer en fonction d’où vous en avez besoin.