Entités - Modèles
Pour créer des entités dans notre application, nous allons utiliser le Maker : php bin/console make:entity.
L'assistant ligne de commande est plutôt clair et simple à utiliser. Choisissez pour chaque propriété que vous voulez créer son type, sa taille, nullable ou non, etc...
Une fois notre entité terminée, le Maker nous a créé une classe d'entité dans src/Entity ainsi qu'une classe de repository dans src/Repository.
L'entité
Cette classe contient différentes propriétés qui deviendront plus tard les colonnes de nos tables.
Les attributs sont définis dans un espace de nom Doctrine\ORM\Mapping, qui est ici automatiquement aliasé en ORM. Quand on utilise un attribut, on n'a donc plus qu'à indiquer #[ORM\...].
Le maker nous a donc fait tout le travail : générer les propriétés de notre classe, ainsi que les attributs qui vont être utiles à Doctrine pour nous permettre ensuite de créer les éléments de structure correspondants dans la base de données.
On le voit au travers des attributs utilisés : Id par exemple, nous sert à définir quel attribut sera la clé primaire de notre table, tandis que GeneratedValue configurera automatiquement l'auto-incrémentation des ID dans notre table.
Retrouvez la liste des attributs Doctrine en cliquant sur ce lien.
Tout comme dans les contrôleurs et l'attribut Route, avant PHP8 on utilisait les annotations pour définir les métadonnées Doctrine des attributs
Enfin, l'encapsulation est incluse par défaut, puisque pour chaque attribut on peut trouver un getter et un setter associés.
Le repository
En plus de la classe d'entité, le maker nous a généré une autre classe dans le dossier src/Repository : un dépôt avec le nom de l'entité comme préfixe.
On verra plus tard l'utilisation concrète des repositories. Pour le moment, on retiendra la définition générale : un repository nous permet de communiquer avec la base de données à propos d'une entité. On ne voudra donc surtout pas supprimer ce fichier.
En une commande de la console, nous avons donc généré 2 fichiers relatifs à notre entité. Mais si on va consulter la base de données, rien n'a changé. Effectivement, il va falloir réutiliser la console si on veut effectivement mettre à jour la base de données à partir de nos nouvelles entités.
Mise à jour de la base de données
Nous allons voir 2 manières de mettre à jour la base de données : les migrations et les mises à jour à la volée.
Dans tous les cas, les mises à jour de base de données se font en 2 étapes : préparation & revue du code SQL qui va être exécuté, puis exécution de la mise à jour.
Avant de pouvoir effectuer des mises à jour dans la base de données, il faut renseigner l'URL d'accès à la base de données dans le fichier .env.local, qui n'est pas intégré au gestionnaire de versions (Documentation)
Migrations
Une migration va être représentée par un fichier décrivant les changements à effectuer (en SQL) au sein de la base de données.
Ainsi, plus on a de migrations, plus on a de traces des différents changements de structure effectués. C'est un peu comme si on versionnait notre structure de base de données.
Générer une migration
Pour générer une migration, on va simplement exécuter la commande suivante du Maker :
php bin/console make:migration
On commence à voir que les commandes du maker sont toutes préfixées par make:
Cette commande va comparer le contenu de nos classes d'entités avec le contenu de la structure de la base de données, puis générer une classe de migration dans le dossier migrations, contenant le code SQL nécessaire à la synchronisation des 2 côtés (code & BDD).
Une fois la migration générée, elle n'est pas encore exécutée. La base de données n'est donc pas encore impactée.
On peut (et idéalement, on doit) aller vérifier dans le fichier généré que le code SQL correspond aux mises à jour que l'on souhaite effectuer.
Exécuter une migration
Une fois le code SQL passé en revue, on peut exécuter la mise à jour, donc exécuter la migration :
php bin/console doctrine:migrations:migrate
# Ou plus court
php bin/console d:m:m
Dans ce cas, le package de migrations de Doctrine prend le relais : il va vérifier les migrations déjà éventuellement exécutées, pour éviter d'exécuter la même 2 fois, et exécuter celles qui doivent l'être.
Le package de migrations est un autre projet de Doctrine. Dans notre projet à nous, il est automatiquement intégré au sein de Symfony grâce au package doctrine/doctrine-migrations-bundle
Pour vérifier les migrations déjà effectuées, il se réfère simplement à la base de données. Après la première migration, on remarquera la présence d'une table doctrine_migration_versions. Elle contient le FQCN de la classe de migration qu'on vient d'exécuter, la date et le temps d'exécution.
L'approche avec migrations pour la base de données est la manière recommandée pour gérer les évolutions de structures. Elle présente l'avantage principal d'être rigoureuse, avec la génération de classes de migrations permettant de cibler précisément et rigoureusement les mises à jour effectuées. Par ailleurs, ces classes sont intégrées au contrôle de version, on peut donc avoir un historique plus précis des modifications de structure effectuées.
Cependant, il faut bien veiller à ne pas s'emmêler les pinceaux dans les différentes mises à jour de structures, et que l'outil de migration s'y retrouve également
Mise à jour à la volée
Le fonctionnement est similaire, mais ne génère aucun fichier de migration. Tout s'effectue dans la console.
Revue du code qui va être exécuté : php bin/console doctrine:schema:update --dump-sql.
Exécution à la volée des mises à jour nécessaires : php bin/console doctrine:schema:update --force.