Composer默认只读取当前目录的composer.json,不自动向上或向下查找;推荐用--working-dir指定工作目录,路径相对于当前shell位置,且需手动配置autoload映射。

composer 命令默认只认当前目录的 composer.json
它不会自动向上查找父目录的 composer.json,也不会向下进入子目录——除非你明确告诉它去哪。很多同学在项目子目录(比如 packages/my-lib)里执行 composer install,结果报错:Could not find a composer.json file in /path/to/packages/my-lib。这不是 bug,是设计行为。
用 --working-dir 强制指定工作目录
这是最干净、最推荐的方式,不依赖 shell 切换,也不污染当前 shell 环境:
-
composer install --working-dir=packages/my-lib→ 在packages/my-lib下读取并执行其composer.json -
composer update --working-dir=src/legacy-app→ 即使你在项目根目录,也能更新子应用的依赖 - 支持所有 composer 命令:
require、dump-autoload、run-script等都可用 - 注意:路径是相对于当前 shell 所在位置的,不是相对于
composer.json的
临时切换 shell 目录再运行(慎用)
虽然简单,但容易出错,尤其在脚本或 CI 中:
-
cd packages/my-lib && composer install && cd -—— 看似可行,但cd -在非交互式 shell(如 GitHub Actions)中可能失效 - 如果命令中途失败(比如网络中断),当前工作目录就卡在子目录里了,后续命令可能误操作
- 某些 IDE 终端或容器环境对
cd后的状态继承不一致,导致预期外的vendor路径写入 - 别用
pushd/popd替代——它们在不同 shell(bash/zsh/sh)下行为不统一
为什么不用 COMPOSER 环境变量?
虽然文档提过 COMPOSER 变量可指定配置文件路径,但它只影响「加载哪个 composer.json」,不改变工作目录逻辑:
-
COMPOSER=packages/my-lib/composer.json composer install仍会在当前目录生成vendor/和composer.lock,极大概率引发路径错乱 - 它适合替换配置文件名(如
composer.local.json),不适合跨目录管理多个独立 composer 项目 - 真正需要多项目隔离时,每个子目录应具备完整结构(含自己的
vendor、autoload.php),靠--working-dir驱动才安全
--working-dir 成功安装了子目录依赖,主项目的自动加载器默认不包含它——得手动加 "psr-4" 映射或运行 composer dump-autoload --working-dir=... 单独生成子目录的 autoloader。










