composer插件发布需满足三项硬性要求:①type必须为"composer-plugin";②require中须含"composer-plugin-api": "^2.9";③extra中须声明"class"且类实现plugininterface;git tag必须带v前缀;autoload须严格匹配命名空间与文件路径。

发布 Composer 插件和发布普通 PHP 包流程相似,但关键区别在于 type 必须为 composer-plugin,且 Packagist 会特别校验 extra.class 和 composer-plugin-api 依赖 —— 缺一不可,否则插件不会被识别或激活。
composer.json 必须满足的三项硬性要求
Packagist 在索引时会严格检查以下字段,任一缺失或格式错误都会导致“Package not found”或插件不生效:
-
type字段必须显式设为"composer-plugin"(不能省略,也不能写成plugin或composer_plugin) -
require中必须包含"composer-plugin-api": "^2.9"(当前 Composer 2.x 最低兼容版本;用^2.7可能触发 autoload 失败) -
extra中必须声明"class": "Your\Namespace\PluginClass",且该类必须实现ComposerPluginPluginInterface
常见错误:本地 composer install 能跑通,但提交到 Packagist 后显示 Invalid package information —— 大概率是 extra.class 值里用了相对命名空间(如 MyPlugin),或路径拼写大小写不一致(Windows 下可能侥幸通过,Linux 下直接失败)。
打 Git tag 的版本命名必须带 v 前缀
Packagist 默认只识别以 v 开头的语义化标签,比如 v1.0.0、v0.5.2。即使你的 composer.json 里写了 "version": "1.0.0",它也会被忽略;只有 tag 名才作数。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- ✅ 正确命令:
git tag -a v1.0.0 -m "First stable release"+git push origin v1.0.0 - ❌ 错误示例:
git tag 1.0.0(无v)、git tag v1.0(缺补零)、git tag plugin-v1.0.0(含非法前缀)
如果已推错 tag,不要尝试 git tag -d v1.0.0 && git push origin :refs/tags/v1.0.0 后重打 —— Packagist 不会自动刷新旧 tag 的元数据,必须去后台手动点 “Update” 才能重新抓取。
用户 require 时插件不自动激活?检查 autoload 和类路径
插件类加载失败是最隐蔽的问题:没有报错,但 activate() 方法完全没执行。根本原因通常是 autoload 配置与实际文件结构不匹配。
- 确保
autoload使用psr-4,且末尾有反斜杠:"Your\Namespace\": "src/"(不是"Your\Namespace": "src/") - 类文件路径必须严格对应命名空间,例如
extra.class = "My\Plugin\MainPlugin"→ 文件必须是src/Plugin/MainPlugin.php - 运行
composer dump-autoload -o后,检查vendor/composer/autoload_psr4.php是否真包含了你的映射项
一个典型现象:你在 activate() 里写了 $io->write('loaded'),但执行 composer install 时什么也不输出 —— 八成是 autoload 没生效,而不是插件逻辑有问题。
插件发布后最易被忽略的一点:它不会出现在 vendor/ 下的常规包列表里,而是由 Composer 内部单独加载;所以别指望用 ls vendor/myorg/my-plugin 来验证是否装成功 —— 看 composer show 输出里有没有你的插件名,或者加个 die('here') 在 activate() 开头更可靠。










