Here are some cloning and reference gotchas we came up against at Last.fm.
1. PHP treats variables as either 'values types' or 'reference types', where the difference is supposed to be transparent. Object cloning is one of the few times when it can make a big difference. I know of no programmatic way to tell if a variable is intrinsically a value or reference type. There IS however a non-programmatic ways to tell if an object property is value or reference type:
<?php
class A { var $p; }
$a = new A;
$a->p = 'Hello'; var_dump($a);
$ref =& $a->p; var_dump($a);
?>
2. unsetting all-but-one of the references will convert the remaining reference back into a value. Continuing from the previous example:
<?php
unset($ref);
var_dump($a);
?>
I interpret this as the reference-count jumping from 2 straight to 0. However...
2. It IS possible to create a reference with a reference count of 1 - i.e. to convert an property from value type to reference type, without any extra references. All you have to do is declare that it refers to itself. This is HIGHLY idiosyncratic, but nevertheless it works. This leads to the observation that although the manual states that 'Any properties that are references to other variables, will remain references,' this is not strictly true. Any variables that are references, even to *themselves* (not necessarily to other variables), will be copied by reference rather than by value.
Here's an example to demonstrate:
<?php
class ByVal
{
var $prop;
}
class ByRef
{
var $prop;
function __construct() { $this->prop =& $this->prop; }
}
$a = new ByVal;
$a->prop = 1;
$b = clone $a;
$b->prop = 2; $a = new ByRef;
$a->prop = 1;
$b = clone $a;
$b->prop = 2; ?>