HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Поговорим про обновление зависимостей. Для обновления всех зависимостей нужно выполнить команду composer update. Чтобы выполнить обновление конкретной зависимости - команду composer update vendor-name/project-name. А вот то,<em>как</em>будет происходить обновление, зависит от содержимого composer.json.</p>
1 <p>Поговорим про обновление зависимостей. Для обновления всех зависимостей нужно выполнить команду composer update. Чтобы выполнить обновление конкретной зависимости - команду composer update vendor-name/project-name. А вот то,<em>как</em>будет происходить обновление, зависит от содержимого composer.json.</p>
2 <p>Рассмотрим возможные варианты:</p>
2 <p>Рассмотрим возможные варианты:</p>
3 <p>В коде выше:</p>
3 <p>В коде выше:</p>
4 <ul><li>* означает, что можно ставить любую версию библиотеки. После выполнения команды обновления в папке vendor окажется последняя доступная версия package1</li>
4 <ul><li>* означает, что можно ставить любую версию библиотеки. После выполнения команды обновления в папке vendor окажется последняя доступная версия package1</li>
5 <li>1.3.5 - это конкретный номер. Если версия библиотеки жестко зафиксирована, никакая команда не сможет обновить ее</li>
5 <li>1.3.5 - это конкретный номер. Если версия библиотеки жестко зафиксирована, никакая команда не сможет обновить ее</li>
6 </ul><p>Кроме этих вариантов, существует масса других способов указать зависимость, часть из них вы видите в списке выше. Все они подробно описаны в<a>официальном руководстве</a>.</p>
6 </ul><p>Кроме этих вариантов, существует масса других способов указать зависимость, часть из них вы видите в списке выше. Все они подробно описаны в<a>официальном руководстве</a>.</p>
7 <h2>Lock-файл</h2>
7 <h2>Lock-файл</h2>
8 <p>На предыдущем шаге каждая новая установка зависимостей приводила сначала к созданию, а потом и обновлению lock-файла composer.lock.</p>
8 <p>На предыдущем шаге каждая новая установка зависимостей приводила сначала к созданию, а потом и обновлению lock-файла composer.lock.</p>
9 <p>Попытаемся разобраться в смысле этого файла. В файле composer.json указываются зависимости - мы уже изучили, как устанавливать и обновлять их. Кроме того, вы уже знаете, что у каждой зависимости могут быть свои зависимости, которые тоже обновляются, и так до бесконечности. Зависимости зависимостей называются<strong>транзитивными</strong>, и с ними не все так просто. Все настолько не просто, что существует понятие<a><strong>ад зависимостей</strong></a>(<em>dependency hell</em>).</p>
9 <p>Попытаемся разобраться в смысле этого файла. В файле composer.json указываются зависимости - мы уже изучили, как устанавливать и обновлять их. Кроме того, вы уже знаете, что у каждой зависимости могут быть свои зависимости, которые тоже обновляются, и так до бесконечности. Зависимости зависимостей называются<strong>транзитивными</strong>, и с ними не все так просто. Все настолько не просто, что существует понятие<a><strong>ад зависимостей</strong></a>(<em>dependency hell</em>).</p>
10 <p>Проблема заключается в том, что мы никак не фиксируем версии транзитивных зависимостей. Предположим, что в нашем пакете есть зависимость A с зафиксированной версией 1.3.2, у которой в зависимостях стоит пакет B с версией *. В такой ситуации без lock-файла, composer install поставил бы версию зависимости A указанной версии, но того же самого нельзя сказать про пакет B. Composer поставит последнюю доступную версию из репозитория. Такое поведение не детерминировано. Если создатель обновит B так, что нарушится обратная совместимость, наш проект просто сломается, так как перестанет работать A.</p>
10 <p>Проблема заключается в том, что мы никак не фиксируем версии транзитивных зависимостей. Предположим, что в нашем пакете есть зависимость A с зафиксированной версией 1.3.2, у которой в зависимостях стоит пакет B с версией *. В такой ситуации без lock-файла, composer install поставил бы версию зависимости A указанной версии, но того же самого нельзя сказать про пакет B. Composer поставит последнюю доступную версию из репозитория. Такое поведение не детерминировано. Если создатель обновит B так, что нарушится обратная совместимость, наш проект просто сломается, так как перестанет работать A.</p>
11 <p>Для примера представим, что мы полгода не заходили в проект, а затем зашли и поставили зависимости заново, удалив папку vendor или выполнив новое клонирование. С вероятностью почти 100% ничего не заработает. Как правило, пакеты обновляются часто, и какой-нибудь из них обязательно изменит мажорную версию за столь большой срок.</p>
11 <p>Для примера представим, что мы полгода не заходили в проект, а затем зашли и поставили зависимости заново, удалив папку vendor или выполнив новое клонирование. С вероятностью почти 100% ничего не заработает. Как правило, пакеты обновляются часто, и какой-нибудь из них обязательно изменит мажорную версию за столь большой срок.</p>
12 <p>Очевидный, но не рабочий выход из данной ситуации - вручную отслеживать зависимости всех зависимостей и явно прописывать их версии в composer.json. Такой способ сработает. Но даже в проекте с пятью зависимостями может быть несколько сотен транзитивных зависимостей - вдумайтесь в эту цифру. И это мы еще не говорим про то, что пакеты обновляются и меняются. Такую ситуацию невозможно контролировать: в какой-то момент зависимости просто перестанут обновляться.</p>
12 <p>Очевидный, но не рабочий выход из данной ситуации - вручную отслеживать зависимости всех зависимостей и явно прописывать их версии в composer.json. Такой способ сработает. Но даже в проекте с пятью зависимостями может быть несколько сотен транзитивных зависимостей - вдумайтесь в эту цифру. И это мы еще не говорим про то, что пакеты обновляются и меняются. Такую ситуацию невозможно контролировать: в какой-то момент зависимости просто перестанут обновляться.</p>
13 <p>Другой выход - требовать того, чтобы создатели всех библиотек всегда жестко указывали версии. Из-за человеческого фактора это не сработает, а автоматизация этого процесса привела бы к полному параличу.</p>
13 <p>Другой выход - требовать того, чтобы создатели всех библиотек всегда жестко указывали версии. Из-за человеческого фактора это не сработает, а автоматизация этого процесса привела бы к полному параличу.</p>
14 <p>И тут на сцену выходит lock-файл. По сути это автоматизированное решение первого способа. Его содержимое выглядит примерно так:</p>
14 <p>И тут на сцену выходит lock-файл. По сути это автоматизированное решение первого способа. Его содержимое выглядит примерно так:</p>
15 <p>Первый запуск установки зависимостей сформирует этот файл. Туда записываются все установленные зависимости, в том числе транзитивные с их версиями. При дальнейших запусках composer install всегда ставится то, что указано в lock-файле, даже если удалить папку vendor или в Packagist добавятся новые версии пакетов. Повторный запуск через любой промежуток времени приведет к тому же результату. Теперь всегда можно быть уверенным - если заработало сейчас, то заработает и потом, причем у всех пользователей.</p>
15 <p>Первый запуск установки зависимостей сформирует этот файл. Туда записываются все установленные зависимости, в том числе транзитивные с их версиями. При дальнейших запусках composer install всегда ставится то, что указано в lock-файле, даже если удалить папку vendor или в Packagist добавятся новые версии пакетов. Повторный запуск через любой промежуток времени приведет к тому же результату. Теперь всегда можно быть уверенным - если заработало сейчас, то заработает и потом, причем у всех пользователей.</p>
16 <p>Наличие lock-файла никак не влияет на поведение команды update для прямых зависимостей. Если указанный в composer.json пакет обновился и может быть обновлен в соответствие с тем, как указана его версия, то загрузится новая версия. В этом случае lock-файл обновится автоматически. После этого нужно только не забыть зафиксировать его изменение в репозитории.</p>
16 <p>Наличие lock-файла никак не влияет на поведение команды update для прямых зависимостей. Если указанный в composer.json пакет обновился и может быть обновлен в соответствие с тем, как указана его версия, то загрузится новая версия. В этом случае lock-файл обновится автоматически. После этого нужно только не забыть зафиксировать его изменение в репозитории.</p>
17 <p>На самом деле, поведение чуть сложнее, и количество различных ситуаций тоже больше. Но для понимания схемы работы нашего описания выше вполне достаточно.</p>
17 <p>На самом деле, поведение чуть сложнее, и количество различных ситуаций тоже больше. Но для понимания схемы работы нашего описания выше вполне достаточно.</p>