說說PHP中foreach引用的一個坑
阿新 • • 發佈:2019-02-17
先來看看下面這段程式碼:
<?php $arr = array('apple','banana','cat','dog'); foreach($arr as $key=>$val) { //some code } echo $val; //輸出dog echo $key; //輸出3 //下面對val進行賦值 $val = 'e'; print_r($arr); //輸出Array ( [0] => apple [1] => banana [2] => cat [3] => dog )
說明:在上面的foreach迴圈中,當迴圈結束後,$key和$val變數都不會被自動釋放掉。值會被儲存下來。而且此時修改$val的值不會影響$arr。
引用:如果想在遍歷陣列的過程中修改陣列的元素,可以在foreach中對$val使用引用。此時被引用的元素$val指向當前陣列元素的記憶體地址,即共享一段記憶體地址。因此修改$val的值會同時改變$arr[$key]的值。
再來看看下面一段在foreach中使用引用的程式碼,這是最近在專案中遇到的一種情況:
<?php $arr = array('apple','banana','cat','dog'); //在foreach中使用引用 foreach($arr as $key => &$val) { $val = 'new value'; } echo $val; //輸出new value echo $key; //輸出3 $val = 'egg'; print_r($arr); //輸出Array ( [0] => new value [1] => new value [2] => new value [3] => egg )
說明:在foreach中使用&引用後,當foreach結束後,$key和$val變數也都不會被自動釋放掉,但是此時$val和$arrcount($arr) - 1指向相同的記憶體地址。因此,此時修改$val的值也會改變了$arr[3]的值。
這種情況下很容易犯的錯誤就是像上面例子所示,在迴圈外面繼續使用被foreach引用的變數,這樣會使開發者得不到預期的資料。因此,為了避免這種情況的發生,應該在適當的位置釋放變數的引用。以上面的程式碼為例:
<?php $arr = array('apple','banana','cat','dog'); //在foreach中使用引用 foreach($arr as $key => &$val) { $val = 'new value'; } unset($val); echo $val; //報錯,Notice: Undefined variable: val echo $key; //輸出3 $val = 'egg'; print_r($arr); //輸出Array ( [0] => new value [1] => new value [2] => new value [3] => new value ) 在foreach結束後unset $val,此時會釋放對$val的引用。因此改變$val不會對$arr造成影響。
這是最近在專案中遇到的坑和解決方案的總結,如果錯誤或更好地建議,歡迎指出。
原文地址:http://www.aintnot.com/2015/04/25/talk-about-a-hole-in-php-foreach-quote/