L’article propose une solution pour gérer les transactions en couche applicative dans une architecture hexagonale, sans dépendre de l’infrastructure comme Doctrine. L’idée centrale est d’introduire un port TransactionManagerInterface dans l’application, implémenté par un adaptateur Doctrine qui utilise wrapInTransaction() pour encapsuler les opérations dans une transaction unique. Cela permet d’éviter les problèmes de cohérence, comme des modifications partielles en cas d’échec, en regroupant plusieurs opérations (persistance, mise à jour) dans un bloc atomique.
L’auteur illustre le problème avec un cas concret : la création d’une commande et la mise à jour simultanée des stocks. Sans gestion centralisée, chaque appel à flush() (via add() ou update()) crée une transaction implicite, risquant des incohérences si une étape échoue. La solution repose sur un service applicatif (OrderService) qui dépend uniquement des interfaces de domaine et du TransactionManagerInterface, isolant ainsi la logique métier des détails d’infrastructure.
Enfin, l’implémentation montre comment le TransactionManager utilise les mécanismes natifs de Doctrine pour gérer les transactions de manière robuste, y compris les erreurs PHP, tout en maintenant une séparation claire des responsabilités. Les méthodes add() et update() des repositories doivent éviter d’appeler flush() directement pour préserver l’intégrité transactionnelle.