PHP Composer: личные впечатления

// Ноябрь 14th, 2012 // PHP, Веб-разработка

В этом посте я расскажу о личных впечатлениях от использования такой интересной штуки, как Composer. Если кто не в курсе, это менеджер зависимостей для PHP библиотек, который облегчает установку, обновление и поддержку различных библиотек в вашем проекте.Программисту для комфортной работы нужна инфраструктура (это я вам точно говорю :-). Это и удобное кресло, мощная машина с двумя мониторами, и совеременная IDE, средства работы с базами данных, инструменты отладки. Но кроме того важна инфраструктура разработки самого проекта.

Возьмём к примеру Ruby. Этот язык, блин, ну просто законодатель мод в сфере веб-дева. Там и удобные инструменты скаффолдинга (ну в ZF это тоже есть), и такие штуки, как rake для выполнения задач. Я уж не говорю про миграции, юнит-тесты со всяческими mock-объектами. Когда я кодил на Ruby ощущение было сродни тому, что сидишь в комфортабельном кресле в бизнес-классе в самолете и единственной твоей проблемой является выбор напитка под настроение.

Шучу-шучу. Не всё так радужно в Ruby :-) Есть куча кривых гемов, разработчики иногда выпускают такооое чудо, что мама не горюй. Я уж молчу про низкоуровневое шаманство, когда надо сделать что-то типа распределённой или многопоточной системы. Но речь в посте будет не об этом. А о том, что в Ruby есть такая штук, как RubyGems.

RubyGems это система для управления зависимостями в Ruby проекте. В частности есть такая штука как Bundler, который одним движением устанавливает нужные пакеты или обновляет их. Именно с него наглым образом был списан он послужил вдохновением для Composer.

Что умеет Composer

 

Итак, краткий обзор фич. Их всего две: управление пакетами и автозагрузка классов. Надо сказать, что без composer обе эти задачи отнимали достаточно много времени. Интернет до сих пор пестрит статьями в стиле «как связать ZF 1.x и Doctrine 2» или «как установить Doctrine 2 ODM и Doctrine 1 ORM». Извращение, скажет вы. Я спеуиально утрировал, но согласитесь, приходится довольно сильно заморачиваться чтобы скрестить некоторые фреймворки или библиотеки. С выходом Composer ситуация поменялась.

Отдельное спасибо надо сказать за человеческую автозагрузку. Ух сколько времени я когда-то потратил на интеграцию Zend_Loader_Autoloader и Doctrine/ClassLoader. Теперь это в прошлом. Садимся в кресло :-)

Пример composer.json

 

Вот пример файла с описанием зависимостей из одного проекта.

