1

I have some code that appears to behave differently between PHP 4 and PHP 5. 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
                                    // resetting 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 PHP 4, 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 PHP 5? What can I do to force foo2 to make a copy of this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Doug T.
  • 64,223
  • 27
  • 138
  • 202

4 Answers4

3

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Matijs
  • 2,533
  • 20
  • 24
3

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

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
)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
VolkerK
  • 95,432
  • 20
  • 163
  • 226
2

Yes, PHP 5 is now copying by reference. Now you have to clone the object to make a copy of it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
t00ny
  • 1,598
  • 1
  • 11
  • 8
1

PHP has used references since version 5. To copy objects, use:

$copy = clone $object;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Martin Wickman
  • 19,662
  • 12
  • 82
  • 106