Connecter Symfony 7 à une base de données

Avec Docker et MariaDB

Symfony Bash Docker

Créé le

Au sommaire :

Si vous avez bien suivi les articles précédents, vous disposez maintenant d'un environnement de développement PHP sous docker et sur lequel Symfony 7 est installé.
Et nous avons également installé une base de données MariaDB.

Nous allons donc voir ici comment connecter Symfony à notre base de données MariaDB et comment tester la connexion.

1. Les fichiers d'environnements Symfony

Avant de passer à la base de données, il est utile d'aborder briévement les fichiers d'environnements.
Dans le prochain chapitre nous installerons le bundle Doctrine et cela affectera ce fichier avec des valeurs d'exemple.
Il est donc intéressant de le voir évoluer.

Symfony met à disposition un fichier d'environnement permettant de configurer notre application.
Ce fichier se nomme ".env" et est disponible à la racine de votre application.
Par défaut, le fichier ".env" ressemble à cela :


# ./.env

# In all environments, the following files are loaded if they exist,
# the latter taking precedence over the former:
#
#  * .env                contains default values for the environment variables needed by the app
#  * .env.local          uncommitted file with local overrides
#  * .env.$APP_ENV       committed environment-specific defaults
#  * .env.$APP_ENV.local uncommitted environment-specific overrides
#
# Real environment variables win over .env files.
#
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
# https://symfony.com/doc/current/configuration/secrets.html
#
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration


###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=520d6e050c43ed44283ad18cc15255c2
###< symfony/framework-bundle ###
    

Comme indiqué dans les commentaires de ce fichier, c'est ici que l'on trouvera la configuration par défaut.
Mais il est possible de remplacer ces valeurs ou d'en ajouter de nouvelles en créant un fichier d'environnement spécifique.

Nous pouvons par exemple créer un fichier pour notre environnement de développement en local que nous nommerions ".env.local".
Cela nous permettrait ainsi de remplacer les valeurs de APP_ENV ou APP_SECRET ou de créer de nouvelles variables d'environnement.

Dans notre cas, nous définirons nos variables directement dans le fichier ".env" car elles ne seront utilisées que pour notre environnement de développement local.
Et nous souhaitons donc le conserver notre sur notre dépôt de code Git.

2. Installer le bundle Doctrine

Passons à l'installation du bundle Doctrine.
Nous pourrons ainsi nous appuyer sur ce dernier afin de gérer les transactions entre notre application et notre base de données.

Pour ceux qui se pose la question, oui vous pourriez très bien créer votre propre classe de connexion à la bdd.
Mais Doctrine intégre de nombreuses fonctionnalités très pratiques qui facileterons notre quotidiens.
Nous en verrons quelques exemples dans les prochains articles.

Pour le moment, commençons par mettre à jour nos bundles !

Dans un premier temps, il faut lancer les conteneurs :


docker comopse up -d
    

Et entrer dans le conteneur "blog-server" :


docker exec -it blog-server /bin/bash
    

Puis lancer la commande "composer update" :


root@e9b83459b3f9:/var/www/html# composer update
Loading composer repositories with package information
Restricting packages listed in "symfony/symfony" to "7.0.*"
Updating dependencies
Lock file operations: 1 install, 24 updates, 0 removals
  - Upgrading myclabs/deep-copy (1.12.0 => 1.13.1)
  - Upgrading nikic/php-parser (v5.1.0 => v5.5.0)
  - Upgrading php-webdriver/webdriver (1.15.1 => 1.15.2)
  - Upgrading phpunit/php-code-coverage (11.0.5 => 11.0.9)
  - Upgrading phpunit/php-file-iterator (5.0.1 => 5.1.0)
  - Upgrading phpunit/phpunit (11.3.1 => 11.5.22)
  - Upgrading psr/log (3.0.0 => 3.0.2)
[...]
  - Upgrading symfony/deprecation-contracts (v3.5.0 => v3.6.0): Extracting archive
  - Upgrading symfony/service-contracts (v3.5.0 => v3.6.0): Extracting archive
  - Upgrading symfony/event-dispatcher-contracts (v3.5.0 => v3.6.0): Extracting archive
  - Upgrading symfony/polyfill-php83 (v1.30.0 => v1.32.0): Extracting archive
  - Upgrading symfony/http-client-contracts (v3.5.0 => v3.6.0): Extracting archive
  - Upgrading php-webdriver/webdriver (1.15.1 => 1.15.2): Extracting archive
  - Upgrading symfony/panther (v2.1.1 => v2.2.0): Extracting archive
Generating autoload files
58 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

What about running composer global require symfony/thanks && composer thanks now?
This will spread some 💖  by sending a ★  to the GitHub repositories of your fellow package maintainers.

Run composer recipes at any time to see the status of your Symfony recipes.

Executing script cache:clear [OK]
Executing script assets:install public [OK]

Found 4 security vulnerability advisories affecting 4 packages.
Run "composer audit" for a full list of advisories.
root@e9b83459b3f9:/var/www/html#
    

