Monorepositorio con PHP: organización del código en la práctica

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿por qué un monorepositorio en PHP?

\n

El desarrollo de aplicaciones PHP complejas (CRM, SaaS, frameworks) a menudo se enfrenta a un dilema: almacenar todo el código en un solo repositorio (monorepositorio) o dividirlo en múltiples microservicios y paquetes. Un monorepositorio (monorepo) con PHP es una estrategia en la que varios proyectos relacionados (librerías, módulos, aplicaciones) residen en un único repositorio de Git.

\n

En la práctica, esto proporciona:

\n
    \n
  • Historial de cambios unificado — es más fácil rastrear cómo un cambio en un paquete afectó a otro.
  • \n
  • Configuración simplificada de CI/CD — un solo pipeline para compilar y probar todos los componentes.
  • \n
  • Reducción de duplicación — configuraciones, scripts y dependencias compartidos.
  • \n
  • Iteración rápida — no es necesario publicar paquetes en Packagist para pruebas locales.
  • \n
\n

Sin embargo, un monorepositorio requiere disciplina. Sin una organización adecuada del código, se convierte en un "monolito espagueti". En este artículo, analizaremos los pasos prácticos para organizar un proyecto PHP en un monorepositorio.

\n\n

1. Estructura de directorios del monorepositorio

\n

El principio clave es una separación clara entre paquetes y aplicaciones. Veamos un ejemplo de una arquitectura típica:

\n\n
project-root/\n├── apps/\n│   ├── web/                  # Aplicación web (Symfony/Laravel)\n│   │   ├── public/\n│   │   ├── src/\n│   │   └── composer.json\n│   └── api/                  # Aplicación API (Lumen/Slim)\n│       ├── public/\n│       ├── src/\n│       └── composer.json\n├── packages/\n│   ├── core/                 # Núcleo (interfaces comunes, entidades)\n│   │   ├── src/\n│   │   └── composer.json\n│   ├── billing/              # Módulo de pago\n│   │   ├── src/\n│   │   └── composer.json\n│   └── notifications/        # Módulo de notificaciones\n│       ├── src/\n│       └── composer.json\n├── tools/                    # Scripts de desarrollo (PHP-CS-Fixer, PHPStan)\n├── composer.json             # Manifiesto raíz\n└── phpstan.neon              # Configuración de análisis común
\n\n

Tenga en cuenta: cada paquete en packages/ es una librería Composer completa con su propio composer.json. Esto permite aislar las dependencias y probarlas por separado.

\n\n

Ejemplo de composer.json para el paquete 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. Gestión de dependencias con Composer

\n

El composer.json raíz es el corazón del monorepositorio. Contiene:

\n
    \n
  • La lista de todos los paquetes conectados localmente (a través del repositorio path).
  • \n
  • Las dependencias de desarrollo para todo el proyecto (PHPUnit, PHPStan, GrumPHP).
  • \n
  • Scripts para automatización (análisis estático, pruebas).
  • \n
\n\n

Ejemplo de composer.json raíz

\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

Puntos clave:

\n
    \n
  • symlink: true

Blogs

Book Recommendations