Drupal 8: Работа с Composer

Начиная с Drupal 8.1 работа с composer в Drupal становится де-факто обязательной, и в этой статье мы рассмотрим как им пользоваться.

03.09.2016
68 комментариев
36 мин.

Материал полностью переписан в мае 2018

Данная статья полностью переписана на момент 8.5.x версии (май 2018). За этот срок очень многое изменилось, как в подходе к разработке, так и к стандартному файлу composer.json из ядра, также, я набрался опыта, появились интересные решения и всё, наконец, устаканилось. ? Данная версия будет содержать меньше примеров, так как то, что требовалось делать раньше, уже внедрено на уровне ядра и это утратило смысл.

Начиная с Drupal 8.1 в ядро был внедрён Composer, для управления зависимостями проекта. С этого момента подход к разработке, деплою и прочему начал меняться.

Работа с Composer теперь неотъемлемая часть процесса при разработке и поддержке сайта на 8-ой версии. Вы никуда от него не убежите, и нравится он вам или нет, вам придется его использовать. Так что, лучше сразу подружитесь с ним и полностью начните сопровождать проект с его помощью. На самом деле, Composer — круто! По началу напугает, будут непонимания, но со временем, вы будете только рады. Особенно после стандартного подхода деплоя и управления 8-кой, это просто рай.

Для всех новых проектов на 8-ке, а также старых, если у вас есть желание и возможности, я настоятельно рекомендую использовать Drupal Project. Поверьте, проверьте, это просто и круто. Все беды с композером на данный момент лишь потому, что его внедрили после релиза 8-ки, и по уму, надо вообще запретить качать ядро друпала в виде архивов, либо оставлять их как ознакомительный вариант с исходным кодом (сейчас это делать, очевидно, очень проблематично, но вангану что Drupal 9, скорее всего, когда выйдет, будет поставляться именно так, без архивов). Надо делать как Symfony, попробуйте найдите архивы у них на сайте для загрузки, то-то же. Данный проект, немного меняет структуру проекта, но решает просто тонну различных проблем стандартного подхода от drupal.org. Друпал будет там тот же, всё будет абсолютно идентично, работа с проектом изменится совсем чуточку, из-за немного измененной структуры, но плюсы, которые открывает данный подход, просто перекрывают всё. Работать, деплоить, обновлять и сопровождать проект будет просто сказка, после адовой солянки из стандартной сборки. Эта штука, вообще тема для отдельной статьи, и если интересно, могу про неё детальнее рассказать, если есть трудности с пониманием что это.

Возвращаясь к композеру. Если вы не знакомы с ним, то это пакетный менеджер. Если вы имели опыт или знаете как работают пакетные менеджеры в Linux apt, yum и прочие, или, например, NPM или Yarn, то это примерно тоже самое, только для PHP. Он позволяет вам запрашивать и устанавливать различные "пакеты" (зависимости), удалять их, и выполнять различные действия в процессе выполнения.

В Drupal, композер позволяет вам качать и обновлять, как модули и темы, так и ядро. И считайте что это уже обязательно. Уже множество модулей ставятся исключительно композером, да, вы можете скачать и даже, возможно включится, но работать не будет из-за недоступных зависимостей в виде пакетов из композера, которые руками вам никак не закинуть. И раз вам придется ставить часть через композер, проще всё ставить через него, будет всё стандартно внутри проекта, а не солянка, что эти модули так, другие сяк, и сиди гадай как всё обновить корректно.

Композер работает на основе двух файлов: composer.json и composer.lock. Первый содержит всю информацию, какие требуются пакеты, что, куда и как ставить и прочие настройки, скрипты и т.д. Он подразумевает то, что в нём можно править руками и вмешиваться в его структуру. Composer.lock содержит уже актуальную информацию о текущем проекте. Данный файл автоматически генерируется даже если его нет, править его не нужно. О том, для чего он, будет чуточку позже.

Стандартный composer.json

Чтобы немного понять что там и к чему, давайте рассмотрим стандартный composer.json поставляемый с Drupal.

