PHP 7.0 中 __autoload 未被移除,但仅当未调用 spl_autoload_register() 时才作为兜底机制触发;一旦注册任何自动加载器,__autoload 即失效,且不可恢复。

PHP 7.0 中 __autoload 仍能工作,但**仅当未注册任何其他自动加载器时才被调用**——这是它“看似失效”最根本的原因。PHP 7.0 并未移除 __autoload,而是将其降级为“兜底机制”,一旦调用了 spl_autoload_register()(哪怕只注册一次),__autoload 就彻底静默,不再触发。
触发前提:必须是“首次引用未定义类”
自动加载只在 PHP 解析器真正需要类定义时才启动,不是在声明、注释或字符串中出现类名就触发。以下操作会触发:
new MyClass()MyClass::staticMethod()-
class Child extends MyClass { }(父类未加载) -
interface A extends MyClass { }(错误写法,但若 MyClass 是接口且未加载,也会触发) -
function foo(MyClass $x) { }(仅在运行时实际传入该类型对象前不触发;但类型声明本身不触发加载)
以下不会触发:
-
$class = 'MyClass';(纯字符串) -
class_alias('MyClass', 'Alias');(别名定义不触发加载) -
is_a($obj, 'MyClass')(运行时检查,类未加载则返回 false,不触发 autoload)
执行顺序:spl_autoload_register 优先级绝对高于 __autoload
PHP 内部维护一个自动加载器队列。只要调用过 spl_autoload_register(),无论注册的是空函数、匿名函数还是静态方法,__autoload 就被绕过。即使你之后又 unset 了所有加载器,__autoload 也不会恢复。
立即学习“PHP免费学习笔记(深入)”;
- ✅ 正确做法:统一使用
spl_autoload_register,避免混用 - ❌ 危险组合:
function __autoload(){...}+spl_autoload_register(function(){...})→ 后者生效,前者被忽略 - ⚠️ 注意:Composer 自动生成的
vendor/autoload.php必然调用spl_autoload_register,因此在 Composer 项目中__autoload永远无效
命名空间类的路径解析必须手动处理
__autoload 接收的参数是完整的类名(含命名空间),例如 AppControllersHome。它不做任何转换,不会自动把 替换成 /,也不会补扩展名或目录前缀。
常见错误写法:
function __autoload($class) { require "$class.php"; } → 报错:找不到 AppControllersHome.php(路径非法)
正确示例(需自行规范化):
function __autoload($class) { $file = __DIR__ . '/src/' . str_replace('\', '/', $class) . '.php'; if (file_exists($file)) require $file; }
调试技巧:快速验证是否触发
不要依赖报错信息判断,而要用主动探测:
- 在
__autoload函数开头加echo "Loading: $class "; die;,看是否输出 - 用
var_dump(spl_autoload_functions());查看当前已注册的加载器列表(若非空,则__autoload已被屏蔽) - 检查是否在
new或::之前就已require了该类文件(类已定义,自然不触发)



















