Подтвердить что ты не робот

Ошибка или взлом? $GLOBALS

$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)

Почему так странный результат?

4b9b3361

Ответ 1

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

Мы знаем, что 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.