早上好,
我似乎对自己的代码是盲目的,所以如果几周前写的一段代码,我想请一些额外的眼睛和建议。
守则(缩短)
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);
}
}
如果需要更多代码来诊断问题的原因,请告诉我,我会添加更多代码。
提前感谢您的时间!
我承认没有详细浏览您的代码,但我想您对此有问题:
对象变量不包含对象本身作为值 [...]。它只包含一个对象标识符,允许对象访问器查找实际对象。当一个对象通过参数发送,返回或分配给另一个变量时,不同的变量[...]保存标识符的副本,该标识符指向同一对象。
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