2013-02-28 138 views
3

我試圖將包含來自sql結果集的元素的對象插入到數組中。我的代碼是這樣的:在foreach循環後覆蓋的數組

$data = array(); 
$sql = "SELECT id,type,name,username FROM users"; 
foreach ($conn->query($sql) as $row) { 
    $this->set_id($row['id']); 
    $this->set_type($row['type']); 
    $this->set_username($row['username']); 
    $this->set_password($row['password']); 

    $data[] = $this; 
} 

我ResultSet是正確的,但我得到的foreach循環結束後的值覆蓋從過去的記錄我的陣列單元。例如,如果我有這些結果{1,'type1','user','pass'}{2,'type2','foo','bar'},當我print_r我的$data數組循環的外側,我只得到第二個結果集重複兩次。我究竟做錯了什麼?

+2

您每次循環時更新$ this的單個實例,然後將每個數組元素指向相同的$ this ....如果$ this是您的模型,那麼您需要每個數組元素的新實例 – 2013-02-28 09:28:06

回答

3

在實例方法中,$this總是指向當前類實例;在每次循環迭代中,您都修改實例本身,然後將其添加到$data;但是在賦值的時候不會創建副本,而是添加對同一個實例的引用。

最後你在每個索引處都有一個具有相同對象的數組。

您將需要創建你在每次循環是類的新實例:

foreach ($conn->query($sql) as $row) { 
    $obj = new self; // create new instance of ourselves 

    $obj->set_id($row['id']); 
    $obj->set_type($row['type']); 
    $obj->set_username($row['username']); 
    $obj->set_password($row['password']); 

    $data[] = $obj; 
} 

這是一個個人的建議,但我要麼動一靜方法或這裏面的代碼單獨上課。

0

無論$this是什麼,它都是對某種對象的引用。因此,當您更新該對象時,保存在數組中的所有引用仍然指向同一個對象。你必須在每個循環中定義一個新的對象。

+1

Downvoter關心評論? – yourdeveloperfriend 2013-02-28 09:35:33

+0

Upvoted以彌補;) – leafnode 2013-02-28 10:16:43

0

您在迭代開始時並未創建新的$this對象。在這兩個迭代中,您都在修改同一個對象,並將它添加到數組中。處理對象時,它們通過引用傳遞,這意味着您不會向數組添加副本,而是添加對$ this變量的引用。也許您應該將$row添加到數組中,但您仍然會將保存的數據覆蓋到$this

您也可以使用clone關鍵字(請參閱manual)保存對象的副本。

更多信息:http://php.net/manual/en/language.references.php

+0

關於-1的任何解釋? – leafnode 2013-02-28 09:57:54

+0

你是否同樣​​喜歡。我認爲有人只是-1我們所有人。 – yourdeveloperfriend 2013-02-28 17:31:29

1

對象不一樣,工作,$this總是相同的對象,並對其進行修改在每個迭代。你可能使用$data[] = clone $this;每次創建一個新的實例,但這是不好的類設計,你最好把你的課分成兩個獨立的類。

一個類不應該有一個以上的責任,但是你的行爲同時充當數據庫網關和域模型。

+0

+1對於很好的解釋:) – 2013-02-28 09:37:30

+0

謝謝fab,我解決了這個分離模型和數據庫任務! – stebcom 2013-02-28 10:24:14