Как создать монолитный пакет Composer со встроенным плагином composer?

Я хочу, чтобы мой пакет поставлялся со встроенным плагином composer.

У меня есть такая структура:

composer.json
src/
...
plugin/
composer.json
src/
...

Корень composer.json настроен так:

{
"name": "foo/bar",
"type": "library",
"autoload": {
"psr-4": {
"Foo\\Bar\\": "src/"}
},
"repositories": [
{
"type": "path",
"url": "./tools",
"options": {
"symlink": false
}
}
],
"require": {
"foo/bar-plugin": "*"}
}

И встроенный композитор-плагин plugin/composer.json как это:

{
"name": "foo/bar-plugin",
"type": "composer-plugin",
"require": {
"composer-plugin-api": "^1",
"composer/composer": "^1",
"foo/bar": "*"},
"autoload": {
"psr-4": {
"Foo\\Bar\\Plugin\\": "src/"}
},
"extra": {
"class": "Foo\\Bar\\Plugin\\MyComposerPlugin"}
}

Обратите внимание, что здесь существует двусторонняя зависимость — плагин зависит от foo/barи сам проект зависит от foo/bar-plugin,

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

Теперь после установки, если я просто наберу composerЯ ожидал бы увидеть плагин объявить себя, так же, как и раньше, верно?

Вместо этого он генерирует фатальную ошибку «класс не найден», как только он пытается сослаться на любой класс, принадлежащий foo/bar пакет.

Как будто композитор потерял след того факта, что foo/bar-plugin требует foo/barи по какой-то причине его классы не загружаются автоматически.

Есть ли причина, по которой это не должно быть возможно? Почему бы и нет?

Конечно, я могу просто упаковать этот материал в отдельный внешний пакет, но это не имеет особого смысла, поскольку эти пакеты просто будут зависеть друг от друга — они фактически представляют собой единое целое, упаковывая их как два пакета. приведет к путанице основной версии увеличивается с каждым небольшим изменением, как в основном каждый выпуск foo/bar сломает foo/bar-plugin,

В идеале, я хотел бы просто добавить плагин composer прямо в основной пакет, но кажется, что по какой-то причине это невозможно? Только пакет с типом composer-plugin разрешено добавлять плагины, кажется?

16

Решение

Если плагин является частью вашего пакета, вы не должны использовать его как таковой. Композитор предлагает альтернативы.

Как упоминал Йенс в комментарии к вашему вопросу, в скриптах есть ключ composer.json, Вы можете вызывать команды оболочки внутри, но также вызывать статические методы класса.

О плагинном решении — композитор прямо упоминает об этом на своем сайте:

Composer не делает никаких предположений о состоянии ваших зависимостей до установки или обновления. Следовательно, Вы не должны указывать сценарии, которые требуют управляемых Composer зависимостей в перехватчиках событий pre-update-cmd или pre-install-cmd. Если вам необходимо выполнить сценарии перед установкой или обновлением, убедитесь, что они содержатся внутри вашего корневого пакета.

(примечание моей стороны — это также примерно относится к плагинам).

В любом случае — предоставить вам решение: отказаться от «плагина». Вместо этого измените ваш composer.json файл так выглядит следующим образом:

composer.json

{
"name": "foo/bar",
"type": "library",
"autoload": {
"psr-4": {
"Foo\\Bar\\": "src/"}
},
"require": {
},

"scripts": {
"post-install-cmd": [
"Foo\\Bar\\Composer\\Plugin::postInstall"],
"post-update-cmd": [
"Foo\\Bar\\Composer\\Plugin::postUpdate"]
}

}

Кроме того, в src/Composer создание папки Plugin.php:

ЦСИ / Композитор / plugin.php

<?php

namespace Foo\Bar\Composer;

use Foo\Bar\Test;

/**
* Composer scripts.
*/
class Plugin
{
public static function postInstall()
{
print_r("POST INSTALL\n");
print_r(Test::TEST_CONST);
print_r("\n");
}

public static function postUpdate()
{
print_r("POST UPDATE\n");
print_r(Test::TEST_CONST);
print_r("\n");
}
}

Как видите, он печатает константу из класса Test. Создать его в src/:

SRC / test.php

<?php

namespace Foo\Bar;

/**
* Test class.
*/
class Test
{
const TEST_CONST = "HERE I AM";
}

Запустите это и проверьте, как оно заканчивается.

1

Другие решения

Других решений пока нет …