Composer.json в PHP: полный разбор инструмента управления зависимостями

Раздел: Инструменты разработки -> Управление зависимостями

Работа с composer.json: управление зависимостями PHP

Файл composer.json является центральным элементом управления зависимостями в PHP-проектах. В нем описываются требования к пакетам, конфигурация автозагрузки, скрипты и многие другие параметры. Ниже рассмотрено основное решение (базовое описание) и несколько вариантов настройки с пояснениями целей и типичных проблем.

Как создать минимальный composer.json для проекта?

Основная цель: определить имя проекта, описание, требуемые пакеты и способ автозагрузки классов.

{
  "name": "myvendor/myapp",
  "description": "Пример приложения",
  "require": {
    "php": ">=8.0",
    "monolog/monolog": "^2.0"
  },
  "autoload": {
    "psr-4": {
      "MyApp\\": "src/"
    }
  }
}

Docker php composer (composer в docker php)

После создания файла выполняется composer install. Пакет Monolog загружается в vendor, автозагрузка настраивается по PSR-4. Возникающая проблема: если не указать автозагрузку, классы не будут находиться – в логах появится ошибка Class not found.

Почему после добавления пакета класс не находится?

Ошибка чаще всего связана с несоответствием namespace в коде и пути в autoload. Например, если неймспейс MyApp\ а файл лежит в src/Models, но класс называется MyApp\Models\User – автозагрузка сработает, только если директория Models существует внутри src. Если же структура другая, нужно либо менять autoload на classmap, либо добавлять в autoload несколько префиксов.

Как указать зависимость только для разработки?

Цель: установить пакеты для тестирования, code style, PHPStan, которые не нужны на production.

{
  "require-dev": {
    "phpunit/phpunit": "^10.0",
    "phpstan/phpstan": "^1.10"
  }
}

Autoload php composer (автозагрузка классов с помощью composer в php)

Установка производится командой composer install --no-dev на продакшне. Типичная ошибка: использование класса из dev-пакета в основном коде – на продакшне вызовет фатальную ошибку.

Как настроить автозагрузку по PSR-0?

Цель: поддержка устаревших библиотек, использующих PSR-0.

{
  "autoload": {
    "psr-0": {
      "MyLib_": "src/"
    }
  }
}

Php composer package (управление пакетами composer в php)

Проблема: PSR-0 требует имена классов с подчеркиваниями, что не соответствует современным стандартам. При переходе на PSR-4 может потребоваться рефакторинг.

Как добавить пользовательский репозиторий?

Цель: установить пакет не из Packagist, а из приватного Git-репозитория или локальной папки.

{
  "repositories": [
    {
      "type": "vcs",
      "url": "https://github.com/mycompany/mylib"
    },
    {
      "type": "path",
      "url": "../mylib-local",
      "options": {
        "symlink": true
      }
    }
  ]
}

Composer php 8.1 (установка composer для php 8.1)

После добавления репозитория можно указать пакет mycompany/mylib в require. Ошибка: если версия в репозитории не соответствует require (например, не указан тег), composer выдаст предупреждение о неверном формате версии.

Как зафиксировать минимальную стабильность?

Цель: разрешить или запретить установку нестабильных версий (dev, alpha, beta).

{
  "minimum-stability": "stable",
  "prefer-stable": true
}

Php composer json (php: работа с composer.json)

Если разработчик хочет использовать dev-версию конкретного пакета, можно указать её явно в require: "monolog/monolog": "dev-main". Проблема: при minimum-stability: stable и отсутствии prefer-stable, composer может не установить пакет, если его стабильная версия не найдена – в итоге ошибка Could not find a matching version.

Как задать платформенные требования (версию PHP, расширения)?

Цель: гарантировать, что на целевой машине установлена нужная версия PHP и расширения.

{
  "require": {
    "php": ">=8.0, <8.3",
    "ext-json": "*",
    "ext-mbstring": "*"
  },
  "config": {
    "platform": {
      "php": "8.1"
    }
  }
}

Composer platform php (платформа composer (platform config))

Ключ config.platform позволяет имитировать определённую платформу для разрешения зависимостей (полезно, когда разработка ведётся на PHP 8.2, а продакшн на 8.1). Типичная ошибка: указание в platform версии, которая не совпадает с фактической, – тогда установленные пакеты могут использовать функции, недоступные в реальной среде.

Как управлять скриптами (hooks)?

