Php 臭虫还是黑客$全球的

Php 臭虫还是黑客$全球的,php,arrays,global-variables,Php,Arrays,Global Variables,检查此代码的输出,第二行有注释和无注释。 我的结果(PHP5.3.0)。 第二行 $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 g

检查此代码的输出,第二行有注释和无注释。 我的结果(PHP5.3.0)。 第二行

$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"]));
}
没有第二行:

int(1) int(2) int(3) int(4) int(5) int(6) NULL

为什么会有如此奇怪的结果?

这里有一个可能的解释:

我们知道,
foreach
始终:

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

这意味着原始数组的内部指针未更改,并且
key()
将始终返回相同的值(我们在注释该行时可以看到)。事实上,如果我们进行
var\u转储($GLOBALS)
,我们会得到:

int(1) int(1) int(1) int(1) int(1) int(1) int(1)
(无参考资料)

但一旦我们生成对数组的引用(使用
$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"
  }
因此,
foreach
循环确实会迭代原始数组,并更改内部指针,从而影响
key()



总而言之:这是引用的问题,而不是
$GLOBALS

我很诚实。。我不知道。。获取$GLOBALS的指针不应该改变变量。显然$alter接管了控制权。如果在分配数组后将$alter设置为NULL,则该数组甚至无效,并在以下循环中导致错误。这可能与
$GLOBALS
实际上是一个引用数组本身有关。PHP中的引用总是很时髦。@BoltClock,您可以将$GLOBALS替换为另一个数组变量,这个hack也很有效。)我不明白为什么这应该是一个“hack”。优势是什么?在我看来,这要么是一个bug,要么是一种奇怪的行为,要么是可以解释的。+1我想象有个可怜的家伙试图在foreach循环中更改这个复制数组的值。
 ["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"
  }