post-install-cmd不会每次composer install都执行,仅当vendor不存在或为空、composer.lock缺失或不匹配且未加--no-scripts时触发;更稳定的选择是post-autoload-dump,它在autoload.php生成后必执行。

post-install-cmd 不会在每次 composer install 时执行,它只在真正“从零安装依赖”时触发——vendor 目录不存在或为空、composer.lock 缺失或与 composer.json 不匹配,且没加 --no-scripts 才会跑。
post-install-cmd 为什么经常不执行
你配好了、写对了、路径也没错,但脚本就是静默跳过。这不是 Composer 抽风,而是触发条件根本没满足:
-
vendor/已存在且完整 → Composer 直接跳过安装流程,post-install-cmd不触发 -
composer.lock存在且和composer.json的require完全匹配 → 即使你删了vendor重装,它也可能复用 lock 并跳过钩子(尤其 Composer 2.2+) - CI/CD 脚本里写了
composer install --no-scripts→ 所有post-*钩子被强制禁用 - 事件名写成
PostInstall、post_install_cmd、post-install→ Composer 完全忽略,不报错也不提示
怎么验证它是不是真被触发了
别靠 composer run-script post-install-cmd 去“测试”,那只是手动执行一个同名脚本,和安装流程无关:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
composer run-script post-install-cmd不加载 Composer 的上下文(比如包列表、$COMPOSER_EVENT环境变量可能为空) - 它不会重建 autoload,也不会通知插件,纯属命令行字符串执行
- 真正验证方式:删掉
vendor/和composer.lock,再跑composer install,看输出里有没有Executing script ...行 - 加
-v参数可看到详细日志:composer install -v,留意是否出现Running post-install-cmd hook
想“每次 install 都执行”,该用哪个钩子
单靠 post-install-cmd 无法保证每次运行。更可靠的选择是 post-autoload-dump:
- 它在
vendor/autoload.php或vendor/composer/autoload_psr4.php实际被写入后触发 - 覆盖所有场景:
composer install、composer update、甚至composer dump-autoload - 时机稍晚(autoload 已就绪),适合清理缓存、生成代理类、调用框架初始化逻辑
- 注意:
composer install --no-scripts仍会跳过它;如果 autoload 文件没重写(比如 vendor 没变),它也不会触发
配置时最容易踩的坑
脚本写对了,但执行失败,往往卡在路径、权限或环境上:
- 脚本路径基于项目根目录解析,写
php scripts/init.php比php ./scripts/init.php更安全(避免某些 shell 解析差异) - PHP 脚本里若要用到
vendor/autoload.php,必须显式引入:require __DIR__ . '/vendor/autoload.php'; - Windows 下慎用 shell 命令如
cp .env.example .env,改用 PHP 脚本或加#!/usr/bin/env php头 - 不要在脚本里写
cd vendor/bin再调命令——当前工作目录就是项目根目录,切过去反而导致autoload.php找不到
真正复杂的地方不在语法,而在触发逻辑的“确定性”:Composer 的钩子不是按命令名直觉触发的,而是严格绑定到内部状态变更(lock 是否过期、autoload 是否重写)。你得先判断自己要做的事,到底依赖“安装完成”还是“自动加载就绪”——选错钩子,再完美的脚本也白搭。










