/ PHP

PHP의 foreach 버그

코드1

$array = array('a','b','c','d','e','f');

foreach($array as &$v) {
	echo $v;
}

echo PHP_EOL;

foreach($array as $v) {
  echo $v;
}

foreach 로 배열을 두번 돌렸다. 한번은 By Reference, 한번은 By Value 로 돌렸다. 그랬더니 결과는 기대와 다르게 아래와 같이 나왔다.

abcdef
abcdee

PHP에서는 변수 선언이 따로 없고, { } (Code Block) 안에서 새로운 변수를 썼다고 해서 해당 블럭 안에서만 사용되는 지역변수가 아니기 때문에 발생하는 현상이다.

그런데 왜 하필이면 맨 마지막에 a도, b 도 아닌 e가 들어갔을까? 아래의 코드를 돌려보면 원인을 어느정도 짐작 할 수 있다.

코드2

function prettyPrintArray($array) {
	foreach($array as $_v) echo "{$_v}";
	echo PHP_EOL;
}

$array = array('a','b','c','d','e','f');

foreach($array as &$v) { }

foreach($array as $v) {
	prettyPrintArray($array);
}

$v = "test";
prettyPrintArray($array);

위 코드는 아래와 같은 결과를 보여준다.

abcdea
abcdeb
abcdec
abcded
abcdee
abcdee
abcdetest

결과를 보면 첫번째 foreach 문에서 사용했던 $v 는 레퍼런스 속성을 그대로 가지고 코드 끝까지 영향을 미치고 있다. foreach 문에서 비록 $v 라고 쓰였지만, PHP 에서 새로운 foreach 문을 사용하기 시작할 때 $v 의 속성을 초기화 하지 않음으로 생긴 문제이다. 이해가 아직 쉽게 되지 않으면 아래의 코드3을 먼저 보고 코드2를 보면 좀 더 쉽게 이해를 할 수 있을 것이다.

코드3

function prettyPrintArray($array) {
	foreach($array as $_v) echo "{$_v}";
	echo PHP_EOL;
}

$array = ['a','b','c','d','e','f'];

foreach($array as &$v)
	echo $v;

$v = "test";

echo PHP_EOL;

prettyPrintArray($v);

foreach 로 돌리면서 할당했던 $value 를 아래에서 수정했다. 결국 아래와 같이 배열의 마지막 내용이 변경되어있다.

abcdef
abcdetest

이 문제를 해결하려면 foreach 문이 끝나고 해당 변수를 unset 해주는 것으로 임시 대처가 가능하다.