Monorepo avec PHP : organisation du code pour des projets évolutifs
Dans le développement PHP moderne, la gestion du code devient cruciale à mesure que le projet grandit. L'approche traditionnelle avec plusieurs dépôts séparés (polyrepo) entraîne souvent des problèmes de synchronisation, de duplication des dépendances et des difficultés lors du refactoring. L'alternative est le monorepo, où tout le code, y compris les bibliothèques, les utilitaires et les applications, est stocké dans un seul dépôt Git. Dans cet article, nous allons voir comment organiser un monorepo en PHP en utilisant Composer, Git et des outils modernes.
Qu'est-ce qu'un monorepo et pourquoi en a-t-on besoin en PHP ?
Un monorepo est un dépôt unique contenant plusieurs projets, paquets ou modules qui peuvent être logiquement liés. Pour un développeur PHP, cela signifie que le cœur du framework, le service API, le panneau d'administration et les bibliothèques communes se trouvent dans un seul dossier.
Avantages du monorepo :
- Versionnage unique : Toutes les modifications sont commitées de manière atomique — une correction dans une bibliothèque est immédiatement accompagnée de la mise à jour du code qui l'utilise.
- Simplification du refactoring : Vous pouvez modifier l'interface d'un paquet et mettre à jour immédiatement toutes les dépendances dans le cadre d'une seule pull request.
- Standardisation des outils : Un seul fichier
composer.jsonpour la racine, des règles de linting et de test unifiées. - Réduction de la duplication : Le code commun (par exemple, DTO, helpers) n'a pas besoin d'être publié sur Packagist — il est accessible directement.
Cependant, un monorepo exige de la discipline : sans une structure claire, il se transforme en « dépotoir ». La clé du succès est une organisation correcte avec l'autoload de Composer et les sous-modules Git ou des outils spécialisés comme monorepo-builder.
Structure d'un monorepo en PHP
Examinons une structure typique pour un projet PHP qui comprend plusieurs bibliothèques et une application. Le répertoire racine ressemble à ceci :
my-monorepo/├── packages/│ ├── core/ # Bibliothèque de base (cœur)│ │ ├── src/│ │ │ └── CoreClass.php│ │ └── composer.json│ ├── logger/ # Journalisation│ │ ├── src/│ │ └── composer.json│ └── api/ # Paquet API (peut être une application séparée)│ ├── src/│ │ └── Controllers/│ └── composer.json├── apps/│ └── web/ # Application web (Laravel/Symfony)│ ├── public/│ ├── src/│ └── composer.json├── composer.json # composer.json racine (méta-paquet)├── phpunit.xml.dist└── .gitignorePrincipes d'organisation :
- Tous les paquets se trouvent dans
packages/. Chaque paquet a son proprecomposer.jsonavec un nom unique (par exemple,mycompany/core). - Les applications (frontend, admin, API) se trouvent dans
apps/. Elles peuvent utiliser les paquets depackages/comme dépendances locales. - Le
composer.jsonracine sert à la configuration globale (autoload, scripts).
Configuration de Composer pour fonctionner avec un monorepo
Pour que l'autoloading PHP fonctionne sans publier les paquets sur Packagist, nous utilisons les dépôts de type path. Ajoutez le bloc suivant dans le composer.json racine :
{ "name": "mycompany/monorepo", "require": { "mycompany/core": "*", "mycompany/logger": "*" }, "repositories": [ { "type": "path", "url": "packages/*" } ], "autoload": { "psr-4": { "MyCompany\\\\": "packages/" } }, "scripts": { "test": "phpunit" }}Maintenant, lors de l'exécution de composer install, Comp