---
title: "A la découverte des variables d'environnement de Symfony"
excerpt: "Dans cet article, nous allons partir à la découverte des variables d'environnement de Symfony, et vous allez voir qu'il y a une infinité de façons de les définir ou des les utiliser!"
publishDate: 2022-03-11T00:00:00.000Z
tags: ["symfony", "env", "variables"]
canonical: "https://yoandev.co/a-la-decouverte-des-variables-d-environnement-de-symfony"
---

<YouTube id="n_wGBA_dl68" />

## Objectifs

Dans cet article, nous allons partir à la découverte des variables d'environnement de Symfony, et vous allez voir qu'il y a une infinité de façons de les définir ou des les utiliser!

**Au programme :**
- **Définir des variables d'environnement**
  - Définir des variables d'environnement avec un fichier ```.env``` et ```.env.local```
  - Hierarchie des fichiers de variables d'environnement
- **La CLI**
  - Dumper les variables d'environnement
  - Lister les variables d'environnement en CLI
- **Accéder aux variables d'environnement**
  - Accéder aux variables d'environnement depuis les contrôleurs
  - Accéder aux variables d'environnement depuis les services
  - Accéder aux variables d'environnement depuis Twig
- **Mettez vos variables d'environnement en sécurité**
  - Utilisation du systeme de gestion des secrets de Symfony

## Initier notre projet Symfony

Créons notre projet et entrons dans le dossier :

```shell
symfony new variables_environement --webapp
cd variables_environement
```
Créons un controller de test :

```shell
symfony console make:controller TestController
```
Démarrons notre application :

```shell
symfony serve -d
```

Et supprimons toutes références à Webpack dans le fichier ```templates/base.html.twig``` :

```html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}Welcome!{% endblock %}</title>
        <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text></svg>">
        {# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
        {% block stylesheets %}
        {% endblock %}

        {% block javascripts %}
        {% endblock %}
    </head>
    <body>
        {% block body %}{% endblock %}
    </body>
</html>
```

## Définir des variables d'environnement

### Définir des variables d'environnement avec un fichier ```.env``` et ```.env.local```

Par default, Symfony utilise les variables d'environnement définies dans le fichier ```.env``` pour définir les variables d'environnement.