composer.json
{
    "name": "drupal/drupal",
    "description": "Drupal is an open source content management platform powering millions of websites and applications.",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "require": {
        "composer/installers": "^1.0.24",
        "wikimedia/composer-merge-plugin": "^1.4"
    },
    "replace": {
        "drupal/core": "^8.6"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "preferred-install": "dist",
        "autoloader-suffix": "Drupal8"
    },
    "extra": {
        "_readme": [
            "By default Drupal loads the autoloader from ./vendor/autoload.php.",
            "To change the autoloader you can edit ./autoload.php.",
            "This file specifies the packages.drupal.org repository.",
            "You can read more about this composer repository at:",
            "https://www.drupal.org/node/2718229"
        ],
        "merge-plugin": {
            "include": [
                "core/composer.json"
            ],
            "recurse": true,
            "replace": false,
            "merge-extra": false
        },
        "installer-paths": {
            "core": ["type:drupal-core"],
            "modules/contrib/{$name}": ["type:drupal-module"],
            "profiles/contrib/{$name}": ["type:drupal-profile"],
            "themes/contrib/{$name}": ["type:drupal-theme"],
            "drush/contrib/{$name}": ["type:drupal-drush"],
            "modules/custom/{$name}": ["type:drupal-custom-module"],
            "themes/custom/{$name}": ["type:drupal-custom-theme"],
            "libraries/{$name}": ["type:drupal-library"]
        }
    },
    "autoload": {
        "psr-4": {
            "Drupal\\Core\\Composer\\": "core/lib/Drupal/Core/Composer"
        }
    },
    "scripts": {
        "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
        "post-autoload-dump": "Drupal\\Core\\Composer\\Composer::ensureHtaccess",
        "post-package-install": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "post-package-update": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "drupal-phpunit-upgrade-check": "Drupal\\Core\\Composer\\Composer::upgradePHPUnit",
        "drupal-phpunit-upgrade": "@composer update phpunit/phpunit --with-dependencies --no-progress",
        "phpcs": "phpcs --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --",
        "phpcbf": "phpcbf --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    ]
}

Я также добавил туда "libraries/{$name}": ["type:drupal-library"], так как не ясно, почему в ядре до сих пор этого нет, зато это есть в drupal project.

  • name: Название проекта/пакета.
  • description: Описание.
  • type: Тип определяет что это за пакет и файл вообще. Типы можно указывать какие хотите. Для Drupal проектов есть свои типы drupal-core, drupal-module, drupal-profile, drupal-theme, drupal-drush, drupal-custom-module и drupal-custom-theme. А ещё есть drupal-library для библиотек. По сути, их тип влияет в итоге на то, куда данный пакет будет установлен. Сам композер по умолчанию имеет несколько поддерживаемых типов:
    • library: (по умолчанию) Подразумевает что пакет является библиотекой и установится в vendor папку.
    • project: Определяет что это корневой файл всего проекта. Как раз, корень сайта - это проект, а не какой-то конкретный пакет.
    • metapackage: Пустой пакет, который содержит только composer.json с зависимостями и ничего более.
    • composer-plugin: Пакет является плагином для композера.
  • license: Тут указывается лицензия для пакета или проекта.
  • require: Это вложенный "массив" из зависимостей. Тут указываются все необходимые для проекта зависимости в виде массива, где ключ название пакета, а значение - его верисия. В стандартном файле ядра две зависимости, но это далеко не все.
  • replace: Список пакетов которые заменяются текущим. В данном случае, это значит что запросив drupal/core, он по сути ничего не сделает, так как текущий пакет его заменяет.
  • extra: Раздел для дополнительных конфигураций работы композера.
    • merge-plugin: Это раздел настроек для зависимости wikimedia/composer-merge-plugin, которая добавляет поддержку этого раздела и пользуется им. В нем указется какие дополнительные файлы composer.json внутри проекта нужно подгружать когда вызывается композер. Это позволяет вам указывать какие-то специфичные зависимости, собирать свой composer.json в кастомных модулях и теме, но так как они не качаются композером, то их зависимости не будут обнаружены, данный плагин позволяет их находить.
    • installed-paths: Этот раздел позволяет задать, что и куда будет установлено. Вот здесь какраз используется type. У всех модулей на drupal.org по умолчанию тип drupal-module, на основе данного соответствия он понимает, что модуль нужнно положить в папку modules/contrib/{$name} где переменная $name заменится на название пакета. По умолчанию все они ставятся в vendor.
  • scripts: Данный раздел позволяет подключать различные скрипты. У композера есть хуки (события) на которые можно подключать свои скритпы. В данном массиве это и происходит, в качестве ключа указывается собатыие на которое реагировать, а в значении либо команда, либо путь до объекта который будет вызываться в этот момент. Если нужно указать несколько, то значение становится массивом значений.
  • repositories: В данном массиве объявляются репозитории в которых будут искаться пакеты и качаться. По умолчанию подключен packagegist, у друпала есть свой репозиторий для всех проектов с drupal.org, он там и подключается. Таким образом это позволяет качать модули и темы с drupal.org через композер. Вы можете добавлять свои собственные или другие сторонние репозитории, а также закрытые для компании и пользоваться.

Как правило, данный файл руками правится крайне редко, все зависимости прописываются туда автоматически при установке, и удаляются при удалении.

Установка, обновление и удаление пакетов

Три самые популярные команды композера, запомните их - считайте, вы освоили композер.

Установка производится в следующем формате: composer require PACKAGENAME. Можно указывать сразу несколько нужных пакетов на установку разделяя их пробелом. Пакеты имеют формат vendor/name. Так намного проще разруливать ситуации когда есть одноименные пакеты. Для всех проектов с drupal.org формат будет drupal/PROJECT_NAME. Таким образом, для установки, например, модуля Paragraphs нужно прописать composer require drupal/paragraphs.

Обновление происходит аналогично, только можно опустить название пакета composer update обновит все зависимости прописанные в composer.json. Хитрость тут в том, что обновит он только те что прописаны, например, если модуль прописывает свои зависимости для композера, то они не обновятся данной командой, пока не будет вызвана с ключом --with-dependencies. Чтобы обновить вообще все пакеты, включая их зависимости, нужно вызывать так composer update --with-dependencies. Таким образом, нужно вызывать команду когда выходят обновления минорных версий ядра, так как зависимые пакеты могут сильно измениться за это время. Вы также можете указать конкретный пакет(ы) для обновления: composer update drupal/paragraphs.

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

Установка определенных версий

По умолчанию, запрос пакета на установку скачает самую последнюю актуальную (отдав предпочтение стабильной) версию. Может получиться так, что вам потребуется другая ветка модуля, или же, дев версия.

Установка конкретной версии имеет вид composer require PACKAGENAME:VERSION. Подобным нужно пользоваться только когда это действительно необходимо.

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

Композер сильно опирается, на так называемые, семантические версии: major.minor.patch. У друпал проектов же версии имеют формат major.minor.

Примеры указания конкретных версий:

  • 1.2=1.2.0-stable, 1.0-dev, 1.0-alpha3, 1.0-rc5: Такой вариант также позволяет сделать version lock. Таким образом, пакет будет строго данной версии всегда, так как это строгое указание. Он никогда не обновится до других версий пока это не будет явно запрошено указанием новой версии.
  • ^1.2>=1.2.0 < 2.0.0: Позволяет скачать версию определенной мажорной версии и обновлять её только в пределах данной версии. Самый распространенный способ и используется по умолчанию при запросе пакета без указания специфичных требований к версии. Это защищает от смены мажорных версий, которые почти всегда приведут к поломке.
  • ~1.2>=1.2 < 2.0.0: Похоже на пример выше, но как можете заметить, это практически идентичное обозначение как и ^1.2, но оно не допускает обновлений patch. У друпал модулей и тем таких нет, поэтому какой из вариантов использовать — нет никакой разницы. Но я использую всегда ^1.2, так как композер при запросе пакета без версии запрашивает аналогично и всё получается в едином стиле.

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

Допустим, вы хотите поставить модуль Pararaphs на вот этот момент. Так как это коммит, то вы можете сослаться на его hash. У данного коммита хэш be6a91c8aaa1e174d1145c3af9d49944efade49a. Вы можете указать либо: composer require drupal/paragraphs:1.x-dev#be6a91c8aaa1e174d1145c3af9d49944efade49a, либо просто composer require drupal/paragraphs:1.x-dev#be6a91c (первые 7 символов хэша).

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

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

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

Есть такой пакет, который будет делать это за вас каждый раз как что-то обновляется. Это невероятно удобно!

Для того чтобы оно работало, первым делом нужно установить его на проект: composer require cweagans/composer-patches.

После чего, можно описывать патчи в composer.json. Описываются они в разделе extra, в нём необходимо будет создать дополнительное вложение patches, а уже в нем, формат следующий: ключ - название пакета, а его значение, массив где указываются все патчи, ключем которого является короткое описание патча, чтобы не забыть, а значение - путь до патча.

На примере стандартного composer json это выглядело бы следующим образом:

{
    "name": "drupal/drupal",
    "description": "Drupal is an open source content management platform powering millions of websites and applications.",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "require": {
        "composer/installers": "^1.0.24",
        "wikimedia/composer-merge-plugin": "^1.4",
        "cweagans/composer-patches": "^1.6"
    },
    "replace": {
        "drupal/core": "^8.6"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "preferred-install": "dist",
        "autoloader-suffix": "Drupal8"
    },
    "extra": {
        "_readme": [
            "By default Drupal loads the autoloader from ./vendor/autoload.php.",
            "To change the autoloader you can edit ./autoload.php.",
            "This file specifies the packages.drupal.org repository.",
            "You can read more about this composer repository at:",
            "https://www.drupal.org/node/2718229"
        ],
        "merge-plugin": {
            "include": [
                "core/composer.json"
            ],
            "recurse": true,
            "replace": false,
            "merge-extra": false
        },
        "installer-paths": {
            "core": ["type:drupal-core"],
            "modules/contrib/{$name}": ["type:drupal-module"],
            "profiles/contrib/{$name}": ["type:drupal-profile"],
            "themes/contrib/{$name}": ["type:drupal-theme"],
            "drush/contrib/{$name}": ["type:drupal-drush"],
            "modules/custom/{$name}": ["type:drupal-custom-module"],
            "themes/custom/{$name}": ["type:drupal-custom-theme"],
            "libraries/{$name}": ["type:drupal-library"]
        },
        "patches": {
          "drupal/core": {
            "Add startup configuration for PHP server": "https://www.drupal.org/files/issues/add_a_startup-1543858-30.patch",
            "Patch from local file": "patches/fix.patch"
          }
        }
    },
    "autoload": {
        "psr-4": {
            "Drupal\\Core\\Composer\\": "core/lib/Drupal/Core/Composer"
        }
    },
    "scripts": {
        "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
        "post-autoload-dump": "Drupal\\Core\\Composer\\Composer::ensureHtaccess",
        "post-package-install": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "post-package-update": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "drupal-phpunit-upgrade-check": "Drupal\\Core\\Composer\\Composer::upgradePHPUnit",
        "drupal-phpunit-upgrade": "@composer update phpunit/phpunit --with-dependencies --no-progress",
        "phpcs": "phpcs --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --",
        "phpcbf": "phpcbf --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    ]
}

Запросив данный пакет, он добавился в require, а руками мы добавили раздел с патчами, где один патч скачается с drupal.org и применится, а второй, будет взят с диска.

Когда патч станет неактуальным он будет писать что не удалось применить патч. Это не значит что вашу проблему пофиксили, но стоит зайти туда, откуда взяли патч, и посмотреть, действительно ли решена проблема, или требуется новый патч.

Установка JavaScript библиотек

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

Во-первых, это держит ваш репозиторий проекта в чистом виде, данные зависимости не имеет смысл добавлять в репозиторий так как они сами скачаются при запросе. Во-вторых, это достаточно описать один раз, в дальнейшем простой копипаст и корректировка версий. Многие модули сами предлагают такой способ установки зависимых JS библиотек.

JS библиотек нет в репозиториях композера, так как он для PHP, то данная возможность достигается путем добавления новых репозиториев в composer.json файл, которые прямо ведут на библиотеку, а затем её запрос.

Самая важная часть в объявлении репозитория. Есть как минимум 2 варианта провернуть это.

Первый вариант подразумевает установку напрямую из VCS репозитория:

Пример установки Swiper из GitHub репозитория.
{
    "type": "package",
    "package": {
        "name": "nolimits4web/swiper",
        "type": "drupal-library",
        "version": "4.0.7",
        "source": {
            "url": "https://github.com/nolimits4web/Swiper",
            "type": "git",
            "reference": "v4.0.7",
            "no-api": true
        }
    }
}
  • type: указываем что это не настоящий репозиторий, а пакет.
  • package: описание пакета
    • name: Название пакета. Старайтесь сохранять стандартное именование vendor/package. Это достаточно просто, по сути, из того же git это username/repo-name. Я также эту строку привожу всегда к нижнему регистру.
    • type: Так как это в 99 из 100 просто JS библиотека, а в Drupal модули ставятся в libraries папку, то указываем что это drupal-library. Благодаря соответствиям данный пакет сам установится в libraries.
    • version: Версия которая объявлена в разделе. Она учитывается при запросе пакета композером, но ни на что больше не влияет.
    • source: Описание источника пакета. Для git это следующие значения:
      • url: Путь до репозитория. Можно указывать без окончания .git, композер сам добавит эту приставку.
      • type: git если git, иной если другой.
      • reference: То, что он вытащит из репозитория. Указывается либо tag из VCS, либо hash конкретного коммита (или 7 первых его символов).
      • no-api: (опционально) Данная пометка только для репозиториев на GitHub. Это позволяет отключить использование GitHub API. По умолчанию, для таких пакетов композер будет пытаться получить все данные при помощи API, что должно ускорить работу. По факту же, это только тормозит и имеет смысл только на очень крупных проектах.

Второй вариант лучше во многих смыслах. Во-первых, он проще объявляется. Во-вторых, он быстрее отрабатывает из-за его сути.

Пример объявляения вторым способом
{
    "type": "package",
    "package": {
        "name": "dimsemenov/photoswipe",
        "type": "drupal-library",
        "version": "4.1.2",
        "dist": {
            "url": "https://github.com/dimsemenov/PhotoSwipe/archive/v4.1.2.zip",
            "type": "zip"
        }
    }
}

Данный пример делает всё тоже самое что и первый. Отличие лишь в том, что вместо source тут указывается dist. Внутри него есть url, содержащий ссылку на архив, и type, указывающий на тип архива.

Ссылки на эти архивы, всегда лежат в releases на гитхабе и их очень просто скопировать. Данный вариант проще, так как он просто качает и распаковывает куда надо, первый же вариант клонирует репозиторий и переключает на эту версию, что естественно сказывается на скорости.

О всех других тонкостях можно почитать в офф. доке.

Для того чтобы установит эти пакеты, далее достаточно просто вызвать штатную установку по name указанному вами: composer require nolimits4web/swiper dimsemenov/photoswipe и оба они скачаются и поместатся в libraries.

Вот пример такого файла, опять же, на основе нашего стандартного composer.json из ядра и двух примерах выше.

{
    "name": "drupal/drupal",
    "description": "Drupal is an open source content management platform powering millions of websites and applications.",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "require": {
        "composer/installers": "^1.0.24",
        "wikimedia/composer-merge-plugin": "^1.4",
        "cweagans/composer-patches": "^1.6",
        "dimsemenov/photoswipe": "^4.1",
        "nolimits4web/swiper": "^4.0"
    },
    "replace": {
        "drupal/core": "^8.6"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "preferred-install": "dist",
        "autoloader-suffix": "Drupal8"
    },
    "extra": {
        "_readme": [
            "By default Drupal loads the autoloader from ./vendor/autoload.php.",
            "To change the autoloader you can edit ./autoload.php.",
            "This file specifies the packages.drupal.org repository.",
            "You can read more about this composer repository at:",
            "https://www.drupal.org/node/2718229"
        ],
        "merge-plugin": {
            "include": [
                "core/composer.json"
            ],
            "recurse": true,
            "replace": false,
            "merge-extra": false
        },
        "installer-paths": {
            "core": ["type:drupal-core"],
            "modules/contrib/{$name}": ["type:drupal-module"],
            "profiles/contrib/{$name}": ["type:drupal-profile"],
            "themes/contrib/{$name}": ["type:drupal-theme"],
            "drush/contrib/{$name}": ["type:drupal-drush"],
            "modules/custom/{$name}": ["type:drupal-custom-module"],
            "themes/custom/{$name}": ["type:drupal-custom-theme"],
            "libraries/{$name}": ["type:drupal-library"]
        },
        "patches": {
          "drupal/core": {
            "Add startup configuration for PHP server": "https://www.drupal.org/files/issues/add_a_startup-1543858-30.patch",
            "Patch from local file": "/patches/fix.patch"
          }
        }
    },
    "autoload": {
        "psr-4": {
            "Drupal\\Core\\Composer\\": "core/lib/Drupal/Core/Composer"
        }
    },
    "scripts": {
        "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
        "post-autoload-dump": "Drupal\\Core\\Composer\\Composer::ensureHtaccess",
        "post-package-install": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "post-package-update": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "drupal-phpunit-upgrade-check": "Drupal\\Core\\Composer\\Composer::upgradePHPUnit",
        "drupal-phpunit-upgrade": "@composer update phpunit/phpunit --with-dependencies --no-progress",
        "phpcs": "phpcs --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --",
        "phpcbf": "phpcbf --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        {
            "type": "package",
            "package": {
                "name": "nolimits4web/swiper",
                "type": "drupal-library",
                "version": "4.0.7",
                "source": {
                    "url": "https://github.com/nolimits4web/Swiper",
                    "type": "git",
                    "reference": "v4.0.7",
                    "no-api": true
                }
            }
        },
        {
            "type": "package",
            "package": {
                "name": "dimsemenov/photoswipe",
                "type": "drupal-library",
                "version": "4.1.2",
                "dist": {
                    "url": "https://github.com/dimsemenov/PhotoSwipe/archive/v4.1.2.zip",
                    "type": "zip"
                }
            }
        }
    ]
}

Дополнительный способ

Также есть вот такой проект — Asset Packagist. Данный проект — репозиторий для Composer, в котором собираются пакеты из NPM и Bower репозиториев, где с 99% вероятностью можно всегда найти JS зависимость для модулей. Я не пробовал его на живых проектах, но для старта это может стать намного лучше, помимо его простоты, он также содержит актуальные версии, а не фиксированные как в первых двух вариантах. Такой огромный репо также скажется на скорости работы композера, если при подключении это не стало критично — почему бы и нет?

Подключается он следующим образом. В repositories добавляется:

{
  "type": "composer",
  "url": "https://asset-packagist.org"
}

Затем догружается зависимость, чтобы installer-paths работал корректно: composer require oomphinc/composer-installers-extender

Затем, в installer-paths нужно поправить место куда будут устанавливаться данные пакеты:

{
    "name": "drupal/drupal",
    "description": "Drupal is an open source content management platform powering millions of websites and applications.",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "require": {
        "composer/installers": "^1.0.24",
        "wikimedia/composer-merge-plugin": "^1.4"
    },
    "replace": {
        "drupal/core": "^8.6"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "preferred-install": "dist",
        "autoloader-suffix": "Drupal8"
    },
    "extra": {
        "_readme": [
            "By default Drupal loads the autoloader from ./vendor/autoload.php.",
            "To change the autoloader you can edit ./autoload.php.",
            "This file specifies the packages.drupal.org repository.",
            "You can read more about this composer repository at:",
            "https://www.drupal.org/node/2718229"
        ],
        "merge-plugin": {
            "include": [
                "core/composer.json"
            ],
            "recurse": true,
            "replace": false,
            "merge-extra": false
        },
        "installer-types": ["bower-asset", "npm-asset"],
        "installer-paths": {
            "core": ["type:drupal-core"],
            "modules/contrib/{$name}": ["type:drupal-module"],
            "profiles/contrib/{$name}": ["type:drupal-profile"],
            "themes/contrib/{$name}": ["type:drupal-theme"],
            "drush/contrib/{$name}": ["type:drupal-drush"],
            "modules/custom/{$name}": ["type:drupal-custom-module"],
            "themes/custom/{$name}": ["type:drupal-custom-theme"],
            "libraries/{$name}": ["type:drupal-library", "type:bower-asset", "type:npm-asset"]
        }
    },
    "autoload": {
        "psr-4": {
            "Drupal\\Core\\Composer\\": "core/lib/Drupal/Core/Composer"
        }
    },
    "scripts": {
        "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
        "post-autoload-dump": "Drupal\\Core\\Composer\\Composer::ensureHtaccess",
        "post-package-install": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "post-package-update": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "drupal-phpunit-upgrade-check": "Drupal\\Core\\Composer\\Composer::upgradePHPUnit",
        "drupal-phpunit-upgrade": "@composer update phpunit/phpunit --with-dependencies --no-progress",
        "phpcs": "phpcs --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --",
        "phpcbf": "phpcbf --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        {
            "type": "composer",
            "url": "https://asset-packagist.org"
        }
    ]
}

