Поговорим про обновление зависимостей. Для обновления всех зависимостей нужно выполнить команду composer update
. Чтобы выполнить обновление конкретной зависимости — команду composer update vendor-name/project-name
. А вот то, как будет происходить обновление, зависит от содержимого composer.json
.
Рассмотрим возможные варианты:
require {
'package1': "*",
'package2': "1.3.5",
'package3': ">2.3.4",
'package4': "~3.9",
'package5': "^1.2"
}
В коде выше:
*
означает, что можно ставить любую версию библиотеки. После выполнения команды обновления в папкеvendor
окажется последняя доступная версияpackage1
1.3.5
— это конкретный номер. Если версия библиотеки жестко зафиксирована, никакая команда не сможет обновить ее
Кроме этих вариантов, существует масса других способов указать зависимость, часть из них вы видите в списке выше. Все они подробно описаны в официальном руководстве.
Lock-файл
На предыдущем шаге каждая новая установка зависимостей приводила сначала к созданию, а потом и обновлению lock-файла composer.lock
.
Попытаемся разобраться в смысле этого файла. В файле composer.json
указываются зависимости — мы уже изучили, как устанавливать и обновлять их. Кроме того, вы уже знаете, что у каждой зависимости могут быть свои зависимости, которые тоже обновляются, и так до бесконечности. Зависимости зависимостей называются транзитивными, и с ними не все так просто. Все настолько не просто, что существует понятие ад зависимостей (dependency hell).
Проблема заключается в том, что мы никак не фиксируем версии транзитивных зависимостей. Предположим, что в нашем пакете есть зависимость A
с зафиксированной версией 1.3.2
, у которой в зависимостях стоит пакет B
с версией *
. В такой ситуации без lock-файла, composer install
поставил бы версию зависимости A
указанной версии, но того же самого нельзя сказать про пакет B
. Composer поставит последнюю доступную версию из репозитория. Такое поведение не детерминировано. Если создатель обновит B
так, что нарушится обратная совместимость, наш проект просто сломается, так как перестанет работать A
.
Для примера представим, что мы полгода не заходили в проект, а затем зашли и поставили зависимости заново, удалив папку vendor
или выполнив новое клонирование. С вероятностью почти 100% ничего не заработает. Как правило, пакеты обновляются часто, и какой-нибудь из них обязательно изменит мажорную версию за столь большой срок.
Очевидный, но не рабочий выход из данной ситуации — вручную отслеживать зависимости всех зависимостей и явно прописывать их версии в composer.json
. Такой способ сработает. Но даже в проекте с пятью зависимостями может быть несколько сотен транзитивных зависимостей — вдумайтесь в эту цифру. И это мы еще не говорим про то, что пакеты обновляются и меняются. Такую ситуацию невозможно контролировать: в какой-то момент зависимости просто перестанут обновляться.
Другой выход — требовать того, чтобы создатели всех библиотек всегда жестко указывали версии. Из-за человеческого фактора это не сработает, а автоматизация этого процесса привела бы к полному параличу.
И тут на сцену выходит lock-файл. По сути это автоматизированное решение первого способа. Его содержимое выглядит примерно так:
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "ab2dac1e4b8d91d81b2295ca726e9499",
"packages": [
{
"name": "illuminate/collections",
"version": "v5.5.27",
"source": {
"type": "git",
"url": "https://github.com/illuminate/collections.git",
"reference": "07d58f7f663d5033a08541f9c481d33ad3f514a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/collections/zipball/07d58f7f663d5033a08541f9c481d33ad3f514a5",
"reference": "07d58f7f663d5033a08541f9c481d33ad3f514a5",
"shasum": ""
}
}
]
}
Первый запуск установки зависимостей сформирует этот файл. Туда записываются все установленные зависимости, в том числе транзитивные с их версиями. При дальнейших запусках composer install
всегда ставится то, что указано в lock-файле, даже если удалить папку vendor
или в Packagist добавятся новые версии пакетов. Повторный запуск через любой промежуток времени приведет к тому же результату. Теперь всегда можно быть уверенным — если заработало сейчас, то заработает и потом, причем у всех пользователей.
Наличие lock-файла никак не влияет на поведение команды update
для прямых зависимостей. Если указанный в composer.json
пакет обновился и может быть обновлен в соответствие с тем, как указана его версия, то загрузится новая версия. В этом случае lock-файл обновится автоматически. После этого нужно только не забыть зафиксировать его изменение в репозитории.
На самом деле, поведение чуть сложнее, и количество различных ситуаций тоже больше. Но для понимания схемы работы нашего описания выше вполне достаточно.
Самостоятельная работа
- Склонируйте репозиторий php-package
- Внутри репозитория выполните команду
composer update
и изучите вывод командыgit diff
- Попробуйте изменить версию любого пакета в
composer.json
и выполнить его установку (доступные версии есть на сайте Packagist) - Обратите внимание на результат — файл
composer.lock
обновился
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.