PHP自动加载()是否可以从同一类的另一个自动加载()中加载一个类?

PHP自动加载()是否可以从同一类的另一个自动加载()中加载一个类?,php,dynamic,autoload,Php,Dynamic,Autoload,好的,这是一个艰难的时刻。。。我想,我觉得答案是否定的,但在这种情况下,我想要一些替代答案 我在一个可以动态创建类的框架中有一个非常复杂的_autoload()函数。动态创建一个名为AuthActions的类需要三个类——这三个是:fRecordSet、RecordSet和AuthAction(注意,这个类上没有s) 我的自动加载程序将在它加载的任何类上查找静态方法“init”,并尝试运行该方法。在我的ActiveRecord类上,它尝试使用AuthActions来获取特定活动记录上支持的操作的

好的,这是一个艰难的时刻。。。我想,我觉得答案是否定的,但在这种情况下,我想要一些替代答案

我在一个可以动态创建类的框架中有一个非常复杂的_autoload()函数。动态创建一个名为AuthActions的类需要三个类——这三个是:fRecordSet、RecordSet和AuthAction(注意,这个类上没有s)

我的自动加载程序将在它加载的任何类上查找静态方法“init”,并尝试运行该方法。在我的ActiveRecord类上,它尝试使用AuthActions来获取特定活动记录上支持的操作的列表。AuthAction(no S)也在其init中调用AuthActions,因此基本上加载活动记录,并尝试加载AuthActions,触发加载其他三个,然后,当它完成加载AuthAction时,仍然在原始自动加载程序中,AuthAction尝试调用AuthActions,这会触发另一个自动加载,因为原始自动加载程序尚未完成

这导致以下内容得到澄清,其中包含一些回音陈述:

正在尝试加载ActiveRecord
正在尝试加载fActiveRecord
fActiveRecord通过/var/www/dotink.org/inkwelldemo/inc/lib/flow加载
ActiveRecord通过/var/www/dotink.org/inkwelldemo/inc/lib加载
正在尝试加载AuthActions
正在尝试加载记录集
正在尝试加载fRecordSet
fRecordSet通过/var/www/dotink.org/inkwelldemo/inc/lib/flow加载
通过/var/www/dotink.org/inkwelldemo/inc/lib加载的记录集
正在尝试加载AuthAction
AuthAction通过/var/www/dotink.org/inkwelldemo/models加载

致命错误:在第24行的/var/www/dotink.org/inkwelldemo/models/AuthAction.php中找不到类“AuthAction”

这里的问题是,对uu 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,所以我无法想象它是一个bug

更新:

AuthAction上init方法()的代码如下:

        /**
     * 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时才失败。很明显,我可以删除这段代码,它会工作的——AuthActions的原始加载将成功完成,因为所有先决条件类都会加载

也就是说,init()是这段代码最合适的位置,即使我无法使用尚未在init()中加载的相互依赖类,我仍然希望保留该功能。任何实现该功能的替代方法都非常好。。。理想情况下,PHP应该有这样的事件,例如,当触发“自动加载”事件时,可以注册回调。这将允许代码在原始自动加载后运行,并将解决这个看似毫无意义的限制


话虽如此,任何关于如何在每次加载类时自动调用init()的建议都是值得赞赏和欢迎的。

\uuu autoload方法仅在您尝试使用尚未定义的类/接口时才会被调用

因此,以你为例

function __autoload($class) {
  $test = new Bar();
}

$foo = new Bar();
您试图加载的类
bar
不是必需/必需的,因此该类没有定义,因此它调用了u autoload方法作为最后手段,然后在自动加载中,您再次尝试加载未定义的同一类

使用_自动加载的正确方法如php站点所示

<?php
function __autoload($class_name) {
    require_once $class_name . '.php';
}

$obj  = new MyClass1();
$obj2 = new MyClass2(); 
?>

你所有的init都可以放在构造函数中,不是吗

除非我在你的问题中遗漏了什么…

我认为

我的自动加载器将查找静态 方法“init”加载任何类 试着运行它

是解决你问题的关键。您的自动加载程序不应该运行任何东西,它应该包括(或以其他方式定义)类,而不包括其他内容


定义类时(即,在静态“init”方法中),您试图运行哪种类型的代码?

您可能希望查看SPL实现,以便更好地了解如何使用它。如果遵循Zend风格的类/目录结构和名称空间,或者使用5.3和名称空间机制,您可以进行一些非常灵活的文件加载。据我所知,SPL只不过是创建了一堆自动装弹机。我的做了一些完全不同的事情,但不管怎样,SPL自动加载器并不能解决手头的问题,因为每个自动加载器在尝试加载当前加载的同一类时仍然会受到相同的突然死亡。我是否可以在原始海报中添加:,我提供的示例只是为了说明行为是如何不同的,这取决于autoload是否在内部触发,以及它是否由th调用