Introduction to Objects and References in PHP Memory


I first drafted this article while studying for my PHP certification in an effort to better understand how PHP manages variables and objects in memory. After a lot of research, I realized that it was not easy to find answers to my questions, so once I had finished, I decided to document the information so that people can find it all in one place.

In this article, I will talk about how object and variable references are controlled in memory, since this is an issue that can generate discussion and differing opinions. One question to ponder is: “By default, are objects passed by reference or by copy in PHP?” I’m going to talk first about what references are not in PHP; secondly, I’ll discuss what they are, and finally, I will examine how the garbage collector works in PHP.

How does PHP create objects in memory when performing a statement like $a = new Foo();? Nowadays, memory is not as expensive and limited a resource as it was in the past. However, it is still important for good PHP developers to know and understand how variables and objects are managed internally during the execution of their application.

P1

Objects and References in PHP

Many people say—in PHP books and online—that objects in PHP are passed by reference by default. Others say that objects in PHP are allocated by copy. To figure out which statement is correct, first, we have to analyze what is (and what is not) a reference in PHP.

What Aren’t References in PHP?

More important than knowing what references are in PHP is knowing what they are not. In PHP, references are not C-style pointers; you cannot do arithmetic operations with references as you can with C pointers. Why? Because, unlike in C, PHP references are not really memory addresses, since they are not numbers indicating a memory location. But then, what are references?

What Are References in PHP?

In PHP, references are “aliases” that allow two different variables to read and write a single value. Put another way, they are mechanisms that allow access to the same value from variables with different names so that they behave as if they are the same variable. Keep in mind that in PHP, variable names and the content of variables are two entirely different things, linked in what it is called the “symbols table.” So, when we create a reference, it simply adds an alias for that variable in the symbol table. Suppose we have the following code:

$a = new Foo();

When the above statement is executed, the variable $a is created in memory, an object of type Foo is created in memory, and an entry is added to the symbol table which indicates that the variable $a“references” (or is related to, or points to, or whatever you want to call it) the Foo object, but it is not a pointer to that object, per se. Conceptually, we have something like this illustration:

P2

Pop quiz: What happens if we execute this?

$b = $a;

It is not that $b becomes a reference of $a; neither can we say that $b is a copy of $a. What really happened is that we have created a new variable $b in memory and then added a new entry in the symbols table indicating that the variable $b also references the same Foo object that $a does. So, visually, we have something similar to what it is shown in this illustration:

P3

Now, if we execute:

$c = &$a;

We will have created a third variable $c in memory, but not a new entry in the symbols table for $c. Instead, in the symbols table, it is recorded that $c is an alias for $a, so it will behave identically but $c is not a pointer to $a—unlike in C, which creates something called pointers to pointers. To visualize, we have something similar to what it is shown in this illustration:

P4

As soon as we want to modify the value of any of these three variables (i.e., write a new value), PHP will have to create a new z_val structure in memory to separate the content of the variable $b and the pair $a/$cso they can each be modified independently without affecting the other’s value. So, if we add the following line to the previous script:

$b = new Bar();

In memory, we will have a situation as represented in the following illustration:

P5

Now, let’s consider a more complete example:

<?php

class myClass {
    public $var;
		
    function __construct() {
	$this->var = 1;
    }

    function inc() { return ++$this->var; }
}

$a = new myClass(); // $a "references" a Foo object
$b = $a; //b also references the same Foo object as a
//($a) == ($b) == <id> of Foo object, but a and b are different entries in symbols table

echo "$a = ";var_dump($a);
echo "$b = ";var_dump($b);

$c = &$a; //$c is an alias of $a
//($a, $c) == <id> of Foo object, c is an alias of a in the symbols table
echo "$c = ";var_dump($c);

$a = NULL;
//The entry in the symbols table which links "$a" with Foo object is removed
//Since that entry was removed, $c is not related to Foo anymore
//Anyway, Foo still exists in memory and it is still linked by $b
echo "$a = ";var_dump($a);
echo "$b = ";var_dump($b);
echo "$c = ";var_dump($c);
echo "$b->var: ".$b->inc();
echo "$b->var: ".$b->inc();

$b = NULL;
//The entry in the symbols table which links "$b" with the Foo object is removed
//There are no more entries in the symbols table linked to Foo,
//So, Foo is not referenced anymore and can be deleted by the garbage collector

echo "$b = ";var_dump($b);

The output produced by the implementation of the script above is:

$a = object(myClass)#1 (1) { ["var"]=> int(1) } 
$b = object(myClass)#1 (1) { ["var"]=> int(1) } 

$c = object(myClass)#1 (1) { ["var"]=> int(1) } 
$a = NULL 
$b = object(myClass)#1 (1) { ["var"]=> int(1) } 
$c = NULL 
$b->var: 2
$b->var: 3

$b = NULL

PHP Garbage Collection

Finally, let’s see how PHP garbage collection works since it was introduced in version 5.3. An object or variable in PHP memory will be removed by the PHP garbage collector when there are no references to that object in the symbols table. That is, PHP maintains references counter of an object from the time it is created so that during the execution of the script PHP, the counter increments and decrements that reference counter based on the variables that are “pointing” to it. Once the reference count reaches 0 (i.e., nothing is referencing that object and, therefore, it is not being used), PHP marks that object as removable, so that in the next pass of the PHP garbage collector, it will be removed from memory, freeing that space for reuse. If you’d like more in-depth detail about how PHP garbage collection works, read this documentation.

Closing Thoughts

I hope I have clarified a little how PHP handles objects and variables in memory and how it “selects” the objects that should be removed by the PHP garbage collector.

Now that you understand how PHP manages variables and objects in memory internally, grab your laptop and start to experiment with some code to prove what you’ve learned. Try playing around with variables and references. Also, experiment with how changing the value of a variable could affect the value of another referencing it. Here’s a question for you: What will be the values of $a and $b after the code below is executed?

$a = '1';
$b = &$a;
$b = "2$b";

If you’re interested in reading more about PHP performance features, check out this post by fellow Toptaler Vilson Duka.

Feel free to share on social networks. Find the buttons below this post. This opinion article is for informational purposes only.

Remember, information/knowledge is never enough. Let us spread the word!

Follow my blog for more insightful articles: http://temitopeadelekan.com

LinkedIn connect: Temitope Adelekan

Twitter: @taymethorpenj

 

 

 

This is article is written by  Agustin Villalba

Brought to you by Toptal

Edited by Temitope Adelekan

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s