文章动机
魔术方法__autoload()能够实现自动加载类、尝试加载未定义的类。自 PHP 7.2.0 起被废弃,并自 PHP 8.0.0 起被移除。官方推荐使用spl_autoload_register()。这两个函数有什么异同?为什么要自动加载?为什么说是自动?spl_autoload_register()的“注册”行为是什么?
为什么
不使用自动加载,如果当前脚本要包含多个类文件就需要写多个include、require。烦。如果使用__autoload,要维护一个臃肿的__autoload实现。所以要用自动加载,而且是spl_autoload_register。
抛出问题
不同类库不同命名机制下,怎么实现自动加载?一个个命名规则去匹配加载吗?累呀。
实现自动加载的原理
观察opcode会发现PHP实现自动加载机制的方式是:
- __autoload()
- 将autoload_func指针指向某一PHP函数(通常使用C语言在PHP拓展中实现)
怎么触碰到第二个方法呢(第一个快要废弃了惹)?SPL帮到你。SPL中有个功能实现了autoload机制。他的方法是通过将函数指针autoload_func指向自己实现的具有自动加载功能的函数来实现的。也就是通过将autoload_func指向spl_autoload或者spl_autoload_call的函数地址来实现自动加载。
spl_autoload使用:spl_autoload(类名,类文件的拓展名)
说回让autoload_func指向问题,如何让autoload_func指向spl_autoload、spl_autoload_call?使用spl_autoload_register()即可。(spl_autoload_register()还可以将用户定义的自动加载函数注册到autoload_functions中,这个后面讲)
在PHP脚本中第一次调用spl_autoload_register()时不使用任何参数就可将autoload_func指向spl_autoload()。然后按照sql_autoload()的使用方法去定义你要加载的逻辑就好。
sql_autoload功能简单,想要更灵活就用spl_autoload_call。
sql_autoload_call又是什么原理?
sql_autoload_call的实现:在SPL模块内有个全局变量autoload_functions,是个HashTable,里面每个元素都是函数指针,这些函数指针指向的都是一些具有自动加载类功能的函数。就像这样:
spl_autoload_call的逻辑里就是:按顺序执行autoload_functions里的函数,每执行完一个函数就判断是否加载了类,如果加载好了则返回,不往下执行了;如果全部执行完都没加载到你要的类,他也不会弹出错误提示。这里要注意的哦。
那谁来把这些函数塞进autoload_functions呢?是sql_autoload_register()。
回到问题
针对不同类库不同命名机制,要实现自动加载的做法:根据每个类库不同的命名机制实现各自的自动加载函数,然后使用spl_autoload_register分别将其注册到SPL自动加载函数队列中即可。