Ниже приведён пример отлично работающего кода:
Array
(
[0] => 2
[1] => 3
[2] => 4
)
А теперь лёгким движением руки этот код превращается... превращается... в конструкцию со странным неочевидным функционалом.
Array
(
[0] => 2
[1] => 3
[2] => 3
)
Что же произошло? Собственно, ничего такого, чтобы мы сами не просили сделать PHP. В первом цикле мы объявили ссылку &$item, которая после завершения работы цикла указывает на элемент массива $list[2]. Далее мы пробегаемся ещё раз по массиву, на каждом шаге присваивая переменной $item очередное значение. Т.к. в PHP область видимости переменных не ограничивается блоком составного оператора, то переменная $item во втором цикле - это та же самая переменная из первого цикла. Поэтому, одновременно с установкой значения переменной $item, это же значение присваивается и элементу $list[2].
Шаг 0: $item = $list[2] = $list[0] = 2
Шаг 1: $item = $list[2] = $list[1] = 3
Шаг 2: $item = $list[2] = $list[2] = 3
Никаких ошибок нет, но получить-то мы хотели несколько другой результат. Есть несколько вариантов, чтобы обезопасить себя от таких неожиданностей. Первый вариант - никогда не забываем принудительно чистить переменные. Вот этот код всегда работает так, как задумано.
Пишите на PHP и прибудет с вами сила!
$list = array(1, 2, 3); foreach ($list as &$item) { $item++; } print_r($list);Запускаем, получаем логичный вывод:
Array
(
[0] => 2
[1] => 3
[2] => 4
)
А теперь лёгким движением руки этот код превращается... превращается... в конструкцию со странным неочевидным функционалом.
$list = array(1, 2, 3); foreach ($list as &$item) { $item++; } print_r($list); foreach ($list as $item) { ; } print_r($list);Мы всего лишь организовали второй цикл foreach по одному и тому массиву. И в этот раз print_r выдал совсем иные результаты.
Array
(
[0] => 2
[1] => 3
[2] => 3
)
Что же произошло? Собственно, ничего такого, чтобы мы сами не просили сделать PHP. В первом цикле мы объявили ссылку &$item, которая после завершения работы цикла указывает на элемент массива $list[2]. Далее мы пробегаемся ещё раз по массиву, на каждом шаге присваивая переменной $item очередное значение. Т.к. в PHP область видимости переменных не ограничивается блоком составного оператора, то переменная $item во втором цикле - это та же самая переменная из первого цикла. Поэтому, одновременно с установкой значения переменной $item, это же значение присваивается и элементу $list[2].
Шаг 0: $item = $list[2] = $list[0] = 2
Шаг 1: $item = $list[2] = $list[1] = 3
Шаг 2: $item = $list[2] = $list[2] = 3
Никаких ошибок нет, но получить-то мы хотели несколько другой результат. Есть несколько вариантов, чтобы обезопасить себя от таких неожиданностей. Первый вариант - никогда не забываем принудительно чистить переменные. Вот этот код всегда работает так, как задумано.
$list = array(1, 2, 3); foreach ($list as &$item) { $item++; } print_r($list); unset($item); // !!! foreach ($list as $item) { ; } print_r($list);Второй вариант - для изменения элементов массива не используем ссылки, используем конструкцию $key => $value. С ней также нет никаких проблем.
$list = array(1, 2, 3); foreach ($list as $key => $item) { $list[$key]++; } print_r($list); foreach ($list as $key => $item) { ; } print_r($list);Ну и самый правильный вариант, при котором мы не только избегаем описанной проблемы, но и многих других - максимально сокращаем область видимости переменных, выделяя логические части кода в отдельные функции. Этот вариант неплохо бы совмещать с одним из первых двух.
$list = array(1, 2, 3); $incrementList = function ($list) { foreach ($list as $key => $item) { $list[$key]++; } return $list; }; $list = $incrementList($list); print_r($list); $doList = function ($list) { foreach ($list as $key => $item) { ; } return $list; }; $list = $doList($list); print_r($list);Здесь $item первого цикла и $item второго цикла - разные переменные.
Пишите на PHP и прибудет с вами сила!