Composer полезен для проектов, которым для работы необходимы сторонние программные пакеты. Эти пакеты в свою очередь могут зависеть от других пакетов, и так далее.
Даже если такой сторонний пакет всего один, использование Composer может быть удобным и полезным.
Пакеты Composer размещает в специальном каталоге (vendor
). Добавлять пакеты в своё хранилище системы контроля версий не надо. Туда нужно занести только файл конфигурации composer.json
, где и перечислены нужные пакеты, а при изменении их состава или обновлении версий запускать специальную команду.
Таким образом, в хранилище находится только собственный код проекта, а сторонние библиотеки загружает Composer.
Composer официально называют менеджером зависимостей для PHP, подобному npm для Node.js, подчеркивая отличие от менеджеров пакетов (таких как Apt или Yum в Linux). Отличие состоит в практике использования: установке пакетов внутри отдельных проектов, а не глобально на уровне операционной системы, хотя Composer поддерживает оба варианта.
Рабочий пакет самого Composer состоит из одного файла - composer.phar
.
Все операции, проводимые Composer, требуют запуска этого файла (а точнее - передачи его интерпретатору PHP).
"Установка" Composer заключается в размещении этого файла тем или иным образом и бывает локальной (в рамках каталога отдельного проекта) - и глобальной (для всех проектов, на уровне ОС).
Глобальную установку нужно провести один раз, и после этого можно будет использовать Composer во всех проектах без необходимости в каждый из них его устанавливать.
Установка вручную позволяет создать переносимый рабочий пакет, который не придется заново устанавливать при переносе на другие системы. Там нужно будет только прописать нужный каталог в системную переменную Path.
-
Скачиваем файл
composer.phar
по адресу https://getcomposer.org/download/latest-stable/composer.phar. (Ссылка взята со страницы https://getcomposer.org/download/, раздел Manual Download, Latest Stable.) -
Создаем каталог, куда переносим файл
composer.phar
. Например,D:/portable/composer
. -
Добавляем этот каталог в системную переменную
Path
.Win + R
--> Дополнительные параметры системы --> Переменные среды --> Системные переменные --> Path --> Изменить --> Создать --> ... --> OK --> OK -
В этом же каталоге создаем файл
composer.bat
следующего содержания:
@php "%~dp0composer.phar" %*
(Например, так: echo @php "%~dp0composer.phar" %* > composer.bat
.)
- Открываем командную строку (
Win + R
,cmd
) и даем команду:
composer
Должна появиться распечатка опций composer.
Это запускается composer.bat
.
Команду нужно дать какого-нибудь другого каталога, чтобы проверить изменения в Path
.
Глобальная установка сводится к двум простым действиям:
- Скачать на сервер файл
https://getcomposer.org/download/latest-stable/composer.phar
.
Это можно сделать с помощью wget
или другой аналогичной команды:
wget https://getcomposer.org/download/latest-stable/composer.phar
Если никакие утилиты для копирования на сервере не установлены, можно сделать это прямо с помощью php
:
php -r "copy('https://getcomposer.org/download/latest-stable/composer.phar', 'composer.phar');"
Либо воспользоваться установщиком (раздел Command-line installation), который делает то же самое и проверяет контрольную сумму.
Важно также дать всем права на исполнение:
chmod a+x composer
- Прописать расположение
composer.phar
в переменной$PATH
, чтобы не приходилось каждый раз указывать полный путь. Как вариант - поместить файл в каталог, который уже есть в$PATH
, например,/usr/local/bin
.
Если прав на запись нет, можно сделать alias
для личного пользования:
alias composer="php ~/composer"
Заодно убрать из имени файла расширение для более короткой записи (composer
вместо composer.phar
).
Скорее всего, команду нужно будет дать с помощью sudo
:
sudo mv composer.phar /usr/bin/composer
Т.к. composer.phar
содержит в начале фрагмент #!
, в Linux его можно запускать из командной строки как исполняемый файл - писать просто composer ...
вместо php composer ...
.
Можно, например, проверить успешность установки:
cd ~
composer -V
Composer version 2.5.5 2023-03-21 11:50:05
Кроме того, нужно назначить файлу разрешение на запуск (сразу после копирования его, как правило, нет из-за настроек umask
):
chmod u+x,g+x,o+x composer
Установку можно провести всего двумя командами. В обеих фигурирует одинаковое имя файла, поэтому его предварительно удобно записать в переменную.
export destination=/usr/bin/composer
sudo wget -O $destination https://getcomposer.org/download/latest-stable/composer.phar
sudo chmod u+x,g+x,o+x $destination
composer.json
, update
, Packagist.org
Любой проект под управлением Composer должен иметь в своем корневом каталоге файл composer.json
, в котором перечислены используемые пакеты и различные настройки. Выглядит он примерно так:
{
"require": {
"monolog/monolog": "^2.9",
"phpoffice/phpspreadsheet": "^1.27"
}
}
Чтобы установить пакеты (загрузить их файлы и поместить в нужные каталоги), нужно в командной строке из корневого каталога проекта дать команду:
# Если Composer установлен глобально:
composer update
# Если Composer установлен на уровне проекта
php composer.phar update
(Примечание: при работе с git-bash под Windows нужно явно указывать расширение исполняемого файла - composer.bat update
)
Подробнее см. на https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies.
Пути к пакетам указываются для Packagist.org - публичного хранилища, предназначенного для использования вместе с Composer. Любой желающий может не только использовать тамошние пакеты, но и публиковать свои собственные.
При желании, можно указать Composer забирать код из любых других хранилищ, в т.ч. собственноручно созданных.
Состоит путь из двух частей - поставщика (vendor) и собственно названия (package) и имеет вид поставщик/пакет
. Часто названия постащика и пакета совпадают (например, monolog/monolog
и др.).
При загрузке Composer создает в корне проекта каталог vendor
и подкаталоги пакетов вида поставщик/пакет
.
Устанавливать и обновлять пакеты можно также выборочно:
composer update monolog/monolog
Сразу после загрузки пакетов Composer создаст файл composer.lock
. Там перечислены точные версии всех пакетов. Этот файл нужно добавить под контроль версий проекта, т.к. именно с его помощью Composer обеспечивает привязку к конкретным версиям пакетов на других копиях кода проекта (отсюда и "lock").
Этот файл использует команда composer install
, которая, собственно, и загружает указанные версии пакетов. При запуске update
эта команда вызывается неявно. Если файл composer.lock
в проекте уже есть, для загрузки пакетов нужно вызывать её, а update
- только для обновления пакетов до последних версий.
composer install
, в частности, может создать и заполнить каталог vendor
, если он еще не существует.
Повторное исполнение команды при уже загруженных файлах пакетов не вызовет ошибок. Это полезно для первичной загрузки и обновления кода используемых пакетов при развертывании основной системы, будь то сервера разработки или основная площадка, поскольку содержимое пакетов не должно быть под контролем версий (см. также stackoverflow).
Можно одной командой добаить пакет в composer.json
и загрузить его самую последнюю версию:
composer require phpoffice/phpspreadsheet
Также эта команда создает файл composer.json
, если это не было сделано ранее.
Можно указывать сразу несколько пакетов:
composer require monolog/monolog phpoffice/phpspreadsheet
Если дать команду, указав вместо имени пакета звездочку - composer require phpoffice/*
, она запросит и выдаст список всех пактов поставщика.
composer remove phpoffice/phpspreadsheet
Эта команда удалит пакет из composer.json
и удалит его файлы. То есть, действие этой команды противоположно composer require
.
Можно давать её с маской:
composer remove monolog/*
В секции require
файла composer.json
можно перечислять и такие требования. Например:
{
"require": {
"php": ">=7.4",
"ext-gd": "*",
"lib-curl": "*",
"another-vendor/package": "1.*"
}
}
Размещать пакеты на Packagist можно на основе репозиториев Github. Для этого в личном кабинете на Packagist достаточно указать адрес репозитория.
Между Packagist и Github должна быть установлена связь: выдан ряд разрешений и пр. Инструкции будут показаны при размещении первого пакета.
Все коммиты нужно снабжать метками, чтобы они были видны composer require/update
без специальных меток (типа dev-main
или *
; они вызвают неполадки при иерархических зависимостях, поэтому их использовать не стоит).
Общепринятым способом публиковать версии пакетов считаются Github releases.
PHP Composer is an anti-pattern.
Пакет phpoffice/phpspreadsheet
среди требований имеет "ext-mbstring": "*"
.
При этом среди зависимостей этот пакет имеет maennchen/zipstream-php
, который в свою очередь требует symfony/polyfill-mbstring
.
Получается, что последний присутствует в проекте без надобности.
Так получается, потому что в composer.json
нет возможности указания зависимостей в случае отсутствия библиотек/расширений в системе.
Composer может установить пакет в виде репозитория git.
Для этого команды install
и require
нужно запускать с ключом --prefer-install=source
(значение по умолчанию - dist
, см. install).
Для дальнейшей работы с репозиторием пакета нужно дать в ее каталоге команду git checkout master
, т.к. Composer при загрузке отсоединяет ветку.
Если пакет уже был установлен в обычном виде, а нужно получить его репозиторий, нужно использовать команду reinstall с вышеукзанным ключом. Она удалит пакет и установит его заново. ВНИМАНИЕ! При этом нужно закрыть все программы, в которых открыт каталога пакета внутри vendor
; в противном случае Composer не сможет его пересоздать, т.к. он занят другой программой, и операция завершится ошибкой, исправить которую можно будет только откатом файлов (git checkout .
) и последующим повторным запуском composer install
.
Можно дать Composer инструкцию искать пакеты и в других местах. Это может потребоваться, если они пока еще не готовы к тому, чтобы представить их широкой публике.
Пакеты при этом могут храниться в репозиториях под котролем git, в т.ч. на github, или просто на каком-то сервере с досутпом по SSH (в таком случае нужно предварительно наладить и проверить соединение).
Единственное к ним требование - наличие в корневом каталоге собственного файла composer.json
с полем name
в виде vendor/package
:
{
"name": "someone/some-package"
}
Для успешной проверки командой composer validate
файл также должен содержать разделы description
и license
.
Этот файл должен находиться под контролем версий, т.е. его нужно добавить под управление git и сделать коммит. Только после этого он станет действовать.
Далее такой пакет нужно указать как один из элементов поля repositories
исходного composer.json
:
"repositories": [
{
"type": "git",
"url": "ssh://username@host:port/path-to-repo"
}
]
Можно указывать пути к репозиториям на локальной машине, например
"url": "D:\\somedir\\somepkg"
После этого можно давать команду на установку.
Если проекту не назначаются версии в виде меток git (tags), обычная команда выдаст ошибку:
Could not find a version of package one234ru/somepkg matching your minimum-stability (stable). Require it with an explicit version constraint allowing its desired stability.
Команде нужно явно указать ветку в виде названия с префиксом dev-
. Например, для ветки master
команда будет выглядить так:
composer require someone/some-package:dev-master
В этом случае пакет всегда устанавливается с исходным кодом - в режиме --prefer-install=source
. Явно указанное значение dist
никакого эффекта не даёт.
Каждый такой пакет нужно указывать в repositories
. Чтобы организовать свой каталог пакетов, нужно где-то разместить файл packages.json
. Об этом подробнее см. тут.
(Как вариант, можно организовать свой packagist-заглушку прям в каталоге prod-площадки, указав packages.json
смотреть прямо в vendor
там.)
ВНИМАНИЕ! При изменении путей в repositories
нужно дать команду composer update
для обновления файла composer.lock
. Если этого не сделать, отправка изменений в вышестоящий репозиторий и запуск там хуков git будет обращаться к старому источнику пакетов.
Кроме того, нужно не забывать делать composer update
при каждом случае доработки пакета и только потом делать commit
и push
. (Например, если работа проходила в локальном каталоге vendor
и затем отправляется в вышестоящий репозиторий пакета.) В противном случае ссылки на версию git
в composer.lock
не обновятся, и на всех других копиях будет использована старая версия, без обновлений. Буквально:
- вносим изменения в пакет,
git commit
git push
- возвращаемся в корневой каталог проекта
- делаем
composer update
; изменения будут получены из вышестоящего хранилища пакета, обновитсяcomposer.lock
; делаемcommit
уже самого проекта, а не библиотеки;
если не хочется гонять содержимое библиотеки туда-обратно, можно просто обновить поляreference
иtime
у соотв. пакета вcomposer.lock
(полеpackages
)
Важно упомянуть следующий специфический случай: доработка файла composer.json
(в частности, раздела autoload
) в рабочем каталоге проекта не окажет влияния на работу команды composer dump-autoload
, поскольку в этом действует версия из хранилища-источника, а не локальная.
Также надо отметить, что Composer сразу прописывает подходящий URL для push. Например:
composer https://github.com/vendor/package (fetch)
composer https://github.com/vendor/package (push)
origin https://github.com/vendor/package (fetch)
origin [email protected]:vendor/package.git (push)
Composer автоматически генерирует файл-автозагрузчик для установленных пакетов.
Можно добавить код в В автозагрузку можно , а также вручную указанных пользователем инструкций.
Выглядит эти инструкции примерно так:
"autoload": {
"psr-4": {
"SomeSpace\\": "."
}
}
Такая конфигурация подходит для случая, когда в корневом каталоге пакета находится файл SomeClass.php
следующего содержания:
<?php
namespace SomeSpace;
class SomeClass {}
Если бы файл находился, к примеру, в подкаталоге src
(как это бывает во многих общедоступных пакетах), то конфигурация автозагрузки выглядела бы так:
"SomeSpace\\": "src/"
Чтобы автозагрузчик подействовал, нужно где-то его подключить:
require __DIR__ . '/vendor/autoload.php';
Файл vendor/autoload.php
возвращает объект автозагрузчика. С его помощью можно дополнять правила автозагрузки. Подробнее см. тут.
В composer.json
можно сделать раздел autoload.
Если, например, весь код располагать в пространстве имён _Local
и складывать его в папку lib
в корневом каталоге проекта, инструкции будут выглядеть так:
{
"autoload": {
"psr-4": {
"_Local\\": "lib/"
}
}
}
Указание искать все пространства имён в каталоге обозначается так:
{
"autoload": {
"psr-4": { "": "src/" }
}
}
После внесения изменений нужно выполнить команду composer dumpautoload.
Также можно проинструктировать composer искать классы в нескольких местах. Причем эта инструкция будет выполняться вместе со стандартной автозагрузкой из каталога vendor
:
{
"autoload": {
"psr-4": {
"_Local\\": "lib/_local",
"SomeVendor\\": "lib/somevendor-dev",
"OtherVendoer\\": [ "lib/othervendor", "tmp/othervendor"]
}
}
}
В любом случае нужно дать команду на загрузку внешнего пакета, как бы он ни был подключён.
Composer более универсален, т.к. он может загружать пакеты прямо из хранилища git, без регистрации их на Packagist.org и где-либо еще.
Composer лучше подходит для поддержания зависимостей, т.к. именно для этого он и создавался. У подмодуля git тоже могут быть подмодули, с --recursive они загрузятся. Однако проверки версий PHP и пр. не будет.
composer --prefer-install=source
- это, по сути, и есть git submodule
При использовании Git composer install
нужно выполнять при инициализации рабочей копии - git checkout
(можно использовать хук вида post-checkout) и при получении изменений - git pull
(post-merge) в случае, если изменился composer.lock
.
При публикации изменений на основной площадке по типу push-to-deploy, когда главный репозиторий находится непосредственно в рабочем каталоге, нужно иметь аналогичный хук post-receive
.
Для реализации такой схемы понадобятся два файла - непосредственно сам хук и скрипт, где сосредоточена собственно рабочая логика:
Хук - файл .git/hooks/post-receive
:
#/bin/sh
echo "This is post-receive hook"
# current dir is .git
sh ../../composer-install-if-necessary.sh
Во всех хуках можно использовать одну и ту же команду.
Скрипт composer-install-if-necessary.sh нужно поместить в каталог выше рабочий копии (..
по отношению к ней). Это логично, если рабочих копий несколько - например, prod и несколько dev, и все они будут его использовать.