После чего можно устанавливать пакеты. Например, swiper из примера выше можно взять из npm репозитория: composer require npm-asset/swiper, а фотосвайп из bower composer require bower-asset/photoswipe.

composer.json в кастом модуле и теме

По хорошему, сейчас каждый модуль или тема должны содержать composer.json, и эту тенденцию можно наблюдать у всех популярных модулей. Даже если вам не нужны никакие зависимости, лучше чтобы он был.

Хотя бы такой минимум:

{
    "name": "drupal/example",
    "description": "This is an example composer.json for example module.",
    "type": "drupal-custom-module",
    "license": "GPL-2.0+"
}

Не забудьте правильно подобрать type.

Если модуль публикуется на drupal.org как полноценный проект, то туда можно добавить побольше информации.

{
  "name": "drupal/PROJECTNAME",
  "type": "drupal-module",
  "description": "My module.",
  "keywords": ["Drupal"],
  "license": "GPL-2.0+",
  "homepage": "https://www.drupal.org/project/PROJECTNAME",
  "authors": [
    {
      "name": "Your name here",
      "homepage": "https://www.drupal.org/u/your_name_here",
      "role": "Maintainer"
    },
    {
      "name": "Contributors",
      "homepage": "https://www.drupal.org/node/NID/committers",
      "role": "Contributors"
    }
  ],
  "support": {
    "issues": "https://www.drupal.org/project/issues/PROJECTNAME",
    "source": "http://cgit.drupalcode.org/test"
  }
}

