PHP自动加载器是否缓存类定义?spl_autoload_unregister失效咨询
你的观察完全正确,PHP确实会在类首次成功加载后,将类定义永久缓存到当前运行的进程内存中,这就是导致你看到和预期不一致结果的核心原因。咱们一步步拆解你的代码执行逻辑:
第一次调用
var_dump(class_exists("blah\myclass")):
此时自动加载器还未注册,blah\myclass也没有被加载到内存,所以输出false,和你的预期一致。加载
Autoloader.php并注册自动加载器后,第二次调用var_dump(class_exists("blah\myclass")):
因为类还不存在,PHP触发了注册的自动加载器,成功找到并加载了blah\myclass类。此时PHP会把这个类的定义存入内存缓存,后续任何对该类的引用都会直接使用这个缓存,不需要再触发自动加载。所以这次输出true,符合预期。执行
spl_autoload_unregister('Autoloader::loader')后,第三次调用var_dump(class_exists("blah\myclass")):
这个注销操作只是移除了自动加载的"触发机制",但已经加载到内存中的类定义并不会被删除。所以PHP直接从缓存中找到已存在的blah\myclass,直接返回true,根本不会再尝试去触发自动加载(毕竟自动加载器已经没了,但类已经在内存里了)。
而当你移除line3(第二次var_dump)时,整个流程变了:
注册自动加载器后,你没有触发类加载,blah\myclass从未被加载到内存。注销自动加载器后,第三次调用class_exists时,既没有自动加载器可以去查找类,内存里也没有类的缓存,所以返回false,和你的预期一致。
额外补充一点:PHP没有提供"卸载"已加载类的内置方法,类一旦被加载到内存,就会一直存在到当前进程结束(比如CLI脚本运行完毕,或者Web请求结束)。只有重启PHP进程才能清除这些类缓存。
内容的提问来源于stack exchange,提问作者NL3294

