Home » Php » Object Assignment in PHP

Object Assignment in PHP

Posted by: admin July 12, 2020 Leave a comment

Questions:

First, sorry for the stupid question, but I was reading an article in php.net and I couldn’t understand what exactly it says.

<?php
class SimpleClass
{
    // property declaration
    public $var = 'a default value';

    // method declaration
    public function displayVar() {
        echo $this->var;
    }
}
?>



<?php

$instance = new SimpleClass();

$assigned   =  $instance;
$reference  =& $instance;

$instance->var = '$assigned will have this value';

$instance = null; // $instance and $reference become null

var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>

And this outputs this:

NULL
NULL
object(SimpleClass)#1 (1) {
   ["var"]=>
     string(30) "$assigned will have this value"
}

$instance and $reference point to same place, I get this and I understand why we get NULL and NULL for them.

But what about $assigned? It’s it also pointing the place where $instance is stored? Why when we use $instance->var it affects $assigned, but when we set $instance to be null, there is no change for $assigned?

I thought that the all three variables point to one place in the memory, but obviously I’m wrong. Could you please explain me what exactly happens and what is $assigned? Thank you very much!

How to&Answers:

$reference points to the value of $instance, which is itself a reference to an object. So when you change the value contained by $instance, $reference reflects this change.

$assigned, on the other hand, is a copy of the value of $instance, and independently points to the object itself to which $instance refers. So when the value $instance is updated to point to nothing (i.e. null), $assigned is not affected, since it still points to the object, and doesn’t care about the contents of $instance.

Answer:

Setting $instance = null; doesn’t update $assigned because it is not updating the data at the location where $instance points. It is instead modifying the $instance pointer itself so that pointer no longer points at the same data as $assigned.

Answer:

An object is a separate entity in memory which can have 1 or more references. If it got 0, it is garbage collected.

A variable containing an object actually points to (refers to) that object.
So when you do this:

$var1 = new Object();
$var2 = $var1;

you just create two variables, pointing to the same object ($var2 copies the value of $var1, but that value is the reference to the object).

If you then write, $var1 = null, you remove that one reference, but $var2 still points to the object.

The & operator actually returns a reference to the variable behind it, so when you write

$var1 = &var2;

then $var1 doesn’t point to the object to which $var2 points as well, but $var1 points to $var2 itself. So when you make $var2 null, $var1 points to that same null.

Answer:

With the following line, we reserve a memory location, in which storing the new Object, and a pointer to it, labeled as $instance:

$instance = new SimpleClass();

With the following line, we create a reference to the pointer $instance, labeled as $reference:

$reference =& $instance;

With the following line, we reserve a new memory location, labeled as $assigned, different and indipendent from the one above, in which we store a copy of the pointer (not the object itself) created above:

$assigned = $instance;

By setting $instance to null, you will unset only the pointer to the memory location which contains the actual object, not the object itself. Any other reference to it (for instance, $reference) will be unset as well.

$assigned is an indipendent copy of the pointer (held in another memory location), which still points to the actual object.

This is why it can be still used to refer to the actual object.

This comment found in the PHP documentation comes in support of what above said:

<?php
class A {
    public $foo = 1;
}  

$a = new A;
$b = $a;
$a->foo = 2;
$a = NULL;
echo $b->foo."\n"; // 2

$c = new A;
$d = &$c;
$c->foo = 2;
$c = NULL;
echo $d->foo."\n"; // Notice:  Trying to get property of non-object...
?>

Note

This represents a kind of exception when speaking about memory management. Whereas copying a variable or array is addressed just by to use the = operator, with objects you shall explicitely use the clone keyword, as stated in the PHP documentation:

An exception to the usual assignment by value behaviour within PHP
occurs with objects, which are assigned by reference in PHP 5. Objects
may be explicitly copied via the clone keyword.

Answer:

Short answer, when you create a reference using &, this is what happens:

$A  ===+
       |===> [symbol table entry x] ====> (memory location)
$B  ===+

When you do a normal assignment after that:

$A  ===+
       |===> [symbol table entry x] ===> (memory location)
$B  ===+                                    ^
                                            |
$C  =======> [symbol table entry y] ========+

Let’s step through the code:

$instance = new SimpleClass();

$assigned   =  $instance;

Assertion:

$assigned === $instance

Both $assigned and $instance reference the same instance of SimpleClass.

$reference =& $instance;

Assertion:

$assigned === $instance === $reference

All variables reference the same instance.

$instance->var = '$assigned will have this value';

Assertion:

$assigned === $instance === $reference

Even though a property of $instance is changed, it doesn’t affect the references.

$instance = null; // $instance and $reference become null

Because $reference is just an alias in the symbol table, it gets the same value as $instance; the reference count of the the original instance (i.e. memory location) gets reduced to 1, the $assigned variable.

Answer:

As you can see in the code

$instance = null; // $instance and $reference become null

$instance has now become equal to null, but before then $assigned was set. so $assigned did not get the null value. $reference received the null value because you referenced it with =& it keeps the value of $instance.

Answer:

It’s really simple:

$a = 3;
$b = $a;
$c = &$a;
$a = 0;

var_dump($a);
var_dump($b);
var_dump($c);

The output will be:

int(0)
int(3)
int(0)

So it not only object assignment but also normal assignment.