好的,这是一个艰难的问题......我想,我觉得答案是否定的,但在这种情况下,我想要一些替代方案的答案。
我在一个可以动态创建类的框架中有一个非常复杂的 __autoload() 函数。为了动态创建一个名为 AuthActions 的类,需要三个类——这三个是:fRecordSet、RecordSet 和 AuthAction(注意那个没有 S)。
我的自动加载器将在它加载的任何类上寻找一个静态方法“init”并尝试运行它。在我的 ActiveRecord 类中,它尝试使用 AuthActions 来获取特定活动记录上支持的操作列表。AuthAction(没有 S)也在它的 init 中调用 AuthActions,所以基本上加载了 Active Record,并尝试加载 AuthActions,触发其他三个的加载,然后当它完成加载 AuthAction 时仍在原始自动加载器中 AuthAction 尝试调用AuthActions 触发另一个自动加载,因为原始的尚未完成。
这会导致以下内容有一些回声语句来澄清:
尝试加载 ActiveRecord
尝试加载 fActiveRecord
fActiveRecord 通过 /var/www/dotink.org/inkwelldemo/inc/lib/flourish
加载 ActiveRecord 通过 /var/www/dotink.org/inkwelldemo/inc/lib 加载
尝试加载 AuthActions
尝试加载 RecordSet
尝试加载 fRecordSet
fRecordSet 通过 /var/www/dotink.org/inkwelldemo/inc/lib/flourish
加载 RecordSet 通过 /var/www/dotink.org/inkwelldemo/inc/lib 加载
尝试加载 AuthAction
AuthAction 通过 / 加载var/www/dotink.org/inkwelldemo/models致命错误:在第 24 行的 /var/www/dotink.org/inkwelldemo/models/AuthAction.php 中找不到类“AuthActions”
这里的问题是,对 __autoload('AuthActions') 的后续调用会成功,因为它需要的三个类现在已经到位......但它似乎只在它已经尝试自动加载'AuthActions'的前提下死了——这似乎是写在 PHP 中的。
在测试这个我发现以下将永远循环没有错误:
function __autoload($class) {
__autoload($class);
}
$foo = new Bar();
虽然下面的这个会出现类似的错误:
function __autoload($class) {
$test = new Bar();
}
$foo = new Bar();
这种行为似乎不一致,因为本质上它们应该等同于同一件事(有点)。如果 PHP 内部触发的自动加载就像用户对 __autoload() 的调用一样,我认为我不会有问题(或者如果我这样做了,那将是它永远循环的问题,这将是一个单独的问题,以确定为什么类没有被加载来解决依赖关系)。
简而言之,我需要一种方法来递归循环基于 PHP 触发的自动加载的自动加载器......这根本不可能吗?这可能是我的特定版本中的错误吗?在我的测试中,它似乎影响了 5.2.6 - 5.3.2,所以我无法想象这是一个整体的错误。
更新:
AuthAction 上的 init method() 代码如下:
/**
* Initializes the AuthAction model
*
* @param array $config The configuration array
* @return void
*/
static public function init($config) {
// Establish permission definitions and supported actions
$every_permission = 0;
$supported_actions = array();
foreach (AuthActions::build() as $auth_action) {
$action_name = $auth_action->getName();
$action_value = intval($auth_action->getBitValue());
$every_permission = $every_permission | $action_value;
$supported_actions[] = $action_name;
define(self::makeDefinition($action_name), $action_value);
}
define('PERM_ALL', $every_permission);
}
您可以看到它在哪里调用 AuthActions 作为一个单独的类,请注意,这只是因为它是在最初的加载尝试中加载的,所以它失败了。我显然可以删除这段代码,它会起作用——AuthActions 的原始加载将成功完成,因为所有先决条件类都被加载。
也就是说,init() 是这段代码最合适的地方,即使我无法使用尚未在 init() 中加载的相互依赖的类,我仍然希望保留该功能。实现该功能的任何替代方式都会很棒......理想情况下,PHP 会为此类事情提供事件,例如,当触发“自动加载”事件时,您可以注册回调。这将允许代码在原始自动加载之后运行,并解决这个看似毫无意义的限制。
话虽如此,任何关于如何在每次加载类时自动调用 init() 的建议都受到赞赏和欢迎。