Monorepository mit PHP: Code-Organisation in der Praxis

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum ein Monorepository in PHP?

\n

Die Entwicklung komplexer PHP-Anwendungen (CRM, SaaS, Frameworks) steht oft vor einem Dilemma: Soll der gesamte Code in einem Repository (Monorepository) gespeichert oder in viele Microservices und Pakete aufgeteilt werden? Ein Monorepository (Monorepo) mit PHP ist eine Strategie, bei der mehrere zusammenhängende Projekte (Bibliotheken, Module, Anwendungen) in einem einzigen Git-Repository liegen.

\n

In der Praxis bietet dies:

\n
    \n
  • Eine einheitliche Änderungshistorie — einfacher nachzuvollziehen, wie sich eine Änderung in einem Paket auf ein anderes ausgewirkt hat.
  • \n
  • Vereinfachte CI/CD-Konfiguration — eine einzige Pipeline zum Erstellen und Testen aller Komponenten.
  • \n
  • Reduzierung von Redundanzen — gemeinsame Konfigurationen, Skripte und Abhängigkeiten.
  • \n
  • Schnelle Iteration — keine Notwendigkeit, Pakete für lokale Tests auf Packagist zu veröffentlichen.
  • \n
\n

Allerdings erfordert ein Monorepository Disziplin. Ohne eine korrekte Code-Organisation wird es zu einem „Spaghetti-Monolithen“. In diesem Artikel werden wir praktische Schritte zur Organisation eines PHP-Projekts in einem Monorepository durchgehen.

\n\n

1. Verzeichnisstruktur des Monorepositorys

\n

Das Schlüsselprinzip ist eine klare Trennung in Pakete und Anwendungen. Betrachten wir ein Beispiel einer typischen Architektur:

\n\n
project-root/\n├── apps/\n│   ├── web/                  # Webanwendung (Symfony/Laravel)\n│   │   ├── public/\n│   │   ├── src/\n│   │   └── composer.json\n│   └── api/                  # API-Anwendung (Lumen/Slim)\n│       ├── public/\n│       ├── src/\n│       └── composer.json\n├── packages/\n│   ├── core/                 # Kern (allgemeine Schnittstellen, Entitäten)\n│   │   ├── src/\n│   │   └── composer.json\n│   ├── billing/              # Zahlungsmodul\n│   │   ├── src/\n│   │   └── composer.json\n│   └── notifications/        # Benachrichtigungsmodul\n│       ├── src/\n│       └── composer.json\n├── tools/                    # Entwicklungsskripte (PHP-CS-Fixer, PHPStan)\n├── composer.json             # Root-Manifest\n└── phpstan.neon              # Allgemeine Analyse-Einstellungen
\n\n

Beachten Sie: Jedes Paket in packages/ ist eine vollwertige Composer-Bibliothek mit eigener composer.json. Dies ermöglicht es, Abhängigkeiten zu isolieren und sie separat zu testen.

\n\n

Beispiel composer.json für das Paket 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\n

2. Abhängigkeitsverwaltung mit Composer

\n

Die root-composer.json ist das Herz des Monorepositorys. Sie enthält:

\n
    \n
  • Eine Liste aller lokal eingebundenen Pakete (über das path-Repository).
  • \n
  • Dev-Abhängigkeiten für das gesamte Projekt (PHPUnit, PHPStan, GrumPHP).
  • \n
  • Skripte zur Automatisierung (statische Analyse, Tests).
  • \n
\n\n

Beispiel einer root composer.json

\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\n

Wichtige Punkte:

\n
    \n
  • symlink: true

Blogs

Buchempfehlungen