supports() 返回 false 是因包未触发安装器,根本原因是 composer.json 的 "type" 字段未严格匹配;getinstallpath() 报错因返回了绝对路径或含斜杠前缀;install() 失败多因未用 $filesystem 操作文件;isinstalled() 缺失或判断宽松会导致重复安装。

supports() 返回 false?包根本没走你的安装器
这是最常被忽略的启动失败点:包压根没触发你的安装器逻辑,不是路径错,是根本没进来。
常见错误现象:Package is not installed in the expected path,但 getInstallPath() 根本没被调用;或者 composer install 完全静默,vendor 下照旧出现包目录。
-
supports()必须严格比对$package->getType()—— 不是包名、不是 vendor 名、不是文件内容,只看composer.json里"type"字段的值 - 确保目标包的
composer.json明确声明了你支持的 type,例如"type": "my-framework-module",不能拼错、不能多空格、不能大小写混用 - 插件自身必须声明
"type": "composer-plugin",且在extra.installer-types中列出该 type,否则 Composer 不会把它和你的 installer 绑定 - 别在
supports()里做耗时操作(如读文件、发 HTTP 请求),它会被反复调用,性能敏感
getInstallPath() 报 InvalidArgumentException?路径格式错了
报错信息通常是 Invalid argument: Path must be relative to project root 或直接抛出 InvalidArgumentException,本质是返回值违规。
关键约束:返回值必须是**相对路径**,且**不能以 / 开头**,哪怕你写的是 /plugins/my-package 也会炸。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 正确写法示例:
return 'plugins/' . $package->getPrettyName();(注意开头无斜杠) - 绝对路径、
./前缀、Windows 风格反斜杠(\)都会触发异常;一律用正斜杠/,Composer 内部会自动适配系统 - 路径中可用变量:
{$name}(不含 vendor)、{$vendor}、{$type},但仅限于extra.installer-paths配置;自定义 installer 类中需手动拼接 - 别硬编码
vendor/或web/等目录——从$config->get('vendor-dir')或项目根目录出发计算更安全
install() 执行后文件没复制过去?漏了 filesystem 或权限问题
路径算对了、supports() 也返回 true,但目标目录空空如也。问题不在逻辑,而在文件操作层。
手动 mkdir + copy 是最大雷区:跨平台路径分隔符、符号链接丢失、覆盖策略缺失、静默失败……全都藏在这里。
- 必须用
$filesystem->ensureDirectoryExists($targetDir)创建目录,而不是mkdir -p - 复制文件必须用
$filesystem->copy($source, $target, true),第三个参数true表示强制覆盖,否则已存在文件会跳过 - 获取源路径时,别假设包解压在
vendor/xxx/yyy—— 应通过$package->getInstallationSource()判断是 dist 还是 source,再结合$composer->getInstallationManager()->getInstallPath($package)获取当前实际位置 - 日志输出务必用
$io->writeError("..."),否则在-q模式下完全看不到任何提示,排查等于盲人摸象
update 后包被删了重装?isInstalled() 没写或判断太松
执行 composer update 时,你的包被清空再重装一遍,autoload 重复生成,甚至触发脚本重跑——这不是 bug,是你没告诉 Composer “它已经装好了”。
isInstalled() 的作用就是让 Composer 跳过已存在的包,但它不像 supports() 那样有默认 fallback,漏写或写错就等于没写。
- 典型实现:检查目标路径是否存在,且包含
composer.json或某个标志性文件(如index.php) - 别只检查目录存在——万一目录是空的,
isInstalled()返回 true 就会导致后续 install 失败 - 路径判断要和
getInstallPath()保持一致,比如后者返回'packages/my-pkg',这里就得检查$installPath . '/composer.json' - 如果目标路径可能被用户手动删除,
isInstalled()返回 false 是合理的,此时 Composer 会走完整 install 流程
supports() 没匹配上、getInstallPath() 返回了绝对路径、install() 没用 $filesystem、isInstalled() 没写——四道门,漏一扇,整个安装流程就掉链子。










