composer脚本不会自动运行,必须显式触发;scripts字段须位于composer.json顶层,键名即命令名、大小写敏感且调用时需完全一致;php脚本须手动require autoload.php,参数传递必须用--分隔。

Composer 脚本不会自动运行,必须显式触发;写进 composer.json 的 scripts 字段只是声明,不是注册命令,更不是开机自启服务。
脚本名怎么写、怎么调用才有效
你定义的键名就是命令名,大小写敏感、不能有空格,且必须和 composer run 后面跟的完全一致。
- 例如
"dev:setup": "php scripts/setup.php"→ 必须用composer run "dev:setup"(Windows 下双引号不可省) -
"post-update-cmd": ["App\Script::clearCache"]→ 运行composer update会自动触发,但composer run-script post-update-cmd也能手动跑 - 拼错成
dev-setup或dev_setup,或漏掉引号,都会静默失败或报Script not found -
scripts字段必须在composer.json顶层,和require同级;写在extra或缩进错位,Composer 直接忽略
PHP 脚本里 new 类报 Class not found 怎么办
Composer 执行脚本时默认不加载项目 autoloader,这不是 bug,是设计隔离——你得自己引入。
- 在 PHP 脚本第一行加:
require __DIR__ . '/../vendor/autoload.php';(注意:如果脚本在scripts/目录下,__DIR__指向的是该目录,不是项目根目录) - 别用
include 'vendor/autoload.php'(路径错误)、也别依赖__autoload()(已废弃) - 确保类已声明在
autoload或autoload-dev中,并执行过composer dump-autoload - 回调方法必须是
public static,且不能直接 new 未声明 autoload 的第三方类(比如new Illuminate\Support\Str会失败)
传参为什么收不到?-- 是关键分隔符
Composer 不解析参数,只负责透传;漏掉 --,参数就被它自己吃掉了,脚本完全收不到。
- 正确:
composer test -- --filter=TestFoo→phpunit收到--filter=TestFoo - 错误:
composer test --filter=TestFoo→ Composer 尝试解析--filter,报错或忽略 - PHP 脚本里别依赖
$_SERVER['argv'](索引偏移不可靠),优先读getenv('COMPOSER_ARGS')(Composer 4.0+ 提供) - 如果是
php scripts/deploy.php这种写法,参数会原样进$argv,但第一个元素是脚本路径,第二个才是你传的参数
为什么脚本看起来“没执行”?常见静默失效点
Composer 不校验 scripts 配置合法性,写错也不会提前报错,只在运行时挂掉或跳过。
- 脚本值是字符串但命令不存在(如写
"test": "phpunit"却没装phpunit),会报sh: phpunit: not found - 用了数组语法但 Composer 版本太低(
7+才支持多命令链式执行) - CI 环境默认加了
--no-scripts,或设置了COMPOSER_NO_INTERACTION=1导致钩子被跳过 - 权限问题:Linux/macOS 下脚本文件没加可执行位,又没显式写
php xxx.php,就会失败
最常被忽略的其实是工作目录和 autoloader 路径的组合逻辑——__DIR__ 指哪、vendor/autoload.php 在哪、脚本是否真被 Composer 启动(而不是你双击或 php xxx.php 直接跑),这三者错一个,Class not found 就必然出现。











