Introduction : pourquoi un monorepo en PHP ?
\nLe développement d'applications PHP complexes (CRM, SaaS, frameworks) se heurte souvent à un dilemme : stocker tout le code dans un seul dépôt (monorepo) ou le diviser en plusieurs microservices et paquets. Le monorepo avec PHP est une stratégie où plusieurs projets liés (bibliothèques, modules, applications) se trouvent dans un seul dépôt Git.
\nEn pratique, cela offre :
\n- \n
- Un historique unique des modifications — plus facile de suivre comment un changement dans un paquet a affecté un autre. \n
- Une configuration CI/CD simplifiée — un seul pipeline pour la construction et les tests de tous les composants. \n
- Une réduction des doublons — configurations, scripts et dépendances partagés. \n
- Une itération rapide — pas besoin de publier les paquets sur Packagist pour les tests locaux. \n
Cependant, le monorepo exige de la discipline. Sans une organisation correcte du code, il se transforme en « monolithe spaghetti ». Dans cet article, nous allons détailler les étapes pratiques pour organiser un projet PHP dans un monorepo.
\n\n1. Structure des répertoires du monorepo
\nLe principe clé est une séparation claire entre paquets et applications. Prenons l'exemple d'une architecture typique :
\n\nproject-root/\n├── apps/\n│ ├── web/ # Application web (Symfony/Laravel)\n│ │ ├── public/\n│ │ ├── src/\n│ │ └── composer.json\n│ └── api/ # Application API (Lumen/Slim)\n│ ├── public/\n│ ├── src/\n│ └── composer.json\n├── packages/\n│ ├── core/ # Cœur (interfaces communes, entités)\n│ │ ├── src/\n│ │ └── composer.json\n│ ├── billing/ # Module de paiement\n│ │ ├── src/\n│ │ └── composer.json\n│ └── notifications/ # Module de notifications\n│ ├── src/\n│ └── composer.json\n├── tools/ # Scripts de développement (PHP-CS-Fixer, PHPStan)\n├── composer.json # Manifeste racine\n└── phpstan.neon # Paramètres d'analyse communs\n\nRemarque : chaque paquet dans packages/ est une bibliothèque Composer complète avec son propre composer.json. Cela permet d'isoler les dépendances et de les tester séparément.
Exemple de composer.json pour le paquet core
\n{\n "name": "myproject/core",\n "type": "library",\n "autoload": {\n "psr-4": {\n "MyProject\\\\Core\\\\": "src/"\n }\n },\n "require": {\n "php": ">=8.1"\n },\n "extra": {\n "branch-alias": {\n "dev-main": "1.x-dev"\n }\n }\n}\n\n2. Gestion des dépendances avec Composer
\nLe composer.json racine est le cœur du monorepo. Il contient :
- \n
- La liste de tous les paquets connectés localement (via le dépôt
path). \n - Les dépendances de développement pour l'ensemble du projet (PHPUnit, PHPStan, GrumPHP). \n
- Les scripts d'automatisation (analyse statique, tests). \n
Exemple de composer.json racine
\n{\n "name": "myproject/monorepo",\n "type": "project",\n "repositories": [\n {\n "type": "path",\n "url": "packages/*",\n "options": {\n "symlink": true\n }\n }\n ],\n "require": {\n "myproject/core": "@dev",\n "myproject/billing": "@dev",\n "myproject/notifications": "@dev"\n },\n "require-dev": {\n "phpunit/phpunit": "^10.0",\n "phpstan/phpstan": "^1.10",\n "friendsofphp/php-cs-fixer": "^3.0"\n },\n "autoload": {\n "psr-4": {\n "MyProject\\\\": "packages/*/src/"\n }\n },\n "scripts": {\n "test": "phpunit",\n "analyse": "phpstan analyse",\n "cs-fix": "php-cs-fixer fix"\n }\n}\n\nPoints clés :
\n- \n
- symlink: true