scripts字段必须位于composer.json顶层,嵌套在extra、config或子目录中均无效;值支持字符串、数组、关联数组三种写法;生命周期事件名大小写敏感且须拼写准确;生产环境需显式启用脚本执行。

scripts字段必须写在composer.json顶层,不能嵌套
Composer只认项目根目录下composer.json最外层的scripts对象。写在extra、config或子目录的composer.json里,完全无效——脚本不会注册,composer run xxx会报Script xxx is not defined。
常见错误包括:
- 把
"scripts": {...}塞进"extra": {...}里 - 在vendor包自己的
composer.json中加scripts,指望它影响主项目 - 用IDE自动生成配置时,误套了多层JSON结构
正确位置示例:
{
"name": "my/app",
"type": "project",
"scripts": {
"hello": "echo 'Hi'"
}
}
脚本值支持字符串、数组、关联数组三种写法
值类型决定执行逻辑和容错能力,选错容易导致命令中途退出或静默失败。
- 单字符串(如
"clear-cache": "php artisan cache:clear"):适合简单命令,但任一环节出错就终止,不继续后续步骤 - 字符串数组(如
"clear-cache": ["php artisan cache:clear", "php artisan config:clear"]):顺序执行,前一条失败后默认仍会执行下一条(除非shell本身用&&连接) - 关联数组(如
"deploy:check": {"script": "php -r \"exit(extension_loaded('opcache') ? 0 : 1);\"", "description": "Check OPcache is enabled"}):可加description用于composer list展示,也方便CI中做条件判断
注意:@xxx语法只能用于数组内调用其他脚本,比如["@clear-cache", "@migrate"];单独字符串里写@clear-cache会报错。
生命周期事件名必须拼写准确,大小写敏感
Composer对事件名是硬匹配,post-install-cmd少个-、多一个s,或者写成PostInstallCmd,都不会触发。
- 常用有效事件只有四个真正可用于部署:
post-install-cmd、post-update-cmd、post-root-package-install、post-create-project-cmd -
pre-*类事件一旦失败,整个composer install流程中断,不建议放关键逻辑 -
post-autoload-dump只在dump-autoload时触发,跟文件复制、权限设置等部署动作无关,别指望它清缓存或改目录权限
验证是否生效:加--verbose运行composer install,看到Executing script ...日志才算绑定成功。
生产环境部署时scripts默认不执行,必须显式控制
CI/CD上线时composer install常“看起来成功”,但post-install-cmd根本没跑——因为生产模式默认禁用脚本,尤其当用了--no-dev或--no-scripts时。
- 安全起见,部署命令应显式启用:
composer install --no-dev --optimize-autoloader --no-interaction(默认仍执行post-*) - 若担心误触发开发脚本,改用
composer run-script deploy:post-install --no-dev,把关键逻辑拆成独立命名脚本 - 绝对避免在
scripts里写sudo chmod或chown——部署用户通常无权提权,且权限应由部署工具(如Ansible)统一管理
最容易被忽略的一点:本地测试用composer install能跑通,不代表上线就能跑;必须在目标环境用相同参数组合实测一次post-install-cmd是否真执行了。











