8

我有一个使用以下方法注册的自动加载器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 在他的回答中所暗示的那样。

所以,这个故事的寓意是,如果你打算使用一个类类型函数,或者上面提到的任何一个混合类型变量的函数,在将它传递给类类型函数之前先检查它。

4

2 回答 2

3

在什么情况下/函数调用会调用自动加载器?

我意识到,鉴于评论中提到的问题,这基本上是一个次要问题,但仍然值得回答。

自动加载函数,即__autoload()代码中的一个函数或通过 注册的回调函数,spl_autoload_register在——且仅当——PHP 需要访问尚未定义的类时才被调用。这在任何地方都可以完成,很少有例外,例如class_exists,它的参数告诉 PHP 不要调用任何自动加载器。

PHP 手册有一个专门用于自动加载的页面。如果有任何混淆,我建议对其进行审查。

于 2012-12-20T05:07:18.130 回答
0

您可以使用debug_backtracedebug_print_backtrace找出调用自动加载器函数的确切位置。

从技术上讲,它应该只在脚本引用不存在的类名时由 PHP 调用。

于 2012-12-20T04:16:58.787 回答