Цель: выполнять автоматические действия после определённых событий (install, update, autoload-dump).

{
  "scripts": {
    "post-install-cmd": [
      "@clear-cache",
      "php artisan config:cache"
    ],
    "post-update-cmd": [
      "@clear-cache"
    ],
    "clear-cache": "rm -rf var/cache/*"
  }
}

Vendor php (директория vendor в php (composer))

Проблема: если скрипт завершается с ошибкой, composer прерывает выполнение. Для отладки можно использовать @composer --verbose.

Как обработать конфликтующие пакеты?

Цель: предотвратить установку несовместимых библиотек.

{
  "conflict": {
    "vendor/package": ">=2.0",
    "vendor/old-lib": "*"
  }
}

Ошибка: если конфликтующая версия уже установлена, composer при попытке обновления выдаст сообщение The requested package conflicts with ....

Расширенные примеры работы с composer.json

Как создать псевдоним для репозитория, чтобы переопределить версию пакета?

Цель: использование частного форка с другой версией вместо оригинального пакета.

Пример
{
  "repositories": [
    {
      "type": "package",
      "package": {
        "name": "monolog/monolog",
        "version": "2.9.0",
        "source": {
          "url": "https://github.com/myfork/monolog",
          "type": "git",
          "reference": "ac1e5e5f"
        }
      }
    }
  ]
}
Результат: composer install скачает именно этот форк, игнорируя packagist.

Важно: такой подход создаёт изолированную среду, но при обновлении нужно менять reference вручную.

Как добавить кастомный установщик для нестандартных типов пакетов?

Цель: устанавливать пакеты в произвольную директорию, а не в vendor.

Пример
{
  "require": {
    "composer/installers": "^1.0"
  },
  "extra": {
    "installer-paths": {
      "themes/{$name}/": ["type:wordpress-theme"],
      "plugins/{$name}/": ["type:wordpress-plugin"]
    }
  }
}
После установки любой пакет с типом "wordpress-theme" будет помещён в themes/имя_пакета/.

Ошибка: если не указать composer/installers, кастомные пути работать не будут – composer использует только свою стандартную установку в vendor.

Как использовать platform.php для имитации более низкой версии PHP, чем установлена?

Цель: гарантировать совместимость с минимальной версией.

Пример
{
  "config": {
    "platform": {
      "php": "8.0.0"
    },
    "platform-check": false
  },
  "require": {
    "php": ">=8.0.0"
  }
}
composer update будет подбирать версии пакетов так, как будто PHP - 8.0, даже если локально 8.2.

Проблема: если в коде используются фичи PHP 8.1 (например, Fibers), composer это не отследит – нужно дополнительно проверять статическим анализом.

Как настроить автоматическую оптимизацию автозагрузчика для production?

Цель: ускорить загрузку классов, генерируя classmap или OPcache-friendly файл.

Пример
{
  "config": {
    "optimize-autoloader": true,
    "classmap-authoritative": true,
    "apcu-autoloader": true
  }
}
После composer install --no-dev --optimize-autoloader будет сгенерирован classmap, а автозагрузчик не будет проверять файловую систему – только classmap.

Важно: при добавлении нового класса нужно перегенерировать autoload (composer dump-autoload -o).

Как добавить запрещённые (banned) пакеты в composer.json?

Цель: предотвратить установку уязвимых или устаревших пакетов.

Пример
{
  "conflict": {
    "vendor/unsafe-package": "*",
    "vendor/old-package": "<=1.0.0"
  }
}
Если кто-то попытается добавить "vendor/old-package" в require, composer выдаст ошибку конфликта.

Рекомендуется использовать composer audit для проверки известных уязвимостей, а не только conflict.

Как создать composer.json для библиотеки с несколькими автозагрузками (PSR-4 + classmap)?

Цель: обеспечить автозагрузку как современных PSR-4 классов, так и устаревших глобальных функций.

Пример
{
  "autoload": {
    "psr-4": {
      "MyApp\\": "src/"
    },
    "classmap": [
      "legacy/"
    ],
    "files": [
      "src/helpers.php"
    ]
  }
}
Файлы в legacy/ будут просканированы один раз (при dump-autoload), а helpers.php будет загружаться всегда.

Ошибка: если legacy-класс дублирует namespace из PSR-4, возможен конфликт – composer выдаст предупреждение. Лучше избегать пересечений.

PHP: работа с composer.json - comments

En
Php composer json (php)