为什么字符串*RECURSION*出现在输出中,并且每个包含的数组名称在$GLOBALS数组输出中都以下划线字符开头


Why is the string *RECURSION* appearing in the output and every contained array name is initiating with underscore character in $GLOBALS array output?

我在本地机器上使用以下PHP版本,并且只在本地主机上运行PHP程序。

PHP 5.3.10-1ubuntu3.13 with Suhosin-Patch (cli) (built: Jul  7 2014 18:54:55)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies

我写了一个非常简单的PHP程序,如下所示:

<!DOCTYPE html>
<html>
  <body>
  <?php
    $x = 5;
    $y = 10;
    print_r($GLOBALS);
    die;
    function myTest() {
      global $x, $y;
      $y = $x + $y;
    }

    myTest(); // Run function
    echo $y; // Output the new value for variable $y
  ?>
  </body>
</html>

执行上述程序后,我在浏览器窗口中得到以下输出:

Array ( [GLOBALS] => Array *RECURSION* [_POST] => Array ( ) [_GET] => Array ( ) [_COOKIE] => Array ( ) [_FILES] => Array ( ) [x] => 5 [y] => 10 )

从上面的输出中,我不明白为什么字符串RECURSION会被显示,从它来的地方。这背后的原因是什么?

还有,为什么下划线字符出现在所有包含数组**(_POST, _GET, _FILES)**的开头?

最简单的方法是想象一下如果*RECURSIVE*没有显示会是什么样子:

Array 
( 
    [GLOBALS] => Array 
        (
            [GLOBALS] = Array
                (
                      [GLOBALS] = Array
                          (
                                  ...
                          )
                      ...
                )
            [_POST] => Array ( )
            [_GET] => Array ( )
            ...
        ) 
    [_POST] => Array ( ) 
    [_GET] => Array ( ) 
    [_COOKIE] => Array ( ) 
    [_FILES] => Array ( ) 
    [x] => 5 
    [y] => 10 
)

$GLOBALS包含对所有全局变量的引用,并且由于$GLOBAL本身是一个全局变量,因此它也包含对自身的引用。正如您所看到的,上面的操作将导致一个永远不会结束的递归模式,这仅仅是因为$GLOBALS -数组包含了对自身作为元素的引用。这意味着用print_r()打印它是不可能的,因为它会导致无限递归。因此,print_r()函数通过添加字符串*RECURSION*来解决这个问题。以下是php手册中的一段话:

在PHP 4.0.4之前,如果给定一个包含直接或间接引用自身的数组或对象,print_r()将永远持续下去。print_r($GLOBALS)就是一个例子,因为$GLOBALS本身就是一个全局变量,它包含对自身的引用。

这也意味着显示任何包含对其自身递归引用的对象都将导致显示此字符串。一个简单的例子是:

$a = array(&$a); //$a contains one element with a reference to itself
print_r($a); //prints: Array ( [0] => Array ( [0] => Array *RECURSION* ) ) 

尽管注意这不会向您隐藏任何信息-如果记住所有这些,您仍然知道GLOBALS -元素包含的内容(基本上与打印的内容相同)。

回答你的第二个问题:名称以下划线开头的原因很简单,因为几个"超全局"变量这样做。它可以更容易地将超全局变量与常规变量区分开来,并且(在某种程度上)防止人们错误地使用这些名称。因此,当访问_POST -数组时,例如,您使用$_POST而不是$POST,这意味着$GLOBALS -变量中的元素键变为_POST,因为它是变量的"实际"名称。