composer部署时真正有效的自动事件只有四个:post-install-cmd(lock不存在或过期时触发)、post-update-cmd(update及部分install触发)、post-root-package-install(项目自身安装完成时触发)、post-create-project-cmd(create-project时触发),其他如pre-autoload-dump等不适用于部署任务。

自动运行的命令必须写在 composer.json 的顶层 scripts 字段里,且事件名只能是 post-install-cmd、post-update-cmd 等 Composer 官方定义的全小写短横线格式——写成 PostInstall 或 post_install_cmd 都不会触发。
哪些事件名真正有效?
Composer 只认固定几个生命周期事件,部署时真正能用的只有这四个:
-
post-install-cmd:仅当composer.lock不存在或过期时触发(比如首次拉代码) -
post-update-cmd:每次composer update后必触发,也覆盖部分install场景(如 lock 存在但依赖有变更) -
post-root-package-install:只在你自己的项目(非依赖包)安装完成时触发,适合初始化配置文件 -
post-create-project-cmd:仅用于composer create-project创建新项目时,适合模板项目预设
别指望 pre-autoload-dump 或 post-autoload-dump 做部署任务——它们只在 autoloader 重建时跑,跟权限、缓存、目录生成无关。
脚本怎么写才不白配?
常见错误是脚本没生效,其实多半是结构或语法问题:
-
scripts必须是composer.json的顶层字段,不能塞进extra或config里 - 值必须是数组(多条命令)或字符串(单条),不能是对象或 null
- 所有引号必须是英文双引号,逗号不能多也不能少,末尾不能有逗号
- 命令含空格或特殊字符(如
php artisan migrate --force)时,整条命令要用双引号包裹 - 别写
cd vendor这类路径切换——Composer 执行脚本时工作目录就是项目根目录,硬切反而导致路径错乱
示例(最小可用配置):
{
"scripts": {
"post-install-cmd": [
"@php -r "echo '✅ Install done\n';"",
"php artisan key:generate",
"chmod -R 755 storage/"
],
"post-update-cmd": ["@post-install-cmd"]
}
}
为什么脚本有时不执行?
不是脚本写得不对,而是触发条件被忽略了:
-
post-install-cmd在--no-scripts参数下默认不执行——CI/CD 部署时如果加了这个参数,脚本就彻底静音 - 本地开发常用
composer install --no-dev,但忘了加--no-interaction,某些交互式命令会卡住整个流程 - 生产环境部署建议显式加
--no-dev --no-interaction,但一定不要漏掉--no-scripts,否则可能意外执行开发用脚本(比如启动 Swoole 服务) - 脚本里调用
php时,实际走的是 CLI 版 PHP,其memory_limit可能比 Web 版小很多,大操作(如迁移)容易崩,建议写成php -d memory_limit=-1 artisan migrate
自定义命令和自动钩子混用要注意什么?
自定义脚本(比如 "deploy:clear-cache")必须手动运行 composer run deploy:clear-cache,它不会自动触发。但你可以让它复用自动钩子逻辑:
- 用
@post-install-cmd引用已有脚本,避免重复写命令 - 不同脚本之间共享逻辑时,推荐把具体操作抽成独立 PHP 类方法(如
MyDeploy::clearCache()),再在scripts里调用,比堆 shell 命令更可控 - 如果脚本要操作文件权限或系统命令(如
chmod、icacls),Linux/macOS 和 Windows 写法完全不同,别试图一条命令通吃
真正容易被忽略的是:没有哪个配置能让脚本「每次 install 都稳稳执行」——post-install-cmd 本身就有触发盲区,想覆盖全部场景,得靠 post-update-cmd + post-autoload-dump 组合,或者干脆放弃自动,改用 CI/CD 流水线显式调用 composer run。











