Drupal 8: Работа с Composer

03.09.2016

В общем дело тут такое, вообще эту статью я не планировал и вообще даже не знал об этом. Хотел написать про одно, полез в другое, а оказалось вот это :) Поэтому могут быть неточности, так как с композером раньше серьезно сталкиваться не приходилось.

Суть в том, что в Drupal 8.1 в ядро интегрировали composer и теперь всё можно делать через него. Это на самом деле очень удобно, так как зависимости проекта хранятся в файле, их очень легко установить в одну команду и обновить. Но не без недостатков, на данный момент, по крайней мере у меня, drush и drupal compose не умеют с этим обращаться, и если у модуля какая-то зависимость через композер, то он её не установит, и придется контролировать руками, также установка через обе тулзы не добавляют модули в зависимости композера и теряется функционал композера и часть его смысла. Не ясно как узнавать доступные версии для пакета на установку, только указав неверную версию он выдает какой-то список, может кто в комментах подскажет.

Особо вдаваться в подробности по работе с композером я не буду, он уже не молодой, известный по нему куча гайдов в сети, я буду описывать лишь в рамках Drupal сайта.

Установка ядра через composer

Если у вас чистый проект, то проще ядро сразу тянуть через композер, делается это очень просто

# Загрузка текущей стабильной версии Drupal 8.1
composer create-project drupal/drupal FOLDER 8.1.*@stable
# В предыдущем примере ядро скачается в папку FOLDER,
# но если вы хотите чтобы ядро развернулось в текущей папке
# используйте данную команду
composer create-project drupal/drupal . 8.1.*@stable
# Хотите использовать dev версию ядра?
composer create-project drupal/drupal . 8.1.*@dev

Подключение репозиториев

Не важно как вы устанавливали сайт. Через Composer, из архива, через драш, вообще никакой разницы нет, все они содержат в корне файлик composer.json и требуют дополнительных действий для использования composer по полной программе.

Для полноценной работы нужно подключить репозитории Drupal.org, так как по умолчанию они не подключены, вы не сможете устанавливать проекты с drupal.org, так как композер их просто не найдет. Все по принципу репозиториев в Linux, если вы, конечно, знакомы с этим подходом.

Добавление Drupal.org репозитория в Composer
composer config repositories.drupal composer https://packages.drupal.org/8

То же самое и работает для Drupal 7 https://packages.drupal.org/7, но там composer.json придется заготовить руками как я понял, не тестил, но поддерживается.

Если вы всё сделали правильно, в корневом composer.json должно появиться упоминание подключенного нами репозитория.

Подключенный репозиторий для Drupal 8

Установка модулей и тем через Composer

После подключения репозитория, нам станут доступны для загрузки все модули и темы с drupal.org. Для загрузки модулей и тем используется команда в следующем формате: composer require drupal/<project_name>, где вы и подставляете название проекта.

Примеры установок через композер
composer require drupal/token
composer require drupal/rules
Модули в зависимостях composer.json
Модули в своей папке.

Как вы видите, модули скачались, добавились в зависимости композера, а также разместились в папке modules. Теперь их нужно включить через drush, drupal console или административный интерфейс, это уже не играет никакой роли.

Установка в modules/contrib

Как вы можете заметить, у меня есть папка contrib, куда я складываю модули с drupal.org, и если drush и drupal console это учитывали и складывали модули туда, то composer об этом не знает.

Для этого нам нужен плагин для composer, который позволит указывать папку назначения. Нам потребуется плагин который позволяет делать разбивку что куда ставить.

Первым делом нам нужно установить его.

composer require composer/installers

После того как установили этот плагин, мы должны в package.json написать для него настройки. Для этого, в раздел "extra" мы добавим ему свои настройки. Учтите что там уже есть настройки, поэтому не нужно затирать, а лишь добавлять.

"extra": {
    "installer-paths": {
        "core": ["type:drupal-core"],
        "libraries/{$name}": ["type:drupal-library"],
        "modules/contrib/{$name}": ["type:drupal-module"],
        "profiles/contrib/{$name}": ["type:drupal-profile"],
        "themes/contrib/{$name}": ["type:drupal-theme"],
        "drush/{$name}": ["type:drupal-drush"],
        "modules/custom/{$name}": ["type:drupal-custom-module"],
        "themes/custom/{$name}": ["type:drupal-custom-theme"]
    }
}

Теперь вы можете попробовать установить новый модуль, или написать composer install и вы заметите, что старые модули ещё раз скачались, только в этот раз в contrib. Поэтому лучше сразу всё это в начале проекта проконтролировать, либо затем удалить их из корневой папки modules и сбросишь кэш.

