我有一个使用以下方法注册的自动加载器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)
这些东西永远不会是类,所以永远不应该使用new
orclass_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 在他的回答中所暗示的那样。
所以,这个故事的寓意是,如果你打算使用一个类类型函数,或者上面提到的任何一个混合类型变量的函数,在将它传递给类类型函数之前先检查它。