Ошибка или взлом? $ GLOBALS - PullRequest
17 голосов
/ 21 мая 2011
$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 Ответ

12 голосов
/ 21 мая 2011

Вот возможное объяснение:

Мы знаем, что 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 перебирает исходный массив и изменяет внутренний указатель, что влияет на key().


Подводя итог: это проблема со ссылками, а не с $GLOBALS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...