pre-install-cmd 仅在需重新解析依赖(lock缺失/不匹配或--force-install)时触发,且必须返回0才能继续安装;它不是每次install都执行的通用钩子,误用会导致安装中断或镜像配置失效。

pre-install-cmd 脚本不是“install 前随便跑个命令”的通用入口,它只在真正要安装依赖(而非仅解包)前触发,且必须返回 0 才能让 install 继续执行。
pre-install-cmd 触发的真实条件
很多人误以为只要运行 composer install 就会进 pre-install-cmd,其实不然:
- 如果项目已有有效的
composer.lock(即版本已锁定、composer.json未变更),composer install只是读 lock 文件并解包,不触发pre-install-cmd - 只有当
composer.lock不存在、或内容与composer.json不匹配(比如新增/删了require)、或显式加了--force-install时,Composer 才会进入“安装决策流程”,此时才调用pre-install-cmd - 相比之下,
composer update总会走完整解析流程,所以pre-update-cmd更稳定可靠
脚本返回值决定 install 是否继续
pre-install-cmd 是阻断式钩子:脚本进程退出码非 0,整个 composer install 就直接中止,不会报错提示“为什么停”,只会卡在那或输出类似 Script xxx handling the pre-install-cmd event returned with error code 1
- PHP 脚本末尾记得加
exit(0),尤其用了die()或异常未捕获时容易意外返回非 0 - Shell 命令链要用
&&连接,避免中间某步失败但后续仍执行(如php check.php && echo ok) - 测速类脚本(如
bin/check-mirror.php)若因网络超时没写入配置,必须主动exit(0)让 install 继续,而不是让 PHP 默认返回 255
动态修改镜像配置的正确写法
想在 pre-install-cmd 里换 packagist 镜像,不能只改环境变量或临时设 COMPOSER_REPO_PACKAGIST——Composer 已启动,这些对当前进程无效。必须写入配置生效点:
- 推荐写入项目级
auth.json的config.repo.packagist字段,用composer config repo.packagist https://mirrors.aliyun.com/composer/ --file auth.json - 或者用 PHP 直接写 JSON 到
auth.json,确保格式合法(注意 JSON 缩进和逗号) - 不要碰全局
~/.composer/auth.json,多项目并发时会互相覆盖 - 写完立刻用
composer config --list验证是否生效,避免“以为改了其实没生效”
常见错误现象与排查线索
遇到 pre-install-cmd 没执行、执行了但没效果、或 install 卡住,优先查这几处:
-
composer.json里"scripts"键名拼错:必须是"pre-install-cmd"(全小写、连字符、无空格),写成preInstallCmd或pre_install_cmd都无效 - 脚本路径不存在或权限不足:比如写
"php bin/check.php",但bin/check.php没chmod +x或路径错位 - 脚本里用了相对路径(如
file_get_contents('config/mirror.json')),实际工作目录是项目根,不是脚本所在目录,要用__DIR__定位 - Composer 版本太老(composer --version 确认
最易被忽略的是:这个钩子本质是“决策前检查”,不是“每次 install 都该跑的初始化入口”。真要每次执行,得换用 post-autoload-dump(生成自动加载后必触发)或显式绑定到自定义 script 命令里调用。


