Самый быстрый способ получить такой файл: drush generate composer.

Если вы объявите такой файл и зависимости в кастомном модуле и теме, то ваши зависимости не будут загружены. Для этого нужно не забыть добавить путь до composer.json файла в разделе "merge-plugin". Проще всего, добавить следующего вида: "modules/custom/*/composer.json".

Экономия памяти ?

Такая гибкость достигается путем не хилой прожорливости по памяти. Использовать композер на хостинге или слабом VPS может закончиться остановкой операции из-за нехватки памяти. В идеале composer нужно memory_limit 1024M. Где-то это невозможно, где-то это очень проблемно.

И решение у композера есть, его нужно просто использовать правильно! Те две команды что мы рассмотрели ранее require и update при своём вызове всегда запускают полный парсинг всех репозиториев и данных о каждом проекте. Потому столько памяти и жрется. Эти две команды должны быть в обороте только на локалке и дев сервере где лимиты не должны быть проблемой.

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

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

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

Причем вам даже не обязательно иметь полноценный сайт для того чтобы доустановить пакет или обновить их все. Вы можете просто склонировать себе репозиторий проекта на локалку, установить\обновить\удалить всё что необходимо, закоммитить изменения в composer.json и composer.lock, запушить, а на продакшене fetch, pull, composer install и вуаля, всё быстро и просто.

git — лучший друг для composer.

Выполнение команд после установки и\или обновления

Данную операцию я делаю вообще на каждом проекте. Все дело в том, что я активно использую модуль robotstxt, который позволяет управлять файлом robots.txt в админке и иметь разыне версии под разные языки и т.д. Если вы с ним работали, то в курсе, что для его работы надо удалять файл robots.txt в корне сайта. После обновлений он всегда возвращается на место и это раздражает. Благодаря композеру, это фиксится очень просто.

Для этого в scripts разделе нам нужно добавить команду на событие post-update-cmd. Как правило сервера на линуксах, поэтому команда будет rm -f robots.txt.

