Composer: управление зависимостями PHP-проекта
Разбираем, что решает Composer, зачем нужен composer.lock, чем отличаются composer install и composer update, и как ставить зависимости на VPS с ограниченной памятью.
Зачем нужен Composer
До появления Composer PHP-разработчики подключали сторонние библиотеки вручную: скачивали архив с исходным кодом, распаковывали его в проект, прописывали require_once на нужные файлы и вручную следили, чтобы одна библиотека не тянула за собой конфликтующую версию другой. Такой подход быстро превращался в хаос на любом проекте крупнее одностраничного сайта — особенно когда несколько библиотек полагались на разные версии одной и той же третьей зависимости.
Composer решает эту проблему как менеджер зависимостей: он читает список нужных пакетов и их допустимых версий из файла composer.json, вычисляет граф совместимых версий с учётом требований каждой зависимости друг к другу, скачивает нужные файлы из репозитория Packagist (или другого источника) и генерирует единый автозагрузчик классов, через который всё это подключается в коде одной строкой.
Второй, менее очевидный, но не менее важный результат работы Composer — воспроизводимость. Если весь процесс установки на разных машинах даёт ровно один и тот же набор версий библиотек, разработчик на своём ноутбуке, сервер тестового окружения и production-сервер работают с идентичным кодом сторонних зависимостей, а не с случайно разными версиями, полученными в разное время.
Эта статья разбирает, как устроены composer.json и composer.lock, чем отличаются установка и обновление зависимостей, как работает автозагрузка классов по стандарту PSR-4, и что делать, если процесс установки упирается в ограничения небольшого VPS по памяти.
Установка Composer на VPS
Composer — это не пакет из репозитория дистрибутива в привычном смысле, а отдельный исполняемый PHP-скрипт (phar-архив), который принято ставить глобально в систему через официальный установочный скрипт, а не через устаревшую версию из apt.
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
php -r "unlink('composer-setup.php');"
Флаг --install-dir указывает, куда поместить исполняемый файл (обычно /usr/local/bin, который уже есть в PATH на большинстве дистрибутивов), а --filename задаёт имя команды — после этого шага composer можно вызывать из любой директории без указания полного пути.
composer --version
composer diagnose
Команда composer diagnose полезна сразу после установки: она проверяет доступность сети, права на директории кэша, версию PHP и включённые расширения, и заранее подсвечивает проблемы окружения, которые иначе всплыли бы только в момент первой реальной установки зависимостей проекта.
composer.json: структура файла зависимостей
composer.json — центральный конфигурационный файл проекта, описывающий его имя, зависимости и правила автозагрузки классов. Он создаётся один раз (вручную или командой composer init) и затем редактируется по мере добавления новых библиотек.
{
"name": "acme/site",
"require": {
"php": ">=8.2",
"monolog/monolog": "^3.0",
"guzzlehttp/guzzle": "^7.8"
},
"require-dev": {
"phpunit/phpunit": "^10.0"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Секция require, помимо сторонних пакетов, часто содержит и требование к самому PHP (php: >=8.2) — это не устанавливает интерпретатор автоматически, а лишь фиксирует минимальную версию, при попытке установки на сервере со старым PHP Composer сразу сообщит о несовместимости вместо непредсказуемого падения приложения уже во время работы.
Операторы версий в require — отдельная важная деталь: символ ^ перед версией (^3.0) разрешает обновления в пределах совместимой мажорной версии по правилам семантического версионирования, тильда (~7.8) ограничивает диапазон ещё туже, а точная версия без операторов жёстко фиксирует её без каких-либо автоматических обновлений вообще.
require и require-dev: разделение по назначению
Не все зависимости нужны на production-сервере в равной степени. Библиотеки для тестирования (PHPUnit), статического анализа кода (PHPStan, Psalm) или отладки нужны только разработчику на этапе написания и проверки кода — на боевом сервере они лишь занимают место и потенциально расширяют поверхность возможных уязвимостей без какой-либо пользы.
composer require monolog/monolog
composer require --dev phpunit/phpunit
Флаг --dev записывает пакет в секцию require-dev вместо require. При установке на production-сервере используется флаг --no-dev, который полностью пропускает все dev-зависимости, ускоряя установку и уменьшая итоговый размер папки vendor.
composer install --no-dev --optimize-autoloader
Флаг --optimize-autoloader дополнительно ускоряет автозагрузку классов в production, заранее строя оптимизированную карту классов вместо динамического поиска файлов по правилам PSR-4 на каждый запрос — на проектах с большим числом классов разница в скорости первого обращения к каждому классу заметна, особенно при высокой нагрузке.
composer.lock: почему обязательно коммитить в репозиторий
Версии в composer.json — это диапазоны допустимых значений, а не точная фиксация конкретной версии: запись ^3.0 разрешает установку и 3.0.0, и 3.4.2, и любой другой версии в пределах третьей мажорной ветки, которая существует на момент установки. Сам по себе composer.json ничего не говорит о том, какая именно версия была фактически установлена и протестирована.
composer.lock решает эту проблему: после разрешения графа зависимостей Composer записывает в него точные версии всех установленных пакетов вместе с контрольными суммами их содержимого. Пока composer.lock присутствует в проекте, команда composer install берёт версии именно из него, полностью игнорируя диапазоны из composer.json — то есть install гарантированно ставит один и тот же набор версий на любой машине, где выполняется, будь то ноутбук разработчика, CI-раннер или production-сервер.
Файл composer.lock существует именно для того, чтобы зафиксировать, какая версия каждой зависимости была реально протестирована — не коммитить его означает добровольно отказаться от воспроизводимости сборки.
Принцип из официальной документации Composer
Практическое следствие для безопасности: без committed composer.lock повторная установка зависимостей на production через несколько месяцев после первого деплоя может незаметно подтянуть новую минорную или патч-версию какой-то транзитивной зависимости, вышедшую за это время, — включая версию с новой уязвимостью, несовместимым поведением или попросту неожиданным багом, которого не было на момент тестирования релиза.
Единственный файл, который в этой связке действительно не нужно коммитить, — сама папка vendor. Она полностью восстанавливается из composer.lock командой composer install на любой машине и обычно занимает заметный объём, а иногда содержит платформо-зависимые бинарные файлы, собранные под конкретную архитектуру или ОС, что делает её хранение в Git не только избыточным, но и потенциально проблемным при переносе между разными окружениями.
composer install и composer update: в чём реальная разница
Эти две команды — источник самой частой путаницы у новичков, хотя разница между ними принципиальна и напрямую связана с composer.lock из предыдущего раздела. composer install читает существующий composer.lock и устанавливает ровно те версии, что в нём зафиксированы, вообще не пересчитывая граф зависимостей заново — это быстрая и полностью детерминированная операция.
composer install --no-dev --optimize-autoloader
composer update, напротив, игнорирует текущий composer.lock, заново разрешает граф зависимостей на основе диапазонов версий из composer.json (подтягивая самые новые версии, допустимые этими диапазонами) и перезаписывает composer.lock результатом — это ровно та операция, ради которой существует лок-файл, и выполнять её на production-сервере почти никогда не следует.
composer update
composer update guzzlehttp/guzzle
Практическое правило простое и без исключений: на этапе разработки, когда нужно осознанно поднять версии зависимостей, используется composer update с последующим тестированием и коммитом обновлённого composer.lock; на production и в CI/CD-пайплайне при каждом деплое выполняется исключительно composer install, которая никогда не должна незапланированно менять версии установленных библиотек.
Автозагрузка классов: как работает PSR-4
Секция autoload в composer.json описывает, как классы проекта сопоставляются с файлами на диске, избавляя от ручных require_once на каждый файл. Стандарт PSR-4 задаёт простое правило: пространству имён (namespace) соответствует директория, и вложенность неймспейса совпадает со вложенностью папок.
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
В примере выше класс с полным именем App\Services\Mailer\Mailer автоматически ищется по пути src/Services/Mailer.php — Composer сам сгенерирует нужный код автозагрузчика, и в коде проекта достаточно написать use App\Services\Mailer, чтобы класс подключился без единого явного require.
composer dump-autoload -o
Команду composer dump-autoload нужно выполнять вручную только в редких случаях — например, после переименования классов или изменения правил autoload в composer.json без изменения самого списка зависимостей, когда обычный composer install не запускается заново. Флаг -o (то же самое, что --optimize-autoloader) строит статическую карту «класс → файл» вместо динамического разбора правил PSR-4 на каждый запрос, что заметно ускоряет первое обращение к каждому классу под нагрузкой.
Память и таймауты Composer на небольшом VPS
Разрешение графа зависимостей — вычислительно тяжёлая задача, особенно на проектах с десятками пакетов и глубокими цепочками транзитивных зависимостей: Composer перебирает множество комбинаций совместимых версий, прежде чем найти рабочее решение, и на это может потребоваться заметный объём оперативной памяти PHP-процесса.
На VPS с 512 МБ – 1 ГБ оперативной памяти это нередко приводит к падению composer install или composer update с ошибкой нехватки памяти, особенно если на сервере одновременно работают другие сервисы (веб-сервер, база данных), уже занимающие большую часть доступного объёма. Первый и самый надёжный способ обойти проблему — временный своп-файл, дающий процессу запас на время установки без постоянного увеличения потребления диска.
fallocate -l 1G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
Второй способ — снять с самого Composer ограничение по памяти PHP явно через переменную окружения, не трогая общесистемный memory_limit, который может быть намеренно занижен для остальных PHP-процессов на сервере по соображениям стабильности.
COMPOSER_MEMORY_LIMIT=-1 composer install --no-dev --optimize-autoloader
Дополнительно стоит убедиться, что на сервере отключено расширение Xdebug на время установки зависимостей — оно значительно замедляет любой PHP-процесс, включая сам Composer, и часто оказывается случайно включённым на сервере, изначально настроенном как окружение для отладки, а не для production. Наконец, для проектов с действительно тяжёлым деревом зависимостей практичнее вообще не запускать composer install на маленьком production-VPS: зависимости устанавливаются на этапе CI/CD-пайплайна на более мощной машине (см. статью про GitHub Actions), а на сервер передаётся уже готовая папка vendor как часть артефакта деплоя.
Безопасность зависимостей: аудит и осторожные обновления
Каждая сторонняя библиотека — это код, которому проект доверяет наравне с собственным, и уязвимость в популярном пакете затрагивает разом все проекты, которые его используют. Начиная с Composer 2.4 в инструмент встроена команда проверки известных уязвимостей в установленных версиях зависимостей.
composer audit
Команда сверяет версии пакетов из composer.lock с базой данных известных уязвимостей и выводит список найденных проблем с указанием, в какой версии уязвимость исправлена — эту проверку разумно встроить в CI/CD-пайплайн, чтобы обновление с известной уязвимостью не проходило через пайплайн незамеченным.
Помимо формального аудита, полезны и более простые практики: избегать указания веток вроде dev-master в качестве версии зависимости на production (такая запись может незаметно подтянуть ещё не выпущенный и не протестированный код при обновлении), устанавливать пакеты только с Packagist или из явно указанных доверенных приватных репозиториев, и не бросаться на самую свежую мажорную версию сразу после релиза, дав экосистеме время на обнаружение возможных проблем в первых патч-версиях.
Типичные ошибки при работе с Composer
Коммит папки vendor в Git вместо только composer.json и composer.lock — раздувает репозиторий, замедляет клонирование и создаёт риск несовместимости платформо-зависимых бинарных файлов между окружениями разработчиков и сервером.
Отсутствие composer.lock в репозитории — превращает каждую установку зависимостей в лотерею с неизвестным заранее результатом и лишает всю команду и production-сервер гарантии одинаковых версий библиотек.
Запуск composer update прямо на production-сервере вместо composer install — способен незапланированно подтянуть новые версии зависимостей с изменённым поведением прямо в момент деплоя, минуя любое тестирование.
Использование полностью открытых версий вроде "*" или веток вида dev-master в require — лишает composer.json смысла как декларации совместимых версий и открывает дорогу для установки чего угодно при следующем update.
Игнорирование ошибок несовместимости версии PHP при установке — если composer.json требует php: >=8.2, а на сервере стоит 8.0, Composer честно откажется устанавливать зависимости, и это стоит воспринимать как сигнал обновить PHP, а не пытаться обойти проверку принудительными флагами.
Чек-лист безопасной работы с зависимостями
Шаг 1. Создайте composer.json с явными версионными ограничениями для каждой зависимости (^2.4, а не открытые диапазоны) и укажите минимальную требуемую версию PHP.
Шаг 2. Разделите зависимости на require и require-dev, вынеся инструменты тестирования и отладки в дев-секцию.
Шаг 3. Закоммитьте composer.lock вместе с composer.json, добавив vendor/ в .gitignore.
Шаг 4. На production и в CI/CD используйте только composer install --no-dev --optimize-autoloader, никогда не запускайте update вне этапа осознанного обновления зависимостей.
Шаг 5. На маленьких VPS заранее подготовьте временный своп-файл или переносите готовую vendor как артефакт деплоя вместо установки прямо на сервере.
Шаг 6. Регулярно запускайте composer audit и обновляйте зависимости с известными уязвимостями в приоритетном порядке.
Итог: Composer как основа предсказуемого деплоя PHP-проекта
Composer снимает с разработчика ручное управление совместимостью версий сторонних библиотек и одновременно даёт инструмент для гарантированно одинаковой установки зависимостей на любой машине — при условии, что composer.lock действительно коммитится в репозиторий и на production никогда не запускается update вместо install.
Большая часть проблем с Composer на практике сводится не к самому инструменту, а к нарушению этих двух простых правил: кто-то забыл закоммитить lock-файл, кто-то запустил update прямо на сервере в спешке перед релизом. Соблюдение базовой дисциплины работы с зависимостями избавляет от большинства сюрпризов при деплое.
Если после чтения статьи остаются вопросы по настройке зависимостей конкретного PHP-проекта под ваш VPS — оставьте заявку внизу страницы, поможем разобраться с окружением и настроить процесс деплоя с Composer от начала до конца.
Почему стоит выбрать нас
Быстрый запуск
Подберём конфигурацию и развернём проект в день обращения.
Надёжность
NVMe-диски, защита от DDoS и резервные копии по расписанию.
Поддержка 24/7
Дежурные инженеры на связи в любое время суток.
Настройка под ключ
Установим CMS, настроим веб-сервер, SSL и почту за вас.
Перенос без простоя
Аккуратно перенесём сайт и базу данных на новый сервер.
Прозрачные цены
Актуальные тарифы и честный подбор без навязывания.
Вопросы и ответы
Что произойдёт, если удалить папку vendor целиком?
Ничего страшного — папка vendor не должна храниться в системе контроля версий, она полностью восстанавливается командой composer install на основе файла composer.lock, который и содержит точные версии всех зависимостей.
Нужно ли добавлять vendor в Git?
Нет, стандартная практика — исключить vendor через .gitignore и коммитить только composer.json и composer.lock; сама папка с библиотеками генерируется на каждом окружении заново командой composer install.
Почему composer install зависает или падает с ошибкой памяти на VPS с 512 МБ?
Разрешение графа зависимостей — ресурсоёмкая операция, и на маленьких серверах Composer может упереться в memory_limit PHP; решение — временный своп-файл, переменная COMPOSER_MEMORY_LIMIT=-1 или установка зависимостей на более мощной машине с последующей передачей готовой папки vendor на продакшн.
В чём разница между require и require-dev?
require описывает зависимости, без которых приложение не может работать в production (фреймворк, драйверы БД), а require-dev — инструменты, нужные только разработчику (PHPUnit, PHPStan, отладочные пакеты); на боевом сервере такие пакеты обычно не устанавливаются вовсе.
Как обновить только один конкретный пакет, не трогая остальные?
Командой composer update имя/пакета — Composer пересчитает версию только указанного пакета и его прямых зависимостей, оставив версии остальных библиотек зафиксированными в composer.lock без изменений.
Что делать, если composer.lock конфликтует при слиянии двух веток в Git?
Ручное редактирование composer.lock практически никогда не работает корректно из-за встроенной контрольной суммы файла — правильный путь: разрешить конфликт в composer.json, затем выполнить composer update, чтобы Composer пересобрал lock-файл заново на основе актуальных требований.
Безопасно ли указывать версию зависимости как звёздочку (*)?
Нет, это открывает дорогу для установки абсолютно любой, в том числе будущей несовместимой мажорной версии пакета при следующем composer update — разумнее использовать операторы вроде ^2.4, ограничивающие обновления рамками совместимой мажорной версии.
Стоит ли переходить с Composer 1 на Composer 2, если проект давно работает на первой версии?
Да, Composer 2 заметно быстрее разрешает зависимости и активнее поддерживается разработчиками; Composer 1 официально не получает обновлений безопасности, поэтому продолжение работы на нём — риск для актуальности используемых инструментов установки.
Как оплачивать услуги?
Оплата помесячная, для облачных серверов доступна почасовая тарификация. Принимаются карты, банковские переводы и электронные кошельки.
Есть ли круглосуточная поддержка?
Да, дежурные инженеры на связи 24/7.
Выдаёте ли закрывающие документы?
Да, предоставим необходимые документы для оплаты.
Как оставить заявку?
Заполните форму на странице или нажмите «Заказать» — мы свяжемся и поможем с подбором.