Я хочу, чтобы мой пакет поставлялся со встроенным плагином 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
разрешено добавлять плагины, кажется?
Если плагин является частью вашего пакета, вы не должны использовать его как таковой. Композитор предлагает альтернативы.
Как упоминал Йенс в комментарии к вашему вопросу, в скриптах есть ключ composer.json
, Вы можете вызывать команды оболочки внутри, но также вызывать статические методы класса.
О плагинном решении — композитор прямо упоминает об этом на своем сайте:
Composer не делает никаких предположений о состоянии ваших зависимостей до установки или обновления. Следовательно, Вы не должны указывать сценарии, которые требуют управляемых Composer зависимостей в перехватчиках событий pre-update-cmd или pre-install-cmd. Если вам необходимо выполнить сценарии перед установкой или обновлением, убедитесь, что они содержатся внутри вашего корневого пакета.
(примечание моей стороны — это также примерно относится к плагинам).
В любом случае — предоставить вам решение: отказаться от «плагина». Вместо этого измените ваш 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
:
<?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/
:
<?php
namespace Foo\Bar;
/**
* Test class.
*/
class Test
{
const TEST_CONST = "HERE I AM";
}
Запустите это и проверьте, как оно заканчивается.
Других решений пока нет …