Composer自定义命令本质是scripts字段驱动的shell或PHP调用,需严格匹配脚本名、用--分隔参数、确保PHP类可自动加载,否则静默失败;优先用composer xxx触发,含冒号/连字符或冲突时须用composer run-script "xxx"。

Composer 自定义命令不是“注册后就能像 Laravel Artisan 那样自由传参”的 CLI 工具,它本质是 scripts 字段驱动的 shell 或 PHP 调用,所有行为都受限于 Composer 的执行模型——脚本名必须精确匹配、参数必须用 -- 显式分隔、PHP 回调必须可自动加载,漏掉任一环就会静默失败或报 Script not found。
如何正确触发自定义命令:用 composer xxx 还是 composer run-script xxx
优先用 composer xxx(如 composer test),它是 composer run-script xxx 的语法糖,且自动触发对应 pre-xxx/post-xxx 钩子;只有当脚本名含冒号(:)、连字符(-)或与 Composer 原生命令冲突(比如叫 install)时,才必须显式写 composer run-script "dev:start"(Windows 下双引号不能省)。
- 脚本名定义为
"test:unit"→ 必须用composer run-script "test:unit",composer test:unit会报错 - 脚本名是
"build"→composer build和composer run-script build效果一致 - 脚本名恰好是
"update"→composer update会执行原生命令,不是你的脚本,必须用composer run-script update
为什么加了 -- 才能传参给脚本
Composer 把 composer run xxx arg1 arg2 中的 arg1 arg2 当作自己的选项处理,根本不会透传;只有 composer run xxx -- arg1 arg2 才把 arg1 arg2 交给脚本进程。这是最常被忽略的细节,导致 PHPUnit 过滤失效、部署脚本收不到环境标识。
- 正确:
composer test -- --filter=TestFoo→phpunit收到--filter=TestFoo - 错误:
composer test --filter=TestFoo→ Composer 尝试解析--filter,报错或忽略 - PHP 回调里无法通过
$_SERVER['argv']取参,得靠环境变量(如COMPOSER_ARGS)或提前在 shell 层拼接
PHP 回调脚本为什么报 Class not found
Composer 执行 "MyClass::method" 时,只依赖 autoload 配置,不自动 require vendor/autoload.php;类未声明在 autoload 的 psr-4 / classmap 里,或没运行过 composer dump-autoload,就必然失败。
- 确保类文件路径已加入
autoload,例如:"autoload": { "psr-4": { "App\Scripts\": "scripts/" } } - 修改
autoload后必须运行composer dump-autoload,否则新类不可见 - 方法必须是
public static,且不能依赖未加载的第三方类(比如直接 newIlluminateSupportStr会失败) - 避免在回调里写
exit()或die(),会中断整个 Composer 流程
脚本里执行本地命令总报 command not found 怎么办
Composer 不扩展 $PATH,也不自动识别项目 bin 目录;写 phpunit 或 rm 时,系统只查全局 PATH,不会找 ./vendor/bin/phpunit。
- 统一用相对路径:
"test": "./vendor/bin/phpunit"或"test": "php ./vendor/bin/phpunit" - 跨平台清理目录别用
rm -rf,改用php -r "exec('rmdir /s /q build 2>nul || true');"(Windows)或php -r "exec('rm -rf build');"(Linux/macOS) - 想复用其他脚本?用
@clear-cache语法引用同scripts里的命令,比硬编码路径更可靠 - 脚本文件(如
scripts/deploy.php)需有执行权限(chmod +x)且带 shebang(#!/usr/bin/env php),否则./scripts/deploy.php会失败
真正麻烦的从来不是写命令,而是搞清 Composer 在哪一刻、以什么环境、用什么工作目录、是否加载了 autoload、又有没有把你的参数原样塞给子进程——这些细节不验证,脚本在本地跑通,CI 上八成挂掉。











