Поговорим про обновление зависимостей. Для обновления всех зависимостей нужно выполнить команду 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окажется последняя доступная версияpackage11.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обновился
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.