{
"require": {
"doctrine/common": "2.3.0",
"doctrine/migrations": "dev-master",
"doctrine/dbal": "2.3.0",
"doctrine/orm": "2.3.0",
"doctrine/mongodb": "1.0.x-dev",
"doctrine/mongodb-odm": "1.0.x-dev",
"simukti/zf1": "1.12.0",
"zendframework/zendframework": "2.0.3"
},
"autoload": {
"psr-0": {
"ZendExtra": "vendor/netandreus/zend-extra/lib/",
"DoctrineExtra" : "vendor/netandreus/doctrine-extra/lib/",
"MyProject": "vendor/myvendor/myproject/lib/",
"Hydrators": "misc/cache/",
"": "app/default/models/"
}
}

Итак, давайте пройдёмся построчно. В блоке require мы описываем название пакетов в виде vendorName/packageName и минимально необходимые версии для нашего проекта. Потом они будут сами скачиваться и устанавливаться в папку vendor. Как видите Доктрина например раскукожилась сразу в несколько пакетов. Кстати миграции в отдельный пакет выделились совсем недавно, так что следите за новостями проекта. Товарищу simukti выражаю огромную благодарность, за то что он портировал все последние версии ZF 1.x в composer. Когда мне в своё время он понадобился, я начал это делать… да так и не успел в связи с другими задачами. Сейчас же в рамках одного проекта у нас есть возможность использовать компоненты Doctrine 2 ODM + ORM + ZF 1.x + ZF 2.x. Сумасшедший винигрет, но нам он нужен. Т.к. мы потихоньку мигрируем с MySQL (да простит меня Michail Widenius) на MongoDB. Основной костяк — на ZF1, ну а ZF2 — тоже не из праздного любопытсята /* интрига */.

Теперь вторая часть конфига — require. Тут мы задаём классы (вернее их неймспейсы) и места их хранения, т.е. разрешаем пути для соответствующих неймспейсов. Обратите внимание  на несколько моментов. Для гидраторов доктрины (если вы не знаете что это, то можете пропустить) указываем пути, т.к. при отсутствующем автозагрузчике доктрины она не может их найти. Последняя строка — местоположение помойки, где могут лежать классы с любыми неймспейсами. Основная особенность Composer в том, что такая помойка (к счастью) может быть только одна. А вот в нашем проекте классы require’ились откуда попало, поэтому пришлось провести так сказать garbage collection и свалить всё в одну кучу. Придётся конечно когда-нибудь и её разобрать, но теперь по крайней месте весь мусор в одном месте. Ну а ZendExtra и DoctrineExtra — этомои расширения, котоыре я частично описывал в своих постах.

Баги Composer

 

Ну куда же без багов. Самый пожалуй замечатенльный баг fatal: No such remote ‘composer’. Когда вы, уверенные, что у вас всё ок, делаете php composer.phar update, вас ждёт … разочарование.  Пробелема в том, что composer не выкачивает исходники (вернее не обновляет их) если указана dev ветка, и исходники старше 6 месяцев. К сожалению в моём composer.json такими оказались пакеты с доктриной. Решение простое, перед тем, как делать update удаляем пакеты с доктриной.

Второй баг был в том, что в репозитарийх некоторых пакетов лежит файл .gitignore, который выкачивается при update/install. А если потом исходники проекта (вместе с этим пакетом) закоммитить, то они не дойдёт. Например в assembla, с которйо я работаю появляется некий пустой файл вместо папки с сорцами. При этом коммит и пуш проходит нормально, а траварищи жалуются, что к ним ничего не прилетает. Решение простое, после Update стираем наифг файлы .gitignore из изходников с пакетами.

Использовать или нет Composer?

 

Да! Как сказал кто-то, ваша библиотека — отстой, если в её корне не лежит файл composer.json Не ну серьезно, прошли времена php 4, phpclasses, кучи автозагрузчиков в стеке. Давайте перестанем плодить говнокод, будем соблюдать стандарты (ну хотя бы psr-0) и писать так сказать код с человеческим лицом. Я всецело за унификацию и стандартизацию! Enjoy!

Share

Спасибо!


Если вам помогла статья, или вы хотите поддержать мои исследования и блог - вот лучший способ сделать это:


22 Responses to “PHP Composer: личные впечатления”

  1. на 100% согласен. кстати, композер и с Yii прекрасно юзается

  2. AmdY:

    Да, компосер становится стандартом. так же как и PSR, современные проекты без них — маргиналы и работать с ними неприятно.
    К тому же с внедрением в старые проекты компосера и переформатирование cs-fixer занимает час-два, после чего проект начинает выглядеть красиво, а ваши волосы становятся длинными и шелковистыми.

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

    • AmdY:

      p.s. По поводу наработок по doctrine, не нашёл их на гитхабе. репозитории скрыты?
      А то недавно начал использовать вторую ветку, она смотрится дико нефункциональной после первой. Хотелось бы больше привычных плюшек.

  3. google.com Андрей Токарчук:

    Ага, тоже сначала непривычно было. Ну если интересно, могу зарелизить их? Там как раз есть всякие toArray(), fromArray() для модели, несохраняемые доп.поля.

  4. MAXakaWIZARD:

    Помойка может быть не одна. можно задать перечень путей для поиска. Например:

    "autoload": {
            "psr-0": { "": ["library/", "models/"] }
    }
    
  5. isqad88:

    Замечательная статья, было бы интересно подробнее что-нибудь узнать.
    А у меня вопрос, зачем вам для моделей toArray()?

    • google.com Андрей Токарчук:

      Например, есть форма, и необходимо прокинуть в неё все данные из модели. Для этого и используется toArray().

  6. Alex:

    Стоп-стоп, а зачем коммитить либы выкаченные композером? По идее надо коммитить только composer.json, да composer.lock — остальные пусть сами выкачивают, так вроде даже в доке по нему написаны.

    • google.com Андрей Токарчук:

      Да, можно и так делать, чтобы не качать папку vendor. По идее так и надо бы делать, но пока что у меня в vendor лежит некоторые пакеты, которые ещё нигде не опубликованы. В таком случае можно добавить остальные пакеты в .gitignore а потом при каждом деплое запускать php composer.phar update. Думаю, так и сделаю в ближайшее время. Сейчас оставил как есть, на всякий случай (а вдруг будут проблемы со связью с репами).

      • Alex:

        Да, резонно, если хотя бы одна (внешняя) репа будет в дауне, это помешает развернуть приложение, согласен. Композер тут исходит из наиболее удачного положения вещей.

        • google.com Андрей Токарчук:

          Ага, а ещё очень удобно, что после update при коммите видно, что там накодили в библиотеках :-)

  7. Также кроме блока «require» очень удобно использовать «require-dev» для описания модулей, необходимых при разработке проекта. Например, PHPUnit:
    ‘require-dev’: {
    ‘phpunit/PHPUnit’: ‘3.7.*’
    }
    Подгружаться такие модули будут, если вы делаете install/update с параметром —dev.

  8. LutiyFizik:

    Это типа nuget в asp.net?

  9. LutiyFizik:

    А нет, есть там Pakage Manager Но дело не в этом. Просто очень было бы интересно услышать мнение человека который программировал на php и на ruby о asp.net mvc4, я готов по тимвьюре показать как это работает.

Комментировать