Composer 自定义脚本需在 composer.json 的 scripts 对象中定义键值对,键为脚本名(如 dev:clear-cache),值为命令字符串或数组,支持 PHP 方法调用、shell 命令及 Composer 命令,多条命令建议用数组确保顺序,@开头的命令由 Composer 自动解析路径。

Composer 运行自定义脚本,本质是通过 scripts 字段在 composer.json 中声明命令,再用 composer run 或别名触发 —— 不需要写 shell wrapper,也不依赖外部 Makefile。
怎么在 composer.json 里定义一个可运行的脚本
在 composer.json 的 scripts 对象中添加键值对,key 是脚本名(如 post-install-cmd 或自定义名 dev:clear-cache),value 是要执行的命令字符串或数组。支持 PHP 函数调用、shell 命令、其他 Composer 命令。
示例:
"scripts": {
"dev:clear-cache": "php artisan cache:clear",
"test:unit": ["@php vendor/bin/phpunit --testsuite=unit"],
"pre-deploy": [
"@composer install --no-dev --optimize-autoloader",
"php -r \"file_put_contents('VERSION', trim(`git rev-parse HEAD`));\""
]
}
- 单条命令可写字符串,多条建议用数组,保证执行顺序
- 以
@开头的命令(如@composer、@php)会被 Composer 自动解析为当前项目环境下的可执行路径,避免硬编码./vendor/bin/composer - PHP 函数调用需写成
MyClass::myMethod形式,且类必须已加载(通常靠自动加载或autoload-dev)
运行脚本时为什么提示 “Script not found” 或直接静默退出
常见原因不是拼写错误,而是脚本名未被识别或未满足触发条件:
- 手动运行要用
composer run(Composer 2.2+),旧版本用composer run-script - 如果脚本名和 Composer 内置事件名一致(如
post-install-cmd),它只在对应生命周期自动触发,composer run不会默认找它 —— 必须显式声明为普通脚本名或加--dev参数(视配置而定) - 脚本定义在
require-dev包的composer.json里?不会被主项目读取,必须放在根composer.json - 使用了
symfony/console类命令但没加--no-ansi,某些 CI 环境下会因颜色控制符报错退出
PHP 回调函数怎么写才不会报 Class 'xxx' not found
Composer 执行 PHP 回调时,不会自动包含 vendor/autoload.php,除非你显式 require 或用 Composer 提供的自动加载机制。
- 推荐写法:
"scripts": {"check:env": "App\\Scripts\\CheckEnv::run"},并在autoload-dev中注册该命名空间 - 不推荐写法:
"scripts": {"check:env": "require 'scripts/check.php'; check_env();"}—— 路径易错,且无法利用 Composer 的 autoloader - 调试技巧:在回调方法开头加
var_dump(get_included_files()); die;,确认vendor/autoload.php是否已加载 - 如果回调依赖 Laravel 或 Symfony 容器,需先 boot 应用,不能直接调用 service —— 否则容器未初始化,
app()或$container->get()会失败
脚本里执行 shell 命令要注意哪些兼容性问题
跨平台(Linux/macOS/Windows)脚本最容易翻车的地方不在语法,而在路径分隔符、换行符、内置命令可用性:
-
rm -rf var/cache/*在 Windows 的 Git Bash 可能工作,但在原生 CMD 或 PowerShell 会失败 —— 改用php -r "array_map('unlink', glob('var/cache/*'));"更稳 - 路径拼接别用
/硬写,用dirname(__DIR__) . DIRECTORY_SEPARATOR . 'var'或__DIR__ . '/../../var'(PHP 8.1+ 支持str_ends_with()判断后缀,但路径构造仍建议用常量) -
composer run默认继承父 shell 环境变量,但某些 CI(如 GitHub Actions)默认不加载.bashrc,导致php或node命令找不到 —— 建议在脚本里用which php或command -v php检查,或直接写绝对路径(如/usr/bin/php)
真正麻烦的不是“怎么写”,而是“在哪执行”——脚本总是在 Composer 当前工作目录(即 composer.json 所在目录)下运行,cd 切换后若没重置,后续命令可能路径错乱。这点很容易被忽略。










