post-install-cmd 是 Composer 的脚本事件,仅在 vendor/ 不存在或 composer.lock 变更导致实际安装依赖时执行,并非每次 composer install 都触发。

Composer 安装完成后自动执行脚本,靠的是 post-install-cmd 脚本事件,但它**不会在首次 composer install 时无条件触发**——只有当 vendor/ 不存在或 composer.lock 有变动时才运行,且默认不启用。
post-install-cmd 是什么,什么时候真正执行?
它是 Composer 的一个“脚本事件(script event)”,属于生命周期钩子之一,设计用于在 composer install 成功完成依赖安装后执行自定义命令。但要注意:
- 它不等于每次
composer install都跑——如果vendor/已存在、composer.lock未变、且所有包已满足要求,Composer 会跳过安装步骤,post-install-cmd也就不会触发 - 它和
post-update-cmd是两个独立事件:install面向首次或重装场景,update面向依赖升级场景 - 若想“每次 install 都强制执行”,得配合
--no-cache或删掉vendor/+composer.lock(不推荐),更合理的方式是用scripts中的通用钩子或手动调用
如何在 composer.json 中正确配置 post-install-cmd
必须把命令写进 scripts 字段下,且键名严格为 post-install-cmd(大小写敏感)。支持字符串(单条命令)或数组(多条顺序执行):
{
"scripts": {
"post-install-cmd": [
"@php artisan clear-compiled",
"@php artisan optimize:clear",
"chmod -R 755 storage bootstrap/cache"
]
}
}
说明:
- 以
@php开头的命令会复用当前 Composer 进程的 PHP 解释器,避免环境不一致问题 - 普通 shell 命令(如
chmod)需确保系统中存在对应二进制,Windows 下可能失败,建议用跨平台 PHP 脚本替代 - 数组内命令按顺序执行,任一失败(非零退出码)将中断后续执行 —— 若需忽略某步错误,可用
|| true(如ls nonexistent/ || true)
常见失效原因与调试方法
配好了却没执行?大概率卡在这几个点:
-
composer install实际走的是“从 lock 文件快速还原”,没真正安装新包 → 改用composer install --no-cache或先删vendor/测试 -
composer.json放错位置(不在项目根目录),或 JSON 格式错误导致整个scripts段被忽略 - 命令路径错误:比如
artisan不在当前目录,应写成php artisan或确保$PATH包含项目 bin 目录 - 权限问题:Linux/macOS 下脚本无执行权限,或 Windows 下不识别
.bat/.ps1后缀 —— 推荐统一用php xxx.php形式 - 静默失败:加
-v参数查看详细日志:composer install -v,搜索Executing script行确认是否进入钩子
替代方案:何时该用 post-autoload-dump 或自定义脚本?
如果你的需求本质是“类加载更新后做点事”(如生成代理类、刷新注解缓存),post-autoload-dump 更精准,它在每次 autoloader 重建时都触发(包括 install、update、甚至 dump-autoload):
{
"scripts": {
"post-autoload-dump": [
"@php vendor/bin/doctrine orm:generate-proxies"
]
}
}
而更复杂的逻辑(比如需要读取配置、判断环境、并发控制),建议封装为独立 PHP 文件并调用:
{
"scripts": {
"post-install-cmd": "App\\ComposerScripts::postInstall"
}
}
然后在 app/ComposerScripts.php 中写静态方法 —— 这样可测试、可复用、不受 shell 环境限制。
真正容易被忽略的是:脚本事件的执行时机绑定的是 Composer 的内部状态判断,不是用户直觉上的“只要我敲了 install 就该跑”。盯住 vendor/ 和 composer.lock 的存在性与一致性,比反复改配置更有效。










