【问题标题】:Bug or hack? $GLOBALS错误还是黑客? $全球
【发布时间】:2011-05-21 09:39:19
【问题描述】:
$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)

为什么会有这么奇怪的结果?

【问题讨论】:

  • 老实说..我不知道..获取 $GLOBALS 的指针不应该改变变量。
  • 不错的技巧。显然 $alter 接管了控制权。如果在分配数组后将 $alter 设置为 NULL,则数组甚至会变为无效,并导致以下循环出错。
  • 这可能与$GLOBALS 本身就是一个引用数组有关。 PHP 中的引用总是很时髦。
  • @BoltClock,您可以将 $GLOBALS 替换为另一个数组变量,这个 hack 也可以)))
  • 我不明白为什么这应该是一个“黑客”。有什么好处?在我看来,这要么是一个错误、奇怪的行为,要么是可以解释的。

标签: php arrays global-variables


【解决方案1】:

这是一个可能的解释:

我们知道foreach 总是loops over a copy of the array if it is not referenced

除非数组是referenced,否则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"
  }

(无参考)

但是,一旦我们生成了对数组的引用(使用$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"
  }

因此,foreach 循环确实会遍历 原始数组 并更改内部指针,这会影响 key()


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

【讨论】:

  • +1 我想象一个可怜的家伙试图在 foreach 循环中更改这个复制数组的值。
猜你喜欢
  • 2021-05-19
  • 1970-01-01
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-03
相关资源
最近更新 更多