{
    "name": "drupal/drupal",
    "description": "Drupal is an open source content management platform powering millions of websites and applications.",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "require": {
        "composer/installers": "^1.0.24",
        "wikimedia/composer-merge-plugin": "^1.4"
    },
    "replace": {
        "drupal/core": "^8.6"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "preferred-install": "dist",
        "autoloader-suffix": "Drupal8"
    },
    "extra": {
        "_readme": [
            "By default Drupal loads the autoloader from ./vendor/autoload.php.",
            "To change the autoloader you can edit ./autoload.php.",
            "This file specifies the packages.drupal.org repository.",
            "You can read more about this composer repository at:",
            "https://www.drupal.org/node/2718229"
        ],
        "merge-plugin": {
            "include": [
                "core/composer.json"
            ],
            "recurse": true,
            "replace": false,
            "merge-extra": false
        },
        "installer-paths": {
            "core": ["type:drupal-core"],
            "modules/contrib/{$name}": ["type:drupal-module"],
            "profiles/contrib/{$name}": ["type:drupal-profile"],
            "themes/contrib/{$name}": ["type:drupal-theme"],
            "drush/contrib/{$name}": ["type:drupal-drush"],
            "modules/custom/{$name}": ["type:drupal-custom-module"],
            "themes/custom/{$name}": ["type:drupal-custom-theme"],
            "libraries/{$name}": ["type:drupal-library"]
        }
    },
    "autoload": {
        "psr-4": {
            "Drupal\\Core\\Composer\\": "core/lib/Drupal/Core/Composer"
        }
    },
    "scripts": {
        "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
        "post-autoload-dump": "Drupal\\Core\\Composer\\Composer::ensureHtaccess",
        "post-package-install": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "post-package-update": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "drupal-phpunit-upgrade-check": "Drupal\\Core\\Composer\\Composer::upgradePHPUnit",
        "drupal-phpunit-upgrade": "@composer update phpunit/phpunit --with-dependencies --no-progress",
        "phpcs": "phpcs --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --",
        "phpcbf": "phpcbf --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --",
        "post-update-cmd": [
            "rm -f robots.txt"
        ]
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    ]
}

После этого, при каждом вызове update или require он будет вызывать данную команду в конце всех операций. Таким образом файл robots.txt будет удаляться постоянно как только будет появляться и проблема исчезнет.

Прикрепленные файлы
Первая версия статьи с файлами и контекнтом. — article-v1.tar.gz, 37.76 КБ
Drupal
Drupal 8
Composer

Комментарии

xandeadx   сб, 03/09/2016 - 13:11

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

Niklan   сб, 03/09/2016 - 13:43

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

mumac   сб, 24/12/2016 - 13:52

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

Виталий   пт, 07/04/2017 - 09:53

Есть страница проекта установки сайта друпал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 - 10:17

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

Виталий   пт, 07/04/2017 - 10:22

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

Виталий   пт, 07/04/2017 - 10:27

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

Александр   вс, 06/08/2017 - 17:29

Интересная статья. Но друпап так и не обновляеться. Скорее всего Composer в проектах drupal/drupal не может обновлять все файлы https://www.drupal.org/docs/develop/using-composer/using-composer-to-manage-drupal-site-dependencies#scaffold-files как проекты созданные в drupal-composer/drupal-project.

Niklan   вс, 06/08/2017 - 18:03

Как минимум не drupal/drupal а drupal/core. Если ядро установлено как обычно, не через композер проект, то в composer.json, который лежит в корне сайта, надо перенести drupal/core из раздела replace в раздел required. И всё обновится. Либо можно принудительно обновить composer update drupal/core --width-dependencies.

Дмитрий   вт, 14/11/2017 - 14:23

Судя по всему, в последней команде опечатка - лишняя "d" и имелось в виду

composer update drupal/core --with-dependencies

Дмитрий   вт, 14/11/2017 - 14:20

Добрый день, Никита,

Во-первых, хотел поблагодарить за статью - Друпал действительно, явно переходит на Композер, но на мой взгляд, переход происходит как-то "скомканно". Есть как неочевидные и не совсем логичные моменты, при этом попутно ощущается нехватка толковых материалов.

Я тоже сам по себе пришёл к тому, что схема "ставим ядро стандартно, остальное/далее - Композер" представляется оптимальной.

По итогам статьи хотел уточнить у вас насчёт идеи об установке модулей с указанием версий:

  1. Правильно ли я понимаю, что если не указывать версию вообще (напр., "composer require drupal/token"), то будет установлена самая свежая стабильная, рекомендуемая разработчиком версия?

  2. Если да и если сделать так, то будет ли установленный таким образом модуль, нормально обновляться (даже если потом версия изменится, например с 1.х на 2.х)?

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

Niklan   ср, 15/11/2017 - 11:58
  1. Да, скачается последняя стабильная версия самой высокой мажорной версии.
  2. Нет, в composer.json попадет версия на данный момент типа ^1.1. Т.е. все обновления 1.х будут приходить, 2.х - нет.
  3. Тут всё зависит от ситуации. У меня у самого тема не имела стабильных релизов, сейчас сделал альфу и лочу на конкретной версии без апдейтов. Если модуль в сендбоксе, я его как репо подключил бы и поставил жестко на определенный коммит. Как вариант поставить данный модуль или тему как кастомную и хранить их соответственно без связи и обновлений.

Я тоже сам по себе пришёл к тому, что схема "ставим ядро стандартно, остальное/далее - Композер" представляется оптимальной.

Я начал тут эксперименты с drupal-composer/drupal-project вариантом. Он имеет больше плюсов, и по сути 1 незначительный недостаток. Я скорее всего перейду на него с концами. С ним проще и приятнее. Но пока хотябы 1 рабочий проект на такой связке не отгружу, не буду топить за него, хотя мне пока он больше нравится. С ним намного проще.

Дмитрий   вт, 19/12/2017 - 17:52

Спасибо, отвечаю не сразу, в прошедшее время экспериментировал со связкой Друпал + Композер.

Сначала в продолжение вопросов выше:

  1. Тогда правильно ли я понимаю, что если у модуля поменяется версия (1.* -> 2.), то для продолжения его использования надо будет отредактировать вручную composer.json? Или лучше будет удалить модуль и поставить заново уже новую ветку (2.)? Или вообще действовать по ситуации, т.к. разработчики нередко так меняют версии, когда вносят значительные изменения? Есть ли вообще вариант, который считается правильным/рекомендуемым ("каноничным")?

3.1) Понял. А есть ли снова "правильный" вариант действий при установке модулей наподобие, например, /project/captcha (на данный момент 8.x-1.0-beta1) и /project/xmlsitemap (на данный момент 8.x-1.0-alpha2)? Если что, это просто примеры модулей, у которых нет стабильного релиза.

3.2) И как "правильно" ставить, например, темы, которых вообще нет ни в каких репозиториях? Т.е. создал некий человек тему для Друпал 8, выложил её в виде .zip у себя на сайте. Как её предпочтительнее всего устанавливать, если сайт я ставил с помощью drupal-composer/drupal-project?

Я начал тут эксперименты с drupal-composer/drupal-project вариантом. Он имеет больше плюсов, и по сути 1 незначительный недостаток.
Прочитал ваш ответ и тоже начал экспериментировать. По итогам скажу, что согласен в плане удобства. Я не разработчик, поднимаю один единственный сайт, но думаю, что останусь на этом варианте.

