Composer scripts需通过composer <name>或composer run-script <name>显式执行,非自动运行;脚本名不可与内置命令冲突;推荐用PHP脚本替代shell命令以提升跨平台性、错误处理和依赖加载能力。

scripts 里定义的命令到底怎么执行
Composer 的 scripts 不是“写完就能直接运行”的 shell 命令,它本质是一组由 Composer 解析、按规则触发的钩子或别名。你得用 composer run-script <name> 或更常用的 composer <name>(前提是名字不是 Composer 内置命令)来调用。
比如你在 composer.json 里写了:
"scripts": {
"hello": "echo 'Hello from Composer!'"
}
那就必须运行 composer hello ——不是 ./hello,也不是 sh hello,更不会自动在 install 时执行,除非你显式把它挂到 post-install-cmd 这类生命周期事件上。
- 脚本名不能和 Composer 内置命令冲突(如
install、update),否则会被覆盖,且无警告 - 多个命令用分号连接(
"cmd1; cmd2")在 Windows 上可能失败,建议改用symfony/console封装成 PHP 脚本 - 环境变量默认不继承(如
$PATH可能不含项目 bin/),需要显式补全或用php -r启动
PHP 脚本比 shell 命令更可靠
直接写 shell 命令看似简单,但跨平台兼容性差、错误难捕获、参数解析弱。真正稳定的自定义逻辑应该写成 PHP 文件,然后在 scripts 中调用。
例如创建 scripts/build.php:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
#!/usr/bin/env php
<?php
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
die("Run 'composer install' first.\n");
}
require __DIR__ . '/vendor/autoload.php';
echo "Building assets...\n";
// 实际逻辑:调用 webpack、生成版本号等
然后在 composer.json 中注册:
"scripts": {
"build": "php scripts/build.php"
}
- PHP 脚本可直接 require 项目依赖,无需担心 autoloader 加载时机
- 能用
try/catch捕获异常,返回非零退出码让 Composer 中断后续流程 - 参数传递更安全:
composer build -- --env=prod会透传给 PHP 脚本的$argv
常见报错:Class not found 或 command not found
这两个错误最常出现在刚写完脚本却执行失败时:
-
Class not found:说明脚本里用了未 autoload 的类,比如直接 new 了一个没声明命名空间或没加use的类 —— 记住,scripts不自动包含你的应用 autoloader,必须手动require -
command not found:多因路径问题。比如写"lint": "phpcs",但phpcs没装在全局,也没放在vendor/bin/下。应改用"lint": "vendor/bin/phpcs"或确保vendor/bin在$PATH中 - Windows 用户还会遇到
'php' is not recognized—— 因为 Composer 默认不读系统 PATH,需写绝对路径或改用php "%~dp0\vendor\bin\phpcs"(批处理语法)
什么时候该用 event hook 而不是普通 script
如果你希望某个操作“自动发生”,比如每次 composer install 后生成配置文件,就别只定义一个 gen-config 脚本,而要挂到对应事件上:
"scripts": {
"post-install-cmd": [
"@php scripts/gen-config.php"
]
}
注意几点:
- 事件名是固定字符串(如
pre-autoload-dump、post-update-cmd),拼错就静默失效 - 数组形式支持多个命令,用
@php可复用当前 PHP 解释器(避免硬编码php) - 事件脚本默认不接收用户参数,所以不适合交互式操作;若需区分环境,应从
$_SERVER['COMPOSER_DEV_MODE']或环境变量读取
真正麻烦的是调试——事件触发没有回显,出错只会显示 “Script ... handling the ... event returned with error code 1”,得加 echo 或日志才能定位。建议开发期先手动跑一遍对应脚本,确认逻辑没问题再挂事件。

















