Composer scripts执行时找不到可执行文件,是因为它不自动将项目bin目录或本地脚本加入PATH,且不解析相对路径;需显式使用./、绝对路径或@php前缀,并确保权限和环境一致。

scripts里写命令,为什么执行时找不到可执行文件
Composer scripts 本质是 shell 命令调度器,它不自动帮你把项目里的 bin 文件或本地脚本加入 PATH。常见现象是:你在 composer.json 里写了 "dev:check": "php check.php",但运行 composer dev:check 报错 php: command not found 或 check.php: No such file or directory。
原因很简单:Composer 执行脚本时的当前工作目录是项目根目录,但不会自动识别 ./bin、./scripts 这类路径,也不会帮你 resolve 相对路径中的 PHP 解释器。
- 用绝对路径或显式指定解释器:
"dev:check": "php ./check.php"(注意开头的./) - 如果脚本有 shebang(如
#!/usr/bin/env php),确保它可执行:chmod +x check.php,然后直接写"dev:check": "./check.php" - 避免依赖全局命令别名(比如你本地 alias php=/opt/homebrew/bin/php),scripts 不读 shell 的 alias 配置
- Windows 用户注意:CMD 和 Git Bash 行为不同,优先测试用
php -r "echo 'ok';"这类纯 PHP 命令确认基础环境
scripts调用其他scripts,怎么传参和共享变量
Composer 原生不支持参数透传或变量共享。你写 "build": "composer install && composer post-build",后面那个 post-build 是独立执行的,无法拿到前一个命令的 exit code 或 stdout。
更麻烦的是:想让 composer build -- --env=prod 把 --env=prod 传给内部脚本?默认不行 —— Composer 会吃掉双横杠后的所有参数,除非你显式启用 passthru 模式。
- 要透传参数,必须在
scripts定义里加@php或@composer前缀,并配合--:"build": "@php build.php -- --env=prod" -
@php表示用当前 Composer 使用的 PHP 执行该文件;@composer表示递归调用自身(支持参数透传) - 环境变量需手动注入:
"test": "APP_ENV=test phpunit",不能靠 .env 文件自动加载(那是框架层的事) - 多个 scripts 串联建议拆成单个 PHP 脚本控制流程,而不是堆 shell &&,否则失败时难调试
scripts中执行PHP代码,为什么vendor/autoload.php没加载
直接写 "say-hello": "php -r "echo 'hi';"" 没问题,但一旦涉及项目类(比如 new AppHelper()),就会报 Class 'AppHelper' not found —— 因为 php -r 不自动 require autoload。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
这不是 Composer 的 bug,而是 PHP CLI 的默认行为:它不读 composer.json,也不初始化 autoloader。
- 正确做法是用
@php前缀 + 独立 PHP 文件:"say-hello": "@php say-hello.php",并在say-hello.php开头写require __DIR__.'/vendor/autoload.php'; - 也可以用
php -d auto_prepend_file=vendor/autoload.php -r "new App\Helper();",但可读性差,且容易因路径出错 - 别在
php -r里拼长字符串去加载类,容易引号嵌套混乱,也难维护 - 如果只是简单调用已有命令(如
phpunit、php-cs-fixer),确保它们已通过 Composer require-dev 安装,并在 vendor/bin 下存在对应二进制
scripts在CI/CD中执行失败,本地却正常
最常见原因是环境差异:本地有全局安装的工具(如 jq、docker)、PATH 设置不同、PHP 版本不一致,或者 scripts 里用了交互式命令(比如 read、git commit -m)。
CI 环境通常无 TTY、无用户交互能力,且 PATH 往往只包含 /usr/bin 和 /bin,不包含 ~/.composer/vendor/bin 或 node_modules/.bin。
- 所有外部命令尽量用全路径,或先检测是否存在:
"ci:setup": "command -v jq >/dev/null 2>&1 || { echo 'jq missing'; exit 1; } && jq --version" - 禁用交互行为:git 相关命令加
-q或--no-verify;PHP 工具加--no-interaction(如phpunit --no-interaction) - CI 中不要依赖
~或$HOME,用$PWD或.替代 - PHP 版本敏感的操作(如反射、扩展函数),在 scripts 前加版本检查:
php -v | grep -q '8.2' || { echo 'PHP 8.2 required'; exit 1; }
scripts 看似简单,实际是环境、路径、权限、shell 兼容性、PHP 生命周期的交汇点。最容易被忽略的,是把它当成“能跑就行”的胶水逻辑,而忘了它本质是一段脱离框架上下文、直面操作系统执行环境的裸命令链。

















