composer run-script 仅执行 composer.json 中 "scripts" 下严格定义的脚本名,不支持模糊匹配或自动补全;参数传递需用 -- 分隔,且脚本执行时 cwd 为 composer.json 所在目录。

直接说结论: composer run-script 不是执行任意命令的快捷方式,它只调用 composer.json 里 "scripts" 下定义的脚本名——拼错、没定义、没加引号,全都会报错或静默失败。
脚本名必须严格匹配 composer.json 中的键
Composer 不会模糊匹配,也不会自动补全。比如你写了 "scripts": { "dev-start": "php -S localhost:8000" },那必须用 composer run-script dev-start,写成 composer run-script dev_start 或 composer run-script start 都会提示 Script not found。
常见错误现象:Script not found: dev-start(但明明写了)——大概率是大小写不一致、多空格、用了中文标点,或者脚本名在 composer.json 里被意外注释掉了。
- 检查是否用了双引号包裹脚本名:
composer run-script "dev-start"(Windows 命令行尤其需要) - 确认
composer.json中"scripts"是顶层字段,没缩进到"require"或其他块里 - 运行
composer run-script --list查看当前可用脚本,这是最可靠的验证方式
run-script 的参数传递规则很反直觉
想传参给脚本?不能直接跟在后面写 composer run-script test -- --filter=FooTest。中间那个 -- 是分隔符,前面是 Composer 自己的选项,后面才是传给脚本的参数。
使用场景:跑 PHPUnit 时过滤测试用例、传环境变量给部署脚本。
- 正确写法:
composer run-script test -- --filter=FooTest - 错误写法:
composer run-script test --filter=FooTest(这个--filter会被 Composer 当作自己的参数,报错或忽略) - 如果脚本本身是 shell 命令,注意引号嵌套:比如
"php test.php \"--verbose\"",否则空格和特殊字符会断开
别把 run-script 当成 npm run 的平替
Composer 脚本默认不继承当前 shell 环境变量(比如 $PATH),也不自动加载项目根目录下的 .env。很多“本地能跑、CI 报 command not found”的问题都出在这儿。
性能 / 兼容性影响:脚本每次执行都会重新加载 Composer 的 autoloader,频繁调用低效脚本(比如重复 composer dump-autoload)会明显拖慢流程。
- 路径相关命令务必用相对路径:写
"./vendor/bin/phpunit",别写"phpunit"(除非你确定 CI 环境 PATH 已配好) - 需要环境变量?显式导出:
"export APP_ENV=testing && php artisan test",或改用phpdotenv在脚本里加载 - 避免在脚本里反复执行
composer install—— 它不是轻量操作,应由 CI 流程统一管控
真正容易被忽略的是:脚本执行时的当前工作目录(CWD)是 composer.json 所在目录,不是你运行命令时所在的子目录。如果你在 ./tests 下执行 composer run-script test,脚本里的 ./src 依然从项目根开始算——这点和 npm 行为一致,但很多人调试时会下意识切错路径。










