脚本钩子必须满足位置对、名字准、时机到三条件:scripts须在composer.json根层级;事件名严格小写加中划线;post-install-cmd仅vendor为空时触发,post-update-cmd每次update均触发。

脚本钩子不是“写完就跑”,它必须满足三个硬性条件:位置对、名字准、时机到。缺一个,composer install 或 composer update 就会安静地跳过,不报错、不提示、不执行。
scripts 必须放在 composer.json 根层级
它不是配置项,是 Composer 唯一识别钩子的入口。任何嵌套都会被忽略:
-
"extra": { "scripts": { ... } }→ 完全无效,当成普通元数据 -
"config": { "scripts": { ... } }→ 同样被无视 - 正确位置只有:
"scripts": { "post-update-cmd": [...] },直接在composer.json最外层
多项目或 monorepo 场景下,子目录里的 composer.json 中的 scripts 不会被父级 Composer 加载——只认当前工作目录下的根文件。
事件名大小写和连字符必须完全匹配
Composer 不做模糊匹配,拼错一个字符就静默失效。常见错误包括:
-
post-autoloader-dump(多了一个r)→ 无效 -
postdump-autoload(顺序反了)→ 无效 -
post-install cmd(空格代替连字符)→ 无效 -
PostInstallCmd(驼峰或大写)→ 无效
内置事件名全是小写 + 中划线分隔,完整列表以官方文档为准。自定义名(如 ci:test)可任意,但调用时必须和 composer run-script ci:test 完全一致。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
post-install-cmd 和 post-update-cmd 触发条件完全不同
很多人以为 “装完依赖就该跑”,结果发现没反应,其实是搞混了触发逻辑:
-
post-install-cmd:仅当vendor/为空或不存在时,运行composer install才触发;composer require或composer update都不会触发它 -
post-update-cmd:每次composer update(无论是否带参数)都触发;也适用于composer install已有依赖后再次运行的场景 - 想“每次装/更都执行”,别只配一个,推荐统一指向自定义脚本:
"post-install-cmd": ["@build"], "post-update-cmd": ["@build"]
CI 环境中常因缓存导致 vendor/ 未清空,post-install-cmd 直接不跑——加 --no-cache 或改用 post-update-cmd 更可靠。
命令写法必须考虑跨平台和执行环境
字符串命令在 Windows 或 CI 下容易因 shell 解析失败,数组形式才是安全底线:
- ✅ 推荐:
"post-update-cmd": ["@php scripts/clear-cache.php", "npm run build"] - ❌ 危险:
"post-update-cmd": "php scripts/clear-cache.php && npm run build"(Windows 不认&&,引号嵌套易崩) -
@php是 Composer 内置别名,自动调用当前 PHP 可执行文件,避免硬编码路径或系统默认版本不一致 - PHP 脚本里别写
#!/usr/bin/env php—— Composer 不走 shebang,会直接报错 - 脚本路径基于项目根目录,但不要依赖
getcwd();用__DIR__定位资源更稳妥
最常被忽略的一点:钩子执行时,vendor/autoload.php 可能还没生成(尤其 post-install-cmd 首次安装),所以不能在脚本开头就 require 'vendor/autoload.php',更不能直接调用未加载的类方法。










