Composer的scripts不会自动执行,仅在composer install/update或手动run-script时触发;需确认触发方式、脚本名拼写、权限及autoload显式引入。

scripts 里写的命令为什么没执行
Composer 的 scripts 不是写完就自动跑的,它只在特定钩子触发时运行,比如 composer install、composer update 或手动调用 composer run-script。常见错误是改完 composer.json 后直接执行脚本文件,结果报错“command not found”——因为那只是配置,不是可执行入口。
- 确认是否用了正确的触发方式:
composer run-script <script-name>(注意不是php composer.phar <script-name>) - 检查脚本名是否拼写一致,大小写敏感,且没被
scripts-descriptions覆盖掉 - 如果脚本是 PHP 文件,确保开头有可执行权限(Linux/macOS)或用了
php显式调用,例如:"post-install-cmd": "php scripts/post-install.php" - 避免在脚本中依赖未安装的全局二进制(如
node、npm),建议用vendor/bin/xxx或加which xxx判断
怎么让自定义脚本访问 Composer 的 autoload
默认情况下,scripts 执行环境不自动加载项目 autoloader,所以直接 new 一个类会报 Class not found。这不是 Composer 故意设障,而是为了隔离执行上下文——你得自己显式引入。
- 最稳妥的方式:在脚本开头 require
vendor/autoload.php,比如 PHP 脚本第一行写require __DIR__ . '/vendor/autoload.php'; - 如果脚本是命令行工具(如
bin/mytool),建议把它注册为bin目录下的可执行文件,并在composer.json中声明"bin": ["bin/mytool"],这样composer install会自动软链到vendor/bin - 别依赖
__autoload或手动 include 单个文件,容易漏依赖或版本错乱
scripts 钩子执行顺序和失败行为
Composer 按固定顺序触发钩子,比如 pre-install-cmd → install-cmd → post-install-cmd;但关键点在于:任何一个脚本返回非零退出码,后续同阶段钩子都会跳过,整个命令也可能中断(取决于 --no-scripts 是否启用)。
-
pre-*钩子失败会导致主命令中止;post-*失败默认不中断主流程,但会打印警告——除非加了--no-dev或设置了COMPOSER_NO_INTERACTION=1等环境变量影响判断逻辑 - 多个脚本可以共用一个钩子,用数组形式写:
"post-update-cmd": ["MyScript::clearCache", "php artisan optimize:clear"] - 调试时加
-v参数看详细输出,尤其注意 “Script … handling the … event returned with error code …” 这类提示
Windows 下脚本路径和换行符问题
Windows 用户常遇到 bash: ./scripts/deploy.sh: /bin/bash^M: bad interpreter,本质是 CRLF 换行符导致 shell 解析失败;或者 PHP 脚本里用 __DIR__ 拼路径,在 Windows 下反斜杠没被正确转义。
- Shell 脚本务必保存为 LF 换行(VS Code 右下角切换,或用
dos2unix处理),并在 shebang 行写明解释器,如#!/usr/bin/env bash - PHP 脚本中路径统一用
dirname(__FILE__)或__DIR__+DIRECTORY_SEPARATOR,别硬写"./config"或"scripts\init.php" - 避免在
scripts里直接调用.bat文件,优先用跨平台的 PHP 实现,或封装成vendor/bin/xxx再调用
scripts 看似简单,但实际踩坑多集中在执行时机、autoload 加载、跨平台路径和错误传播这四块。最容易被忽略的是:你以为它“像 npm script 一样随时可跑”,其实它严格绑定于 Composer 自身生命周期,且不共享 CLI 环境变量或当前工作目录上下文。