Хотел только узнать какой недостаток вы имеете в виду? Scaffold files (drupal-scaffold) или что-то ещё?

Niklan   сб, 23/12/2017 - 10:12

Тогда правильно ли я понимаю, что если у модуля поменяется версия (1.* -> 2.), то для продолжения его использования надо будет отредактировать вручную composer.json?

да или require написать с новой версией, композер сам обновит.

Или лучше будет удалить модуль и поставить заново уже новую ветку (2.)?

Для этого надо читать путь миграции для конкретного модуля. Какие-то модули поддерживают простой апдейт и легкие правки, какие-то кардинально меняются и требуют полного удаления предыдущей версии.

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

Если у них есть хоть какие-то релизы, ставятся как обычные модули, никакой разницы кроме версии там не будет.

И как "правильно" ставить, например, темы, которых вообще нет ни в каких репозиториях?

/modules/custom, /themes/custom не важно как установлен друпал.

Если позволяют навыки и эти модули\темы имеют репозиторий. Можно его добавить в composer.json с конкретным хэшем, конкретного коммита и он будет сам выкачивать эту версию модуля\темы из репозитория, но обновлять такое я бы крайне не рекомендовал. Поэтому можно смело в кастом сложить (а он туда их и положит) и носить с собой так как обычно нестабильные модули и темы могут очень сильно меняться.

Хотел только узнать какой недостаток вы имеете в виду?

Недостаток является и плюсом. Для меня недостаток лишь в том, что надо для такого варианта править конфиги сервера и он может далеко не везде завестись. Ведь index.php файл находится в web. Если такая возможность есть, изменить конфигруации на хостинге\впске\где-то где надо, то это не проблема, хотя для кого-то может ей стать. Я просто конфиги себе на nginx новые добавил и всё отлично. До сих пор ей пользуюсь, уже проекта 3-4 точно развернул через drupal-roject, полет отличный, всё нравится.

Дмитрий   ср, 03/01/2018 - 14:15
/modules/custom, /themes/custom не важно как установлен друпал.
Снова вынужден вернуться к вам за уточнениями. Прочитал в сети следующее:
We're about to create a Drupal 8 theme! The question that raises is: where should this theme be located, where should I put the files?

If you're familiar with Drupal 7 theming, the first place for you to look at would be drupal/sites/all/themes/{custom/} (the place where all your custom themes lived in Drupal 7).

In Drupal 8, this location has changed. Custom and contrib themes now live in drupal/themes. Also notice that (custom and contrib) modules now live inside drupal/modules (instead of drupal/sites/all/modules/).

Правильно ли я понимаю, что имеется в виду только изменение общего пути? Т.е. мне всё равно нужно создать подпапки /custom в папках выше, в итоге получив ../web/themes/custom/mytheme и ../web/modules/custom/mymodule ? (с учётом того, что Друпал я ставил посредством drupal-composer/drupal-project)

Niklan   пт, 05/01/2018 - 11:03

Создать если нету, если тема\модуль помечены как drupal-custom-theme или drupal-custom-module она создастся автоматически. А вообще да. Лучше изначально создать в папке /web/modules папки contrib и custom. И раскладывать соответственно модули. Хотя композер сам будет складывать куда нужно, особенно в друпал проджект.

Иван   ср, 15/08/2018 - 19:25

Друпал ставил через drupal-project, так же есть своя кастомная тема на основе drupal/bootstrap.

Поставил bootstrap, всё расположилось куда следует. Затем по этой инструкции - https://spinningcode.org/2018/02/using-composer-for-drupal-modules-and-private-bitbucket-repos/ - залил свою тему на битбакет, после ввожу composer require drupal/MYTHEME и получаю вот что (после ввода явок и паролей bitbucket oauth token):

Downloading (connecting...) Downloading (connecting...)Downloading (100%) Writing lock file Generating autoload files

DrupalProject\composer\ScriptHandler::createRequiredFiles

На этом выполнение завершается и..... ничего. Папки themes/custom нет, themes/contrib содержит только bootstrap, моей темы там нет. В админке моя тема тоже не отображается.

Битбакет формирует кривые названия архивов и папок, поэтому залил тему на свой хост, почистив все названия, указал новый путь в composer.json, ввожу опять composer require drupal/MYTHEME и получаю:

Using version dev for drupal/MYTHEME ./composer.json has been updated

DrupalProject\composer\ScriptHandler::checkComposerVersion Loading composer repositories with package information Updating dependencies (including require-dev) Nothing to install or update Writing lock file Generating autoload files DrupalProject\composer\ScriptHandler::createRequiredFiles

И опять ничего.

Куда оно скачалось и что я делаю не так?

Niklan   пн, 27/08/2018 - 13:57

Проверьте, всё ли корректно в extra.installer-paths. Походу все тащится в вендор так как типы не сходятся.

Артём Кирьянов   вс, 31/12/2017 - 02:30

Самая обширная инструкция, нигде не мог найти корректное описание.

Михаил   пт, 09/02/2018 - 11:07

А как быть с библиотеками? Некоторые модули устанавливаются сразу со всеми необходимыми библиотеками, а некоторые нет, это зависит от разработчиков модулей?

Niklan   пт, 16/02/2018 - 08:44

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

Я делаю также через композер в таких случаях. Например.

Кира   чт, 19/04/2018 - 23:49

спасибо за статью - очень помогла. Но есть проблема. Composer установила на VPN. drupal 8.5.2 Используя Composer установил модуль Telephone Type . В composer.json модуль появился, в списке модулей так же. Но! При попытке включить модуль - "This module can be only installed with Composer as it uses composer dependencies." Модули другие, на пример simplenews а он без зависимости Composer, с помощью Composer встал на ура. В чём ошибка моя? Как её решить. Спасибо!

Niklan   пт, 20/04/2018 - 06:16

Модуль вы поставили, а зависимость для него какую-то, он не подтянул. Походу giggsey/libphonenumber-for-php. Попробуйте её руками запросить у композера и потом включить модуль, должно помочь.

Кира   пт, 20/04/2018 - 10:41

а вот тут у меня будут проблемы. НЕ подскажите, как это сделать? composer require drupa/ это же не подойдет?

Кира   вс, 22/04/2018 - 20:15

Спасибо большое. Но на этом проекте не устанавливаеся ни один модуль. Попробовала на трех других проектах на этом же впн - всё встало на ура.

La   вс, 27/05/2018 - 15:26

Здравствуйте. Экспериментирую на локальном сервере XAMPP (+ Windows 10 + GIT).

Пытаюсь установить Drupal 8 с помощью Composer. (composer create-project drupal-composer/drupal-project:8.x-dev my_site--stability dev --no-interaction.) Правильно ли я поняла, что Composer служит только для ЗАГРУЗКИ пакетов? Установку нужно делать с помощью Drush или Drupal Console? Drush установлен глобально. У меня почему-то не получается загрузить его в папку C:/xampp/htdocs/my_site/web.

При вводе: composer require drush/drush;

следует:

No composer.json in current directory, do you want to use the one at C:\xampp\htdocs\my_site? [Y,n]?

Y-Enter:

Using version ^9.3 for drush/drush ./composer.json has been updated

DrupalProject\composer\ScriptHandler::checkComposerVersion Loading composer repositories with package information Updating dependencies (including require-dev) Nothing to install or update Generating autoload files DrupalProject\composer\ScriptHandler::createRequiredFiles

