Привет, Хабр! Сегодня я хотел бы поговорить с вами о знакомых опытным PHP-девелоперам, но загадочных для новичков, штуках — Composer и Packagist. Не сомневаюсь, что для многих здесь текст не станет откровением. Материал для тех, кому с описанным ниже только предстоит столкнуться.
Вы — PHP-разработчик, и вам нужен хороший менеджер зависимостей — как npm или Bundler? Вам надоело мучаться с pear? И вы не хотите вручную качать библиотеки с сайтов и обновлять все зависимости? Тогда самое время познакомиться с Composer и Packagist.
Основы
Начнем с объяснения, что такое Composer, а чуть позже поговорим и про Packagist. Composer — изначально менеджер зависимостей для PHP на уровне проекта. Это значит, что теперь нам не нужно мучиться с когда-то популярным pear, потому что для каждого проекта нужны свои версии библиотек и прочего. Теперь с помощью Composer все зависимости будут установлены в папку vendor в корне вашего проекта, и проекты не будут конфликтовать. Каждому проекту будет доступен свой набор установленных зависимостей.
Также в composer.json можно задать секцию scripts. Если грамотно ее использовать, можно получить легкий деплой-менеджер. Но изучение этой секции оставляю вам в качестве домашнего задания :).
Как это работает? Нужно просто создать файл composer.json в корне проекта и заполнить его согласно документации. Требуемый минимум в этом файле — набор зависимостей. По сути, это просто json-объект, ключ в котором — название нужного пакета, а значение — нужная для проекта версия. Для указания версий используется semver. Например, если для проекта нужны PHP минимум версии 5.4 и библиотека для логгирования monolog 1.9.*, нужно указать следующий объект require.
"require": {
"php": ">=5.4.0",
"monolog/monolog": "1.9.*"
}
Дальше просто нужно в командной строке выполнить команду composer update, и все новые зависимости будут подгружены в папку vendor, и вы сможете их использовать. Да, целиком PHP Composer не подтянет, но проверит, чтобы установленный на машине PHP был нужной версии. А если речь идет о библиотеках, Composer скачает пакет подходящей версии в папку vendor.
Представьте ситуацию: мы наконец-то внедрили в свой проект Composer, вовсю его используем, в общем, мы — молодцы! Но в какой-то момент приходим к ситуации, когда и у разработчиков и на сервере стоят разные версии библиотек. Как быть? Для этого composer рядом с composer.json создает файл composer.lock. В него после команды composer update записывается точная информация о версиях, которые установлены. Его нужно закоммитить в систему контроля версий, и таким образом все разработчики, а также на сервере можно просто выполнить команду composer install, и будут установлены все библиотеки точно таких версий, которые описаны в этом файле.
Пишем свой пакет
Любой желающий разработчик имеет право создать свой composer пакет и выложить в Open Source. Этот процесс я и хочу описать дальше.
Composer пакет по сути — это набор файлов, которые можно подключить в любой проект. Всё это можно отсортировать по папкам, как Вам только захочется. Главное, настроить автозагрузку composer. Какая же структура Composer пакета? Обязательным файлом для любого пакета является composer.json. Это файл в котором хранится вся информация про данный пакет: название, описание, список зависимостей, тип лицензии, и так далее. Вот пример composer.json простого пакета.
{
"name": "dataart/package",
"type": "library",
"description": "Composer package by DataArt",
"license": "MIT",
"require": {
"php": ">=5.4.0",
"illuminate/support": "~4.2"
},
"autoload": {
"psr-4": {
"Dataart\\Package\\": "src/"
}
}
}
Name — имя пакета (формат vendor/name).
Type — тип пакета, данный пакет — библиотека
Description — описание пакета.
License — тип лицензии.
Require — список зависимостей данного пакета. Для него требуется версия PHP не менее 5.4.0 и пакет illuminate/support. Все версии описываются по semver.
Autoload — настройки автозагрузки. В данном случае указано, что неймспейс Dataart\Package начинается в папке src. Т. е. у всех файлов, которые лежат в папке src, должен быть неймспейс Dataart\Package. Если, например, хотите создать класс User и сохранить файл класса в папке Models, неймспейс класса User должен быть Dataart\Package\Models.
В папке src хранятся все нужные для работы пакета файлы. Рекомендуется рядом с папкой src сделать папку tests, и покрыть библиотеку тестами. Далее вся папка, в которой лежит composer.json, должна быть закоммичена на Github. Можно на Bitbucket, но все используют именно Github.
Также composer имеет некоторое количество консольных команд, которые призваны ускорить работу с ним.
init
запустит для вас интерактивную инициализацию composer проекта и, задав несколько основных вопросов, сгенерирует composer.json-файл.
install
считывает composer.json, разрешает зависимости и устанавливает их в папку vendor. Если в папке есть файл composer.lock, будут использованы точные версии, указанные в файле. Это даёт возможность всем разработчикам иметь одинаковые версии всех библиотек.
update
используется, чтобы получить новые версии пакетов, тем самым обновить composer.lock. Также используется, если добавились новые зависимости. Может использоваться также с параметрами. composer update vendor/package1 vendor/package2 обновит только два пакета. Также можно обновить все пакеты одного вендора командой composer update vendor/*
require
добавляет новые зависимости из командой строки. Например, composer require vendor/package:2.* vendor/package2:dev-master. Если не указать версию, composer автоматически подтянет последнюю стабильную версию.
remove
точная противоположность require.
dump-autoload
обновить autoloader, если появились новые классы или правила автолоадинга.
К командам install, update и dump-autoload можно добавить ключ —optimize-autoloader (-o), чтобы конвертировать правила автозагрузки psr-0/4 в «карту классов», чтобы ускорить автозагрузку. Рекомендуется для production окружения.
Open Source It
Закоммитили? Круто, но composer всё равно почему-то не находит пакет и не может его подтянуть для другого проекта. Как быть?
Да, можно указывать конкретные адреса svn/git репозиториев в composer.json, но это неудобно. Намного удобнее иметь какой-то центральный пункт, где есть соответствия пакетов с их адресами репозиториев. Это Packagist.
Он используется для публикации composer пакетов. Опубликовать свой пакет туда очень легко. Достаточно зарегистрироваться на сервисе (или используя Github аккаунт через oAuth2), далее перейти по ссылке Submit Package, указать URL репозитория, а Packagist всё остальное сам подтянет и периодически будет проверять репозиторий на наличие новых версий.
Как происходит версионирование? Версионировать надо согласно системе semver. А указывать версии пакетов, используя тэги в системе контроля версий. Всё очень просто!
Создавайте свои пакеты, публикуйте их и становитесь полноценным участником Open Source сообщества.
Установить composer можно на getcomposer.org.
Посмотреть все доступные PHP-пакеты можно на packagist.org.
Комментарии (17)
OnYourLips
14.04.2015 20:26-7Программировать не PHP без composer — как быть водителем такси без автомобиля.
t1gor
14.04.2015 22:22+1Теперь с помощью Composer все зависимости будут установлены в папку vendor в корне вашего проекта
Согласно документации, папку можно поменять — директивой «vendor-dir»
Странно что вы не упомянули «require-dev», т.к. часто есть библиотеки которые нет смысла хранить на production сервере.hell0w0rd
14.04.2015 22:34-2Согласно документации, папку можно поменять — директивой «vendor-dir»
Что является плохой практикой, поэтому не стоит это упоминать.guyfawkes
14.04.2015 22:47+2А по какой причине это плохая практика?
Punk_UnDeaD
14.04.2015 22:58-2Если структура проекта подразумевает папку vendor в корне, то плохая.
А если не в корне, то хорошая.
В Drupal пакетам следует находиться в «sites/all/vendor».
t1gor
15.04.2015 00:44+3Вы не задумывались о том, что бывают проекты совсем без фреймворков например, где структура папок определяется фантазией и чувством прекрасного разработчика?
Какие-то аргументы в пользу «хорошая» и «плохая» можно услышать?
Я бы тоже с удовольствием выслушал.hell0w0rd
15.04.2015 01:47-3Задумываюсь. Но в любом проекте есть точка входа, composer помимо установки пакетов создает автолоадер, который нужно подключить в этой точке и больше не задумываться об этом.
Если вы меняете название директории vendor, которая является стандартом для php, или node_modules для node — вы автоматически создаете сложности тем, кому этот проект нужно будет поддерживать. И совсем не важно, на каком фреймворке, или без него вы пишите.
Если рассуждать так, как вы, то фантазией разработчика, уставшего от надоедливых пользователей может быть переименование сущности User на Monkey, вы тоже это считаете вполне себе нормальным?
Вот пост на эту темуsvscorp
15.04.2015 09:28+2Если вы меняете название директории vendor, которая является стандартом для php
А можно ссылочку на стандарт PHP для именования папки с зависимостями?
Если вы меняете название директории vendor, которая является стандартом для php, или node_modules для node — вы автоматически создаете сложности тем, кому этот проект нужно будет поддерживать. И совсем не важно, на каком фреймворке, или без него вы пишите.
Если рассуждать так, как вы, то фантазией разработчика, уставшего от надоедливых пользователей может быть переименование сущности User на Monkey, вы тоже это считаете вполне себе нормальным?
Я не могу понять, как я создаю сложности тем, кто будет поддерживать проект? Если принимается решение об именовании папки vendor каким-либо другим именем, наверняка для этого есть причина?
— Существующий проект. Наверняка. Если есть причина, то, скорее всего, все те, кто поддерживает проект — вкурсе изменения
— Новый проект. Если я начинаю поддерживать какой-то проект, в котором изначально было принято решение о другом имени для папки с зависимостями, то какие трудности это создает для меня? :)
Composer Vendor Directory пост
«One True Vendor» — не сильный аргумент, а стремление автора к consistency. Там говорится о том, что папка vendor — «задумано по дизайну». И приводится «хорошая причина для такого дизайна»:
Composer targets the PHP community. It aims to grow the library space. Libraries should be small, focused, flexible and avoid side-effects. The user should be in control.
Если папка будет отлична от vendor — ничего не идет вразрез с «хорошим дизайном» (отсылка к тексту параграфа One True Vendor).
«Autoloading» — не нашел сильных аргументов. Зато есть:
A composer-managed application should have exactly one single include statement. A require vendor/autoload.php in the front controller
Почему это не может быть «require vendor-dir/autoload.php» неясно.
«Single directory» — тоже все весело. Особенно порадовало:
Third, version control. No need to litter your gitignore with random garbage
Т.е. папку vendor, создавая новый проект, совсем не надо добавлять ее в .gitignore :)
Isolation — единственное «заключение» в нем это:
Enough of that. That's why composer is a dependency manager and not a package manager. It manages deps per-project, it isolates them. It disallows sharing the same package directory between projects
Как это связано с именованием папки зависимостей? Неясно. Зато — «мамой клянус!» («trust me, it's totally worth it») присутствует :)
Итог
Человек, написавший пост, явно устал от управления зависимостями с PEAR, особенно работая с несколькими проектами, которые зависят от разных библиотект. И он (человек) стремится к согласованности в именовании папки, что поощримо (я сам ЗА consistency в проектах). Но аргументов нет, есть только — «ппц, да это не круто именовать папку отлично от vendor».
Я тоже предпочитаю «vendor», hell0w0rd, тем более, что пока не приходилось иметь дизайн приложения, который требовал бы изменения дефолтной конфигурации. Но я не исключаю возможности такой необходимости.
И если все зависимости хранятся в одной папке, а не разбросаны по проекту — то по-сути все равно, какая эта папка (если уж дефолтное название изменено, возможно, есть на то причина).
Punk_UnDeaD
14.04.2015 22:53dump-autoload
обновить autoloader, если появились новые классы или правила автолоадинга.
Они не сами появляются и не сами изменяются, Файл composer/installed.json содержит сборную информацию об установленных пакетах и правилах автоподгрузки. Здесь правила можно исправить и dump-autoload будет исправленному верить.
Некоторые пакеты содержат функции в глобальном пространстве имён. Просто так их не подключишь к чему угодно, конфликты будут.
А исправив composer/installed.json запросто.t1gor
15.04.2015 00:40Я думаю что автор имел в виду использование composer автозагрузки доя классов своего проекта, а не библиотек. В таком случае это очень даже имеет смысл.
taliban
16.04.2015 00:05+1«require»: {
«php»: ">=5.4.0",
«monolog/monolog»: «1.9.*»
}
Дальше просто нужно в командной строке выполнить команду composer update, и все новые зависимости будут подгружены в папку vendor, и вы сможете их использовать
qwerty@qwerty ~/work/php/composer $ composer update
[Seld\JsonLint\ParsingException]
"./composer.json" does not contain valid JSON
Parse error on line 1:
«require»: { «php»: ">=5.
--------^
Expected one of: 'EOF', '}', ',', ']'
Не серьезно ведь, вроде как и для новичков пишете, а если не знаком с композером то и не разберется сам.alexsoft Автор
17.04.2015 19:41А не было сказано, что в данном коде указан валидный и полный json для файла composer.json. Описан только раздел require. Естественно, только эта часть не является валидным json.
taliban
17.04.2015 23:21Не суть важно что там было а что не было указано, если пишется для новичков (что собственно и было указано в начале статьи) то нужно учитывать что они как обезьянки повторяют все шаг в шаг, и логично было бы привести такой пример, который действительно работает, от двух скобочек руки не отпали бы наверно.
lesha_firs
вот тоже хорошая стать habrahabr.ru/post/145946