Composer插件必须实现PluginInterface接口、声明"type": "composer-plugin",通过extra字段传参,监听InstallerEvent发布资源,动态获取vendor-dir路径,Windows下需fallback至copy,且须兼容各类composer命令参数。

Composer插件必须实现PluginInterface才能被识别
Composer不通过自动扫描类或命名空间加载插件,而是严格依赖composer-plugin-api版本约束 + 类实现ComposerPluginPluginInterface。没实现这个接口,哪怕类名再规范、autoload配得再好,composer install时也完全不会调用你的代码。
- 必须在
composer.json中声明"type": "composer-plugin",否则composer根本不把它当插件处理 -
extra.plugin-class字段已废弃多年,现在只认autoload中注册的类,并且该类构造函数不能抛异常(否则插件加载失败静默跳过) - 推荐用
"autoload": {"psr-4": {"MyPlugin\": "src/"}},避免classmap导致开发时修改类不生效
资源发布逻辑得挂到InstallerEvent或PackageEvents::POST_PACKAGE_INSTALL
想在包安装后把某些文件“发布”到项目根目录(比如配置模板、前端资源),不能靠activate()一次性复制——那只会运行一次,且发生在插件自身加载阶段,目标包都还没解压。
- 监听
ComposerInstallerInstallerEvent(对应install/update命令执行中)比监听PackageEvents::POST_PACKAGE_INSTALL更可靠:后者在单个包安装完触发,但可能因并发安装顺序错乱,导致依赖未就绪就尝试发布 - 发布路径必须用
$event->getComposer()->getConfig()->get('vendor-dir')动态获取,硬写vendor/在自定义vendor-dir时直接失效 - 别用
file_put_contents覆盖已有文件——应先file_exists检查,或加--force-publish开关,否则用户改过的配置下次会被悄无声息覆盖
composer.json里extra字段是唯一传参入口
插件没法从命令行接收参数,也不能读取项目根目录下任意配置文件。所有定制行为(比如指定发布源目录、是否启用软链接)只能通过项目composer.json的extra块注入。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 格式必须是
"extra": {"my-plugin": {"publish-from": "res/templates", "symlink": true}},插件内用$composer->getPackage()->getExtra()['my-plugin'] ?? []读取 - 不要在
extra里放敏感信息(如token),它会随composer.lock提交到仓库 - 如果用户没配
extra.my-plugin,插件应走默认行为,而不是报错中断整个composer install
Windows下符号链接需要管理员权限,copy才是安全兜底
很多插件想用symlink发布资源以支持热更新,但在Windows上proc_open('mklink')默认失败,即使开了开发者模式,CI环境(如GitHub Actions Windows runner)通常也不具备管理员权限。
- 检测
PHP_OS_FAMILY === 'Windows'后,强制 fallback 到RecursiveCopyIterator,别指望is_link()能跨平台判断成功 -
copy()比exec('xcopy')稳定,后者在路径含空格或特殊字符时容易崩 - 发布前先
unlink目标路径(如果是文件或符号链接),但对目录要用rrmdir递归删,否则copy会把源目录整个塞进目标目录里
真正难的不是写发布逻辑,而是让插件在各种composer install --no-dev --optimize-autoloader -v组合参数下都不报错、不干扰主流程——这意味着每处file_exists都要加@抑制警告,每个exec都要if (function_exists())守门。

