Niklan   вс, 27/05/2018 - 19:21

Да, композер только для загрузки пакетов, о друпал он ничего не знает и, соответственно, сделать не может. Включение и отключение модулей через Drush\Drupal Console.

На счет проблем с загрузкой не подскажу, Windows для работы не использую. Драш там ставится явно как-то иначе, не как на линуксе. Тут он ставится теперь через композер конкретно под проект, а запускается через Drush Launcher который сам понимает откуда и как вызвать драш от проекта.

La   вс, 27/05/2018 - 21:40

Спасибо за ответ. Да, я установила Drush Launcher. Провела установку Drupal 8. Первый вопрос: БД Drush может установить одновременно с установкой Drupal, т. к. я установила её по привычке заранее? Сейчас попыталась загрузить модули с помощью Drush. Получила сообщение:

dl has been deprecated. Please build your site using Composer. Add new proj ects with composer require drupal/[project-name]. Use https://www.drupal.or g/project/composer_generate to build a composer.json which represents the e nabled modules on your site.

  • Что-то типа загрузка с drush dl - устаревший метод. Пользуйтесь Composer.

Попыталась загрузить сразу несколько модулей (как в Drush) через запятую:

composer require drupal/colorbox, incert, admin_toolbar, module_filter,

Получила сообщение: [UnexpectedValueException] Could not parse version constraint incert,: Invalid version string "incert, "

Ни один модуль не загрузился.

Вопрос: Необходимо для каждого модуля указывать желаемую версию? (Это занудно). Или можно всё-таки их охапкой загрузить?

Niklan   пн, 28/05/2018 - 06:15

БД Drush может установить одновременно с установкой Drupal

Честно говоря не знаю. Я пользуюсь Docker4Drupal, там БД уже предустановлена. Скорее всего нужно создать самим. Не припоминаю чтобы друпал сам БД создавал.

Сейчас попыталась загрузить модули с помощью Drush.

Потому что загружать нужно через Composer.

Попыталась загрузить сразу несколько модулей (как в Drush) через запятую:

Это неправильно, вот правильный вариант вашего запроса: composer require drupal/colorbox drupal/incert drupal/admin_toolbar drupal/module_filter

Необходимо для каждого модуля указывать желаемую версию?

Нет.

Или можно всё-таки их охапкой загрузить?

Выше указал как правильно. Разделяются пробелом, то что пакет надо брать от вендора drupal надо указывать у каждого пакета. Все пакеты всегда имеют формат vendor/package и никак иначе. Пакетов в композере навалом, в одном только packegist, который из коробки композер использует, а ещё в drupal свой репозиторий с соответствующим вендором. Названия пакетов пересекаются и он в таком случае запутается что ставить, поэтому формат четкий, указывающий от кого и что брать, а если надо, и какой версии.

La   ср, 30/05/2018 - 21:15

Спасибо Вам огромное! Все модули удалось загрузить одной вашей командой. Ранее не работала с командной строкой, Drush и тем более с Composer. Поэтому часто спотыкаюсь на мелочах.

Юрий   пн, 08/10/2018 - 00:43

Для начала надо писать, что за это за композер, где его взять,как установить на винду( а мне плиз чтобы и с денвером работало) и куда эти команды вводить

Niklan   пн, 08/10/2018 - 09:24

Я же написал что это пакетный менеджер.

На счёт установки, у них простая инструкция: https://getcomposer.org/download/

На винде не знаю как его ставить, на линуксе просто вводятся эти команды и всё готово. Учитывая что локальная разработка у меня и вовсе на контейнерах, то вообще ничего ставить не приходится, всё уже стоит за меня. ?‍

Юрий   пн, 08/10/2018 - 11:19

Про это и речь, 8-ка считай для линуксеров, очень радостно

Niklan   пн, 08/10/2018 - 11:36

Веб-разработка в большей части всегда была и есть про юникс-подобные системы. Насколько я знаю на windows используют опен-сервер, а там композер из коробки.

Композер уже существует очень давно и уже устоявшийся инструмент. Это просто до друпала он дополз с задержкой. И то, пока это не обязательно (если избегать модулей что требуют его). Тем более, там есть установщик на винду и инструкции: https://getcomposer.org/doc/00-intro.md#installation-windows не вижу никаких проблем настроить. Плюс ставят всякие прослойки для консолей нормальных, WSL тот же можно подрубить. В общем это лучше спросить у тех кто разрабатывает под виндой, например тут: https://t.me/drupal_rus, тут больше вероятность что есть разработчики с виндой и разработкой заточенной под друпал.

Denwer, ну такое. Ещё во времена когда я начинал на винде, он работал очень плохо, сейчас он просто мертв, судя по его сайту. Какой php 5.3, когда все на 7.1, 7.2 сидят, на крайняк 5.6. Как там вообще друпал то завелся.

Юрий   ср, 07/11/2018 - 13:16

Примеров не хватает, самых элементарных. К примеру, отсюда никак не узнать, что модуль для друпал нужно ставить как drupal/имямодуля - по описанию кажется что просто имямодуля. И тд.

Niklan   ср, 07/11/2018 - 14:39

Есть в разделе "Установка, обновление и удаление пакетов".

Иван   вт, 04/12/2018 - 02:10

Никита, спасибо тебе за твой труд! Статья очень познавательная! За вечер открыл для себя новый мир )

Дмитрий   пн, 24/12/2018 - 15:39

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

Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 32 bytes) in phar:///usr/local/b in/composer/src/Composer/DependencyResolver/RuleWatchGraph.php on line 52

Niklan   пн, 24/12/2018 - 16:02

Хостинг слабый. В статье целый раздел этому посвящен, как это решается.

И не важно Drupal Project установка, или стандартная. Такая проблема на хостингах с композером выстреливает почти сразу.

Дмитрий   пн, 24/12/2018 - 18:43

Ога решил вопрос. Обновил все локально. Залил на хостинг новый composer.lock и composer install . Все четко, не внимательно читал малость

Максим   вт, 19/02/2019 - 12:03

Не выходит пропатчить через "стандартный composer json". Не знаете в чем дело? Причем, если брать "composer drupal project" - все устанавливает. Уже пробовал и по этой инструкции: "https://groups.drupal.org/node/518975". Просто пишет - нечего обновлять.

Niklan   ср, 20/02/2019 - 07:16

Если нужна помощь, надо побольше информации предоставить :)

Например, стоит ли зависимость которая пачтит, что указано в extra.patches? Надо учитывать что у composer drupal project ядро имеет пакет "drupal/core", а в стандартной поставке, если я не ошибаюсь, надо патчить "drupal/drupal", если проблема именно с патчями на ядро. С остальными должно быть ок, если же они установлены через композер, если же установлены классическим способом, простым заливом в нужнео место, то и не должны патчиться.

Максим   вс, 10/11/2019 - 18:50

В общем, трудности были скорей всего с совместимостью процесса патча с Windows 7. Забыл написать) Перешел на Windows 10, и все заработало.

Максим   чт, 21/02/2019 - 23:10

Зависимость стоит:

    "require": {
         .......
        "cweagans/composer-patches": "^1.6",
         ......
    },

Модули все ставил через composer В Extra:

