
Почему PHP Composer – это больше, чем просто менеджер зависимостей
В настоящее время сложно представить проект без менеджера зависимостей, независимо от того, на каком языке программирования он написан. Для PHP таким менеджером является Composer.
Цель данной статьи – не только познакомить вас с пакетным менеджером Composer, но и рассказать немного больше, чем просто о способах установки и обновления сторонних пакетов.
Что такое Composer?
Composer - это инструмент для управления сторонними библиотеками в PHP-проекте. Он позволяет подключать, устанавливать и обновлять библиотеки или «пакеты», а также управлять их версиями.
Разработка Composer была вдохновлена уже существующими на тот момент менеджерами пакетов: npm (Node.js) и bundler (Ruby). Первый релиз состоялся 1 марта 2012 года.
Это кроссплатформенный инструмент: он одинаково работает на операционных системах Windows, Linux и OSX.
Чем Composer отличается от Pear
До появления Composer в мире PHP-разработки существовал PEAR (PHP Extension and Application Repository) – это фреймворк и система распространения повторно используемых PHP-компонентов.
Дело в том, что у PEAR есть несколько существенных минусов:
- Библиотека устанавливается в масштабе всей системы, а не для каждого проекта отдельно, таким образом, невозможно использовать несколько разных версий одной библиотеки на компьютере.
- Чтобы загрузить библиотеку в PEAR, необходимо набрать определенное количество голосов.
- Существующие решения были часто устаревшими, неактивными или неподдерживающимися.
Основы использования Composer
Простое управление библиотеками и пакетами в PHP-проекте.
Для быстрого старта разработчику нужно знать всего несколько команд, например:
init – инициализация проекта (а зачастую она не требуется при использовании PHP-фреймворка);
require – подключить пакет;
install – установить зависимости;
update – обновить пакеты;
При использовании этих команд можно легко продолжить работу над проектом, не вдаваясь в подробности. Также есть подробная официальная документация, там можно прочесть всю необходимую информацию по установке и использованию.
Но Composer – это больше, чем просто пакетный менеджер. Чтобы в этом разобраться, для начала пройдемся по основам использования:
Composer.json
Центральный файл для управления – composer.json. В нем описываются различные настройки и, самое главное, пакеты, от которых зависит наш проект:

В блоке require указываются необходимые нам пакеты, но их также можно добавить и с помощью команды:

Версии пакетов
Большинство разработчиков при разработке своих пакетов следуют соглашению SemVer – семантическое версионирование. Это соглашение, при котором номер версии указывается в следующем виде:
| MAJOR.MINOR.PATCH,
где MAJOR, MINOR и PATСH - целые числа, начиная с 0.
Когда следует увеличивать версию:
- Major (мажорная версия) - обратно несовместимые изменения в API.
- Minor (минорная версия) - добавлена функциональность и при этом не нарушена обратная совместимость.
- Patch (патч-версия) - баг-фиксы, незначительные доработки.
Некоторые способы указания версий в composer.json:
*Точная версия*
"worksolutions/php-collections": "1.1.7"
*Диапазон версий*
"worksolutions/php-collections": ">=1.0.0"
*Диапазон тильды*
"worksolutions/php-collections": "~1.2.3"
Эквивалентно >=1.2.3 <1.3.0
*Диапазон каретки*
"worksolutions/php-collections": "^1.2.3"
Эквивалентно >=1.2.3 <2.0.0. Используется для ограничения мажорной версии, чтобы гарантировать обратную совместимость
*Диапазон версий подстановочных знаков*
"worksolutions/php-collections": *"1.0.\"**
Эквивалентно >=1.0.0 <1.1
Также, в качестве версии можно указать название ветки или хэш коммита, если в качестве поставщика пакета используется git-репозиторий.
Файл блокировки
При первой установке всех пакетов в проект, которые описаны в composer.json будет создан файл composer.lock, в котором будут указаны точные версии каждого из установленных.
При следующей попытке установки будет браться информация из файла блокировки, загружая точные версии каждого пакета, чтобы не допустить случайных ошибок из-за новых минорных обновлений.
Рекомендуется сохранять файл composer.lock в системе контроля версий.
Основные команды
Инициализация проекта
$composer init
Установка пакетов
$composer install
При первом запуске будет взята информация из файла composer.json, затем создается файл composer.lock, на основе которого и происходит установка.
Обновление
$composer update
Выполняет установку пакетов как будто файла composer.lock не существует. Пакетный менеджер сделает установку согласно composer.json, а затем обновит composer.lock.
Обновление
$composer require
Добавит пакет в composer.json
Автозагрузка
Чтобы использовать классы проекта или установленных библиотек, необходимо подключить сгенерированный файл:

Пример autoload в файле composer.json:

Данную запись можно понимать следующим образом: класс, который имеет путь src/Service/Logger.php будет иметь пространство имен App\Service.
Подключить данный класс можно с использованием директивы use:

