PHP:为什么两个类实例共享相同的数据?
早上好 我似乎对自己的代码是盲的,所以如果几周前写了一段代码,我想请求一些额外的帮助和建议 代码(缩短) 问题 当通过其中一个数据字段对数据进行迭代和分组时,我遇到了一个问题,即存储在两个不同数组中的两个不同类实例包含相同的数据,尽管我不知道为什么?当我使用一个额外的“克隆”时,问题就消失了,但我想了解为什么我的代码会以这种方式运行:PHP:为什么两个类实例共享相同的数据?,php,oop,Php,Oop,早上好 我似乎对自己的代码是盲的,所以如果几周前写了一段代码,我想请求一些额外的帮助和建议 代码(缩短) 问题 当通过其中一个数据字段对数据进行迭代和分组时,我遇到了一个问题,即存储在两个不同数组中的两个不同类实例包含相同的数据,尽管我不知道为什么?当我使用一个额外的“克隆”时,问题就消失了,但我想了解为什么我的代码会以这种方式运行: foreach ($arrValues as $row) { ... $this->calculateStatistics($row); }
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);
}
}
如果需要更多代码来诊断问题的原因,请告诉我,我会添加更多代码
提前感谢您抽出时间 我承认没有详细阅读您的代码,但我想您在这方面有问题: […]对象变量不包含对象本身作为值[…]。它只包含一个允许对象访问器查找实际对象的对象标识符。当一个对象通过参数发送、返回或分配给另一个变量时,不同的变量[…]持有指向同一对象的标识符副本 如果要制作一个对象的两个独立副本,则需要对其进行克隆。如果不这样做,则传递的是同一个对象,对该对象的修改将对传递该对象的任何人可见。例如:
$obj = new stdClass;
$obj->foo = 'bar';
function modify(stdClass $obj) {
$obj->foo = 'baz';
}
modify($obj);
echo $obj->foo; // baz
由于克隆,clone返回$collection的一个副本并将其分配给$collection2b,因为默认对象是在PHP中通过引用定义的;这就像我在上一篇评论中提到的其他评论员一样,我忘记了我在两个数组中都存储了指向$collection对象的相同指针,从而导致了重复。谢谢!非常感谢你给我指出OOP手册部分,现在我明白了。我感到困惑,因为我认为我根本没有修改$collection变量,但我完全忘记了我将指向$collection对象的指针存储在$this->arrTotals和$this->arrStatistics中,所以这就是问题的原因。
$obj = new stdClass;
$obj->foo = 'bar';
function modify(stdClass $obj) {
$obj->foo = 'baz';
}
modify($obj);
echo $obj->foo; // baz