Доброго дня.

Когда я первый раз разбирался с composer, я набросал для себя маленькую шпаргалку и теперь, спустя некоторое время представляю её на суд общественности в несколько доработанном виде.
Данная публикация актуальная для тех, кто в первый раз столкнулся с незаменимым менеджером пакетов для PHP.

Итак, Composer — менеджер пакетов для PHP.

Для чего нужен Composer и простейший пример его использования


Возьмем для примера этот проект
Если в двух словах: то это набор скриптов для работы в VK API
Соответственно, для работы этих скриптов нужно несколько библиотек
Библиотеки перечислены в файле composer.json — ключевой файл при работе с composer

Пример composer.json:

image

В этом проекте используется 5 библиотек. Соответственно, если разработчик решит опубликовать этот проект на github, то ему достаточно закинуть в репу саму папку со скриптами и составить composer.json, в котором будут описаны библиотеки, необходимые для работы этого проекта. Простота очевидна: в репу не нужно вслед за файлами прицепом тащить все нужные библиотеки. Занимает меньше места, проще распространять проект.

Пример работы:

Скачали проект

image

В папке scripts лежат непосредственно скрипты проекта, для работы которых и требуются эти 5 пакетов.

Запускаем установку пакетов:

image

После установки появляется папка vendor, куда складываются установленные пакеты и формируется файл autoload.php

image

Этот файл подключаем к проекту и всё — библиотеки подключены, можно спокойно с ними работать.

image

Простота очевидна: не нужно скачивать и подключать библиотеки и их зависимости самостоятельно, composer всё сделает за Вас. И вся эта пачка подключается одним единственным файлом autoload.php
Все пакеты, которые лежат в vendor, добавляются в автозагрузчик. При этом composer опирается на файлы composer.json, которые должны быть у каждого пакета. Формирование composer.json пакета — это задача разработчика пакета, от потребителя пакета требуется лишь описать в composer.json проекта, какие пакеты нужно подключить.

Это пример composer.json проекта:

image

Это пример composer.json пакета:

image

В секции require прописана зависимость этого пакета — библиотека guzzle http, необходимая для работы библиотеки getjump/vk. В данном случае, т.е. с точки зрения потребителя пакетов, всевозможные зависимости пакетов — это не наша «забота», с зависимостями composer разберётся сам.

Пространство имён пакета прописано в секции autoload

image

getjump\\Vk\\ — наименование пространства имён
src/getjump/Vk/ — директория, в которой лежат файлы с классами пакета
Работа с этой библиотекой в проекте:

image

Core и Friends — это классы библиотеки, которые разложены и прописаны в папке src в соответствии со стандартом PSR-4. Опять же формирование структуры пакета — это работа создателя пакета.
Нам, как потребителю пакета, достаточно прописать в наш проект
include '../vendor/autoload.php';
и все эти классы и пространства имён будут отлично работать.
При этом нам не нужно заморачиваться и писать автозагрузчик. Composer это сделает сам при выполнении команды install.

Установка


Установка Composer глобально


1) Для начала нужно что бы путь к директории с интерпретатором PHP был прописан в переменной окружения path.
Проверим, так ли это:
php –version

image

Если вывод получился типа такого, то этот шаг можно пропустить
На примере Windows 7
Система -> Дополнительные параметры системы -> Дополнительно -> Переменные среды

Далее нас будет интересовать переменная path:

image

Вписываем путь к интерпретатору

image
image

*С давних времён у меня на компьютере лежит сборка xampp, сама сборка здесь нафиг не нужна, а вот интерпретатор с неё вполне подойдёт (версия PHP – 5.6).

2) Перезапускаем терминал.
Создаём директорию и ставим composer (я ставил на диск D)
D:
cd /
mkdir bin
cd bin
php -r «readfile('https://getcomposer.org/installer');» | php
echo php "%~dp0composer.phar" %*>composer.bat

image

3) Добавим в переменную окружения path путь к composer.bat, например для D:\bin должно получиться:

image

Дополнительно можно добавить в path
D:\Users\%userName%\AppData\Roaming\Composer\vendor\bin\
для того, что-бы было удобнее использовать инструменты, глобально установленные через Composer.
(У меня папка Users располагается на диске D, а на C создан симлинк на неё).
Всё, composer установлен и полностью готов к работе.

