scripts 必须位于 composer.json 根层级,键名为命令名(如 "test"),值为字符串或数组形式的 shell 命令或 "Class::method" 调用,且类需在 autoload 中声明并执行 dump-autoload。

composer.json 里 scripts 怎么写才生效
Composer 自定义命令本质是靠 scripts 字段触发的 shell 命令或 PHP 调用,不是“注册命令”那种 CLI 工具。写错位置或格式,composer run 就找不到。
-
scripts必须在composer.json的根层级,不能嵌套在extra或其他字段里 - 键名就是你后面要运行的命令名(比如
"post-install-cmd"是钩子,"dev-start"是手动命令),值可以是字符串(单条命令)或数组(多条顺序执行) - 如果值是 PHP 调用,格式必须是
"MyClass::myMethod",且类必须能被 Composer 自动加载(即已声明在autoload中) - 别在脚本里写
exit或直接die()—— Composer 进程会中断,后续钩子或依赖安装可能卡住
示例:
"scripts": {
"test": ["phpunit --colors=always", "phpstan analyse src/"],
"fix": "php-cs-fixer fix --dry-run=false"
}
为什么 composer run xxx 报错 “Script not found”
这是最常踩的坑:Composer 8.2+ 才默认支持 composer run(以前叫 composer run-script),老版本直接报错或静默忽略。
- 先确认版本:
composer --version,低于 2.2 的建议升级(composer self-update) -
composer run xxx只匹配scripts里的顶层键名,不支持路径、斜杠或点号,比如"ci:build"是合法键名,但运行时得写composer run "ci:build"(带引号,因为冒号在 shell 里有特殊含义) - 别把脚本名和钩子名混淆:
pre-autoload-dump是自动触发的钩子,不能用composer run pre-autoload-dump手动调;它只响应install/update - Windows 用户注意:脚本里用
php而不是php.exe,Composer 会自动补全,硬写反而跨平台失效
scripts 里怎么安全调用 PHP 类方法
直接写 "AppScriptsDeploy::fire" 看似简单,但容易因自动加载失败而报 Class not found —— Composer 不保证在所有阶段都已生成完整 autoloader。
- 确保对应类文件已声明在
composer.json的autoload(如"psr-4": {"App\Scripts\": "src/Scripts/"}),然后执行composer dump-autoload - 方法必须是
public static,非静态方法或构造依赖会失败 - 参数传入受限:只能通过
$argv或环境变量,不能直接传参给静态方法;想传参就改用 shell 包装,例如:"deploy": "php scripts/deploy.php --env=prod" - 别在脚本里做耗时操作(如下载、编译),它会阻塞整个
composer install流程;异步任务建议拆成独立命令,由人手动触发
钩子(hook)和手动命令混用时的执行顺序陷阱
很多人把清理缓存、生成配置等逻辑全堆进 post-install-cmd,结果本地开发没问题,CI 上却失败 —— 因为钩子执行时机依赖当前命令上下文,不是绝对可靠。
-
post-install-cmd和post-update-cmd只在install或update成功后触发,如果某次只运行composer require foo/bar,它属于update,会触发后者;但composer run dev-start完全不触发任何钩子 - 钩子内不要假设
vendor/autoload.php已加载完成:某些极端情况(如部分失败后重试),autoloader 可能还没写入磁盘 - 推荐分层:钩子只做必要基础设施准备(如生成
bootstrap.php),具体业务逻辑收归手动命令(如composer run build-assets),谁需要谁显式运行
真正难处理的是跨平台路径拼接、PHP 版本差异导致的函数不可用(比如 proc_open 在某些共享主机被禁)、以及脚本输出被 Composer 截断(加 --no-ansi 时颜色控制符变乱码)——这些没标准解法,得看具体场景扣日志。


















