Typical OO rules specify that you are provided with either the original memory or a link to the original memory (as in PHP and Java). The reference is different, but they both dereference to the same memory space.
Cloning is used to copy an object in its entirety to a new memory space. This includes all primitives and any reference to objects. So if you have a property that is an object, both the original and the clone will still share the same reference to the property and updates are reflected within both.
Objects are not created with an assignment. They are created when new is called on the class.
As for by reference, no they are different. Objects don't carry their memory pointers during assignment, they carry an object pointer which is simply a pointer to the memory location. Typical usage of the = &$obj will appear to function the same, but it is not and will not work in all situations:
PHP Code:
<?php
class A
{
public $inner;
public function __construct(B $inner)
{
$this->inner = $inner;
}
}
class B
{
public $desc;
public function __construct($desc = "I'm the first B")
{
$this->desc = $desc;
}
}
$b = new B();
$a = new A($b);
$aCopy = $a;
$aRef = &$a;
$aClone = clone $a;
// These will all say I'm the first B
print_r($a);
print_r($aCopy);
print_r($aRef);
print_r($aClone);
function modifyBValue(A $in)
{
$in->inner->desc = "Value change in " . __FUNCTION__;
}
print str_repeat('-', 100) . PHP_EOL;
modifyBValue($a);
// These should now all indicate B value was changed in modifyBValue.
print_r($a);
print_r($aCopy);
print_r($aRef);
print_r($aClone);
function modifyB(A $in)
{
$in->inner = new B("Assigned in " . __FUNCTION__);
}
print str_repeat('-', 100) . PHP_EOL;
modifyB($a);
// These should now all indicate B object was changed in modifyB
print_r($a);
print_r($aCopy);
print_r($aRef);
// This should still say it was modified in modifyBValue:
print_r($aClone);
function modifyANonRef(A $in)
{
$in = new A(new B());
}
print str_repeat('-', 100) . PHP_EOL;
modifyANonRef($a);
// None of these will change:
print_r($a);
print_r($aCopy);
print_r($aRef);
print_r($aClone);
// Here's where we see the difference in byref:
function modifyA(A &$in) // <-- This requires the & in order to modify the original variable and NOT the object pointer (which would have no effect)
{
$in = new A(new B());
}
print str_repeat('-', 100) . PHP_EOL;
modifyA($a); // or just a $a = new A(new B()) would work too
// I'm the first B
print_r($a);
// Assigned in modifyB
print_r($aCopy);
// I'm the first B
print_r($aRef);
// Value change in modifyBValue
print_r($aClone);
So as you can see
$aCopy = $a; and
$aRef = &$a; do not actually do the same thing. There is limited situations for this, which would be the reassignment of a variable using a copy context in a function for example.
This is why when we say objects in PHP are passed by reference it is NOT actually true, but in MOST situations it seems that way. Objects in PHP are passed by OBJECT reference.
BTW, you can override __clone as well to perform a deep copy if you want. That would involve issuing a clone on the $inner in my example, which would make the $aClone never change to reflect that of $a.