错误还是黑客? $全局变量

发布于 2024-11-08 16:18:05 字数 520 浏览 0 评论 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"]));
}

检查此代码的输出,包括注释和未注释的第二行。 我的结果(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["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"]));
}

Check output of this code, with commented and uncommented second line.
My result(PHP 5.3.0).
With second line

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

Without second line:

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

Why so strange result?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

喜爱皱眉﹌ 2024-11-15 16:18:06

这是一个可能的解释:

我们知道 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"
  }

无引用)

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


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

Here is a possible explanation:

We know that foreach always loops over a copy of the array if it is not referenced:

Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer.

That means that the internal pointer of the original array is not changed and key() will always return the same value (as we can see when we comment out the line). And indeed if we do a var_dump($GLOBALS), we get:

 ["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"
  }

(no reference)

But as soon as we generate a reference to the array (with $alter), $GLOBALS['items'] becomes a reference too, because both entries have to point to the same array:

 ["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"
  }

Hence, the foreach loop does iterate over the original array and changes the internal pointer, which affects key().


To sum up: It is a problem with references, not with $GLOBALS.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文