Пакеты
Каждый проект по сути является пакетом. С разницей лишь в том, что название библиотеки обязательное, а проекта нет.
Способы подключения
Существует немало различных способов подключить библиотеку в проект. Так, библиотеку можно подключить, если она доступна через VCS (систему контроля версий), либо использовать прямую ссылку на zip-файл с пакетом.
Подключение пакетов, опубликованных на Packagist, удобный, простой и распространенный метод.
Рассмотрим подключение библиотеки PHP-коллекций через git-репозиторий:

Для подключения в блоке require необходимо указать название репозитория и ветку, а в блоке repositories добавить ссылку на репозиторий.
Данный способ выглядит несложным, однако, проще подключать библиотеки, которые хранятся на Packagist. Рассмотрим пример подключения той же библиотеки, но через Packagist:

Репозиторий Packagist не нужно специально указывать в Composer - он зарегистрирован там по-умолчанию.
Создание собственного пакета
Создание репозитория
Перед тем, как начать разработку нашего пакета, создадим репозиторий на GitHub:

Клонируем репозиторий и переходим в папку проекта

Перед началом инициализации проекта необходимо создать файл .gitignore, где нужно указать директорию vendor, а также файл блокировки composer.lock. Это необходимо для того, чтобы пользователь мог развернуть любую подходящую версию пакета.
Инициализация проекта
Генерируем конфигурационный файл, выполнив команду инициализации

Далее отвечаем на вопросы, именуем пакет в формате <vendor>/<name>, где vendor - имя автора, например, имя пользователя на Github, name - имя пакета.
Тип указываем library, без указания, на данном этапе, дополнительных пакетов.
В итоге при завершении работы команды будет создан файл composer.json:

Создание файла README
Рекомендуется в файле README.md указать:
- Название
- Доступную версию PHP
- Способ установки
- Примеры использования

Версионирование
Версии пакета добавляются с помощью команды git tag.
Пример:
Создаем тег

Отправляем тег в репозиторий

Добавлен тег:

Публикация пакета на Packagist
Переходим на сайт packagist.org, выбираем «Submit».
Указываем ссылку на репозиторий Github и выполняем проверку:

После проверки снова нажимаем «Submit» и пакет будет опубликован:

Скрипты Composer
Скрипт - это определенный сценарий, который выполняется по какому-либо событию, например, установка зависимостей или сброс автозагрузчика.
Таким сценарием может быть любой набор команд командной строки или статический метод PHP-класса.
Существует несколько видов событий:
- Командные события
- События установщика
- События пакета
- События плагина
Определение сценариев
Чтобы определить сценарий, в файле composer.json добавляется свойство scripts, которое содержит пары «событие» - «сценарий». Сценарий может быть объявлен как строка для выполнения одного действия или как массив для указания нескольких скриптов.
Пример объявления скрипта как статический метод PHP:

Пример объявления скрипта как команда командной строки:

Запуск скриптов и пользовательские команды
При необходимости скрипты можно запустить вручную, а не использовать их только при возникновении какого-либо события.
Например, команда:

запустит все сценарии, которые определены для события post-install-cmd.
Если существует необходимость добавить пользовательский сценарий, но все доступные события не подходят под этот сценарий, то существует возможность определить под собственным именем.
Пример:

Запустить скрипт можно с помощью команды run-script, либо как собственную команду composer:

Плагины Composer
Плагин - это обычный пакет, который используется для расширения функциональности при необходимости.
Основное отличие заключается в том, что в composer.json пакет плагина должен иметь тип composer-plugin, атрибут extra должен содержать один или множество классов плагина, а также должен быть подключен специальный пакет composer-plugin-api.
Плагин подключается в проект как обычный пакет Composer. Он также должен быть загружен на Packagist.
Пример:

Создание плагина
Каждый плагин должен реализовывать интерфейс PluginInterface.
Интерфейс содержит методы, в которые передаются экземпляры классов Composer\Composer и Composer\IO\IOInterface.
С помощью этих двух объектов можно прочитать всю конфигурацию, а также управлять всеми внутренними объектами и состоянием.
Также, плагины могут реализовывать EventSubscriberInterface для автоматической регистрации обработчиков событий при загрузке плагина.
Пример класса плагина с обработками события:

Возможности плагина
Composer предоставляет так называемый набор возможностей, которые могут быть реализованы плагинами. Их цель состоит в том, чтобы расширить имеющиеся возможности, не прибегая к изменению внутреннего состояния экземпляра класс Composer.
Чтобы добавить использование возможностей, класс плагина должен реализовывать интерфейс Capable. Данный интерфейс содержит метод getCapabilities(), который возвращает массив с ключом в качестве имени класса Composer Capability и значением в виде собственного имени класса реализации плагина указанной возможности.
Пример реализации собственного поставщика команд.
Команда:

Поставщик команд:

После этого в проекте, где подключен плагин, можно использовать команду:

Выводы
- Composer - это не просто менеджер пакетов, но и удобный инструмент для управления PHP-проектом.
- Большой ряд дополнительных возможностей, которые могут быть полезны при разработке проектов на PHP.
- Лучшим способом погружения в какой-либо инструмент является изучение его официальной документации.

