Composer不支持直接composer hello调用自定义脚本,必须用composer run hello;脚本须定义在composer.json根级scripts字段,值为字符串或数组,路径相对项目根目录。

直接用 composer run 加脚本名,不是 composer xxx —— 这是最常见的误操作。
为什么 composer hello 会报错?
Composer 不支持任意命名的“子命令”语法(比如 composer hello),除非你定义的是内置事件名(如 post-install-cmd)或用了旧版兼容模式(已弃用)。新写法必须显式调用 run 子命令:
-
composer run hello✅ 正确(hello是你在scripts里自定义的名字) -
composer hello❌ 报错:Command "hello" is not defined -
composer run-script hello⚠️ 兼容旧写法,但官方文档已推荐run
composer.json 里 scripts 怎么写才生效?
必须满足三个硬性条件,缺一不可:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 字段位置:必须在
composer.json根对象下,直接写"scripts": { ... },不能嵌套进extra或其他字段 - 值类型:每个脚本值必须是字符串或字符串数组,例如
"clear": "php artisan cache:clear"或"dev:setup": ["@php scripts/init.php", "npm install"] - 路径基准:所有命令里的路径(如
scripts/init.php)都是相对于项目根目录,不是相对于vendor/或当前 shell 路径
执行 PHP 脚本时容易漏掉的关键点
用 @php scripts/migrate.php 这类写法看似简洁,但实际运行常失败,原因很具体:
-
@php只是让 Composer 用它自己的 PHP 可执行文件,不解决自动加载问题 —— 你的脚本里仍需手动require 'vendor/autoload.php'; - PHP 脚本内不能依赖
__DIR__直接拼路径,因为 Composer 执行时工作目录是项目根,但__DIR__指向的是脚本所在目录;建议统一用dirname(__DIR__)回到根再拼 - 参数传递不自动:比如
composer run deploy -- --env=prod,脚本本身得用$argv或$_SERVER['argv']解析,Composer 不帮你映射成函数参数
什么时候该用事件钩子而不是 run?
如果你希望某些操作「自动发生」,而不是每次都要手动敲命令,就该用生命周期事件:
-
post-install-cmd和post-update-cmd最常用,适合数据库迁移、缓存清理、密钥生成等部署后必做动作 - 注意:这些钩子只在对应 Composer 命令成功执行后触发;一旦脚本返回非零退出码(比如迁移失败),整个
composer install就会中断 —— 这不是 bug,是设计用来保障 CI 安全的 - 别把开发专用命令(如
serve)塞进事件钩子里,否则别人composer install会被强制起服务,干扰正常流程
最常被忽略的一点:脚本执行失败时的退出码是否符合预期。很多团队写了 post-update-cmd 迁移,却没加 --no-interaction 或 --force,导致生产环境卡在交互确认上;或者 PHP 脚本里没做异常捕获,错误静默吞掉,最后状态码是 0,CI 以为成功了——这类问题只能靠日志和明确的 exit code 检查来暴露。

















