Blog

Guide de Migration : Passer de Doctrine ORM v2 à v3

Basculez votre projet Symfony sur Doctrine ORM 3 en toute sécurité. Guide par étape depuis 2.19, automatisation avec Rector et nettoyage des dépréciations.

Louis Fortunier Louis Fortunier
|
|
7 min de lecture
| Tech
Résumez cette page avec votre IA préférée :
Migration Doctrine : Le guide complet pour passer de la v2 à v3

Guide de Migration : Passer de Doctrine ORM v2 à v3

La sortie de Doctrine ORM 3, le 3 février 2024, marque un tournant majeur pour l’écosystème PHP. Si la version 2.x nous a accompagnés pendant plus d’une décennie, la v3 apporte une cure de jouvence nécessaire en supprimant les comportements obsolètes et en se reposant sur les fonctionnalités modernes de PHP 8.1+.

Pourquoi franchir le pas ?

Avant de plonger dans le code, voici pourquoi cette migration est cruciale :

  • Standardisation sur les Attributs PHP 8 : La v3 abandonne définitivement les annotations (type @ORM\Column) au profit des attributs natifs. Cela permet une meilleure analyse statique via PHPStan ou Psalm et une meilleure complétion dans l’IDE.
  • Compatibilité avec DBAL v4 : En passant à l’ORM v3, vous débloquez l’utilisation de DBAL 4. Cette version de la couche d’abstraction de base de données a été entièrement revue pour supprimer les abstractions inutiles, ce qui réduit drastiquement l’overhead CPU lors des requêtes SQL complexes.
  • Suppression des “Partial Objects” : Dans la v2, charger des objets partiels (sans tous les champs) était une source majeure de bugs silencieux (accès à une propriété non chargée). La v3 impose une gestion plus saine des données : un objet chargé est un objet complet (propriété hydraté hors relation lazy).
  • Épuration du cycle de vie des entités : Des méthodes ambiguës comme merge() ou l’utilisation de NotifyPropertyChanged ont été supprimées. Cela simplifie la compréhension du Unit of Work (le mécanisme qui suit les changements de vos objets) et rend le comportement de Doctrine beaucoup plus prévisible lors du flush().
  • Lazy-loading optimisé : La gestion des Proxies (les objets fantômes chargés à la demande) a été simplifiée et rendue plus robuste grâce aux nouvelles capacités de réflexion de PHP 8, limitant les erreurs liées à l’initialisation des relations OneToOne ou ManyToOne.
  • Pérennité : La version 2 finit par ne plus recevoir de correctifs de sécurité. Être en v3 vous prépare aux futures évolutions de Symfony et de l’écosystème PHP.

Sommaire de la migration

  1. Étape 1 : Mise à jour vers Doctrine 2.19+
  2. Étape 2 : Nettoyage des dépréciations
  3. Étape 3 : Bascule vers l’ORM v3
  4. Étape 4 : Validation et Stabilisation

Étape 1 : Mise à jour vers Doctrine 2.19+

On ne saute pas dans le vide ! La clé d’une migration réussie est d’atteindre la version la plus haute de la branche 2.x.

Pourquoi cette étape ?

La version 2.19 (et supérieures) a été conçue comme un pont. Elle contient toutes les nouvelles interfaces de la v3 mais conserve la compatibilité ascendante. C’est ici que votre outil de debug commencera à vous alerter.

Monter les dépendances

Utilisez la commande suivante pour mettre à jour l’ensemble des paquets Doctrine vers leur dernière version mineure :

composer update "doctrine/*"

Arrêt obligatoire : Si vos tests échouent ici, ne continuez pas. Votre application doit être parfaitement stable en v2.19 avant d’aller plus loin.

Étape 2 : Nettoyage des dépréciations

C’est l’étape la plus chronophage. La v3 supprime tout ce qui était “deprecated” en v2.

Ce qu’il faut surveiller :

  • Migration vers les Attributs PHP 8 : C’est le changement majeur. La v3 abandonne définitivement le support des annotations dans les DocBlocks. C’est le chantier prioritaire car il rend obsolète toute configuration via commentaires :
    • Mapping Doctrine : Migration impérative de @ORM\... vers #[ORM\...].
    • Validation Symfony : Migration impérative de @Assert\... vers #[Assert\...].
    • Validateurs personnalisés
    • Bundles tiers (Selon vos projets) : Si vous utilisez des bibliothèques spécifiques, vérifiez la conversion des annotations en attributs comme par exemple avec JMS Serializer, NelmioApiDoc, VichUploaderBundle.
  • Ajout de la version complète de MySQL : Doctrine DBAL 4 ne devine plus le patch version de votre base de données ; vous devez désormais lui déclarer explicitement (ex: 8.0.33 au lieu de 8.0).
  • Validation stricte du mapping : L’activation de l’option doctrine.orm.validate_xml_mapping: true devient indispensable pour garantir que vos fichiers de configuration respectent rigoureusement les nouveaux schémas XSD de l’ORM 3 et éviter ainsi tout comportement imprévisible.
  • Fin du mapping automatique dans les contrôleurs :
    Le paramètre doctrine.orm.controller_resolver.auto_mapping passera par défaut à false. Pour éviter que vos injections d’entités dans les méthodes de contrôleur ne s’arrêtent de fonctionner, vous devez soit forcer la valeur à true dans votre configuration, soit (mieux encore) utiliser explicitement l’attribut #[MapEntity] pour déclarer vos résolutions d’objets.
  • Compatibilité des bundles : listez vos bundles qui interagissent avec Doctrine (Gedmo, DoctrineBehaviors, etc.) et assurez-vous qu’une version compatible avec l’ORM v3 est disponible.
  • Refactorisation du Code (liste non exhaustive, si applicable à votre usage) :
    • Accès à l’EntityManager dans un repository : Si votre projet utilise encore la propriété protégée $_em dans les repositories, remplacez-la par l’appel à la méthode getEntityManager().
    • Gestion des paramètres : Si vous utilisez setParameters() avec un tableau simple, privilégiez désormais l’usage de setParameter() de manière unitaire pour chaque variable, ou passez par une ArrayCollection.
    • Fonction doctrine personnalisé : Pour les extensions DQL personnalisées, remplacez les constantes Lexer::T_... par la nouvelle Enum Doctrine\ORM\Query\TokenType.

