Verification: a143cc29221c9be0

Php class passing by reference

Php class passing by reference

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

Handshake

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
"; // Displays "9" echo "$numWidgetsRef = $numWidgetsRef
"; // 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

Roulette wheel

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 "
";
print_r( $bands );
echo "
";

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 "
";
print_r( $bands );
echo "
";

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

Robot

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.