Эту статью можно было бы также назвать "Composer для самых маленьких".

Однако, здравствуйте.

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

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

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

Возьмем для примера этот проект.

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

Пример composer.json
{
    "name": "dosjein/vkdeepmine",
    "description": "DeepMine service for Vkontakti",
    "license": "top-secret",
    "authors": [
        {
            "name": "John Dosje",
            "email": "dosjein@gmail.com"
        }
    ],
    "minimum-stability": "dev",
    "require": {
        "vlucas/phpdotenv": "~1.",
        "erusev/parsedown": "^1.6",
        "getjump/vk": "*",
        "guzzlehttp/guzzle": "*"
    }
}

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

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

Скачиваем проект:

image

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

composer install

image

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

autoload.php
image image

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

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

Пример composer.json проекта
{
    "name": "dosjein/vkdeepmine",
    "description": "DeepMine service for Vkontakti",
    "license": "top-secret",
    "authors": [
        {
            "name": "John Dosje",
            "email": "dosjein@gmail.com"
        }
    ],
    "minimum-stability": "dev",
    "require": {
        "vlucas/phpdotenv": "~1.",
        "erusev/parsedown": "^1.6",
        "getjump/vk": "*",
        "guzzlehttp/guzzle": "*"
    }
}
Пример composer.json пакета
{
    "name": "getjump/vk",
    "description": "Library for work with API Vk.com",
    "keywords": ["php", "vk", "api", "library", "vkontakte"],
    "license": "MIT",
    "authors": [
        {
            "name" : "Pavel S.",
            "email" : "contact@getjump.me"
        }
    ],
    "require": {
        "guzzlehttp/guzzle": "6.*",
        "php": ">=5.5.0"
    },
    "require-dev": {
        "phpunit/phpunit": "4.1.*"
    },
    "autoload": {
        "psr-4": {
            "getjump\\Vk\\": "src/getjump/Vk/"
        }
    }
}

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

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

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

* С давних времён у меня на компьютере лежит сборка 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

Чтобы было удобнее использовать инструменты, глобально установленные через Composer, дополнительно можно добавить в path:

D:\Users\%userName%\AppData\Roaming\Composer\vendor\bin\

* У меня папка 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

Composer готов к использованию:

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

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

"getjump/vk": "*",

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

"repositories": [
  {
    "type": "git",
    "url": "http://github.com/gears-php/framework"
  }
],
"require": {
  "gears-php/framework": "dev-master",
  "mustangostang/spyc": "dev-master"
}

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

image

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

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

{
  "type": "package",
  "package": {
    "name": "pqr/superlib",
    "version": "1.2.3",
    "source": {
      "type": "git",
      "url": "http://github.com/pqr/superlib",
      "reference": "master"
    },
    "autoload": {
      "classmap": [
        "timer.php"
      ],
      "files": [
        "lib_functions.php"
      ]
    }
  }
}

Ключевой момент: в секции 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:

composer update
 image

composer show --installed
 image

composer install  

image
image

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

Команда composer install проверяет, существует ли composer.lock:

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

Команда composer update:

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

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

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

image

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

composer require "getjump/vk:*"

image
image

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

image

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

{
    "name": "gsu/gsu",
    "description": "Test project",
    "license": "top-secret",
    "authors": [
        {
            "name": "Sergey",
            "email": "gsu1234@mail.ru"
        }
    ],
    "require": {
        "getjump/vk": "*",
        "mustangostang/spyc": "^0.6.2"
    }
}

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

image

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

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

image

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

image

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

{
  "name": "gsu/helperurl",
  "description": "Helper URL",
  "keywords": ["url"],
  "license": "MIT",
  "authors": [
    {
      "name": "Sergey G.",
      "email": "gsu1234@mail.ru"
    }
  ],
  "require": {
    "php": ">=5.5.0" 
  },
  "autoload": {
    "psr-4": {
      "gsu\\helperurl\\": "src/gsu/helperurl/"
    }
  }
}

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

image

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

image
image

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

composer require gsu/helperurl

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 composerpackagist.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 должен показывать версию)

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

Автор:
Цыкарев Алексей
Руководитель Digital Spectr