在 composer.json 中跳过目录自动加载,需在 autoload 或 autoload-dev 的 exclude-from-classmap 中配置相对于项目根目录的路径(如 "tests/legacy/"),仅对 classmap 和启用 classmap 生成的 psr-4/psr-0 生效;不支持 files 或纯 psr-4 直接排除,且排除不影响显式 require。

composer.json 里怎么跳过某个目录不自动加载
直接在 autoload 或 autoload-dev 的 exclude-from-classmap 里加路径就行,不是所有 autoload 类型都支持排除,只有 classmap 和 psr-4/psr-0(配合生成 classmap)才认这个配置。
常见错误是往 files 或纯 psr-4 下硬塞 exclude-from-classmap,结果完全没用——它只对最终要写进 vendor/composer/autoload_classmap.php 的那部分生效。
-
exclude-from-classmap必须是相对于项目根目录的路径,比如要排除tests/legacy/,就写"tests/legacy/"(结尾斜杠可选,但建议带上,避免误匹配) - 路径支持通配符
*,例如"tests/*_old/",但不支持**递归匹配 - 如果该目录下有文件已被其他 autoload 规则(如
files)显式引入,排除无效
为什么 vendor 里某些包的测试目录还在自动加载里
因为 Composer 默认会为每个包生成 classmap,包括它们的 tests/ 目录。这不是你项目的问题,而是依赖包自己没配 autoload.exclude-from-classmap。
你不能直接改 vendor 里的 composer.json,下次 composer update 就被覆盖了。正确做法是在自己项目的 composer.json 中,用 autoload-dev + exclude-from-classmap 主动压制:
"autoload-dev": {
"psr-4": {
"Tests\": "tests/"
},
"exclude-from-classmap": [
"vendor/some/package/tests/",
"vendor/another/lib/fixtures/"
]
}
注意:这里 exclude-from-classmap 是作用于整个 classmap 构建过程的,包括扫描 vendor —— 所以能“后发制人”地把别人包里你不想要的路径剔掉。
- 必须运行
composer dump-autoload才生效,install或update会自动触发,但手动修改后别忘了这步 - 排除后,这些路径下的类名不会再出现在
vendor/composer/autoload_classmap.php里,但如果你用require_once显式加载,依然能用 - PHP 8.1+ 的
#[SensitiveParameter]等新特性不会因此失效,排除只影响自动加载机制本身
exclude-from-classmap 不生效的三个典型原因
写了却没用?大概率掉进了这三个坑里的一个:
- 用了
psr-4自动加载但没开classmap-authoritative或没跑dump-autoload --optimize—— 此时 Composer 走的是动态映射,exclude-from-classmap根本不参与查找逻辑 - 路径写成了绝对路径或带
./前缀,比如"./src/Unused/",实际应该写"src/Unused/" - 排除的目录里有文件被
files类型直接 require 了,比如某个包的composer.json里写了"files": ["functions.php"],那这个文件仍会被加载,和 classmap 排除无关
验证是否生效,可以看生成的 vendor/composer/autoload_classmap.php 里有没有对应路径的类映射,或者用 composer show -p 查 classmap 条目。
想彻底禁用某目录的所有自动加载行为
仅靠 exclude-from-classmap 不够。如果那个目录里有 PSR-4 命名空间声明,又没被 classmap 覆盖,它仍可能被动态解析到。
更彻底的做法是:不用 autoload,改用 autoload-dev 并确保生产环境不加载它;或者把目录移到 vendor 外、用 .gitignore 隔离,再通过脚本控制是否复制过去。
- 不要在
autoload里写"": "some-dir/"这种空命名空间映射,极易引发冲突且无法排除 - Composer 2.2+ 支持
--no-autoloader安装,但只适合 CI 场景,日常开发不现实 - 真正难处理的是那些“既想保留代码又不想被自动加载”的场景——这时候就得接受:自动加载和文件存在本身就是耦合的,要么删文件,要么接受它偶尔被扫到
最稳的方式,其实是让那个目录压根不出现在你的 autoload 配置范围内,而不是等它进来再排除。










