pre-install-cmd 仅在满足全部条件时执行:未禁用脚本、composer 版本达标、vendor 不存在或 composer.lock 与 composer.json 不匹配;必须定义在顶层 scripts 字段且为数组,非零退出码会中断安装。

pre-install-cmd 不会在每次 composer install 时运行,只在真正要安装依赖时才触发——这是最常被误解的一点。
pre-install-cmd 什么时候执行?
它不是“只要敲了 install 就跑”,而是严格满足以下全部条件才执行:
- 没加
--no-scripts(否则直接跳过) - Composer 版本 ≥ 1.10(推荐 ≥ 2.2,旧版本行为不一致)
-
vendor/目录不存在 或composer.lock文件内容与当前composer.json不匹配(即 Composer 判定需要重算依赖并安装)
典型静默跳过场景:项目已有完整 vendor/ 且 composer.lock 未改动,此时 composer install 只是校验和解包,pre-install-cmd 根本不会触发——不是配置失效,是逻辑压根没走到那一步。
scripts 字段必须写在 composer.json 顶层
常见错误是把 pre-install-cmd 塞进 extra、config 或嵌套对象里,比如:
{
"extra": {
"scripts": { "pre-install-cmd": ["echo hi"] } ← 无效
}
}
正确位置是和 require、autoload 同级的顶层 scripts 字段:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
{
"scripts": {
"pre-install-cmd": ["php bin/check-mirror.php", "echo 'checking env...'"]
}
}
值必须是数组(哪怕只有一个命令),字符串会报错;命令支持 shell 命令、php xxx.php、带 @ 前缀的已定义脚本别名。
非零退出码会中断整个 install 流程
pre-install-cmd 的每个命令都按顺序执行,任意一个返回非 0 状态码(比如 PHP 脚本里 exit(1)、shell 命令失败),Composer 就立刻中止后续所有操作——包括依赖解析、下载、解包。
- 适合做环境检查(PHP 版本、扩展缺失时
exit(1)) - 不适合做“尽力而为”的操作(如缓存清理失败不该阻断安装)
- 测速类脚本(如
bin/check-mirror.php)必须确保最终return 0;,哪怕没找到更快镜像
注意:post-install-cmd 没这个限制——它总归会执行,但 pre-install-cmd 是守门员,卡住就是卡住。
它和 post-install-cmd 的触发逻辑完全不对称
很多人拿 post-install-cmd 类比理解 pre-install-cmd,结果踩坑。关键差异在于:
-
post-install-cmd只要composer install成功结束就执行(哪怕只是解包),所以更“稳定” -
pre-install-cmd必须有“真安装动作”才触发,首次克隆、删了vendor/、改了composer.json导致 lock 失效时才跑 - 想每次
composer install都执行前置逻辑?得用post-update-cmd+ 手动composer update --lock,或干脆写个 wrapper 脚本调用
真正容易被忽略的是:它的存在本身就意味着“安装流程尚未开始”,所以不能依赖 vendor/autoload.php,也不能假设任何包已加载——所有前置检查必须靠原生 PHP 或系统命令完成。










