Composer scripts需严格遵循执行时机、环境变量、shell行为和返回值规范:必须注册在composer.json的scripts字段,键名合法;多命令用&&连接;PHP回调须静态且可自动加载;注意钩子触发条件、路径与环境变量陷阱;调试时用-v参数和set -x。
Composer 的 scripts 不是“写完就能跑”的黑盒,它依赖执行时机、环境变量、shell 行为和脚本返回值,稍不注意就会静默失败或行为错乱。
如何定义一个真正可触发的自定义脚本
脚本必须注册在 composer.json 的 scripts 字段下,且键名不能含空格或特殊字符(如 post-install-cmd 是合法钩子,但 build:dev server 会解析失败)。
实操建议:
- 普通命令脚本直接写字符串:
"ci-test": "phpunit --no-coverage" - 多命令用分号或
&&连接(注意 shell 兼容性):"dev-start": "composer install && php -S localhost:8000 -t public" - PHP 回调必须是静态方法,且类需能被自动加载:
"post-autoload-dump": ["My\\Script::onAutoload"] - 避免在脚本里写交互式命令(如
read),因为 Composer 默认以非交互模式运行
为什么 post-root-package-install 不起作用
这个钩子只在根项目(即你当前 composer.json 所在项目)首次安装时触发,且仅当该包未被作为依赖引入其他项目时才生效。CI 环境或 composer create-project 场景下容易误判触发条件。
常见错误现象:
- 本地
composer install没执行预期逻辑 → 实际触发的是post-install-cmd,不是post-root-package-install - 用
composer require xxx添加依赖后脚本没跑 → 它属于post-update-cmd范畴 - 脚本中用了
$_SERVER['argv']获取参数 → Composer 不透传 CLI 参数给钩子回调,要用$event->getArguments()(仅限 PHP 回调)
scripts 中的环境变量和路径陷阱
Composer 执行脚本时工作目录始终是项目根目录(即含 composer.json 的目录),但 $PATH 可能不含 vendor/bin,导致调用 php-cs-fixer 等二进制失败。