scripts字段需规范编写:用sh -c包裹多命令、加set -e确保错误中止、避免硬编码路径、脚本名用下划线或驼峰、钩子仅用于轻量幂等操作,复杂逻辑移至外部文件,CI与本地脚本分离,并注意环境变量、工作目录及退出码传递。

composer.json 里的 scripts 字段怎么写才不踩坑
脚本不是随便塞进 scripts 就能跑通的,尤其在团队里,路径、执行顺序、错误传播都容易出问题。最常见的是 cd frontend && npm install 在 Windows 上失败,或脚本里没加 set -e 导致某步出错却继续往下执行。
实操建议:
- 统一用
sh -c包裹多命令,避免 shell 差异:"sh -c 'cd frontend && npm ci && npm run build'" - 所有脚本开头加
set -e(bash/zsh)或cmd /c exit /b 1 &&(Windows 兼容写法),确保任一命令失败即中止 - 避免硬编码路径,优先用
$COMPOSER_BIN_DIR或相对路径(如./bin/xxx),不要写/var/www/project/bin/xxx - 脚本名别用连字符(
post-install-cmd是内置钩子,自定义脚本用下划线或驼峰,比如setup-dev、run-tests)
哪些脚本该用钩子(post-install-cmd),哪些该手动触发
钩子是自动执行的,一旦写错就可能阻断 composer install 流程——比如数据库迁移失败导致整个安装卡住。它适合「必须伴随依赖变更发生的动作」,不适合「可选操作」或「耗时长/需人工确认」的任务。
判断依据:
-
post-install-cmd和post-update-cmd只用于轻量、幂等、无副作用的操作:如清缓存(php artisan cache:clear)、生成 classmap(composer dump-autoload --optimize) - 数据库迁移、前端构建、代码检查这类操作,应拆成独立脚本(如
dev-migrate、build-frontend),由人显式运行composer run dev-migrate,或在 CI 中按需调用 - 如果必须用钩子调前端构建,务必加
--no-interaction和超时控制(timeout 300 -- npm ci),防止卡死
团队协作时 scripts 怎么保持一致且可维护
脚本写在 composer.json 里,看似简单,但多人修改容易冲突、重复、语义混乱。比如 A 提交了 test,B 又加了个 run-tests,C 改了 test 却没通知别人。
关键做法:
- 所有脚本名加前缀,区分用途:
dev:setup、ci:lint、prod:deploy-check,避免命名歧义 - 每个脚本末尾加注释说明用途和前提条件,用
//或#(JSON 不支持注释?那就写在 README.md 的「开发脚本速查表」里) - 复杂逻辑不要塞进 JSON 字符串,改用外部可执行文件:
"dev:setup": "php bin/setup.php",把业务逻辑移出配置 - CI 脚本必须和本地脚本分离,例如
ci:test显式指定--no-coverage,而dev:test默认带 coverage;避免「CI 能过,本地跑不通」
composer run-script 执行时的环境与权限陷阱
很多人以为 composer run 就是简单起个 shell,其实它会重置部分环境变量,且默认不继承当前 shell 的 PATH —— 导致 phpunit 找不到,或 node 版本不对。
排查要点:
- 执行前先确认
which php和composer run -v xxx输出的 PHP 路径是否一致;不一致就用绝对路径,比如/usr/bin/env php - Node.js 相关脚本,优先用
npx而非全局npm,避免团队成员 Node 版本差异影响:"build:js": "npx cross-env NODE_ENV=production webpack --config webpack.prod.js" - 涉及文件操作的脚本(如生成配置、写日志),注意工作目录:Composer 默认在
composer.json所在目录执行,不是当前 shell 路径 - Windows 用户遇到权限拒绝,大概率是 PowerShell 策略限制,临时允许:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
实际协作中最容易被忽略的,是脚本的「退出码传递」——比如一个钩子里调了 phpunit,但没把它的退出码透传出去,结果测试失败了 composer install 却显示成功。这会让 CI 误判,也掩盖真实问题。


