Ещё: при установке можно словить ошибку
[RuntimeException]
The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly
Решение нашлось здесь github.com/composer/composer/issues/2033
Добавляем переменную APPDATA со значением D:\Users\GSU\AppData\Roaming

image

Установка Composer локально


Есть вариант ещё поставить composer локально, но в большинстве случаев в этом нет явной необходимости.
Однако тут установка ещё проще.
Т.к. программа глобально не установлена, нужен загрузочный файл(мини-программа composer), для его загрузки пишем команду:
php -r «readfile('https://getcomposer.org/installer');» | php
теперь в директории проекта появился файл composer.phar
Всё, можно использовать.
php composer.phar require [название пакета]

Отличия глобальной и локальной установки


Команды запускаются по разному при локальной и глобальной установках:

Например:
Локально: php composer.phar require silex/silex ~1.1
Глобально: composer require silex/silex ~1.1

При локальной установке нужно каждый раз скачивать установочный файл в папку текущего проекта
php -r «readfile('https://getcomposer.org/installer');» | php

При глобальной установке этот файл не нужен. Composer запускается при любой текущей директории.

Команды


install — установка пакетов, прописанных в composer.json
update – обновление пакетов
dumpautoload — пересборка автозагрузчика
require somepackage/somepackage:someversion — добавление нового пакета (по умолчанию пакеты ставятся из оф. репозитория). При установке пакет прописывается в composer.json
update --lock — обновление файла блокировки composer.lock
config --global cache-files-maxsize «2048MiB» — пример изменения параметра конфигурации
--profile — добавление этого параметра к любой команде включит показ времени выполнения и объёма использованной памяти
--verbose — подробная инфомация о выполняемой операции
show --installed — список установленных пакетов с описанием каждого
show --platform — сведения о PHP
--dry-run — репетиция выполнения команды. Может добавляться к командам install и update. Эмулирует выполнение команды без её непосредственного выполнения. Необходим для того, чтобы проверить пройдёт ли установка пакетов и зависимостей успешно.
remove — удаление пакета. Точная противоположность require

Синтаксис composer.json


Именование пакетов и варианты описания пакетов

Имя пакета состоит из двух частей разделёных косой чертой: названия поставщика (vendor name) и названия библиотеки.

image

Если пакет оформлен в соответствии со стандартом PSR-4, но опубликован не на packagist.org, а на github, то вместо версии пакета нужно прописать ветку и репозиторий для этого пакета:

image

Пример подключения библиотеки, которая лежит на github, но при этом не оформлена по стандарту PSR-4, а представляет из себя обыкновенное нагромождение файлов с классами и функциями.

Примерный вид:

image

Pqr/superlib — эта та самая «неправильная» библиотека.

В секции repositories для неё пишем такую конструкцию

image

Ключевой момент — секция autoload, здесь указываем нужные нам файлы с классами и функциями.
Структура библиотеки:

image

Содержимое файлов:

image
image

Соответственно в проекте вызов getCurrentTime() будет выглядеть примерно так:
$timer = new pqr\superlib\TimerClass;
echo $timer->getCurrentTime();

Версионирование


При указании допустимых версий пакетов можно использовать точное соответствие (1.2.3), диапазоны с операторами сравнения (<1.2.3), комбинации этих операторов (>1.2.3 <1.3), “последняя доступная” (1.2.*), символ тильды (~1.2.3) и знак вставки (^1.2.3).
Указание тильды (~1.2.3) будет включать в себя все версии до 1.3 (не включительно), так как в семантическом версионировании это является моментом внедрения новых функциональных возможностей. В данном случае будет получена последняя из стабильных минорных версий. Т.е. будет меняться только последняя цифра — 1.2.5, 1.2.8 и тд.

Указание знака вставки (^1.2.3) буквально означает “опасаться только критических изменений” и будет включать в себя версии вплоть до 2.0. Применительно к семантическому версионированию, изменение мажорной версии является моментом внесения в проект критических изменений, так что версии 1.3, 1.4 и 1.9 подходят, в то время как 2.0 — уже нет.
Т.е. не меняется только первая цифра.

Тильда: ~1.2.3 — это самый распространённый и безопасный способ указания версии.

Файл composer.lock