Procédons maintenant à l'installation du bundle Doctrine :


composer require doctrine
    

Voici le résultat que vous devriez obtenir :


root@e9b83459b3f9:/var/www/html# composer require doctrine
./composer.json has been updated
Running composer update symfony/orm-pack
Loading composer repositories with package information
Restricting packages listed in "symfony/symfony" to "7.0.*"
Updating dependencies
Lock file operations: 18 installs, 0 updates, 0 removals
  - Locking doctrine/cache (2.2.0)
  - Locking doctrine/collections (2.3.0)
  - Locking doctrine/dbal (3.9.4)
[...]
  - Installing doctrine/doctrine-bundle (2.14.0): Extracting archive
  - Installing doctrine/doctrine-migrations-bundle (3.4.2): Extracting archive
  - Installing symfony/orm-pack (v2.4.1)
Generating autoload files
73 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

Symfony operations: 3 recipes (65b4fb3608d210ebe0e38e2192e314a1)
  - Configuring doctrine/deprecations (>=1.0): From github.com/symfony/recipes:main
  - Configuring doctrine/doctrine-bundle (>=2.10): From github.com/symfony/recipes:main
  -  WARNING  doctrine/doctrine-bundle (>=2.10): From github.com/symfony/recipes:main
    The recipe for this package contains some Docker configuration.

    This may create/update compose.yaml or update Dockerfile (if it exists).

    Do you want to include Docker configuration from recipes?
    [y] Yes
    [n] No
    [p] Yes permanently, never ask again for this project
    [x] No permanently, never ask again for this project
    (defaults to y): x
  - Configuring doctrine/doctrine-migrations-bundle (>=3.1): From github.com/symfony/recipes:main
  - Unpacked symfony/orm-pack
Executing script cache:clear [OK]
Executing script assets:install public [OK]

 What's next?


Some files have been created and/or updated to configure your new packages.
Please review, edit and commit them: these files are yours.

 doctrine/doctrine-bundle  instructions:

  * Modify your DATABASE_URL config in .env

  * Configure the driver (postgresql) and
    server_version (16) in config/packages/doctrine.yaml

Found 4 security vulnerability advisories affecting 4 packages.
Run "composer audit" for a full list of advisories.
root@e9b83459b3f9:/var/www/html#
    

3. Configurer la BDD

Suite à l'instalation de Doctrine, voici à quoi ressemble le fichier d'environnement par défaut :


# ./.env

# In all environments, the following files are loaded if they exist,
# the latter taking precedence over the former:
#
#  * .env                contains default values for the environment variables needed by the app
#  * .env.local          uncommitted file with local overrides
#  * .env.$APP_ENV       committed environment-specific defaults
#  * .env.$APP_ENV.local uncommitted environment-specific overrides
#
# Real environment variables win over .env files.
#
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
# https://symfony.com/doc/current/configuration/secrets.html
#
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration


###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=520d6e050c43ed44283ad18cc15255c2
###< symfony/framework-bundle ###

###> doctrine/doctrine-bundle ###
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
#
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data_%kernel.environment%.db"
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
###< doctrine/doctrine-bundle ###
    

Comme nous pouvons le remarquer le fichier d'environnement a été altéré par l'installation du bundle Doctrine.
Nous y trouvons maintenant une section "doctrine/doctrine-bundle".

C'est cette section qui va nous intéresser et que nous allons configurer comme suit :


DATABASE_URL="mysql://user:resu@mysql:3306/app?serverVersion=10.4-MariaDB&charset=utf8mb4"
    

L'installation de Doctrine a également ajouté 2 fichiers de configuration :
config/packages/doctrine.yaml
config/packages/doctrine_migrations.yaml

Ainsi que 3 répertoires :
migrations/
src/Entity/
src/Repository/

4. Tester la connexion à la base de données

Nous pouvons maintenant lancer une commande doctrine afin de vérifier que les paramètres que nous avons indiqué sont corrects. Nous allons pour cela demander à Doctrine de créer la base de donnée dont le nom par défaut est "app" comme nous l'avons défini dans le fichier "docker-compose.yml". La commande est la suivante :


bin/console doctrine:database:create
    

Le retour attendu est un message d'erreur nous indiquant que cette base de donnée existe déjà :


Could not create database `app` for connection named default
An exception occurred while executing a query: SQLSTATE[HY000]: General error: 1007 Can't create database 'app'; database exists
    

En effet, lorsque nous avec précisé la variable MYSQL_DATABASE: ${DB_DATABASE:-app} dans le fichier "docker-compose.yml" l'application s'est chargée de créer la base de donnée. Il est donc normal que nous recevions un message d'erreur de ce type.

Mais cela nous montre bien que la connexion fonctionne !

5. Améliorer le fichier d'environnement

C'est ici l'occasion d'améliorer notre fichier d'environnement. Nous allons donc ajouter une section "variables" qui pour le moment contiendra des informations relatives à la base de données. Ces variables pourront ainsi être reprise dans la chaine de configuration DATABASE_URL tout en étant plus lisible.


