unset
5 сентября 2011
Ещё одна интересная особенность PHP, которую хорошо бы знать, чтобы не терять много времени при встрече с ссылочным foreach:
$val = '2'; $arr = array('1', &$val); var_dump($arr); unset($val); var_dump($arr);
Штука действительно очень зла, если про неё забыть. Максим напоминал мне больше, чем целый день…
Комментарии RSS по email OK
Интересно, а какое поведение ожидалось?
это один из тех случаев, которые никогда не должны встретиться в реальном проекте. однако некая нелогичность, безусловно, присутствует:
Если вдуматься, то тут, в принципе, всё логично. Мы имеем две ссылки на одно значение, потом одну убрали (unset), вторая осталась
kipelovets, если проект — база для тысяч приложений и хочется нечто сделать максимально быстро и эффективно, может и встретиться.
Вообще, конечно, поведение логично, если не забывать про то, как на самом деле работают ссылки.
Ох и намучался я объяснять ) Но момент и вправду очень тонкий. Сэм если захочет даст реальный пример где я его выловил.
Было бы неплохо увидеть в живую
Это был баг в Yii. После фикса, правда, подумали ещё и убили источник проблемы.
Ну убивать источник проблемы может было немного излишне, но с & + foreach нужно просто вдолбить себе в голову как аксиому - переменную по ссылке после цикла нужно уничтожить через unset. Иногда этот синтаксис очень неплохо вписывается. Тут как с любым продвинутым инструментом - удобно, круто и можно отрезать себе ногу при неправильном обращении :)
Да, я тоже как-то раз столкнулся с этим foreach со ссылками. Там тоже было интересно. Было 2 цикла foreach подряд (что-то вроде foreach ($array1 as &$element)... а после него foreach ($array2 as &$element)). Попробуйте — будет весело :)
Spider Да я тоже один раз такую ошибку допустил, минут 5 пытался понять что не так, потом дошло что ссылки виноваты. С тех пор всегда делаю unset сразу ещё до написания тела цикла
Да, проблема может легко добавить головной боли в крупном проекте. Но хорошо написанный тест спасет в этой ситуации ;)
Про баг в yii: написал в code-review на гугле, но продублирую и здесь. Далее по коду используется isset() на изменяемые элементы массива. После изменения unset не производится и проверка может отработать не так, как ожидается.
ostin, там же уже отписались ;)