Файл composer.lock сохраняет текущий список установленных зависимостей и их версии. Таким образом, на момент, когда версии зависимостей уже будут обновлены (команда update), другие люди, которые будут клонировать ваш проект, получат те же самые версии. Это позволяет убедиться в том, что каждый, кто получает ваш проект, имеет пакетное окружение, идентичное тому, которое вы использовали при разработке, и помогает избежать ошибок, которые могли бы возникнуть из-за обновления версий.

При каждом выполнении команды update версии обновлённый пакетов прописываются в composer.lock. Этот файл загоняется под систему контроля версий и при установке пакетов на новом сервере поставятся именно те версии пакетов, которые прописаны в этом файле. При выполнении команды install composer будет в первую очередь опираться на composer.lock. Таким образом на разных серверах будет гарантированно установлено одинаковое пакетное окружение с точки зрения версий.

Также, файл composer.lock содержит хэш файла composer.json.
И если json файл был отредактирован, то composer выдаст предупреждение, что файл lock не соответствует json файлу.

В таком случае, нужно выполнить команду composer update --lock, которая обновит composer.lock.

image
image
image
image

Отличие install от update в контексте использования composer.lock


Команда composer install делает следующее:

Проверяет существует ли composer.lock:

— если нет, резолвит зависимости и создаёт его
— если composer.lock существует, устанавливает версии, указанные в нём

Команда composer update:

— Проверяет composer.json
— Определяет последние версии на основе указанных в этом файле
— Устанавливает последние версии
— Обновляет composer.lock в соответствии с установленными

Пример использования с точки зрения создателя проекта


Имеется проект без установленных пакетов

image

Поставили несколько библиотек

image
image

У нас сформировался composer.json с информацией о пакетах

image

Мы можем его дополнить и распространять проект с этим файлом

image

Другой пользователь скачал наш проект, выполнил install и у него в проекте развернулись все нужные пакеты

image

Пример использования с точки зрения создателя пакета


Для примера я создал класс с методом, который будет выводить URL текущей страницы

image

Класс оформлен как пакет и залит на github.

image
image

Составлен composer.json

image

Регистрируюсь на оф. репозитории и добавляю пакет, указывая ссылку на репозиторий, в котором он лежит

image

Всё, пакет добавлен

image
image

Проверяю работоспособность пакета

image

Пакет поставился, вот наш класс:

image

Вызываем метод

image

Всё ок.

image

Composer и PhpStorm


Инициализация

image
image
image
image

Конфигурирование возможности редактирования Composer пакетов

image