# ./.env

# In all environments, the following files are loaded if they exist,
# the latter taking precedence over the former:
#
#  * .env                contains default values for the environment variables needed by the app
#  * .env.local          uncommitted file with local overrides
#  * .env.$APP_ENV       committed environment-specific defaults
#  * .env.$APP_ENV.local uncommitted environment-specific overrides
#
# Real environment variables win over .env files.
#
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
# https://symfony.com/doc/current/configuration/secrets.html
#
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration

###> variables ###
DB_TYPE=mysql
DB_HOST=mysql
DB_VERSION=10.4.34
DB_VERSION_TYPE=-MariaDB
DB_NAME=app
DB_ROOT_PASSWORD=toor
DB_USER=user
DB_PASSWORD=resu
DB_PORT=3306
DB_CHARSET=utf8mb4
###< variables ###

###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=520d6e050c43ed44283ad18cc15255c2
###< symfony/framework-bundle ###

###> doctrine/doctrine-bundle ###
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
DATABASE_URL="${DB_TYPE}://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?serverVersion=${DB_VERSION}${DB_VERSION_TYPE}&charset=${DB_CHARSET}"
###< doctrine/doctrine-bundle ###
    

Outre la lisibilité, l'avantages est aussi de pouvoir passer ces variables au fichier "docker-compose.yml".
De cette façon nous sommes certain que la version téléchargée de MariaDB correspond bien à cette déclarée dans "DATABASE_URL" :


# ./docker-compose.yml

services:

  server:
    build:
      context: .
      dockerfile: ./automation/docker/Dockerfile
    container_name: blog-server
    volumes:
      - ./:/var/www/html
    links:
      - mysql
    ports:
      - 80:80
  
  mysql:
    image: mariadb:${DB_VERSION:-10.4}
    container_name: blog-mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-toor}
      MYSQL_DATABASE: ${DB_NAME:-app}
      MYSQL_USER: ${DB_USER:-user}
      MYSQL_PASSWORD: ${DB_PASSWORD:-resu}
    ports:
      - ${DB_PORT:-3306}:${DB_PORT:-3306}

  phpmyadmin:
    image: phpmyadmin:latest
    container_name: blog-phpmyadmin
    environment:
      - PMA_HOST=${DB_HOST:-mysql}
      - PMA_USER=${DB_USER:-user}
      - PMA_PASSWORD=${DB_PASSWORD:-resu}
    links:
      - mysql
    ports:
      - 8090:80

  mailer:
    image: schickling/mailcatcher
    container_name: blog-mailcatcher
    ports: 
      - 1025:1025
      - 1080:1080
    

Il est également plus simple de mettre à jour la version de MariaDB.
Pour cela, nous devons stopper et supprimer les conteneurs :


docker compose down
    

Modifier la version indiquée dans le fichier ".env" :


DB_VERSION=11.7.2
    

Et enfin, relancer les conteneurs :


docker compose up -d
    

Une nouvelle version de l'image de MariaDB sera téléchargée et utilisée pour construire notre conteneur de base de données :


[+] Running 9/9
 ✔ mysql Pulled                                                                                                                                                                                          6.7s
   ✔ d9d352c11bbd Pull complete                                                                                                                                                                          3.5s
   ✔ 22fa2c713273 Pull complete                                                                                                                                                                          3.5s
   ✔ 59c18060ab85 Pull complete                                                                                                                                                                          3.7s
   ✔ 1209b3d78c26 Pull complete                                                                                                                                                                          3.7s
   ✔ 425c2665a8f0 Pull complete                                                                                                                                                                          3.7s
   ✔ 2c2c2f1d0099 Pull complete                                                                                                                                                                          4.8s
   ✔ 8b0002849893 Pull complete                                                                                                                                                                          4.8s
   ✔ cdda351e58da Pull complete                                                                                                                                                                          4.8s
[+] Running 4/4
 ✔ Container blog-mailcatcher  Started                                                                                                                                                                   0.7s
 ✔ Container blog-server       Started                                                                                                                                                                   1.0s
 ✔ Container blog-phpmyadmin   Started                                                                                                                                                                   0.9s
 ✔ Container blog-mysql        Started 
    

6. Conclusion

Notre application Symfony est maintenant connectée à notre base de données MariaDB !
Nous avons également vu comment tester la connection à une base de données ainsi que la mise à jour de MariaDB.

a. Code source du projet

Si vous souhaitez utiliser ce projet dans l'état où il se trouve à la fin de cet article, vous pouvez le récupérer depuis mon repo Github.
Vous devrez pour cela lancer la commande "git clone" dans votre terminal afin de récupérer le tag v3.0.
N'oubliez pas de remplacer "mon_projet" par le nom que vous souhaitez utiliser pour votre répertoire d'installation :

git clone --depth 1 --branch v3.0 https://github.com/cpesin/contribution-blog-symfony-7-docker.git mon_projet

b. Sources