classmap 查找优先于 psr-4 是因 Composer ClassLoader 中 findFile() 方法硬编码将 classmap 检查置于最前,命中即返回,不触发 psr-4 推导;其本质是执行顺序优先而非注册顺序或权限更高。
classmap 不是“优先于”
ps
r-4,而是“先查、命中即停”——
查表是 autoload 流程的第一步,只要类名在
里有记录,就直接加载,根本不会走到 psr-4 推导逻辑。
为什么 classmap 查找总在 psr-4 之前触发
Composer 生成的
会按固定顺序注册加载器:
→
→
→
。但实际执行时,PHP 的
是逐个调用这些加载器的;而 Composer 内置的
实现中,
查找被硬编码在
方法最开头,它不依赖注册顺序,而是加载器内部的逻辑优先级。
是一张静态数组(
),查找是 O(1) 哈希匹配,快且确定
需要截掉命名空间前缀、替换
为
、拼路径、再
,是动态推导 + 文件系统 IO
哪怕你把
配置写在
顶部,
映射仍会在运行时被优先检查
classmap 覆盖 psr-4 的真实条件
覆盖不是靠“更优先”,而是靠“更早命中”。一个类同时满足两种规则时,
生效的前提是:该类名确实出现在
中。这通常发生在以下情况:
你在
的
字段里显式包含了该类所在目录(例如
),且运行过
该类文件被扫描到,并生成了
→
这样的映射项
而你的
配置是
,此时
会走 psr-4(因为类名以
开头),但
(无命名空间)只能走
如果你误把
同时纳入
和
路径,又写了
,那
仍走
,
则走
—— 类名不同,不冲突
怎么验证当前类到底走哪个加载路径
别猜,直接看生成的映射文件和运行时行为:
稿定在线PS
PS软件网页版
下载
运行
,观察输出里是否提到 “Scanning dir src/ for classmap” 或 “Found class Helper in src/Helper.php”
打开
,搜索类名,如果存在,说明已进 classmap
打开
,确认你的命名空间前缀(如
)是否对应正确路径(如
)
临时加一句
在
后,看返回路径是
还是
等
classmap-authoritative 模式下 psr-4 彻底失效
启用
后,Composer 加载器会跳过所有文件系统扫描逻辑,只查
。此时:
任何未被 classmap 收录的类,即使符合 psr-4 规则,也会报
必须确保
字段在
中存在(哪怕为空数组),否则该 flag 不生效
运行
后,检查
是否非空;若为空,说明没扫到任何类——可能路径配置错误,或类文件放在了未声明的目录(如
)
最容易被忽略的一点:classmap 的“优先”本质是“唯一入口”,不是“更高权限”。一旦你启用了
,psr-4 就不再是备选方案,而是完全不可用——它连尝试的机会都没有。
classmapautoload_classmap.phpvendor/autoload.phpfilespsr-4classmappsr-0spl_autoload_register()ClassLoaderclassmapfindFile()classmapvendor/composer/autoload_classmap.phppsr-4\/file_exists()psr-4composer.jsonclassmapclassmapautoload_classmap.phpcomposer.json"classmap""src/"composer dump-autoload"AppHelper""src/Helper.php"psr-4"App\": "src/"new AppHelper()Appnew Helper()classmapsrc/Helper.phpclassmappsr-4namespace App;new Helper()classmapnew AppHelper()psr-4composer dump-autoload -vvendor/composer/autoload_classmap.phpvendor/composer/autoload_psr4.php"App\"["src/"]var_dump($loader->findFile('Helper'));require 'vendor/autoload.php'src/Helper.phpsrc/Http/Helper.php--classmap-authoritativeautoload_classmap.phpClass not found"classmap"composer.jsoncomposer dump-autoload --classmap-authoritative --optimize-autoloaderautoload_classmap.phptests/--classmap-authoritative