Composer scripts 是命令钩子与自定义命令机制,需 composer run-script 显式触发;post-* 钩子仅在对应命令执行且依赖实际安装时调用,vendor 存在且 lock 未变则跳过。

Composer 的 scripts 不是“运行脚本”的快捷方式,而是对命令生命周期的钩子绑定和自定义命令注册机制——直接执行 composer run-script xxx 才算真正触发,而像 post-install-cmd 这类事件钩子,只在对应 Composer 命令(如 composer install)完成时自动调用。
怎么写 scripts 配置才不会被忽略
Composer 读取 scripts 是严格按 JSON 格式解析的,常见失效原因不是语法错,而是键名拼写错误或嵌套层级不对:
-
scripts必须是根级字段,不能放在extra或config下 - 键名区分大小写:
post-update-cmd有效,post-update-CMD无效 - 值可以是字符串(单条命令)、字符串数组(顺序执行)、或关联数组(含
script和dev等字段)
{
"scripts": {
"test": "phpunit",
"build": [
"@clear-cache",
"php build.php"
],
"clear-cache": {
"script": "rm -rf var/cache/*",
"dev": true
}
}
}
自定义命令如何支持参数传递
Composer 默认不透传参数给 scripts 中的命令,必须显式用 -- 分隔:
-
composer run-script test -- --filter=MyTest→phpunit --filter=MyTest -
composer run-script build -- --env=prod→ 数组形式脚本不自动接收,需改用封装脚本或symfony/console工具处理参数 - 若脚本值是字符串,参数会原样追加;若是数组,只有最后一条命令能收到
--后的参数
为什么 post-install-cmd 没有执行
这不是 bug,是 Composer 的缓存与执行策略导致的:
- 当
vendor/已存在且composer.lock未变,composer install会跳过依赖安装,也跳过所有post-*钩子 -
解决方法:加
--no-cache强制刷新,或先composer install --dry-run看是否真触发了钩子 - 更可靠的做法是把关键逻辑移到
scripts自定义命令中,用composer run-script xxx显式调用
PHP 脚本里怎么获取当前 Composer 运行上下文
Composer 不提供全局上下文对象,但可通过环境变量和约定路径识别运行环境:
-
COMPOSER_DEV_MODE:值为1表示 dev 模式(composer install --no-dev时为0) -
COMPOSER_HOME:指向 Composer 全局配置目录 - 脚本中访问项目根目录应使用
getcwd(),而非假设在vendor/bin下运行 - 避免硬编码
./vendor/autoload.php—— 推荐用require __DIR__.'/../vendor/autoload.php';(脚本放bin/下时)
真正容易被忽略的是:scripts 中的 PHP 命令默认不继承 vendor/bin 到 $PATH,所以写 "test": "phpunit" 要求 phpunit 已全局安装或通过 bin-dir 配置软链到项目根目录;否则得写成 "test": "vendor/bin/phpunit"。










