PHP解释器的每一次传递过程是什么


What does each pass of the PHP interpreter process?

我有一个包含文件,它定义了一个类,然后创建了一个带有该类实例化的全局,以及一个返回全局的函数(用于在其他函数中访问)。

代码方面:

class X {
    ...
}
global $x;
$x = new X();
function x() {
    global $x;
    return $x;
}

到目前为止一切似乎都很好。然后出现了一种情况,(显然)这个文件被包含了不止一次——它是由一个框架完成的,所以我不能将它限制为包含一次——这导致了试图重新定义类的错误。

所以我在顶部添加了代码:

if (class_exists('X')) {
    return;
}

我发现$x不再被定义。因此,解释器似乎必须运行一次,找到类定义,但不能处理后面的语句。然后它似乎进行了第二次传递,发现类存在,所以它返回时从未执行类实例化。

所以我把顶部的代码改为:

if (class_exists('X')) {
    global $x;
    $w = new X();
    function x() {
        global $x;
        return $x;
    }
    return;
}

现在,我在尝试重新声明函数时遇到了一个错误(原始声明仍在文件的底部)。因此,即使实例化X的代码没有被执行,函数似乎也被定义了。

所以文件的顶部现在看起来是这样的:

if (class_exists('X')) {
    global $x;
    $w = new X();
    if (function_exists('x')) {
        return;
    }
    function x() {
        global $x;
        return $x;
    }
    return;
}

所以现在一切都正常运转。

根据我所看到的,我的最佳猜测是,解释器进行一次收集类和函数定义的传递,然后进行另一次使用这些定义执行代码的传递。这种解释正确吗?有没有我遗漏的细微差别?

无论如何,我不是一个专业的PHP程序员,所以任何信息都是值得赞赏的。

然后出现了一种情况,(显然)这个文件被包含了不止一次——它是由一个框架完成的,所以我不能将其限制为包含一次

然后你可以把你的代码分成两个文件:

  1. 在可多次调用的文件中添加include_once
  2. X类移到另一个文件中,这个新的填充将被1中添加的include_once包括在内

有了这个,2。文件将只包含一次,即使1。文件被调用多次。

您可能应该使用require_once(而不是include_once),因为如果找不到文件,它将返回错误。