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 :

symfony new variables_environement --webapp
cd variables_environement

Créons un controller de test :

symfony console make:controller TestController

Démarrons notre application :

symfony serve -d

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

<!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) :

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.

cp .env .env.local

Nous pouvons checker les variables d’environnement avec la debug barre :

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 :

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 :

cp .env.local .env.dev

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

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 :

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 :

cp .env.dev .env.dev.local

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

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 :

composer dump-env dev # ou prod

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

<?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

// 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 :

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 :

symfony console debug:dotenv

Le résultat de la commande est hyper clair :

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 :

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

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

symfony console debug:container --env-vars

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

    #[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 !

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

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

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é :

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 :

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

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

Et utilisons notre argument $demo dans notre service :

<?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 :

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 :

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 :

{% 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é :

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 :

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 :

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 :

php bin/console secrets:set DEMO_SECRET

Pour la production :

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 // 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 :

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 :

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

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

{% block body %}

    {{ DEMO_SECRET }}

{% endblock %}

Dumpons nos variables d’environnement :

composer dump-env dev

Et constatons le résultat :

Set d’un secret en local

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

php bin/console secrets:set --local  DEMO_SECRET

Dumpons nos variables d’environnement :

composer dump-env dev

Et vérifions :

Quelques outils pour gérer les secrets

  • Lister les secrets :
php bin/console secrets:list --reveal
------------- ---------------------- ---------------------------- 
  Secret        Value                  Local Value                 
 ------------- ---------------------- ---------------------------- 
  DEMO_SECRET   "Ceci est un secret"   "Ceci est un secret local"  
 ------------- ---------------------- ----------------------------
  • Supprimer un secret :
php bin/console secrets:remove DEMO_SECRET