错误或黑客?$ GLOBALS

Kei*_*ein 17 php arrays global-variables

$GLOBALS["items"] = array('one', 'two', 'three', 'four', 'five' ,'six', 'seven');
$alter = &$GLOBALS["items"]; // Comment this line
foreach($GLOBALS["items"] as $item) {
  echo get_item_id();
}

function get_item_id(){
  var_dump(key($GLOBALS["items"]));
}
Run Code Online (Sandbox Code Playgroud)

检查此代码的输出,带注释和未注释的第二行.我的结果(PHP 5.3.0).用第二行

int(1) int(2) int(3) int(4) int(5) int(6) NULL
Run Code Online (Sandbox Code Playgroud)

没有第二行:

int(1) int(1) int(1) int(1) int(1) int(1) int(1)
Run Code Online (Sandbox Code Playgroud)

为何如此奇怪的结果?

Fel*_*ing 12

这是一个可能的解释:

我们知道,如果没有引用,它foreach总是遍历数组的副本:

除非引用了数组,否则foreach操作指定数组的副本而不是数组本身.foreach对数组指针有一些副作用.

这意味着原始数组的内部指针不会更改,并且key()将始终返回相同的值(我们在注释掉行时可以看到).事实上,如果我们这样做var_dump($GLOBALS),我们得到:

 ["items"]=>
  array(7) {
    [0]=>
    string(3) "one"
    [1]=>
    string(3) "two"
    [2]=>
    string(5) "three"
    [3]=>
    string(4) "four"
    [4]=>
    string(4) "five"
    [5]=>
    string(3) "six"
    [6]=>
    string(5) "seven"
  }
Run Code Online (Sandbox Code Playgroud)

(没有参考)

但是一旦我们生成对数组的引用(with $alter),$GLOBALS['items']也会成为引用,因为两个条目都必须指向同一个数组:

 ["items"]=>
  &array(7) {
    [0]=>
    string(3) "one"
    [1]=>
    string(3) "two"
    [2]=>
    string(5) "three"
    [3]=>
    string(4) "four"
    [4]=>
    string(4) "five"
    [5]=>
    string(3) "six"
    [6]=>
    string(5) "seven"
  }
  ["alter"]=>
  &array(7) {
    [0]=>
    string(3) "one"
    [1]=>
    string(3) "two"
    [2]=>
    string(5) "three"
    [3]=>
    string(4) "four"
    [4]=>
    string(4) "five"
    [5]=>
    string(3) "six"
    [6]=>
    string(5) "seven"
  }
Run Code Online (Sandbox Code Playgroud)

因此,foreach循环会迭代原始数组并更改内部指针,这会影响key().


总结:这是引用的问题,而不是$GLOBALS.