scripts 钩子需在 composer.json 顶层 scripts 对象中,使用预定义小写事件名(如 pre-install-cmd);值可为字符串、数组或对象;php 类方法调用须显式引入 vendor/autoload.php;命令失败会中断执行,建议用 php 脚本保障跨环境一致性。

composer.json 里 scripts 怎么写才生效
脚本钩子必须写在 composer.json 的 scripts 字段下,且顶层键名是预定义的事件名(比如 pre-install-cmd),不是随便起的。Composer 不会执行拼错、大小写不符或未注册的钩子名。
- 确保
composer.json根层级有"scripts": { ... }对象,不是嵌套在其他字段里 - 事件名严格区分大小写:
pre-install-cmd有效,pre-install-CMD或preinstall-cmd无效 - 值可以是字符串(单条命令)、字符串数组(顺序执行)或对象(带
script和event字段的完整配置) - 修改后无需额外注册,运行
composer install等对应命令时自动触发
pre-install-cmd 和 post-update-cmd 的典型用途差异
pre-install-cmd 在 composer install 解析依赖前执行,适合做环境检查、清理缓存或校验配置;post-update-cmd 在 composer update 完成依赖安装后触发,更适合生成 autoload、构建前端资源或刷新路由缓存。
-
pre-install-cmd:常用于php -v检查 PHP 版本、test -f .env确认环境文件存在 -
post-update-cmd:常见于php artisan optimize:clear(Laravel)、composer dump-autoload或调用 Webpack 构建 - 注意:
post-install-cmd只在首次install触发,不是每次update;想覆盖两者行为,得同时写post-install-cmd和post-update-cmd
脚本里调用 PHP 类方法要加 vendor/autoload.php
直接写 "MyScript::run" 这类静态方法调用时,Composer 默认不会自动加载你的类——它只负责执行命令,不接管 PHP 自动加载上下文。
- 必须显式引入 autoloader:
"php -r \"require 'vendor/autoload.php'; MyScript::run();\"" - 更稳妥的做法是封装成独立可执行脚本(如
bin/deploy.php),然后在 scripts 中写"php bin/deploy.php" - 别依赖当前工作目录是项目根目录——用
__DIR__或getcwd()显式处理路径,否则 CI 环境容易失败 - 错误现象示例:
PHP Fatal error: Class 'MyScript' not found,就是没加载 autoload 导致的
调试 scripts 钩子为什么没运行
最常见原因是命令退出码非 0:只要脚本中任意一条命令返回非零状态,Composer 就中断后续流程,并可能静默跳过后续钩子(尤其 pre-* 类型)。
- 加
-v参数看详细日志:composer install -v,能明确看到 “Executing script …” 和返回码 - Shell 命令记得加
set -e或检查 $?,避免部分失败被忽略(比如cp找不到源文件却继续往下) - Windows 用户注意:CMD 不支持单引号包裹多命令,得改用双引号 +
^换行,或直接用 PowerShell 脚本 - CI 环境中
composer install --no-interaction仍会触发 scripts,但交互式提示(如 readline)会卡住,务必改成非交互模式










