Composer Installer插件需实现InstallerInterface接口并在composer.json中声明type,通过插件activate()注册到InstallationManager,supports()返回true且getInstallPath()返回相对于vendor的路径字符串才能生效。

Composer Installer插件的核心是实现 Composer\Installer\InstallerInterface
Composer 自定义 Installer 不是写个脚本就能挂上去的,必须让 Composer 认出你这个类是个合法的安装器。关键在于实现 Composer\Installer\InstallerInterface 接口,并在 composer.json 里通过 type 字段绑定类型。
常见错误是只写了个类、没声明 type,或者 type 和 installer 配置不匹配,导致 Composer 完全忽略你的类。
- 你的包必须声明
"type": "composer-installer"(或任意自定义 type,如"type": "my-plugin") - 在根
composer.json中用"require"引入该包,并确保它被加载 - 在该包的
composer.json里加"autoload"映射,保证类能被自动加载 - 必须提供
supports()方法返回true才会被选中;否则即使类存在也进不了安装流程
怎么让 Composer 在 install/update 时调用你的 Installer
Composer 不会“扫描”所有类去猜谁是 Installer,它靠两层匹配:先看包的 type,再查已注册的 Installer 是否支持该 type。所以你得主动注册——不是靠命令行参数,而是通过 composer-plugin-api 的机制,在插件的 activate() 里注册。
典型场景:你想把 "type": "theme" 的包统一解压到 themes/ 目录,而不是默认的 vendor/。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 插件主类需实现
Composer\Plugin\PluginInterface - 在
activate()中调用$installer = new MyThemeInstaller($io, $composer); $installer->setOutput($io); $composer->getInstallationManager()->addInstaller($installer); - 别漏掉
getInstallPath()返回具体路径,否则 Composer 会 fallback 到vendor/下的默认结构 - 如果
supports()返回false,这个包会被交给默认 Installer 处理,你的逻辑完全不会触发
getInstallPath() 返回的路径必须是相对于 vendor 目录的相对路径
很多人以为可以返回绝对路径,比如 /var/www/themes/my-theme,结果 Composer 报错或静默失败。实际上 getInstallPath() 只接受相对于 vendor/ 根目录的路径字符串,最终安装位置是 vendor/ + 你返回的路径。
例如想把 acme/theme-demo 装到项目根下的 themes/demo,不能直接返回 ../themes/demo(Composer 会拒绝),而应返回 ../../themes/demo 并配合 InstallationManager 的路径解析逻辑——但更稳妥的做法是:用 getInstallPath() 返回 themes/demo,再在 install() 或 update() 中手动移动文件。
- 返回值必须是字符串,不能是
Path::normalize()后的绝对路径 - 返回
themes/demo,实际安装位置就是vendor/themes/demo,不是项目根目录 - 真要装到项目外目录,得在
install()里用Filesystem手动复制,并返回一个占位路径(如placeholder/themes-demo)避免冲突 - 注意 Windows 下路径分隔符,
getInstallPath()应始终用/,Composer 内部会自动转换
调试 Installer 为什么没生效的三个检查点
Installer 不执行是最常遇到的问题,原因往往很隐蔽。别急着重写,先盯住这三个地方:
- 运行
composer show --plugins,确认你的插件已加载且状态为enabled;没出现说明 autoload 或 plugin 声明有误 - 给目标包加
"type": "my-custom-type",然后运行composer install -v,看 verbose 输出里有没有MyCustomInstaller supports my-custom-type: true - 在
supports()里加日志(如file_put_contents('debug.log', ...)),确认它是否被调用;如果没调用,说明 Composer 根本没尝试匹配你的 Installer
最易忽略的是:你的插件包本身不能依赖 composer-plugin-api 的版本高于当前 Composer 版本。比如 Composer 2.5 要求 "composer-plugin-api": "^2.3",但你写了 "^3.0",插件就会被跳过,且无任何提示。

















