foreach處理對象數組:是處理對象的引用,所以經過foreach處理後,對象數組中的對象的數據發生了改變。
foreach處理普通數組:把原數組拷貝一個後,再從中拿出每個元素,我們使用foreach對這些元素進行處理,並不是對原數組的處理,而只是對一個拷貝的處理,所以不管我們怎麼改變其值,原數組的值是不會改變的。
例子如下:
/**
* 先編寫一個簡單的類,存儲HTML控件數據的類
*/
class Element {
/**
* 這裏只作演示,一切簡單化處理
*/
protected $name;
protected $value;
public function __construct($name,$value){
$this->name = $name;
$this->value = $value;
}
public function setName($name){
$this->name = $name;
}
}
$element_list = array();
for($i=0;$i<2;$i++){//生成一個擁有2個Element對象的數組
$element_list[] = new Element('name_'.$i,'value_'.$i);
}
//先打印出$element_list,查看$element_list當前數據
echo '--------old $element_list start--------';
print_r($element_list);
echo '--------old $element_list end--------';
/**
* 使用foreach對$element_list的元素進行處理
* 處理過後,$element_list的元素應該和原來一樣,是不變的
* 因爲foreach不會對原數組的值產生影響
*/
foreach($element_list as $key=>$element){
$element->setName('changed');
}
//我們再打印$element_list來看看它當前的值
echo '--------new $element_list start--------';
print_r($element_list);
echo '--------new $element_list end--------';
/*以下是輸出結果
--------old $element_list start--------
Array
(
[0] => Element Object
(
[name:protected] => name_0
[value:protected] => value_0
)
[1] => Element Object
(
[name:protected] => name_1
[value:protected] => value_1
)
)
--------old $element_list end---------
-------new $element_list start--------
Array
(
[0] => Element Object
(
[name:protected] => changed
[value:protected] => value_0
)
[1] => Element Object
(
[name:protected] => changed
[value:protected] => value_1
)
)
--------new $element_list end--------
*/
從輸出結果可以看出$element_list中對象的數據已經改變,這和原先 我們所瞭解的使用foreach遍歷數組元素,對元素進行處理不會影響到原數組的值是相沖突的,是不是PHP有BUG呢?並不是,出現這種情況的原因 是,PHP5對所有對象都是使用引用,這與PHP4是完全不同的,PHP4在新建對象是要使用&操作符來說明等到的是對象的引用。
既然是引用,那麼$element_list數組裏面存儲的也都只是 Element對象的引用而不是一個對象拷貝。然後我們回到foreach中來,foreach處理數組時,是把原數組拷貝一個後,再從中拿出每個元素, 我們使用foreach對這些元素進行處理,並不是對原數組的處理,而只是對一個拷貝的處理,所以不管我們怎麼改變其值,原數組的值是不會改變的(這個只 對普通的變量有用,PHP5中的對象就不適用了)。如果當前數組是對象數組,那麼在PHP5下,其值就是對象的引用,當我們使用foreach對其進行處 理時,情況是這樣的,如下:
1.首先拷貝一個$element_list,我們把它叫做$element_list_copy。在foreach的處理中,所有處理都是對$element_list_copy數組的處理,並不影響原數組$element_list
2.得到$element_list_copy中的一個元素,對其進行處 理,此時$element_list_copy中的元素也是一個$Element對象的引用,它和$element_list中的值是一樣的,都是一 個$Element對象的引用,它們兩個指向的是同一塊內存空間,所以對$element_list_copy元素的處理和對$element_list 元素的處理,所操作的數據塊是相同的,也就是$element_list_copy中的元素改變了,$element_list中的元素也會相應地改變, 因爲$element_list_copy和$element_list的元素所指向的是同一塊內存,都是同一個$Element對象。
這也就是爲什麼經過foreach處理後,對象數組$element_list中的對象的數據發生了改變。千萬要注意PHP5下對象數組及一般數組使用foreach處理的區別,不然就很有可能出現讓人摸不着頭腦的錯誤產生。