References are a very useful part of PHP and, for that matter, most other programming languages. However, references can be somewhat confusing when you first start learning about them.
This tutorial is a gentle introduction to references in PHP. You find out what references are, and how they work. You learn how to create and delete references, as well as pass references to and from functions. You also explore some other uses of references, and discover situations where PHP creates references automatically on your behalf.
What exactly is a reference, anyway?
A reference is simply a way to refer to the contents of a variable using a different name. In many ways, references are like file shortcuts in Windows, file aliases in Mac OS X, and symbolic links in Linux.
Assigning by reference
An easy way to create a reference is known as assigning by reference. Consider the following simple example:
$myVar = "Hi there"; $anotherVar = $myVar; $anotherVar = "See you later"; echo $myVar; // Displays "Hi there" echo $anotherVar; // Displays "See you later"
Here we’ve created a variable, $myVar
, and given it a value of “Hi there”. Then we’ve assigned that value to another variable, $anotherVar
. This copies the value from the first variable to the second.
We then changed the value stored in $anotherVar
to “See you later”. Since the 2 variables are independent, $myVar
still keeps its original value (“Hi there”), which we then display in the page. So far, so good.
Now, let’s change the above example to assign $myVar
to $anotherVar
by reference, rather than by value. To do this, we simply put an ampersand (&
) after the equals sign:
$myVar = "Hi there"; $anotherVar =& $myVar; $anotherVar = "See you later"; echo $myVar; // Displays "See you later" echo $anotherVar; // Displays "See you later"
Now you can see that $myVar
‘s value has also changed to “See you later”! What’s going on here?
Rather than assigning the value of $myVar
to $anotherVar
— which simply creates 2 independent copies of the same value — we’ve made $anotherVar
a reference to the value that $myVar
refers to. In other words, $myVar
and $anotherVar
now both point to the same value. So when we assign a new value to $anotherVar
, the value of $myVar
also changes.
Note that we could have changed the value of $myVar
to “See you later” instead of changing $anotherVar
, and the result would have been exactly the same. The 2 variables are, in effect, identical.
Removing a reference
You delete a reference using the unset()
function, in the same way that you delete a regular variable.
When you unset a reference, you’re merely removing that reference, not the value that it references:
$myVar = "Hi there"; $anotherVar =& $myVar; $anotherVar = "See you later"; unset( $anotherVar ); echo $myVar; // Displays "See you later"
The value remains in memory until you unset all references to it, including the original variable:
$myVar = "Hi there"; $anotherVar =& $myVar; $anotherVar = "See you later"; unset( $anotherVar ); unset( $myVar ); echo $myVar; // Displays ""
Passing references to functions
References really come into their own when you start passing them as arguments to functions. Normally, when you pass a variable to a function, the function receives a copy of that variable’s value. By passing a reference to a variable, however, the function can refer to — and, more importantly, modify — the original variable.
To pass an argument by reference, you place an ampersand before the parameter name when you define the function:
function myFunc( &$myParam ) { // Do something with $myParam }
Now, whenever you call myFunc()
and pass a variable to it, PHP passes a reference to the variable, rather than the variable’s value.
Let’s look at a simple example of passing by reference:
function goodbye( &$greeting ) { $greeting = "See you later"; } $myVar = "Hi there"; goodbye( $myVar ); echo $myVar; // Displays "See you later"
Here we created a function, goodbye()
, that accepts a reference to a variable. The reference is stored in the parameter $greeting
. The function assigns a new value (“See you later”) to $greeting
, which changes the value stored in the variable that was passed to the function.
We test this out by creating a variable, $myVar
, with an initial value of “Hi there”, and calling goodbye()
, passing $myVar
by reference. goodbye()
then changes the value stored in $myVar
to “See you later”.
So, use pass-by-reference whenever you want a function to change a variable that’s passed to it. Simple!
By the way, don’t be tempted to put an ampersand before the argument name in your function call:
goodbye( &$myVar ); // Don't do this!
The ampersand before the parameter in the function definition is sufficient to pass the variable by reference.
Many built-in PHP functions use pass-by-reference. For example, the sort()
function accepts a reference to the array to sort, so that it can change the order of the elements in the array.
Returning references from functions
As well as passing references to functions, you can return references from functions. To do this, place an ampersand before the function name when you define the function. You should also use assign-by-reference (=&
) when assigning the returned reference to a variable, otherwise you’ll merely assign the value, not the reference. Here’s an example:
$numWidgets = 10; function &getNumWidgets() { global $numWidgets; return $numWidgets; } $numWidgetsRef =& getNumWidgets(); $numWidgetsRef--; echo "$numWidgets = $numWidgets<br>"; // Displays "9" echo "$numWidgetsRef = $numWidgetsRef<br>"; // Displays "9"
In this example, our getNumWidgets()
function retrieves the global variable $numWidgets
and returns a reference to it. We then call getNumWidgets()
, store the returned reference in $numWidgetsRef
, and decrement the value that $numWidgetsRef
points to. This is the same value that is pointed to by $numWidgets
, as you can see by the results of the echo
statements.
You probably won’t use return-by-reference as often as pass-by-reference, but it can be useful in certain situations, such as when you want to write a finder function (or class method) that finds a variable (or class property) and returns a reference to the variable or property, so that the calling code can then manipulate the variable or property.
Using references to change values in foreach
loops
Another handy use of references is to change values in an array when using a foreach
loop. With a regular foreach
loop, you’re working with copies of the array values, so if you change a value you’re not affecting the original array. For example, let’s try to change an array of band names to uppercase with a foreach
loop:
$bands = array( "The Who", "The Beatles", "The Rolling Stones" ); foreach ( $bands as $band ) { $band = strtoupper( $band ); } echo "<pre>"; print_r( $bands ); echo "</pre>";
The above example displays:
Array ( [0] => The Who [1] => The Beatles [2] => The Rolling Stones )
As you can see, the original array has not been changed by the foreach
loop. However, if we place an ampersand before $band
in the foreach
statement then $band
becomes a reference to the original array element, rather than a copy. We can then convert the array elements to uppercase:
$bands = array( "The Who", "The Beatles", "The Rolling Stones" ); foreach ( $bands as &$band ) { $band = strtoupper( $band ); } echo "<pre>"; print_r( $bands ); echo "</pre>";
Our code now runs as intended, producing this:
Array ( [0] => THE WHO [1] => THE BEATLES [2] => THE ROLLING STONES )
Another way to change array values in a loop is to use a for
loop instead of foreach
.
When references are used automatically
So far you’ve looked at 4 ways to create references explicitly:
-
- Assigning by reference
- Passing by reference
- Returning by reference
- Creating a reference in a
foreach
loop
In addition, there are occasions when PHP automatically creates references for you. Most of the time you won’t care, but it can be useful to know this stuff!
When using the global
keyword
When you use global
to access a global variable within a function, you are in fact creating a reference to the global variable in the $GLOBALS
array. So:
function myFunction() {
global $globalVariable;
}
does the same thing as:
function myFunction() {
$globalVariable =& $GLOBALS["globalVariable"];
}
When using $this
When you use the $this
keyword within an object’s method to refer to the object, then it’s worth remembering that $this
is always a reference to the object, rather than a copy of it. For example:
class MyClass { var $aProperty = 123; function aMethod() { $this->aProperty = 456; // $this is a reference to the object } } $myObject = new MyClass(); $myObject->aMethod(); echo $myObject->aProperty; // Displays "456"
Since $this
is a reference to the object in the above example, the method is able to change a property within the object to a new value.
When passing objects around
Unlike other types of variable, whenever you assign, pass, or return an object, you’re passing a reference to the object, not a copy. This is usually what you want to happen, since the function or method you pass an object to usually needs to work on the actual object, not a copy of it. For example:
class MyClass { // (Class definition here) } $myObject = new MyClass(); $yourObject = $myObject; // $yourObject and $myObject point to the same object
In the few situations when you do actually want to make a copy of an object, you can use the clone
keyword.
In fact, things are a bit more subtle than this. When you create an object variable, that variable merely contains a pointer to the object in memory, not the object itself. When you assign or pass that variable, you do in fact create a copy of the variable. But the copy is also merely a pointer to the object — both copies still point to the same object. Therefore, for most intents and purposes, you’ve created a reference.
Summary
In this tutorial you’ve learned the fundamentals of variable references in PHP. You’ve explored assigning, passing, and returning variables by reference; learned how to use references to change array elements in a foreach
loop; and looked at situations where PHP creates references for you automatically.
If you’d like to learn more, check out the References Explained section of the PHP website. Have fun! 🙂
akk says
Thanks, Brilliant tutorial, Very well explained.
matt says
@akk: Thanks for the feedback – I’m glad you found the tutorial helpful. 🙂 References can be a tricky topic!
Asa says
A great learning web forum ever I came across.
Calum says
Excellent! Thanks for showing real use examples.
PROSENTRA says
Thank you man for this great effort, this tutorial explains the topic easily and professionally.
Great work
saeed says
thanks that is very comlete
Erin says
Thank you, Matt!! I have needed a clear explanation of this, and here it is 🙂
Matt Doyle says
You’re welcome Erin, glad it helped 🙂
Constantine says
Thank you very much, only after your tutorial I understood the “References” topic. Had a hard time with it before. Thank you, best wishes!
Matt Doyle says
You’re welcome 🙂
Joseph says
Thanks for this article, with examples very easy to understand. Helpful to understand the references, that can be a little abstract.
Matt Doyle says
You’re welcome, Joseph 🙂
Gary Schankula says
Thank you very much for this useful explanation, Matt.
One thing that I did note was that for me, your &getNumWidgets() example of the use of a global variable did not work in my WordPress site–specifically in my Enfold theme. I had to declare the $numWidgets variable as global outside the function for the function’s reference to it to work:
I’ve seen other posts elsewhere talk about how you have to do this with some plugins.
Thanks again!
Gary
Matt Doyle says
Thanks for your reply Gary! Yes, that’s probably because your code is being called from inside another function in the Enfold theme, and therefore you need to declare that variable as global in that scope also.
Ahmed Ginani says
Thank you Matt!
You explained very clearly so that even a junior level programmer can easily understand the concept of references and avoid the confusions.
Matt Doyle says
Thanks Ahmed ?
med says
thank you so much for this great explanation !
Steven Pennebaker says
outstanding explainer, thanks!