Монорепозиторий с PHP: организация кода для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение

Разработка на PHP часто начинается с одного файла index.php, но по мере роста проекта возникает необходимость структурировать код. Многие разработчики сталкиваются с дилеммой: хранить всё в одном репозитории (монорепозиторий) или разбить на множество маленьких репозиториев (мультирепозиторий). В этой статье мы разберём концепцию монорепозитория для PHP-проектов, покажем, как организовать код для начинающих, и приведём практические примеры.

Монорепозиторий (monorepo) — это подход, при котором код нескольких проектов, библиотек или компонентов хранится в одном репозитории системы контроля версий (Git). В контексте PHP это означает, что ваш основной сайт, API, пакеты и утилиты находятся в одной папке. Это упрощает управление зависимостями, рефакторинг и развёртывание.

В этой статье вы узнаете:

  • Что такое монорепозиторий и зачем он нужен
  • Как организовать структуру папок для PHP
  • Как настроить Composer для работы с монорепозиторием
  • Примеры реальной организации кода

Преимущества монорепозитория для PHP

Многие начинающие PHP-разработчики считают, что монорепозиторий — это "свалка кода". На самом деле, при правильной организации это мощный инструмент. Вот основные плюсы:

  • Простота навигации: Все компоненты проекта находятся в одном месте. Не нужно переключаться между репозиториями.
  • Единая версия зависимостей: Вы используете один файл composer.json для управления пакетами, что исключает конфликты версий.
  • Атомарные коммиты: Изменения в API, фронтенде и библиотеках можно делать в одном коммите, что упрощает откат.
  • Упрощённое тестирование: Интеграционные тесты проходят быстрее, так как все компоненты доступны локально.
  • Единый CI/CD: Один конвейер сборки для всего проекта.

Однако монорепозиторий подходит не всем. Если ваша команда большая (более 20 человек), или проекты сильно различаются по технологиям, лучше рассмотреть мультирепозиторий. Для начинающих и средних проектов — это идеальный выбор.

Структура монорепозитория: базовая схема

Давайте создадим типовую структуру PHP-монорепозитория. Предположим, у нас есть веб-приложение с API и несколькими библиотеками. Вот рекомендуемая иерархия папок:

my-php-monorepo/
├── apps/
│   ├── web/               # Основной сайт (Laravel, Symfony или чистый PHP)
│   │   ├── public/
│   │   ├── src/
│   │   └── config/
│   └── api/               # API-сервер
│       ├── public/
│       ├── src/
│       └── routes/
├── packages/              # Внутренние библиотеки и пакеты
│   ├── core/              # Ядро системы (базовые классы)
│   │   ├── src/
│   │   └── composer.json
│   ├── database/          # Работа с БД (миграции, модели)
│   │   ├── src/
│   │   └── composer.json
│   └── utils/             # Утилиты (валидация, логирование)
│       ├── src/
│       └── composer.json
├── tests/                 # Глобальные тесты
├── docker/                # Docker-конфиги
├── composer.json          # Корневой Composer
├── composer.lock
├── .gitignore
└── README.md

Пояснение:

  • apps/ — содержит исполняемые приложения (сайты, API, консольные скрипты). Каждое приложение имеет свою точку входа (public/index.php).
  • packages/ — внутренние пакеты, которые вы разрабатываете. Они подключаются через composer.json с использованием path-репозиториев.
  • tests/ — корневые тесты (например, интеграционные тесты, которые проверяют взаимодействие между пакетами).
  • docker/ — файлы для Docker (Dockerfile, docker-compose.yml).

Настройка Composer для монорепозитория

Ключевой момент — правильно настроить composer.json в корне проекта. Composer должен знать о ваших внутренних пакетах. Используем репозиторий типа path.

Пример корневого composer.json:

{
    "name": "my-php-monorepo/root",
    "require": {
        "php": "^8.1",
        "monolog/monolog": "^3.0",
        "my-php-monorepo/core": "*",
        "my-php-monorepo/database": "*",
        "my-php-monorepo/utils": "*"
    },
    "repositories": [
        {
            "type": "path",
            "url": "packages/*",
            "options": {
                "symlink": true
            }
        }
    ],
    "autoload": {
        "psr-4": {
            "App\\Web\\": "apps/web/src/",
            "App\\Api\\": "apps/api/src/"
        }
    },
    "scripts": {
        "test": "phpunit",
        "cs-fix": "php-cs-fixer fix"
    }
}

Теперь создадим пакет packages/core/composer.json:

{
    "name": "my-php-monorepo/core",
    "description": "Core library for my PHP monorepo",
    "type": "library",
    "autoload": {
        "psr-4": {
            "MyMonorepo\\Core\\": "src/"
        }
    },
    "require": {
        "php": "^8.1"
    }
}

После этого выполните composer update в корне проекта. Composer создаст символическую ссылку на ваш пакет, и вы сможете разрабатывать его локально, изменения будут сразу видны в приложениях.

Пример использования внутреннего пакета

Создадим класс в packages/core/src/Logger.php:

<?php

namespace MyMonorepo\Core;

class Logger
{
    public function log(string $message): void
    {
        echo "[" . date('Y-m-d H:i:s') . "] " . $message . PHP_EOL;
    }
}

Теперь в приложении

Блоги

Рекомендаций по книгам