composer.json 必须放在项目根目录,因为 Composer 仅识别当前工作目录下的该文件,不向上查找、不向下扫描、不支持多文件嵌套;放错位置将导致 install 失败、类加载错误及 CI 崩溃。

因为 Composer 不会向上查找或跨目录识别 composer.json,放错位置直接导致命令失效、类加载失败、CI 流水线崩坏——这不是“建议”,是硬性运行规则。
为什么 composer.json 必须在项目根目录
Composer 启动时只检查当前工作目录下是否存在 composer.json,它不会:
- 向上遍历父目录寻找(哪怕上两级有正确的
composer.json,它也视而不见) - 向下扫描子目录(
src/composer.json或app/composer.json完全被忽略) - 支持多
composer.json并存管理(所谓“模块化 composer.json”纯属误解)
一旦你把 composer.json 放进 src/,执行 composer install 就会报 Could not find a composer.json file in /path/to/project/src;更隐蔽的问题是:你在错误目录执行成功了,生成的 vendor/ 路径错位,后续 require vendor/autoload.php 找不到文件,Class not found 报错却查不出根源。
composer install 失败或类找不到的典型场景
常见误操作和对应现象:
- 终端当前路径是
./src,却在此处运行composer install→ 报错找不到composer.json - 项目 Git 仓库根是
/myapp,但你把composer.json放在/myapp/backend→composer install在/myapp下执行失败,在/myapp/backend下执行则生成/myapp/backend/vendor,而入口脚本在/myapp/public中 require 的却是相对路径../vendor/autoload.php→ 加载失败 - IDE 自动触发
composer dump-autoload,但工作目录设成了子模块 → 命令看似执行成功,实际没更新对的 autoload 文件
修复永远只有一条路:确认 composer.json 在 Git 仓库最外层目录(即你 clone 下来的第一层),cd 进该目录,删掉所有残留的 vendor/ 和 composer.lock(如果旧的不干净),再跑 composer install。
config.vendor-dir 能不能绕过根目录限制
不能。这个字段只是改 vendor/ 的存放位置,前提是 composer.json 本身已在根目录。
-
"config": { "vendor-dir": "third-party" }✅ 有效,但必须写在根目录的composer.json中 - 先在子目录装过
vendor/,再补加该配置 → Composer 不会移动旧目录,新包仍装进原vendor/,新配置形同虚设 - 路径必须是相对路径(如
"lib"),不能用绝对路径(如"/var/www/lib")或以.开头(如"./vendor") - 改完必须手动删掉现有
vendor/,再执行composer install——dump-autoload或update都不触发重装
库(library)和应用(application)结构差异在哪
区别不在 composer.json 位置,而在内容意图和部署方式:
- 库项目:根目录只有
composer.json、src/、tests/、README.md;vendor/绝对不能出现——它由使用者安装,不是库自身依赖 - 应用项目:根目录可含
public/(Web 入口)、config/、bin/,但vendor/必须与composer.json同级,且必须加进.gitignore;composer.lock则必须提交,它是生产环境依赖一致性的唯一依据 - 无论哪种,
autoload段的psr-4映射必须严格匹配命名空间与物理路径,比如"App\": "src/"就要求src/Http/Controller.php里声明namespace AppHttp;
最容易被忽略的是:你以为改了 config.vendor-dir 就能“自由安排结构”,其实只要 composer.json 不在根目录,所有后续操作都在沙上筑塔——命令、自动加载、CI 构建、甚至 IDE 的符号跳转,都会逐步失准。根目录这一个位置,卡死了整个 Composer 生态的信任起点。


















