Pris au piège!
06 01 2025En tant que développeur, je passe une bonne partie de mon temps à trouver des solutions à des problèmes qui, à première vue, semblent simples. Mais parfois, derrière cette simplicité se cache une opportunité d'apprendre quelque chose de nouveau ou de créer une solution plus adaptée à ses besoins. C'est exactement ce qui m'est arrivé récemment en travaillant sur une entité Cart dans un projet Symfony.
👉 Le problème initial
L'entité concernée utilise deux champs : $updatedAt et $updatedBy. Ces champs sont là pour suivre les modifications effectuées sur l'entité, respectivement avec :
- La date et l'heure de la dernière mise à jour $updatedAt.
- L'utilisateur responsable de cette modification $updatedBy.
Pour gérer automatiquement ces champs, le développeur initial avait choisi d'utiliser Gedmo/Blameable, une extension bien connue pour Doctrine qui permet de mettre à jour ces valeurs automatiquement lors de certains événements (par exemple, à chaque modification de l'entité).
Mais un besoin spécifique est rapidement apparu : je voulais que ces champs soient mis à jour uniquement dans certains cas bien précis. Par exemple, si une modification était effectuée automatiquement par le système (ce qui est mon cas via un CronJob), je ne voulais pas que $updatedAt et $updatedBy soient mis à jour. Gedmo/Blameable ne permettait pas un tel contrôle.
Dans mon cas - comme dit quelque caractère plus haut - un CronJob modifiais Cart ce qui changeais la date de dernière modification $updatedAt (mais pas l'utilisateur, puisque personne n'est attaché à ce CronJob). Le problème est simple : ce n'est en aucun cas une action du propriétaire du panier.
👉 La solution : un listener personnalisé
Après quelques réflexions, j’ai décidé de remplacer Gedmo/Blameable par un listener Doctrine personnalisé. Cela m'a permis de définir clairement 'quand' et 'pourquoi' les champs $updatedAt et $updatedBy sont mis à jour.
👉 Voici les grandes étapes de la mise en place :
- Création d'un listener Doctrine : J'ai écrit un service qui écoute l'événement preUpdate de Doctrine.
- Ajout d'une logique conditionnelle : Dans le listener, j'ai ajouté des conditions pour contrôler la mise à jour des champs en fonction du contexte de la modification.
- Injection du contexte d'action : J'ai introduit un service dédié à la gestion du contexte (était-ce une action utilisateur ? un process automatique ?), ce qui permet une gestion encore plus fine.
☝️ Pourquoi cette approche est meilleure ?
- Flexibilité : Le listener me permet de contrôler exactement les cas où les champs $updatedAt et $updatedBy doivent être modifiés.
- Lisibilité : La logique est centralisée et explicite, ce qui facilite sa compréhension pour d'autres développeurs.
- Évolutivité : Si de nouveaux cas ou besoins apparaissent, il suffit d'ajouter une condition dans le listener.
Remplacer Gedmo/Blameable par un listener personnalisé était une décision motivée par la recherche d’une solution sur mesure. Au-delà de résoudre le problème initial, cette approche m’a permis de mieux comprendre comment tirer parti des événements Doctrine pour répondre à des besoins précis.
Dans le futur, si je suis confronté à des limitations avec des outils "prêts à l’emploi", je n'hésiterai pas à envisager des solutions personnalisées.
Pour ce post, je n'ai pas encore mis en place de système pour afficher du code proprement - j'ai une idée bien précise en tête - à voir si je la mets en place pour le prochain post... 😱