我有一个使用以下方法注册的自动加载器spl_autoload_register():
class MyAutoLoader{
public function __construct(){
spl_autoload_register(array($this, 'loader'));
}
public function loader($className){
var_dump($className);
}
}
$al = new MyAutoLoader(); //Register the autoloader
从 开始var_dump(),自动加载器似乎在很多事情上被调用,比如要插入数据库的数据、参数化的 SQL 查询等等:
string 'name' (length=4)
string 'a:2:{s:5:"label";s:4:"Name";s:8:"required";b:1;}' (length=48)
string 'en_US' (length=5)
string 'object' (length=6)
string 'name = ?' (length=8)
这些东西永远不会是类,所以永远不应该使用neworclass_exists()等加载。
在什么情况下/函数调用会调用自动加载器?我想停止自动加载不是类的“classNames”被调用,因为每个$className都使用 进行检查file_exist(),并且检查这些数据字符串的效率非常低。
问题已解决。我首先按照 Brad 的建议进行了回溯并将跟踪转储到文件中(只需添加一个打开文件并附加到文件的小片段)。
显然,痕迹很大,但我选择了我能找到的最简单的一个。顺便说一句,该跟踪恰好是一个称为数据库 (ORM) 包装器的跟踪器,我编写该包装器是为了包装出色的RedBean ORM 库。我转储的结果$className也验证了这一点,因为这些字符串是数据进入或离开数据库。
话虽如此,我有一个__call()拦截数据库包装器的方法,进行一些处理,将其传递给 RedBean,处理结果,然后将其发送回调用者。
问题:在处理过程中,我正在调用is_subclass_of()和instanceof,这显然会要求自动加载器尝试加载类(因为我们没有任何称为name =?加载的类,也不存在)。
解决方案是实际上确保我们object在调用之前is_subclass_of()有一个instanceof: if(is_object($someproperty) && is_subclass_of($someproperty))。
如果$someproperty不是对象,则if立即短路instanceof并且is_subclass_of()永远不会调用,这意味着永远不会调用自动加载器。
正如布拉德所提到的,使用自动加载器包含各种东西require_once可能会带来巨大的安全风险,同时,多次使用文件系统file_exists()也是非常低效的。
因此,总而言之,每次使用instanceof, is_subclass_of、其他类类型函数、类存在函数和反射方法时都会调用自动加载器,正如 Charles 在他的回答中所暗示的那样。
所以,这个故事的寓意是,如果你打算使用一个类类型函数,或者上面提到的任何一个混合类型变量的函数,在将它传递给类类型函数之前先检查它。