错误或黑客?$GLOBALS

2022-08-30 23:40:11
$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"]));
}

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

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

不带第二行:

int(1) int(1) int(1) int(1) int(1) int(1) int(1)

为什么结果这么奇怪?


答案 1

以下是一个可能的解释:

我们知道,如果未引用数组的副本,则始终循环访问该数组的副本foreach

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

这意味着原始数组的内部指针不会更改,并且将始终返回相同的值(正如我们在注释掉行时所看到的那样)。事实上,如果我们做一个,我们得到: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"
  }

(无参考资料)

但是,一旦我们生成对数组(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"
  }

因此,循环会循环访问原始数组并更改内部指针,这会影响 。foreachkey()


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


答案 2