2013-10-28 162 views
0

早上好,PHP:为什么两个类实例共享相同的数据?

我似乎是codeblind为我自己的代码,所以我想问一些额外的眼睛和一些代码的建议,如果写几周前。

守则(缩短)

class TrackingCostCollection { 
    private $available=0; 
    private $ordered=0; 
    private $differenceNumKits=0; 

    public function fill ($row) { 
    ... 
    } 

    /** 
    * @var TrackingCostCollection $collection 
    */ 
    public function merge ($collection) { 

    $this->available += $collection->available; 
    $this->ordered += $collection->ordered; 
    $this->differenceNumKits= $this->available-$this->ordered; 
    } 
} 

的问题

当迭代和由数据字段我遇到存储内的两个不同的两个不同的类的实例的问题之一分组数据数组包含相同的数据,虽然我不明白为什么?当我使用一个额外的“克隆”的问题消失,但我想了解为什么我的代码的行为方式是这样:

foreach ($arrValues as $row) { 
    ... 
    $this->calculateStatistics($row); 

} 


private function calculateStatistics ($row) { 
    $fieldValue= $row['country']; 
    $collection = new TrackingCostCollection(); 
    $collection->fill($row); 

    if (!isset($this->arrStatistics[$fieldValue])) { 
    $this->arrStatistics[$fieldValue] = $collection2; 
    } else { 
    /* @var TrackingCostCollection $previousCollection2 */ 
    $previousCollection = $this->arrStatistics[$fieldValue]; 
    $previousCollection->merge($collection2); 
    $this->arrStatistics[$fieldValue] = $previousCollection; 
    unset($previousCollection); 
    } 

    // using $collection instead of $collection2 will cause 
    // two array entries containing the same data 

    $collection2= clone $collection; 
    if (!isset($this->arrTotals[$fieldValue])) { 
    $this->arrTotals[$fieldValue] = $collection2; 
    } else { 
    /* @var TrackingCostCollection $previousCollection2 */ 
    $previousCollection = $this->arrTotals[$fieldValue]; 
    $previousCollection->merge($collection2); 
    $this->arrTotals[$fieldValue] = $previousCollection; 
    unset($previousCollection); 
    } 
} 

如果更多的代码是必要的诊断问题的原因只是让我知道我会添加更多。

非常感谢您的时间!

+1

,克隆返回$收集的副本,并将其分配给$ collection2 – demonking

+0

默认对象由PHP参考定义。 – PeeHaa

+0

使用__clone()回调来解决此问题;就像其他评论者提到的那样 –

回答

1

我承认我没有通过任何详细的代码了,但我想你是有这个问题:

[...]的对象变量不包含对象本身作为价值[...]。它只包含一个对象标识符,它允许对象访问器找到实际的对象。当一个对象通过参数发送,返回或分配给另一个变量时,不同的变量[...]保存标识符的副本,该标识符指向同一个对象。

http://php.net/manual/en/language.oop5.references.php

如果你想使对象的两个独立的副本,你需要clone它。如果你不这样做,那么你传递的是同一个对象,任何通过这个对象的人都可以看到对它的修改。例如: -

$obj = new stdClass; 
$obj->foo = 'bar'; 

function modify(stdClass $obj) { 
    $obj->foo = 'baz'; 
} 

modify($obj); 

echo $obj->foo; // baz 
因为克隆
+0

非常感谢我指向OOP手册部分,现在我明白了。我很困惑,因为我认为我根本没有修改$ collection变量,但我完全忘记了我在$ this-> arrTotals和$ this-> arrStatistics中存储了指向$ collection对象的指针,所以这就是导致问题。 – SaschaM78

相关问题