"extra": {
        ....
        "patches": {
            "drupal/core": {
                "Transliterate file name ": "https://www.drupal.org/files/issues/2018-12-05/2492171-128.patch"
            }
         ....
        }

Попробовал прописать "drupal/drupal", но результата не дало. В Итоге поставил "composer drupal/project" но загадка так и осталась не решена) В любом случае спасибо за совет) Если найду решение-отпишусь

xandeadx   пн, 10/06/2019 - 16:07

Не знаю как на линухе, но в винде путь к локальным патчам надо писать без начального слэша: "Patch from local file": "patches/fix.patch"

Niklan   вт, 11/06/2019 - 08:09

Да, ты прав, спасибо, поправил. На линуксах также, начальный / пойдет от корня системы. Я написал так для примера, но щас подумал, действительно с толку сбить может.

Виталий   вс, 24/11/2019 - 03:46

День добрый. Вопрос по патчам: есть вариант, когда в экстра -> патчи указывается следующая конструкция, например: "patchLevel": { "drupal/core": "-p2" }

Можете немного пояснить, что это и насколько это можно применять со своими патчами?

Stepan   пн, 16/03/2020 - 16:16

Подскажите, использование fxp/composer-asset-plugin (https://github.com/fxpio/composer-asset-plugin) это теперь более предпочтительный путь, чем создание "bower-asset", "npm-asset" библиотек в composer в ручном режиме?

Niklan   вт, 17/03/2020 - 10:13

Ещё не смотрел (сам узнал пару дней назад) и не пробовал, поэтому нечего сказать. Сам до сих пор использую asset-packagist.

Насчёт «предпочтительный» не знаю. На asset-packagist уже некоторые контрибы подвязаны, например. Надо следить за ситуацией и пробовать что в итоге удобнее и лучше. Лучше самому попробовать и решить. Главное чтобы вам удобнее было же :) Пока в Drupal сообществе официально ничего на эту тему нет, каждый делает как ему удобнее.

Павел   чт, 21/05/2020 - 17:11

Привет! Первый раз работаю по такому принципу - в связке linux - composer - git. На локалке LAMP dev-версия сайта установленная composer, на VPS-сервере основной сайт-prod и к нему поддоменом test-сайт. Изменения на dev(dev branch) (конфиги, стили, изменения в composer.json и тд) с помощью пуляю на гитхаб, оттуда стягиваю на тестовый test(test branch), там всё восствнавливаю, проверяю, если всё ок то делаю то-же самое и для dev(master branch). Два раза по началу сайт на VPS у меня накрывался медным тазом. Теперь боюсь рисковать. Но система настойчиво рекоммендует обновить ядро. Подскажите как поступить правильно? Я ещё ни разу на этом сайте ничего не обновлял. Вот как я вижу мои действия: 1-вариант. На dev обновляю ядро композером, git push -> на тестовом git pull, composer install 2-вариант. На dev обновляю ядро композером, выгружаю конфиги drush cex -> на тестовом git pull, drush cim (но что-то мне подсказывает что конфиги вообще не должны измениться) 3-вариант - комбинация 1-го и 2-го 4-вариант. Просто и там и там обновить ядро.

Павел   пт, 22/05/2020 - 11:16

Решил, воспользовавшись данной инструкцией https://www.drupal.org/docs/updating-drupal/update-drupal-core-via-composer#s-on-your-production-environment п.4. Правда сначала меня сбило с толку что composer.json не обновился и соответственно не перекинулся. В более подробных шагах https://www.drupal.org/docs/updating-drupal/update-drupal-core-via-composer#update-all-steps правда есть пункт о том что нужно выгрузить конфиги после обновления. Но я этого не выполнил т.к. в описании п.4 об этом не было. Посмотрим, что будет ...

Павел   пт, 22/05/2020 - 16:03

Так, дополню. Внёс небольшие правки в dev-версии, выгрузил конфиг-файлы. Как и ожидал изменения коснулись только исправлений, ничего связанного с обновлением ядра нет. Может кому-то полезно будет.

Kostarh   чт, 19/11/2020 - 13:22

Подскажите, я могу использовать composer только для тех модулей, которое без него не установятся, а все остальное делать по старинке(установка модулей и обновление ядра) Я весь сайт сделал без composer. Drupal 9, обновлял в ручную, после установки swiftmailer через composer, ядро откатилось на версию 9.0.6,хотя стояла версия 9.0.7

Kostarh   чт, 19/11/2020 - 13:50

Или чтобы настроить норм почту, нужно сделать пеобразование ранее загруженного сайта в Composer, удалить все модули которые ставил вручную и поставить их заново через Composer ?

Niklan   чт, 19/11/2020 - 14:52

Нужно все модули запрашивать через Composer. Те что были установлены руками, просто запросить их композером (тех же самых версий) и дальше вести всё через него.

Использовать выборочно — себе дороже. Либо проект ведётся через композер, либо нет. Как миксовать подходы правильно я не скажу, потому что никому не рекомендую, не советую так делать и сам не делаю. Это считается "хаком ядра", если друпал установлен из архива и затем туда ещё запрашиваются зависимости композера. Надо полностью переводить на композер в таком случае и вести соответственно.

Ведите весь проект композером и никаких проблем не будет.

Kostarh   чт, 19/11/2020 - 19:21

Спасибо за развернутый ответ! Я еще все котриб модули ставил в папку modules. Может есть способ перенести все модули в папку contrib без удаления самих модулей?

Kostarh   чт, 19/11/2020 - 21:22

Перенес включенные модули в подпапку contrib, далее запустил update.php и все работает.

Ivan Proshechkin   чт, 26/11/2020 - 18:53

С установкой и обновлением модулей на dev и последующем composer install на live все понятно. Как с удалением пакетов? На dev он удалится и в composer.json этого пакета уже не будет. Удалить сам пакет на Live можно будет только composer update. А это как бы противоречит основной идее неизменности окружения dev и live )).

Niklan   чт, 26/11/2020 - 21:07

Что-то я не понял в чём вопрос?

composer install удалит пакеты которые были удалены на деве. Нет необходимости запускать composer update.

Ivan Proshechkin   пт, 27/11/2020 - 09:43

Упс, проверил, и правда удаляет - все ок, тогда ) Попутно еще один вопрос возник. Composer outdated как-то смотрит на указатели версий в composer.json? Иначе как объяснить что для того же drupal/core-recommended в .json указано ^8.8, реально стоит пакет 8.9.9, а outdated мне показывает наличие версии 9.х, хотя мне важнее было бы видеть что вышла 8.9.10. Только из админки и увидел про 8.9.10

Niklan   пт, 27/11/2020 - 12:18

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

chegor   пн, 22/03/2021 - 12:04

Маленькое уточнение. Иногда, если вы что-то тянете через composer, при этом запуская на сервере только composer install, то что нужно исполнить нужно добавить и в post-install-cmd. (я с таким столкнулся тут https://www.drupal.org/docs/8/themes/barrio-bootstrap-4-drupal-89-theme/bootstrap-barrio-installation/bootstrap-libraries)

SPiRiT   чт, 08/12/2022 - 23:15

Если устанавливливал модули с указанием версии, то как теперь быть? Копировал команду композера со страницы модуля. Теперь каждый модуль обновлять с указанием новой версии и больше никак?