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.

Objects and references in PHP memory and PHP garbage collection

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:

Object references in PHP memory

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:

Object references in PHP memory

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:

Diagram of variables and their aliases

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/$c so 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:

Graphic representation of the situation described above

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 a 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.

Understanding the Basics

What are references in PHP?

In PHP, references are “aliases” that allow two different variables to read and write a single value.

About the author

Agustin Villalba, Germany
member since September 24, 2016
Augustin is a web developer with ten years of experience developing back-end and front-end of web applications. He spearheaded the development of a web project for the FIFA Refereeing Department and developed for the European Molecular Biology Laboratory (www.embl.de). He's also a Zend PHP 5.3 Certified Engineer. [click to continue...]
Hiring? Meet the Top 10 Freelance PHP Developers for Hire in November 2017

Comments

Usama Ahmed
It took me less than 3 secs to find out how php manages objects. PHP official manual has a lot of material on it. Does toptal force you to construct articles from a google search?
Zbynek
pointer and reference in c is not same, int a = 1; int& b = a; there b is reference, int* c = &a; here it is pointer. in php there are no pointers, but there are references like in c, and they behave mostly like in c, so you should not compare c pointers vs php reference, it doesnt have sence.
Agustin
Hi Zbynek, Thank you for comment. Exactly, pointers and references are not the same, that is what we state in the post. Also, as you mentioned, we explain that unlike C pointers, PHP references are not memory addresses, so the comparison is used to remark that they are not the same ;)
Zbynek
are you thinking then there is someone who think php reference is C pointer? i dont think so.
Agustin
I honestly doubt you can find detailed and well explained information about PHP internals in 3 seconds. Although PHP documentation is usually good, it does not mean everybody has your "expertise" to understand it. This post was done based on research and own material, so if you do not like it that's great (of course!), but your comment does not add any discussion or debate about the topic, so there is not much to reply! ;)
Lars Moelleken
Heyho, here a little bit more constructive comment ;-) If you run the following php-script you can simply see how references und copy-on-write is working: start: 88 bytes array: 8524592 bytes function1-begin: 8524608 bytes function1-end: 17049016 bytes array-test4: 8524536 bytes function2-begin: 8524552 bytes function2-end: 8524616 bytes array-test4_ref: 8524552 bytes end: 8524552 bytes https://github.com/voku/php_zval_test/blob/master/test4.php
comments powered by Disqus
Subscribe
The #1 Blog for Engineers
Get the latest content first.
No spam. Just great engineering posts.
The #1 Blog for Engineers
Get the latest content first.
Thank you for subscribing!
Check your inbox to confirm subscription. You'll start receiving posts after you confirm.
Trending articles
Relevant Technologies
About the author
Agustin Villalba
PHP Developer
Augustin is a web developer with ten years of experience developing back-end and front-end of web applications. He spearheaded the development of a web project for the FIFA Refereeing Department and developed for the European Molecular Biology Laboratory (www.embl.de). He's also a Zend PHP 5.3 Certified Engineer.