PHP References

Something you should be aware of, if you are cloning objects containing objects:
Objects are always passed as reference, so the idea of cloning the object when returning is the first thing to do if you want to avoid changing the value because you are operating on a reference. The issue is that the clone keeps the child references.

class test
{
    protected $sub;
    public function __construct()
    {
        $this->sub = new \DateTime();
    }
    
    public function getSub()
    {
        return $this->sub;
    }
}
$test = new test();
var_dump($test->getSub());
$test2 = clone $test;
// change the date from containing object
$test2->getSub()->setDate(2010, 1, 1);
// the original object containing object changed, even if we operated on a clone
var_dump($test->getSub());
/*
Output:
object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "2018-03-08 01:36:52.780668"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(10) "US/Pacific"
}
object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "2010-01-01 01:36:52.780668"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(10) "US/Pacific"
}

To clone the childs you need to override __clone(). So adding this method in the example class will prevent this behavior:

class test
{
    // ...
    
    public function __clone()
    {
        $this->sub = clone $this->sub;
    }
}
 
/* Output:
object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "2018-03-08 01:49:59.623529"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(10) "US/Pacific"
}
object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "2018-03-08 01:49:59.623529"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(10) "US/Pacific"
}
*/

Share This:

Leave a comment

Your email address will not be published. Required fields are marked *