对象被意外重写

时间:2014-06-06 02:14:44

标签: php

我一直在玩这个愚蠢的问题大约一个小时了。以为我只是因为这么晚才工作而失去了大脑。

以下是一些代码:

       foreach ( ..) {

            if ($offer->device_code == 15) {

                $offer->device_code = 2;
                $offer_array[] = $offer;

                $offer->device_code = 1;
                $offer_array[] = $offer;

            } else {

            $offer_array[] = $offer;

            }
        }

        $this->offer_array = $offer_array;
        return true

在我看来,我希望在条件语句中复制device_code == 15的每个$ offer。所以我会在$ offer_array中提供两次,一次是device_code = 1,另一次是device_code = 2.

然而,

$offer->device_code = 1;

覆盖项

$offer->device_code = 2;

首先在$ offer_array中抛出的任何内容都会被覆盖。

有人可以解释为什么会这样吗?什么是解决问题的更好方法?

非常感谢。

1 个答案:

答案 0 :(得分:3)

PHP通过引用分配对象,而不是按值分配。当您使用对象$offer迭代循环并修改它以设置其device_code时,将其附加到数组然后再次修改它并再次追加它,实际上是附加两个对同一个对象到您的阵列上。当您更改其中一个属性时,即使其中一个看起来已经附加到数组,也会更改它们的属性。

如果您希望最终得到两个不同的$offer对象副本,则需要clone它。

if ($offer->device_code == 15) {

    $offer->device_code = 2;
    $offer_array[] = $offer;

    // Clone the object to an entirely new one
    $cloned = clone $offer;
    // and set its property then append to the array
    $cloned->device_code = 1;
    $offer_array[] = $cloned;

} else {

    $offer_array[] = $offer;

}

一个简单的例子:

// Make an object
$s = new stdClass;
// and an array
$a = [];
// Set some properties
$s->one = 1;
$s->two = 2;
// Stick it onto the array
$a[] = $s;
// Change a property and stick another onto the array
$s->two = 3;
$a[] = $s;
print_r($a);
// Oops, both of them have the new value $s->two = 3
Array
(
    [0] => stdClass Object
        (
            [one] => 1
            [two] => 3 <--- no longer 2
        )

    [1] => stdClass Object
        (
            [one] => 1
            [two] => 3
        )

)

// Clone one and change its property
$cloned = clone $s;
$cloned->two = 4;
$a[] = $cloned;
print_r($a);

// The clone retains its own property
// since it points to an entirely different object in memory
Array
(
    [0] => stdClass Object
        (
            [one] => 1
            [two] => 3
        )

    [1] => stdClass Object
        (
            [one] => 1
            [two] => 3
        )

    [2] => stdClass Object
        (
            [one] => 1
            [two] => 4 <-- doesn't affect the other references
        )

)