不能靠composer自动加载临时假包,必须手动干预autoloader——因dump-autoload生成的映射是静态快照,只认composer.json声明路径;未配置autoload-dev并执行dump-autoload,tests/stubs/下的类永远不会进入加载链,且ide或phpunit可能提前冻结autoloader使运行时addpsr4无效。

不能靠 Composer 自动加载临时假包,必须手动干预 autoloader —— 因为 composer dump-autoload 生成的映射是静态的,不支持运行时“注册一个还没存在的包”。
为什么 vendor/autoload.php 加不进你写的假类?
Composer 的 autoload.php 是构建时生成的快照文件,只认 composer.json 里声明过的路径。你把 tests/stubs/MyFakeService.php 放进去,不改 autoload-dev、不跑 composer dump-autoload,它就永远不在自动加载链里。
更麻烦的是:有些 IDE 或测试 runner(比如 PHPUnit 的 process isolation)会提前冻结 autoloader,后续 $loader->addPsr4() 也无效。
- 常见错误现象:
Class 'StubsMyFakeService' not found,哪怕文件存在、命名空间写对了 - 根本原因:不是路径错,是 autoloader 根本没注册这个前缀
- 别指望
require-dev能解决——那是装包用的,不是挂载本地 PHP 文件用的
真正能用的三种动态加载方式
绕过 Composer 自动生成逻辑,直接操作 ClassLoader 实例或硬引入:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 在
phpunit.xml的bootstrap文件里(如tests/bootstrap.php),拿到全局 loader:$loader = require 'vendor/autoload.php';<br>$loader->addPsr4('Stubs\', __DIR__.'/stubs/'); - 如果测试里只用一两个类,更简单:
require_once __DIR__.'/stubs/MyFakeService.php';—— 不依赖命名空间,也不怕 autoloader 冻结 - 用
class_alias()替换真实类(慎用):class_alias('StubsMyFakeService', 'AppServicesRealService');,但要注意类已加载就不能 alias
注意:$loader->addPsr4() 必须在任何类被 new 或 use 前调用,否则无效;Laravel 的 TestCase 默认已在 setUp() 前完成 autoload,所以 bootstrap 是唯一安全时机。
Mockery 和假包混用时的坑
Mockery 本身不解决“假包加载”,它只 mock 已存在的类。如果你要 mock 的类来自一个尚未安装的假包,得先让这个类能被加载,再 mock。
- 别在
setUp()里require_once假类 —— 可能触发多次,导致Cannot declare class错误 - 别用
Mockery::mock('StubsMyFakeService')期望它自动加载 —— 它不会帮你require - 如果假包有复杂依赖(比如用了
IlluminateSupportStr),确保这些真实依赖已装且可加载,否则require_once会直接 fatal
CI 环境下特别容易失效的点
Docker 构建缓存、CI 的 vendor 目录复用、甚至 IDE 的文件监听延迟,都会让你以为“刚改完 autoload-dev 就生效了”,其实没有。
- 每次改完
autoload-dev,必须显式执行:composer dump-autoload --dev - CI 脚本里别省这步,尤其用
--no-cache或--fresh模式时 - 如果用路径仓库(
"type": "path")指向假包,记得composer install后检查vendor/vendor-name/package-name是符号链接还是复制体 —— 链接才能实时反映修改
最常被忽略的是:假包里的类用了 __DIR__ 或 __FILE__ 计算路径,而动态加载后它的实际位置变了,相对路径就崩了。










