J'avais déjà fait un article sur le sujet à propos de Symfony 6, mais il se trouve que la manière d'ajouter un préfixe aux tables en base de données sans changer le nom de nos entités a changé avec Symfony 7.
Dans l'idée, c'est la même chose. On va créer un service, qui sera appelé lors d'un évènement de doctrine, et qui ajoutera le préfixe qu'on aura choisi.
Pourquoi préfixer ses tables ?
Ajouter un préfixe à ses tables a de nombreux avantages. Tout d'abord, pour la sécurité. En effet, une table users, tous les sites du monde en ont une. En cherchant une faille de sécurité, on risque de pouvoir facilement accéder à cette table, même sans connaitre l'arborescence du projet, si elle a un nom trop courant. Et c'est un argument valable même si on peut avoir autant de base de données qu'on veut (soit une par projet) : préfixer ses tables sera toujours un gain non négligeable sur le plan de la sécurité.
Ensuite, si vous êtes sur des petits projets, que vous utilisez un hébergement mutualisé, ou que sais-je encore, qui vous contraint à n'avoir qu'une base de données pour tous vos sites, préfixer vos tables est indispensable. Cela permet de différencier des tables qui auraient le même nom (users et users, par exemple...), en leur ajoutant un préfixe propre à chaque projet. Ainsi, nous aurions ck_users et bk_users, pour des sites comme cooking et booking par exemple. Plus de confusion possible, plus de risques d'agir sur les mauvaises tables.
Enfin, pour un travail de maintenance et de sauvegarde, le jour où vous avez besoin de faire une sauvegarde ou de réinstaller les tables d'un projet, pouvoir les sélectionner grâce à un préfixe commun est un énorme atout : plus de risques d'oublis, ou au contraire d'associer des tables d'un autre projet à votre sauvegarde...
Bref, c'est une très bonne hygiène de travail, tant sur les plans technique, sécuritaire et pratiques !
Sauf que dans Symfony, l'ORM doctrine récupère les entités, et à partir de leur nom, crée les tables automatiquement. C'est super pratique, mais ça pose un problème : est-ce que si je veux préfixer mes tables, j'accepte d'avoir des noms de classes bizarres, comme CkUser ou BkUser, à la place de User, tout simplement ?
C'est la solution qui vient à l'esprit quand on ne sait pas trop comment imposer à Doctrine le préfixe : on choisit de préfixer directement les entités dans le code.
Création d'un service d'ajout d'un préfixe
S'il est impossible de trouver quoi que ce soit dans la documentation de Symfony, la doc de Doctrine donne quelques indications à propos des préfixes.
Tout d'abord, créer un fichier DatabaseTablePrefix.php
, stocké dans un dossier src\Service
.
Configurer le service
Une fois ce code enregistré, il faut mettre en place la configuration associée.
Dans le fichier config/services.yaml
, on met ce code :
Attention à l'indentation, c'est très important de bien revenir aux bonnes lignes au bon moment. Dans ce code, on dit à symfony qu'il faut appeler notre service à chaque fois que doctrine est appelé. Et on en profite pour lui dire que nous stockerons la valeur de notre variable $prefix
dans notre fichier .env
. C'est un choix que j'ai fait pour tout regrouper au même endroit. Bien sûr, on aurait pu lui donner sa valeur ici. Mais puisque dans le .env
nous avons toutes les infos concernant la BDD, autant y ranger le préfixe aussi non ?
Définir le préfixe dans le .env
Et donc, pour finir, il faut aller dans le .env
pour donner la valeur de notre préfixe :
Les guillemets autour du prefix_
sont facultatifs. Évidemment, vous remplacerez "prefix" par ce que vous voudrez ! 😉
Vous aviez déjà fait votre migration sans préfixe ?
Si vous aviez déjà lancé votre projet, créé vos fichiers de migration, et tout le tralala, il va falloir revenir en arrière. En effet, on vient de voir comment ajouter un préfixe à nos tables, mais cela n'est pas rétroactif : si vous avez déjà fait vos fichiers de migration avec des noms de tables sans préfixe, lorsque vous demanderez à Doctrine d'effectuer la migration, elle n'ajoutera pas les préfixes, puisqu'ils ne sont pas écrits.
C'est au moment de la création des fichiers de migrations que le préfixe pourra être ajouté. Pour cela, on va avoir quelques lignes de commandes à faire.
Nettoyer la base de données des tables existantes :
Cette commande permet de vider totalement la base de données.
Vider le cache de Symfony
Faire la migration avec les préfixes des tables
Effectuer la migration en base de données
Conclusion
Ça y est ! vous avez vos tables préfixées en base de données, et pourtant vous pouvez continuer à travailler avec vos entités sans que rien ne change dans votre code.
Mieux encore : cela est pris en compte quelque soit votre environnement de travail : local, prod, test... Toutes vos tables seront préfixées de la même manière, ce qui est important pour un soucis de cohérence.
A l'exception de deux tables tables (il faut toujours des exceptions) : la table messenger_messages
et la table doctrine_migration_versions
, qui sont gérées par symfony (et ses dépendances), ne prennent pas en compte le préfixe. Allez savoir pourquoi, c'est un mystère.
C'est un peu embêtant, parce que lorsqu'on fera la mise en production de plusieurs projets symfony sur un hébergement mutualisé par exemple, et bien il n'y aura qu'une seule fois ces tables pour tous les projets.
Cependant ce n'est pas dramatique, parce qu'en production ( et particulièrement sur mutualisé où vous n'avez peut-être même pas accès à la ligne de commande), ces deux tables ne nous serviront pas (pour les migrations c'est sûr, pour les messages, ça dépend des cas...)
Si vous connaissez la réponse à cette énigme, n'hésitez pas à la proposer dans les commentaires !
One Reply to “Ajouter un préfixe aux tables en base de données sans changer le nom des entités dans Symfony 7”
Excellent sujet et très bonne explication comme d’hab 😉
Un grand merci