Новая структура загрузки.

Если вы обратили внимание на консоль, когда устанавливали модули или же взглянули в зависимости composer.json, то могли бы заметить, что все модули устанавливаются по умолчанию в dev версии. Это не очень хорошо. Для того чтобы качались стабильные версии, вы должны указать соответствующую версию в формате composer require drupal/<project_name>:<version>

Примеры установки конкретных версий
# Последняя стабильная версия на данный момент.
composer require drupal/token:1.0-beta-1
# Установка dev версии
composer require drupal/token:1.x-dev
# Скачать последнюю стабильную версию 1.x
# На момент написания, последняя 1.0-beta-1, её он и скачает.
composer require drupal/token:1.*
# Самым надежным и правильным будет следующий вариант.
# Он скачает последнюю стабильную версию 1.x
# Но если уже выйдет 2.x версию у модуля, он её не скачает.
# ~1.0 равносильно >=1.0 <2.0.0
# ~1.0.0 равносильно >=1.0.0 <1.1.0
composer require drupal/token:~1.0-stable

Больше всего о версиях, как их указывать и как они себя ведут на официальном сайте composer.

Трансформация версий:

  • {Platform.x}-{major}.{minor}-{stability#} — {major}.{minor}.0-{stability}{#}
  • 7.x-3.4-beta2 — 3.4.0-beta2
  • 7.x-2.10-rc2 — 2.10.0-rc2
  • 7.x-1.0-unstable3 — unstable releases will not be translated, and not available to composer
  • 7.x-1.0-alpha5 — 1.0.0-alpha5
  • 7.x-0.1-rc2 — 0.1.0-rc2
  • 7.x-1.x-dev — 1.x-dev

Удаление пакетов

Всё очень просто, выполняется это одной командой и это удаляет как прописанную зависимость, так и физически модуль. Но будьте крайне осторожны, ведь сначала надо удалить модуль из друпала, а уже затем физически.

composer remove drupal/token

Поиск пакетов

Вы также можете искать модули через композер. Всё очень просто.

composer search token

Автоматическое применение патчей

Бывает что в модуле есть какая-то ошибка, которая пофикшена только в dev, но вы хотите остаться на стабильной версии, или вообще пофикшена, но нету решения нигде как в патче. Раньше патчи надо было применять руками, теперь это можно скинуть на композер.

Композер, сам по себе, не умеет это делать, но есть плагин который это умеет делать.

Установка composer patches
composer require cweagans/composer-patches
"extra": {
    "patches": {
        "drupal/drupal": {
            "Add startup configuration for PHP server": "https://www.drupal.org/files/issues/add_a_startup-1543858-30.patch"
        }
    }
}

Как видно из примера выше, для патчей мы должны создать раздел patches в разделе extra. Далее указывается пакет, к которому применяется патч, описание и путь до патча.

Использование composer.json в своём модуле

В можете объявить свой composer.json в кастомном или контрибном модуле, не важно, есть у модуля зависимости или нет. В обычном виде он выглядит следующим образом.

composer.json без зависимостей
{
    "name": "drupal/example",
    "description": "This is an example composer.json for example module.",
    "type": "drupal-module",
    "license": "GPL-2.0+"
}

Как видите, вы можете указать лишь описание, название, тип и лицензию. Я так понимаю, что для кастомных модулей указывать drupal/example некорректно, так как могут возникнуть проблемы если появится соответствующий модуль в репозитории. Как мне кажется, правильнее указывать в формате name/module_name. Где в начале вы можете указать свой ник, имя, компанию. Если у кого есть опыт с этим, поправьте меня в комментариях.

К слову, указание типа обязательно. На данный момент существуют следующие типы:

  • drupal-core
  • drupal-module
  • drupal-theme
  • drupal-library
  • drupal-profile
  • drupal-drush
  • drupal-custom-theme
  • drupal-custom-module

А ниже более комплексный пример, взято из модуля Mobile Detect.

{
  "name": "drupal/mobile_detect",
  "description": "Mobile_Detect is a lightweight PHP class for detecting mobile devices.",
  "type": "drupal-module",
  "homepage": "https://drupal.org/project/mobile_detect",
  "authors": [
    {
      "name": "Matthew Donadio (mpdonadio)",
      "homepage": "https://www.drupal.org/u/mpdonadio",
      "role": "Maintainer"
    },
    {
      "name": "Darryl Norris (darol100)",
      "email": "admin@darrylnorris.com",
      "homepage": "https://www.drupal.org/u/darol100",
      "role": "Co-maintainer"
    }
  ],
  "support": {
    "issues": "https://drupal.org/project/issues/mobile_detect",
    "irc": "irc://irc.freenode.org/drupal-contribute",
    "source": "https://cgit.drupalcode.org/mobile_detect"
  },
  "license": "GPL-2.0+",
  "minimum-stability": "dev",
  "require": {
    "mobiledetect/mobiledetectlib": "~2.8"
  }
}

Для чего это? Ну по сути, если нет никаких зависимостей, ни для чего. Если же есть зависимости, то когда ваш модуль установят через composer, он также установит и все его зависимости.

В заключении

Как я уже написал, у меня крайне мало знаний о composer, я это всё раскопал, лишь потому что для другого гайда потребовался модуль, в котором как раз лежит composer.json со своими зависимостями, без которых он не заводится. Ну я решил и разобраться что к чему. Если есть замечания или предложения дополнить\поправить что-то, прошу в комментарии.

Также стоить указать что данный подход не обязателен, но если вы нарветесь на модуль с зависимостями через композер, вы как минимум его должны будете закачать через композер. Устанавливать все модули через него, или же только с composer.json где прописаны зависимости - на ваше усмотрение. На drupal.org нету никаких конретик по этому поводу. На данный момент это предоставляется как вариант организации проекта, репозитории находятся в бета режиме и некоторые возможности composer ещё не поддерживаются. Например, семантические версии. Но это официальная возможность начиная с 8.1 и для всех последующих версий. Соответственно из-за этого модуль Composer Manager для Drupal 8 deprecated.

Комментарии

xandeadx
03.09.2016

Композер нужен только если пишешь/ставишь модуль использующий либы с packagist.org. Для другого пока бесполезен, drush + drush make более функциональны.

Niklan
03.09.2016

Так и есть, вот официальное сравнение Drush vs Composer. Но я так понял композер так тесно интегрируют именно для того чтобы заменить им drush make.

mumac
24.12.2016

Добрый день, спасибо за труд и статью. Может уже что-то поменялось, но у меня модули начали устанавливаться в определенную папку, после изменения записи в "extra" на "installer-paths": { "modules/contrib/{$name}/":["type:drupal-module"] }

Алексей
06.03.2017

drush и drupal compose не умеют с этим обращаться

Drush и drupal consle? Опечатка?

Алексей
06.03.2017

drush и drupal compose не умеют с этим обращаться

Drush и drupal consle? Опечатка?

Виталий
07.04.2017

Есть страница проекта установки сайта друпал8 через композер https://github.com/drupal-composer/drupal-project и у меня получилось установить. А вот с обновить друпал у меня не получилось. На сайте написано что для этого надо сделать следующее:

Updating Drupal Core

This project will attempt to keep all of your Drupal Core files up-to-date; the project drupal-composer/drupal-scaffold is used to ensure that your scaffold files are updated every time drupal/core is updated. If you customize any of the "scaffolding" files (commonly .htaccess), you may need to merge conflicts if any of your modfied files are updated in a new release of Drupal core.

Follow the steps below to update your core files.

1. Run composer update drupal/core --with-dependencies to update Drupal Core and its dependencies.
2.Run git diff to determine if any of the scaffolding files have changed. Review the files for any changes and restore any customizations to .htaccess or robots.txt.
3.Commit everything all together in a single commit, so web will remain in sync with the core when checking out branches or running git bisect.
4.In the event that there are non-trivial conflicts in step 2, you may wish to perform these steps on a branch, and use git merge to combine the updated core files with your customized files. This facilitates the use of a three-way merge tool such as kdiff3. This setup is not necessary if your changes are simple; keeping all of your modifications at the beginning or end of the file is a good strategy to keep merges easy.

Выполняю первый пункт composer update drupal/core --with-dependencies команда в терминале выполняется, но в отчёте на сайте версия друпала не поменялась, ввожу команду git diff получаю сообщение Not a git repository To compare two paths outside a working tree: usage: git diff [--no-index] Что делать , какие дальнейшие шаги, честно говоря я не понял что надо делать в пунктах 2,3, 4 приведённой выше инструкции.

Niklan
07.04.2017

Честно говоря, я не пробовал данный подход. А вы ядро устанавливали также через композер?

Виталий
07.04.2017

Да, как указано на указанном сайте, просто выполняю команду composer create-project drupal-composer/drupal-project:8.x-dev some-dir --stability dev --no-interaction и процесс прошёл, просто запускаю из папки www а корневую папку на хостинге определяю www.mysite.web

Виталий
07.04.2017

вернее команда выглядит так composer create-project drupal-composer/drupal-project:8.x-dev mysite --stability dev --no-interaction

Содержимое данного поля является приватным и не предназначено для показа.