上代碼
$arr = array( 'a'=> 'a11', 'b'=> 'b22', 'c'=> 'c33', ); foreach ($arr as $k=>&$v){ // Do somethind } foreach ($arr as $k=>$v){ var_dump($v); }
這樣的代碼, var_dump 會輸出什麼? 各位可以試試, 答案
string(3) "a11" string(3) "b22" string(3) "b22"
結果裡, 第三行變成了 key='b' 的value. 問題就出在第一個循環的引用.
今天就踩到了一個這樣的坑, 查問題用了很久. 簡單來說, foreach循環使用的引用, 循環結束後有所保留. php.net 著重寫了:
Warning
Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().
對於上面這個例子, 第一個循環結束後, $v引用仍然存在. 由於兩個循環的變量命名一致, 第二個循環開始, $v 每次都會被賦值. 直到最後, $v 被設置成了
前一個元素的值.
原理很簡單, 文檔寫的明明白白. 但如果工作中遇到相關的bug是很坑的, 定位需要很久. 還得需要寫碼的時候就注意:
1. 減少引用的使用
2. 如果需要在foreah使用引用, 應該用函數將封裝起來