composer.json 的 scripts 字段需用 post-install-cmd 和 post-update-cmd 钩子,以数组形式写入 "@php vendor/bin/phpunit --no-coverage" 等命令;注意避免 --no-scripts、确保路径权限有效,并可通过 || true 或封装脚本使测试失败不中断安装。

composer.json 的 scripts 字段怎么写
Composer 允许你在安装或更新依赖后自动执行命令,关键在于 scripts 字段中的 post-install-cmd 和 post-update-cmd 钩子。这两个钩子会在 composer install 或 composer update 成功完成后触发。
你不需要额外插件,只要确保 phpunit 可执行(通常通过 vendor/bin/phpunit)且已声明为 require-dev 依赖即可。
- 把 PHPUnit 命令直接写进
scripts,例如:"post-install-cmd": ["@php vendor/bin/phpunit --no-coverage"] - 如果项目根目录有
phpunit.xml或phpunit.xml.dist,vendor/bin/phpunit会自动读取配置,无需重复指定参数 - 避免写成
"post-install-cmd": "phpunit"—— 这会尝试调用全局 phpunit,可能版本不匹配或根本不存在 - 多个命令可用数组形式,每项独立执行;单条命令可写字符串,但推荐统一用数组格式,更清晰
为什么 post-install-cmd 不总如预期运行
默认情况下,composer install 在 CI 环境或使用 --no-scripts 标志时,会跳过所有 scripts。这是常见“没反应”的原因。
- 本地测试时,确认没加
--no-scripts;CI 脚本里常默认禁用,需显式启用:composer install --no-interaction不等于禁用脚本,但--no-scripts会彻底跳过 - 若依赖已全部存在且
composer.lock未变,install实际走的是“从 lock 安装”,仍会触发post-install-cmd;但update才真正刷新依赖,对应钩子是post-update-cmd - 脚本执行失败(比如测试挂了)会导致整个
composer install返回非零退出码——这在 CI 中可能被误认为安装失败,需根据场景决定是否容忍测试失败
如何让测试失败时不中断安装流程
Composer 默认将 script 的退出码透传给主命令。若希望“安装照常完成,测试失败只报错不中断”,得靠 shell 层级处理。
立即学习“PHP免费学习笔记(深入)”;
- Linux/macOS 下可用
|| true:例如"post-install-cmd": ["sh -c 'vendor/bin/phpunit || true'"] - Windows CMD 不支持
||简写,建议统一用sh或改用 cross-platform 工具如roave/composer-dev-bundle(但会增加复杂度) - 更稳妥的做法是封装为独立脚本文件(如
bin/run-tests.php),在其中捕获异常、记录结果、始终返回 0 —— 这样可控性最强,也方便加日志或条件判断
{
"require-dev": {
"phpunit/phpunit": "^10.5"
},
"scripts": {
"post-install-cmd": [
"@php vendor/bin/phpunit --no-coverage"
],
"post-update-cmd": [
"@php vendor/bin/phpunit --no-coverage"
]
}
}
实际生效的关键不在语法多精巧,而在两点:确认钩子没被禁用,以及 PHPUnit 路径和权限在目标环境真实可用。尤其在 Docker 或 CI runner 中,vendor/bin/phpunit 可能因 shebang 或 PHP 版本不一致而无法执行——这时候直接调用 php vendor/phpunit/phpunit/phpunit 反而更可靠。










