Composer scripts 是 shell 命令的快捷别名,本质为终端可执行命令映射;需注意 PATH 隔离、参数透传用 --、调用其他脚本须加 composer run、事件钩子有严格触发时机。

scripts字段本质是 shell 命令的快捷别名
Composer 的 scripts 不是新语言,也不是执行 PHP 逻辑的沙箱——它只是把键名映射成终端里能直接运行的命令行。你敲 composer run test,实际就是执行 vendor/bin/phpunit 或你写的任意 shell 指令。
常见错误现象:composer run build 报错 Command not found,但手动进项目目录跑 npm run build 没问题——这是因为 scripts 默认不继承当前 shell 的 PATH,也不加载 .bashrc/.zshrc。
- 所有命令都在项目根目录下执行,路径相对于此
- 环境变量默认只有系统级(如
HOME),不包含项目级配置(比如.env) - Windows 下若用 Git Bash,注意
cmd和bash解析差异:双引号、反斜杠、&&连接符行为不同 - 推荐统一用单引号包裹整个命令,避免 shell 提前解析变量或通配符
怎么让自定义脚本支持参数传递
Composer 本身不解析脚本参数,但通过 -- 可透传。比如定义 "ci:php": "php ./tests/run.php",调用时写 composer run ci:php -- --filter=testLogin,后面的内容会原样交给 php ./tests/run.php。
使用场景:CI 流水线中复用同一脚本但切换测试组、生成环境配置、动态指定日志级别。
-
--必须紧挨着命令名之后,不能写成composer run ci:php --filter=xxx(这样参数会被 composer 自己吃掉) - PHP 脚本内用
$argv接收,注意$argv[0]是脚本路径,第一个透传参数是$argv[1] - Node.js 脚本同理,用
process.argv.slice(2) - 避免在
scripts里写复杂条件判断——不如扔进独立脚本文件里做
scripts里调用其他scripts要加run子命令
想在一个 script 里复用另一个,不能直接写 "post-install-cmd": "dump-autoload",这会报 Command "dump-autoload" is not defined。必须显式调用 composer run 或 composer 原生命令。
性能影响:嵌套 composer run 会多启一个 Composer 进程,开销不大,但循环调用可能卡住(比如 A 调 B,B 又调 A)。
- 调内置命令:用
"post-install-cmd": "composer dump-autoload -o"(注意不是composer run dump-autoload) - 调自定义 script:用
"build": "composer run lint && composer run test" - 不要省略
composer前缀——否则会被当成本地 shell 命令找 - 如果脚本里用了
exit 1,记得加set -e或检查返回值,否则失败后仍继续执行后续命令
event-triggered scripts容易忽略执行时机和退出码
像 pre-autoload-dump、post-create-project-cmd 这类钩子,不是“每次 composer run 就触发”,而是严格绑定到对应生命周期事件。比如 post-install-cmd 只在 composer install 成功后运行,且只在首次安装或 lock 文件变更时触发。
容易踩的坑:把构建逻辑全塞进 post-install-cmd,结果 CI 每次拉代码都重跑 webpack,浪费时间;或者脚本出错但没设 set -e,导致后续步骤在脏环境中执行。
- 事件脚本默认继承上一命令的退出码:若
composer install失败,post-install-cmd不会执行 - 若需强制运行(比如清理临时文件),改用
post-install-cmd+"always": true(需 Composer 2.5+) - 调试时加
echo "running post-install-cmd at $(date)",比猜更可靠 - 别在
pre-autoload-dump里修改composer.json——此时 autoloader 还没重建,可能导致类找不到
事情说清了就结束










