如何使用内置的composer-plugin创建单片Composer包?

min*_*.dk 16 php json composer-php composer-plugin

我希望我的软件包附带一个内置的composer-plugin.

我有这样的结构:

composer.json
src/
    ...
plugin/
    composer.json
    src/
        ...
Run Code Online (Sandbox Code Playgroud)

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": "*"
    }
}
Run Code Online (Sandbox Code Playgroud)

而内置的composer-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"
    }
}
Run Code Online (Sandbox Code Playgroud)

注意这里有一个双向依赖 - 插件依赖于foo/bar,项目本身依赖于foo/bar-plugin.

这就是它变得奇怪的地方.在使用eg composer install或者进行全新安装的过程中composer update,一切都很好 - 插件就是这样,现在,这意味着只需在控制台上宣布自己.

现在,在安装之后,如果我输入composer,我希望看到插件宣布自己,和以前一样,对吗?

相反,它一旦尝试引用属于该foo/bar包的任何类,就会生成致命的"类未找到错误" .

这就好像作曲家忘记了foo/bar-plugin需要的事实foo/bar,并且由于某种原因,它的类不能自动加载.

有什么理由不应该这样吗?为什么不?

当然我可以将这些东西打包在单独的外部包中,但这没有多大意义,因为这些包只是相互依赖 - 它们实际上是一个单元,将它们打包成两个包是随着每一个微小的变化都会导致一大堆主要版本的增加,因为基本上每一个版本foo/bar都会破坏foo/bar-plugin.

理想情况下,我想简单地将composer-plugin直接添加到主程序包中,但看起来由于某种原因这是不可能的?composer-plugin似乎只允许包含类型的包添加插件?

Tom*_*ski 1

如果插件本质上是你的包的一部分,你不应该这样使用它。Composer 提供了替代方案。

正如 Jens 在对您的问题的评论中提到的,composer.json. 你可以在里面调用shell命令,也可以调用静态类方法。

关于插件解决方案 - Composer 在其网站上明确提到了这一点:

在安装或更新之前,Composer 不会对依赖项的状态做出任何假设。因此,您不应在 pre-update-cmd 或 pre-install-cmd 事件挂钩中指定需要 Composer 管理的依赖项的脚本。如果您需要在安装或更新之前执行脚本,请确保它们独立于您的根包中。

(我的旁注 - 这也大致适用于插件)。

无论如何 - 为您提供一个解决方案:放弃“插件”方法。相反,修改您的composer.json文件,使其如下所示:

作曲家.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"
        ]        
    }

}
Run Code Online (Sandbox Code Playgroud)

此外,在src/Composer文件夹中创建Plugin.php

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,它打印测试类中的常量。创建它src/

src/测试.php

<?php

namespace Foo\Bar;

/**
 * Test class.
 */
class Test
{
    const TEST_CONST = "HERE I AM";
}
Run Code Online (Sandbox Code Playgroud)

运行它并检查它是如何发挥作用的。