composer怎么运行自定义指令_composer自定义scripts脚本

2次阅读

composer 的 scripts 是命令别名与生命周期钩子的组合,键名成为可执行命令,路径须基于项目根目录,推荐用 vendor/bin/xxx 和 php 脚本透传参数,失败默认不中断流程。

composer怎么运行自定义指令_composer自定义scripts脚本

怎么在 composer.json 里定义自定义 script

Composer 的 scripts 是个配置块,不是插件也不是命令行工具——它本质是「命令别名 + 生命周期钩子」的组合。你写进去的每个键,都会变成一个可执行的 composer run-script xxx 或直接 composer xxx(如果名字不冲突)。

常见错误是把路径写成相对当前目录,比如 "php ./bin/mytool.php";实际运行时工作目录是项目根(即 composer.json 所在目录),但用户可能在子目录下执行 composer xxx,所以路径必须写死或用 $COMPOSER_HOME 等环境变量兜底。

  • 脚本名不能含空格、斜杠,建议全小写+下划线,比如 post-install-dev 合法,my:command 会报错
  • 支持数组形式写多条命令,按顺序执行,遇到非零退出码就中断:["php -v", "php ./scripts/check.php"]
  • 如果想让脚本在 composer install 后自动跑,得用 post-install-cmd 这类预定义钩子名,而不是随便起名

为什么有些 script 执行后没反应或报 command not found

最常踩的坑是:脚本里调用了未安装或未加入 $PATH 的二进制文件。比如写了 "phpunit",但本地没全局装 PHPUnit,也没通过 vendor/bin/phpunit 显式调用。

另一个隐形问题是 windowsunix 的 shell 差异:Windows 默认用 cmd.exe,不认单引号、反引号、管道符;而 Composer 在 Windows 上默认不启用 bash 兼容模式。

  • 优先用 vendor/bin/xxx 而不是裸命令,比如 "vendor/bin/phpcs --standard=PSR12 src/"
  • 避免 &&|$() 这类 shell 特性,改用 PHP 脚本封装逻辑
  • 检查 composer config --list | grep bin-dir,确认 bin-dir 没被设成空或非法路径

如何让 script 支持传参(比如 composer build -- --env=prod

Composer 原生不解析 script 后面的参数,-- 后的内容会被丢弃,除非你手动处理。真正能透传参数的方式只有一种:用 php 调用自定义 PHP 文件,并在脚本里读取 $argv

比如定义:"build": "php scripts/build.php",然后在 scripts/build.php 里用 array_slice($argv, 1) 拿到所有参数。

  • composer run-script build -- --env=prod 中的 --env=prod 不会自动变成 $argv 的一部分,必须靠 PHP 脚本自己解析
  • 不要试图用 exec()shell_exec() 去拼接命令,容易被注入;用 proc_open() 更安全
  • 如果只是简单开关,可用环境变量替代:运行前设 ENV=prod composer build,脚本里读 getenv('ENV')

script 执行失败时为什么有时不中断 install/update

因为 Composer 默认把 script 当作“尽力而为”操作。除非你显式设置了 "process-timeout": 0 或在 script 命令末尾加 || exit 1,否则一个 post-update-cmd 里某条命令失败,整个流程仍会继续。

更麻烦的是,某些脚本(如生成 autoload 文件)失败后,后续依赖可能加载失败,但 Composer 不会回滚已安装的包。

  • 关键脚本建议加兜底判断:比如 "php -m | grep -q xdebug || (echo 'xdebug missing' >&2; exit 1)"
  • CI 环境中务必加 --no-interaction --no-ansi,避免因交互式提示卡住
  • 调试时用 composer run-script xxx -v 查看完整命令和 stderr 输出,别只看返回码

真正难搞的不是写 script,而是搞清它在哪种上下文里跑、PATH 是什么、当前 uid 有没有权限访问目标路径——这些不会报错,只会静默失败。

text=ZqhQzanResources