|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75158 Cloning objects whith members that hold references to other members
Submitted: 2017-09-05 15:27 UTC Modified: 2017-09-06 09:04 UTC
From: krulis at ksi dot mff dot cuni dot cz Assigned:
Status: Not a bug Package: Class/Object related
PHP Version: 7.1.9 OS: all
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Bug Type:
From: krulis at ksi dot mff dot cuni dot cz
New email:
PHP Version: OS:


 [2017-09-05 15:27 UTC] krulis at ksi dot mff dot cuni dot cz
When I have an object and one member variable is a reference to another member variable, clone of such object is not correctly constructed. In the test script, you can see Foo class with two members: $data and $ref. $ref is set to be a reference to $data of the same object.

When object of foo is cloned. The clone's $data is in fact reference to original object's $data. In other words, clone should in fact do $c->data = $o->data (shallow copy by = operator), but instead, it seems like $c->data =& $o->data.

Note that the references are in fact not used, and when they are removed (line in the constructor is commented), it starts to work correctly again. I have also tested integer values in $data (beside arrays) and they work all the same.

This behavior was observed on Windows 7.1.9 and Linux 5.6.26. A similar problem was described in #66040, but I am not sure, whether they are connected or not.

Test script:
class Foo {
	public $data = [];
	public $ref;
	public function __construct()
		$this->ref =& $this->data;

$o = new Foo();
$c = clone($o);
$o->data[] = 42;

var_dump($c->data);  // writes out an array with one item (42), even though the array should be empty

Expected result:
I would expect that $c->data === [] at the end.


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2017-09-05 17:15 UTC]
I don't think this is a's just that references are really, really, confusing.

For the line "$this->ref =& $this->data;" this does not create a variable called 'ref' that is a reference to the 'real' variable called 'data'. 

Instead it moves the variable elsewhere and sets both 'data' and 'ref' to be a reference to that variable. This in unlike other programming languages that use pointers. In those, creating a point to a value does not affect how the original value is stored. But in PHP, creating a reference does make the original property become a reference.

A workaround for this is to explicitly copy the values, destroy the variable with unset() to remove the fact that it's a reference to another variable, and then copy the values over.

class Foo {
    public $data;
    public $ref;
    public function __construct() {
        $this->data = [];
        $this->ref = &$this->data;

    public function __clone() {
        $values = (array)$this->data;
        $this->data = [$values];
        $this->ref = &$this->data;

$o = new Foo();
$o->data[] = 1;

$c = clone($o);
$o->data[] = 42;

Or you could just not use references.
 [2017-09-06 09:04 UTC]
-Status: Open +Status: Not a bug
 [2017-09-06 09:04 UTC]
Closing as not a bug, because I think that's how references 'work'.
PHP Copyright © 2001-2023 The PHP Group
All rights reserved.
Last updated: Fri Dec 08 07:01:27 2023 UTC