views:

168

answers:

4

I have some code that appears to behave differently between php4 and php5. This code below:

class CFoo
{
    var $arr;

    function CFoo()
    {
        $this->arr = array();
    }

    function AddToArray($i)
    {
        $this->arr[] = $i;
    }

    function DoStuffOnFoo()
    {
        for ($i = 0; $i < 10; ++$i)
        {
            $foo2 = new CFoo();
            $foo2 = $this;          // I expect this to copy, therefore
                                    // reseting back to the original $this
            $foo2->AddToArray($i);
            echo "Foo2:\n";
            print_r($foo2);
            echo "This:\n";
            print_r($this);
        }
    }
}

$foo1 = new CFoo();
$foo1->DoStuffOnFoo();

Previously, in php4, the assignment of $foo2 above would reset $foo2 back to the value that $this was originally set at. In this case, I would expect it to be set to a CFoo with an empty $arr member. However, the assignment of $foo2 to $this is acting as an assignment by reference. Foo2 is acting as an alias to this. Therefore when I call "AddToArray" on foo2, $this's $arr is also being appended to. So when I go to reassign foo2 back to this, instead of getting the initial value of this, I get essentially a self assignment.

Has this behavior changed in php5? What can I do to force foo2 to make a copy of this?

+2  A: 

In php 4 a copy was made of an object iunless you assigned it by reference (using &=). In php 5 a reference to the object is assigned.

So after assigning $this to $foo2, $foo2 points to $this and not to a new copy of CFoo.

To make a copy in php 5 you say clone $this.

In either case the previous new statement is wasted.

Matijs
how do I force a copy?
Doug T.
Just added the answer.
Matijs
+3  A: 

The object-orientated part of php has been hugely overhauled in php5. Objects are now passed (not exactly but almost) as references.
see http://docs.php.net/clone

edit: example

$x1 = new StdClass;
$x1->a = 'x1a';

$x2 = $x1;
$y = clone $x1;

// performing operations on x2 affects x1 / same underlying object
$x2->a = 'x2A';
$x2->b = 'x2B';

// y is a clone / changes do not affect x1
$y->b = 'yB';

echo 'x1: '; print_r($x1);
echo 'y:'; print_r($y);

prints

x1: stdClass Object
(
    [a] => x2A
    [b] => x2B
)
y:stdClass Object
(
    [a] => x1a
    [b] => yB
)
VolkerK
+1  A: 

Php uses references since version 5. To copy objects use:

$copy = clone $object;

Martin Wickman
+2  A: 

yes php5 is now copying by reference, now you have to clone the object to make a copy of it.

t00ny