Зарегистрируйтесь, чтобы продолжить обучение

Lock-файл PHP: Настройка окружения

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

composer logic

На самом деле, поведение чуть сложнее, и количество различных ситуаций тоже больше. Но для понимания схемы работы нашего описания выше вполне достаточно.


Самостоятельная работа

  1. Склонируйте репозиторий php-package
  2. Внутри репозитория выполните команду composer update и изучите вывод команды git diff
  3. Попробуйте изменить версию любого пакета в composer.json и выполнить его установку (доступные версии есть на сайте Packagist)
  4. Обратите внимание на результат — файл composer.lock обновился

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
Программирование на PHP, Разработка веб-приложений и сервисов используя Laravel, проектирование и реализация REST API
10 месяцев
с нуля
Старт 26 декабря

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»