Composer autoload 是配置驱动的映射系统,通过 composer.json 的 PSR-4 等配置生成 vendor/autoload.php 及映射文件,类加载依赖 dump-autoload 更新路径映射,而非手写加载器。

autoload 不是手写加载器,而是配置驱动的映射系统
Composer 的 autoload 机制本质不是让你去写一个 __autoload() 或 spl_autoload_register() 回调函数,而是通过 composer.json 中的配置(如 "psr-4"),让 Composer 在 install 或 dump-autoload 时,自动生成一套符合 PSR-4 规范的映射逻辑。最终生效的是 vendor/autoload.php 引入的 autoload_real.php 和它背后的一系列映射文件(比如 vendor/composer/autoload_psr4.php)。
- 你改了类文件路径或命名空间,但没运行
composer dump-autoload→ PHP 找不到类,报Class not found - 手动
require 'vendor/autoload.php'没问题,但若再自己写个require_once加载同名类 → 可能触发重复定义或覆盖 Composer 的注册顺序 - PSR-0 已被弃用,新项目别配
"psr-0";历史项目迁移时,composer validate会警告
psr-4 映射怎么生效:从 new 到文件加载的完整链路
当你执行 new AppControllerUserController(),PHP 发现类未定义,就触发 Composer 注册的自动加载器。它查 autoload_psr4.php,拿到 'App' => ['app/'],再把命名空间转成路径:AppControllerUserController → app/Controller/UserController.php,最后 include 这个文件。
- 路径必须严格匹配:命名空间末尾的反斜杠
和目录分隔符一一对应,App\Http对应app/Http/,不能少斜杠也不能多斜杠 - 文件名必须和类名完全一致(大小写敏感):类
UserController必须在UserController.php,不是usercontroller.php(Linux 下直接失败) - 每个 PSR-4 映射项只支持一个根目录:不能写
"App\": ["app/", "src/app/"],Composer 会静默忽略第二个
composer dump-autoload 是重绘地图,不是清缓存
composer dump-autoload 的唯一作用,是重新扫描你配置的源码路径(如 app/、src/),生成新的映射数组,写入 vendor/composer/ 下的 PHP 文件。它不下载包、不改 vendor/ 结构、也不清 OPCache。
- 新增了一个
app/Service/Logger.php,但运行时报错 → 必须执行composer dump-autoload,否则映射里没有这条记录 - 开发中频繁改类名或移动文件?可以加
-o参数:composer dump-autoload -o会额外生成classmap,跳过路径推导,性能略高,但生成慢、体积大,只建议部署时用 -
autoload-dev配置(如Tests/)默认只在composer install --dev或显式运行dump-autoload时写入映射;如果autoload和autoload-dev都映射了Tests\,前者优先,后者被静默跳过
为什么 autoload 多了会变慢?关键在系统调用
PSR-4 是“按需加载”,看似高效,但每次 include 都要走一次 stat() + open() + read() 系统调用。几千个类 = 几千次磁盘 I/O —— 这才是真实瓶颈,不是 PHP 解析慢。
- 开发环境无所谓;生产环境若类极多(如 Laravel 的 Facade + Service Provider + Command 全加载),建议用
composer dump-autoload -o启用 classmap,把所有类路径预存为数组,省掉路径拼接和stat - 别为了“看起来整洁”把一个工具类拆成十几个小文件再配 PSR-4;合理合并 + classmap 更实际
- OPCache 开启后,
include的文件内容会被缓存,但文件是否存在仍要stat—— 所以 classmap 依然有收益
dump-autoload。这两点加起来,占了本地“Class not found”问题的八成以上。


