Conseil Smartbooster : Utilisez l’outil Rector. Il existe des règles spécifiques pour Doctrine qui automatiseront 90% des changements de syntaxe pour vous.

Exemple d’utilisation de Rector pour le mapping

  1. Installation
composer req  rector/rector --dev
  1. Configuration : Créez un fichier rector.php à la racine de votre projet.
 <?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Doctrine\Set\DoctrineSetList;

return RectorConfig::configure()
    ->withPaths([
        __DIR__ . '/src',
    ])
    // Adaptez à votre version de PHP
    ->withPhpVersion(Rector\ValueObject\PhpVersion::PHP_84)
    ->withPreparedSets(doctrineCodeQuality: true)
    ->withComposerBased(doctrine: true);

    // Ou sur une version plus ancienne de rector
    // ->withSets([
    //      DoctrineSetList::DOCTRINE_CODE_QUALITY,
    //      DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES,
    //  ])
  1. Lancement de la correction Commencez par un test sans modifier les fichiers pour vérifier les changements :
vendor/bin/rector process --dry-run

Si le résultat vous convient, appliquez les modifications :

vendor/bin/rector process

Étape 3 : Bascule vers l’ORM v3

Une fois que votre projet tourne en 2.19 sans aucun message de dépréciation dans les logs de Symfony, modifiez votre fichier composer.json avec la version majeur supérieur. Exemple :

{
    "require": {
        "doctrine/orm": "^3.0",
    }
}

Puis lancez la mise à jour :

composer update doctrine/*

Étape 4 : Validation et Stabilisation

Cette étape cruciale sert à garantir que le changement de moteur interne n’a pas altéré la logique métier de votre application. Orm v3 modifie la manière dont les objets sont chargés et dont le SQL est généré. Sans une validation rigoureuse, vous risquez des régressions silencieuses en production (données incomplètes, erreurs de types ou baisses de performance).

La Checklist de Validation

  • Analyse Statique (PHPStan/Psalm) : C’est votre premier rempart. La v3 étant strictement typée, relancez une analyse pour détecter les incompatibilités de types entre vos entités et votre code métier.
  • Tests Unitaires : Vérifiez que la logique interne de vos entités (calculs, méthodes métier) n’est pas impactée par le passage aux Attributs ou aux nouvelles contraintes de mapping.
  • Tests d’Intégration (Base de données) : C’est le point le plus critique. Relancez vos tests qui interagissent réellement avec la base de données pour valider que les requêtes DQL/SQL complexes produisent toujours le résultat attendu.
  • Analyse du Schéma : Utilisez la commande php bin/console doctrine:schema:validate. Elle doit confirmer que votre mapping est synchrone avec l’état actuel de votre base de données. Capture d'écran du succès de la commande doctrine:schema:validate dans le terminal
  • Tests Manuels (Audit du Profiler) : Naviguez sur les pages clés de votre application et surveillez le Profiler Symfony. Vérifiez qu’il n’y a pas d’explosion du nombre de requêtes suite à la nouvelle gestion des Proxies.

Note importante : Cette checklist ne doit pas être réservée à la fin du projet. Pour une migration sereine, appliquez ces vérifications à chaque étape du processus. Ne considérez la migration comme terminée que lorsque votre barre de tests est 100% verte et que l’analyse statique ne remonte plus aucune erreur de type.

Conclusion

La migration vers Doctrine 3 demande de la rigueur, surtout sur la correction des dépréciations en amont. Cependant, une fois terminée, votre application gagne en robustesse et en clarté. Prêt à migrer ? Commencez par un composer update "doctrine/*" et écoutez ce que vos logs vous disent !

Liens utiles

Louis Fortunier
Louis Fortunier Développeur
Mots clés :
#Qualité #Productivité

Articles similaires

Vous avez un projet ?

Contactez-nous pour savoir comment nous pouvons vous aider.