自定义脚本不会自动运行,必须通过 composer run 或生命周期钩子(如 post-install-cmd)触发;写进 composer.json 的 scripts 字段只是声明,不是注册命令。

直接结论:自定义脚本不会自动运行,必须通过 composer run 或生命周期钩子(如 post-install-cmd)触发;写进 composer.json 的 scripts 字段只是声明,不是注册命令。
脚本名怎么写、怎么调用才有效
你定义的键名就是命令名,大小写敏感、不能有空格,且必须和 composer run 后面跟的完全一致。例如:
"scripts": {
"dev:setup": "php scripts/setup.php",
"post-update-cmd": ["My\Script::clearCache"]
}
对应调用方式是:
-
composer run "dev:setup"(注意双引号,Windows 必须加) -
composer run-script "post-update-cmd"(不推荐,composer run更统一) - 或直接
composer update→ 自动触发post-update-cmd
常见失效原因:
- 脚本名拼错,比如写成
dev-setup却调用composer run dev_setup - 没加引号,Windows 下
composer run dev:setup会报错或静默失败 -
scripts字段缩进到require或其他块里,导致 Composer 根本读不到
PHP 回调脚本为什么报 Class not found
Composer 执行 MyScript::method 时,不会自动加载项目 autoloader,所以类找不到不是配置漏了,而是执行环境没引入。
必须确保两点:
- 类已声明在
autoload或autoload-dev中,并执行过composer dump-autoload - 方法是
public static,且参数签名兼容(可选接收$event对象)
最稳妥的做法是在 PHP 脚本开头显式引入:
require __DIR__ . '/vendor/autoload.php';
别依赖 __autoload 或手动 include 单个文件——容易漏依赖,也绕不开 Composer 的自动加载机制。
传参和跨平台执行要注意什么
想把 --filter=TestFoo 传给 PHPUnit,必须用 -- 显式分隔:
- ✅ 正确:
composer run test -- --filter=TestFoo - ❌ 错误:
composer run test --filter=TestFoo(参数被 Composer 拦截)
脚本内容也要适配:
- Shell 命令建议用数组格式:
["vendor/bin/phpunit", "--testsuite=unit"],避免空格/引号解析问题 - Windows 下别硬写
php.exe,用@php或直接php,Composer 会自动补全 - 路径一律用相对路径:
./vendor/bin/phpcs,不写phpcs(依赖 PATH 不可靠)
环境变量如 $PATH 默认不继承,.env 文件也不会自动加载,需在脚本内手动处理。
钩子脚本该放哪、什么时候跑
post-install-cmd 和 post-update-cmd 不是“装完/更新完就跑”,它们绑定的是具体命令:
-
composer install→ 触发post-install-cmd -
composer update或composer require xxx→ 只触发post-update-cmd,不触发post-install-cmd - 与自动加载相关的操作(如刷新缓存、生成映射),优先用
post-autoload-dump,它更精准、更稳定
多个脚本共用一个钩子时,用数组写法:
"post-autoload-dump": [ "My\Cache::clear", "php artisan config:clear" ]
任意一个返回非零退出码,后续同钩子里的脚本都会跳过——这点容易被忽略,调试时加 -v 看实际退出码。