Если опция выставлена, то нельзя будет так просто взять и отредактировать файлы внутри vendor/*/*

Установка пакетов

image
image
image
image
image

Нюансы, тонкости, сложные ситуации


Ошибка: Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them. Nothing to install or update
Решение: composer update --lock

Долго выполняется update при большом числе установленных библиотек
Composer проверяет все зависимости пакетов, а если пакетов много — то это надолго.
Решение: если нужно обновить только одну библиотеку, то указываем её явно:

composer update package/name

Ещё можно добавлять параметр "--prefer-dist" (хотя, по идее, он должен быть включён по умолчанию), тогда composer будет стараться ставить библиотеку из zip-архива, а не клонировать репозиторий.

The "****.json" file could not be downloaded: failed to open stream: HTTP request failed!
Composer пытается дергануть пакет по HTTP, хотя нужно по HTTPS
Решение: composer config --global repo.packagist composer packagist.org

The package is not available in a stable-enough version according to your minimum-stability setting
see for more details.
Стабильной версии у пакета нет, а установка dev версии не разрешена в конфиге.
Решение: либо выставить параметр «minimum-stability»: «dev» и «prefer-stable»: true, чтобы ставить по возможности стабильные версии, либо — если это ваш собственный пакет — создать тег с версией (стикер stable в readme на github должен показывать версию)

История развития и ключевые изменения


— первый релиз состоялся 1 марта 2012 и весь 2012 инструмент активно развивается
— январь 2014 — реализована автозагрузка на основе PSR-4
— март 2016 — вышла в свет бета-версия (1.0.0-beta1). Добавлены команды show --tree для отображения установленных пакетов в виде дерева, why-not — показывает почему нельзя уставить пакет, update --interactive — позволяет выбрать какие пакеты обновлять, а также множество других улучшений и исправлений.
— 4 апрель 2016 — был представлен первый стабильный релиз Composer — 1.0.0

Декабрь 2014 — один из ключевых коммитов в репозиторий composer
github.com/composer/composer/commit/ac676f47f7bbc619678a29deae097b6b0710b799
Суть изменения — отключён сборщик мусора

image
image

habrastorage.org/getpro/habr/comment_images/db3/59a/972/db359a972df6730e52f292b5c52095b8.gif

Ссылки


Офсайт: getcomposer.org
Официальный репозиторий пакетов: packagist.org
Репозиторий composer: github.com/composer/composer
Отличный большой туториал по использованию Composer: daylerees.com/composer-primer
Список команд и подробный пример файла composer.json: composer.json.jolicode.com

Комментарии (25)


  1. iit
    06.02.2019 16:05

    Наступила неделя "простых инвайтов" от TM, количество некачественно оформленных статей будет увеличено в двое, количество авторов со слитой кармой будет утроено.


    Resident234 — если серьезно, то советую пока скрыть статью в черновики и доработать её, пока не слили карму.


    1. SerafimArts
      07.02.2019 03:37

      Да ладно, пусть и устаревшая, но довольно приличная статья для тех, кто ещё не успел войти в мейнстрим, получше всяких DBX и аналогичных, что сыпятся последнее время.

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


      1. istepan
        08.02.2019 07:38

        > приличная статья для тех, кто ещё не успел войти в мейнстрим

        И таких оооочень много. В свое время был удивлен.


  1. NorthDakota
    06.02.2019 16:11

    залейте картинки на habrastorage.org


    1. NorthDakota
      06.02.2019 16:13

      Боже, они всё-таки загрузились. Не загружайте такие картинки никуда…


  1. vdem
    06.02.2019 16:58

    Текст вместо картинок использовать религия не позволяет?
    И — кому надо столь иллюстрированное пособие «для самых маленьких», разве что тем, кто пользуется той же ОС и прочим инструментарием что и Вы.


  1. Gemorroj
    06.02.2019 17:09

    Информационность хорошая, глупостей нет.
    Форматирование пойдет (ну да, картинки можно было бы спрятать под спойлеры, но это мелочь, имхо).


    1. Compolomus
      07.02.2019 03:02

      Неожиданная встреча. Если я не обознался. Я когда то тоже писал файловый менеджер.


  1. arkamax
    06.02.2019 20:01

    Указание тильды (~1.2.3) будет включать в себя все версии до 1.3 (не включительно), так как в семантическом версионировании это является моментом внедрения новых функциональных возможностей. В данном случае будет получена последняя из стабильных минорных версий. Т.е. будет меняться только последняя цифра — 1.2.5, 1.2.8 и тд.

    Если бы все авторы библиотек / пакетов придерживались семантики — было бы замечательно. На практике же нет волшебного джинна, который стучал бы по голове любителям вкидывать новые фичи (вместе с багами) в maintenance updates, вследствие чего приходится часто прикручивать жесткие версии («1.2.5») как минимум на наиболее важные зависимости. Никто не мешает попробовать и с тильдой, просто учтите риски.


    1. SerafimArts
      07.02.2019 03:45

      вследствие чего приходится часто прикручивать жесткие версии («1.2.5»)

      Веселуха начинается тогда, когда основные пакты тысячу лет назад обновились, а какая-то зависимость висит в мастере. И начинается что-то вроде "sonata-project/olololo-admin-bundle": "dev-master@dev#commit278843ghdog872".


      Было пару раз такое (при обновлении symfony 2.8 -> 3.0), никому не рекомендую поступать аналогично. Там композер начинает творить ад (включая 1.8.3+, т.е. последние билды). Ну например, он качает исходники из указанного коммита, а сам composer.json строит по последнему доступному в мастер ветке, так что любые изменения в нём ломают весь проект к чертям, даже lock не помогает.


      1. arkamax
        07.02.2019 06:16

        Ну например, он качает исходники из указанного коммита, а сам composer.json строит по последнему доступному в мастер ветке

        В каком смысле он «composer.json строит» — это если composer require использовать, чтобы он вписал зависимость в composer.json? Я просто обычно вписываю строку в «require» напрямую в редакторе, и потом composer update — так он вроде бы держит указанный коммит. Или я что-то не так понял?


        1. SerafimArts
          07.02.2019 14:12

          Помимо composer.json есть ещё lock для версий и installed.json из которого он всё читает, генерируя автолоад и проч. Так вот, этот installed не соответсвует указанным.


          1. arkamax
            07.02.2019 18:52

            А, так понятно — просто в оригинале я прочитал, что он «composer.json строит по последнему доступному в мастер ветке», потому и запутался. Сейчас проверил в проекте — у меня такого не происходит, installed.json содержит те же хэши коммитов, что указаны в composer.json, притом upstream ушел дальше, новые коммиты там есть. Сам composer версии 1.6.3. Может, что-то еще пошло не так (тм)?


            1. SerafimArts
              07.02.2019 23:46

              1) Там не в хеше дело, хеш он записывает в `lock` как раз тот, который указан в самом `json`. Там сами внутренности другие (т.е. все require, autoload и проч.). Именно они берутся из самого последнего коммита.
              2) А ещё я тут подумал: Это возможно бага в artifactory (это шняжка для проксирования), попробую завтра на работе отрубить её и проверить что будет, если тянуть напрямую из packagist.


      1. BoShurik
        07.02.2019 12:15

        Да, это есть в документации:

        Note: This feature has severe technical limitations, as the composer.json metadata will still be read from the branch name you specify before the hash. You should therefore only use this as a temporary solution during development to remediate transient issues, until you can switch to tagged releases. The Composer team does not actively support this feature and will not accept bug reports related to it.

        Отчасти это послужило «пинком под зад» в расстановке semver-тегов для своих внутренних компонтентов


  1. SbWereWolf
    07.02.2019 00:43

    композер можно установить не только из командной строки — https://getcomposer.org/download/:

    Windows Installer
    The installer will download composer for you and set up your PATH environment variable so you can simply call composer from any directory.

    Download and run Composer-Setup.exe — it will install the latest composer version whenever it is executed.

    За статью спасибо. Про публикацию пакета очень интересно.

    Раздел «Composer и PhpStorm» на самом деле было бы приятней прочитать текстом чем на картинках, тем более что на скринах нет пояснений на что смотреть и что кликать, если это инструкция, то надо описывать последовательность действий, к картинкам нужны комментарии.


  1. Compolomus
    07.02.2019 02:54

    Можно ещё добавить про composer init


  1. almassar
    07.02.2019 08:06

    Народ подскажите как организовать процесс разработки пакета? Вот есть у меня пакет и есть приложение которое использует его. Потом я что то изменил в пакете или исправил баг. Что потом делать? Менять новую версия и отправлять в гит, а потом в приложение запустить composer update? И так что нужно каждый раз делать?


    1. Compolomus
      07.02.2019 08:55

      В зависимости от сложности изменений меняйте версии, обновлять каждый раз, на то она и разработка. Сложнее когда зависимостей для пакета много, и по мере надобности править одновременно несколько пакетов. Главное хуки в репах настроить, чтоб пакажист сам тянул, ну и оно ещё требует подождать, так как версии не сразу подтягивает. Есть неочевидный прикол на пакажисте, я вместо логина прописывал мыло, и долго не понимал, почему хук не работает


    1. Compolomus
      07.02.2019 08:58

      Хотя можно наверное указать дев ветку, и просто тянуть без исправлений версии


    1. iit
      07.02.2019 11:27

      Если хотим стабильности то — да обновлять каждый раз и контролировать версии.
      Версии нужно контролировать тегами git.


      Желательно следовать semver https://semver.org/lang/ru


    1. arkamax
      07.02.2019 19:01

      Уточню, на всякий случай — если пакет стянут с гитхаба, то в vendor/[vendor]/[package] окажется копия соответствующего GIT-репозитария. Соответственно, можно прямо в этой папке спокойно работать с гитом, менять ветки как захочется, и высылать изменения в апстрим, если позволяют права работы с репозитарием. Когда наигрались и изменения приняты (и в идеале помечены тегом) — обновляем composer.json, делаем composer update. Как по мне — достаточно удобно. Если это общеизвестная информация, прошу прощения за капитанство.


  1. trawl
    08.02.2019 11:28

    Раз уж решили описать публикацию в packagist, можно заодно и описать процесс настройки веб-хуков на гитхабе


    1. BoShurik
      08.02.2019 12:53

      Там теперь достаточно подключить профиль к GitHub и дать соответствующие права. Если
      вы авторизовались через GitHub давно, как я, то надо просто разлогиниться и войти снова, тогда вам предложат доставить разрешения. После этого все библиотеки будут обновляться автоматически


      1. trawl
        08.02.2019 12:59

        О как! А я всё ручками, да ручками… Спасибо!