Si on consulte ce fichier on peut voir qu'il y a plusieurs variables d'environnement (*j'ai supprimé les commentaires*) :

```shell
APP_ENV=dev
APP_SECRET=d039c490ad66d067877186a6640183ab
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
DATABASE_URL="postgresql://symfony:ChangeMe@127.0.0.1:5432/app?serverVersion=13&charset=utf8"
```

La bonne façon de définir des variables d'environnement est de créer un fichier ```.env.local``` qui contient les variables d'environnement à utiliser pour le développement sur votre machine et de ne jamais définir des variables d'environnement dans le fichier ```.env``` (qui est commit sur Git).

Finalement, le fichier ```.env``` est une sorte de **template** qui permet de définir des variables d'environnement utilisées dans le projet.

Copions donc le fichier ```.env``` dans un fichier ```.env.local```.

```shell
cp .env .env.local
```
Nous pouvons checker les variables d'environnement avec la debug barre :

![](./images/2022-03-05-18-55-55.png)

Ajoutons une variable d'environnement :
- Dans le fichier ```.env```
  ```DEMO=```
- Dans le fichier ```.env.local```
  ```DEMO="Ceci est une démo"```

Et checkons les variables d'environnement :

![](./images/2022-03-05-18-59-37.png)

### Hierarchie des fichiers de variables d'environnement

Nous l'avons juste avant, le fichier ```.env.local``` est prioritaire sur le fichier ```.env```.

Mais il est possible d'ajouter encore de la finesse dans votre architecture de projet en créant un fichier ```.env.dev``` qui contient des variables d'environnement spécifiques à un environnement de développement.

Et copions le contenu du fichier ```.env.local``` dans le fichier ```.env.dev``` :

```shell
cp .env.local .env.dev
```

Et modifiont légèrement le contenu du fichier ```.env.dev``` :

```shell
DEMO="Ceci est une démo depuis le fichier .env.local"
```

Nous constatons que le fichier ```.env.dev``` est prioritaire sur le fichier ```.env.local``` :

![](./images/2022-03-05-19-12-57.png)

Poussons encore plus loin dans notre architecture de projet en créant un fichier ```.env.dev.local``` en y copiant le contenu du fichier ```.env.dev``` :

```shell
cp .env.dev .env.dev.local
```

Nous constatons que le fichier ```.env.dev.local``` est prioritaire sur le fichier ```.env.dev``` :

![](./images/2022-03-05-19-14-52.png)

## La CLI

### Dumper les variables d'environnement

Pour des raisons de performances, noatement en production, et afin d'éviter de parser les fichiers ```.env``` à chaque requête, nous pouvons utiliser la commande ```dump-env``` pour afficher les variables d'environnement dans un fichier PHP :

```shell
composer dump-env dev # ou prod
```

Un fichier ```.env.php``` sera créé à la racine du projet :

```php
<?php

// This file was generated by running "composer dump-env dev"

return array (
  'APP_ENV' => 'dev',
  'APP_SECRET' => 'd039c490ad66d067877186a6640183ab',
  'MESSENGER_TRANSPORT_DSN' => 'doctrine://default?auto_setup=0',
  'DATABASE_URL' => 'postgresql://symfony:ChangeMe@127.0.0.1:5432/app?serverVersion=13&charset=utf8',
  'DEMO' => 'Ceci est une démo depuis le fichier .env.dev.local',
);
```

Modifier le contenu du fichier ```.env.php``` (**A ne jamais faire, c'est uniquement pour la démo**) :

```php
<?php

// This file was generated by running "composer dump-env dev"

return array (
  'APP_ENV' => 'dev',
  'APP_SECRET' => 'd039c490ad66d067877186a6640183ab',
  'MESSENGER_TRANSPORT_DSN' => 'doctrine://default?auto_setup=0',
  'DATABASE_URL' => 'postgresql://symfony:ChangeMe@127.0.0.1:5432/app?serverVersion=13&charset=utf8',
  'DEMO' => 'Ceci est une démo depuis le fichier .env.local.php',
);
```

Et vérifions que les variables d'environnement sont bien modifiées :

![](./images/2022-03-05-19-22-50.png)

### Lister les variables d'environnement en CLI

La multiplicité des fichiers peut rendre la lecture des variables d'environnement difficile.
C'est pourquoi il existe une commande qui permet de lister les variables d'environnement :

```shell
symfony console debug:dotenv
```

Le résultat de la commande est hyper clair :

![](./images/2022-03-05-19-38-40.png)

## Accéder aux variables d’environnement

Maintenant que nous avons vu comment récupérer les variables d'environnement, nous pouvons les utiliser dans notre application.

### Accéder aux variables d’environnement depuis les contrôleurs

Afin d'acceder à vos variables d'environnement depuis les contrôleurs, nous devons les ajouter dans notre fichier ```config/services.yaml``` :

```yaml
parameters:
    DEMO: '%env(DEMO)%'
```

Vérifions avec une nouvelle commande que notre variable d'environnement est bien présente :

```shell
symfony console debug:container --env-vars
```

Dans notre controlleur ```src/Controller/TestController.php``` ajoutons de quoi accéder à la variable d'environnement :

```php
    #[Route('/test', name: 'app_test')]
    public function index(): Response
    {
        $demo = $this->getParameter('DEMO');
        dd($demo);
        
        return $this->render('test/index.html.twig', [
            'controller_name' => 'TestController',
        ]);
    }
```
Et vérifions !

![](./images/2022-03-05-19-50-09.png)

### Accéder aux variables d’environnement depuis les services

Voyons maintenant comment accéder aux variables d'environnement depuis les services.

#### La méthode "manuelle"

Commençons par créer un service dans le fichier ```src/Service/DemoService.php``` qui permet de récupérer les variables d'environnement :

```php
<?php

namespace App\Service;

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class DemoService
{
    public function __construct(ParameterBagInterface $parameterBag)
    {
        $this->parameterBag = $parameterBag;
    }
    
    public function getDemo(): string
    {
        return $this->parameterBag->get('DEMO');
    }
}
```

Et modifions notre controlleur ```src/Controller/TestController.php``` pour utiliser notre service :

```php
<?php

namespace App\Controller;

use App\Service\DemoService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class TestController extends AbstractController
{

    #[Route('/test', name: 'app_test')]
    public function index(DemoService $demoService): Response
    {
        dd($demoService->getDemo());

        return $this->render('test/index.html.twig', [
            'controller_name' => 'TestController',
        ]);
    }
}
```
On rafraichit notre page, c'est bien le contenu de la variable d'environnement qui est affiché :

![](./images/2022-03-05-19-50-09.png)

#### La méthode "automatique"

Plutôt que d'utiliser le ```ParameterBagInterface``` dans le service pour récupérer les variables d'environnement, nous pouvons utiliser la méthode "automatique" de Symfony pour injecter les variables d'environnement.

Dans notre fichier ```config/services.yaml``` ajoutons :

```yaml
parameters:
    DEMO: '%env(DEMO)%'

services:
    # ...   
    App\Service\DemoService:
        arguments:
            $demo: '%env(DEMO)%'
```

Et utilisons notre argument ```$demo``` dans notre service :

```php
<?php

namespace App\Service;

class DemoService
{
    public function __construct(
        public string $demo
    ) {
    }
    
    public function getDemo(): string
    {
        return $this->demo;
    }
}
```

Nous pouvons vérifier que tout fonctionne :

![](./images/2022-03-05-19-50-09.png)

### Accéder aux variables d’environnement depuis Twig

Nous pouvons aussi accéder aux variables d'environnement depuis Twig.

Pour cela, nous devons ajouter une variable d'environnement dans notre fichier ```config/packages/twig.yaml``` :

```yaml
twig:
    default_path: '%kernel.project_dir%/templates'
    globals:
        DEMO: '%env(DEMO)%'
```

Et dans notre fichier ```templates/test/index.html.twig``` nous pouvons accéder à la variable d'environnement directement :

```html
{% extends 'base.html.twig' %}

{% block title %}Hello TestController!{% endblock %}

{% block body %}

    {{ DEMO }}

{% endblock %}
```
Et on rafraichit notre page, c'est bien le contenu de la variable d'environnement qui est affiché :

![](./images/2022-03-07-09-42-46.png)

## Mettez vos variables d’environnement en sécurité

Comme nous l'avons vu jusqu'ici, nous pouvons accéder aux variables d'environnement depuis n'importe quel endroit de notre application. Nos stockons les variables d'environnement dans un *simple* fichier.

C'est certe pratique mais pas necessairement sécurisé.

### Utilisation du systeme de gestion des secrets de Symfony

Symfony propose un système de gestion des secrets basé sur un systeme de clés cryptographiques.

#### Génération des clés

Première étape, nous allons générer les clés :

```shell
php bin/console secrets:generate-keys
```

Nous constatons que les clés sont générées avec succès dans les deux fichiers suivants :

- config/secrets/dev/dev.decrypt.private.php
- config/secrets/dev/dev.decrypt.public.php

Si vous souhaitez générer les clés pour la production :

```shell
APP_ENV=prod php bin/console secrets:generate-keys
```

Nous constatons que les clés sont générées avec succès dans les deux fichiers suivants :

- config/secrets/prod/prod.decrypt.private.php
- config/secrets/prod/prod.decrypt.public.php

**Pensez à vérifier que votre fichier ```prod.decrypt.private.php``` est bien présent dans votre ```.gitignore``` :**

```
/config/secrets/prod/prod.decrypt.private.php
```
#### Ajouter une variable d'environnement à la liste des secrets

Pour ajouter un nouveau secret (```DEMO_SECRET: Ceci est un secret```) nous devons utiliser la commande suivante :

```shell
php bin/console secrets:set DEMO_SECRET
```

*Pour la production :*

```shell
APP_RUNTIME_ENV=prod php bin/console secrets:set DEMO_SECRET
```

Nous constatons la création d'un nouveau fichier ```config/secrets/dev/dev.DEMO_SECRET.80921a.php``` qui contient notre variable d'environnement chiffrée :

```php
<?php // dev.DEMO_SECRET.80921a on Mon, 07 Mar 2022 10:07:38 +0100

return "\xCD\x9B\x7F6\xDC\xC9\x82\xE6\xEB\xE2\x808\xBF\xA9P\xA8\x9BL\x3A\xA5\xC0\xBD\xA6\xA6\xA7\x7D\x10\xCD\xE9\xD0\xBEg\xA3ez\x8A\xC2\x91k\xD04DDLo\x9D\xB9\x17\xCD\xC9\x989\x24\x3A\xC3U\xFCFP\x5CQ\xC0\xB9\xA3T\x60";
```

Et accédons à notre variable d'environnement depuis Twig :

```yaml
twig:
    default_path: '%kernel.project_dir%/templates'
    globals:
        DEMO: '%env(DEMO)%'
        DEMO_SECRET: '%env(DEMO_SECRET)%'
```

Modifions notre fichier twig ```templates/test/index.html.twig``` :

```html
{% extends 'base.html.twig' %}

{% block title %}Hello TestController!{% endblock %}

{% block body %}

    {{ DEMO_SECRET }}

{% endblock %}
```

Dumpons nos variables d'environnement :

```shell
composer dump-env dev
```

Et constatons le résultat :

![](./images/2022-03-07-10-12-58.png)

#### Set d'un secret en **local**

Vous pouvez aussi **set** un secret en local (valable uniquement sur votre machine) :

```shell
php bin/console secrets:set --local  DEMO_SECRET
```

Dumpons nos variables d'environnement :

```shell
composer dump-env dev
```

Et vérifions :

![](./images/2022-03-07-10-30-46.png)

#### Quelques outils pour gérer les secrets

* Lister les secrets :

```shell
php bin/console secrets:list --reveal
------------- ---------------------- ---------------------------- 
  Secret        Value                  Local Value                 
 ------------- ---------------------- ---------------------------- 
  DEMO_SECRET   "Ceci est un secret"   "Ceci est un secret local"  
 ------------- ---------------------- ----------------------------
```

* Supprimer un secret :

```shell
php bin/console secrets:remove DEMO_SECRET
```
