Article
The PHP Anthology Volume 1, Chapter 2 - Object Oriented PHP
Using a Reference
To pass using a reference, you need to use the reference operator & (ampersand). For example:
<?php
$color = 'blue';
$settings['color'] = &$color;
?>
$settings['color']/#rc#/ now contains a reference to the original $color variable.
Compare the following examples, the first using PHP’s default copying behavior:
<?php
$color = 'blue';
$settings['color'] = $color; // Makes a copy
$color = 'red'; // $color changes
echo $settings['color']; // Displays "blue"
?>
The second involves passing by reference:
<?php
$color = 'blue';
$settings['color'] = &$color; // Makes a reference
$color = 'red'; // $color changes
echo $settings['color']; // Displays "red"
?>
Passing by reference allows us to keep the new variable “linked” to the original source variable. Changes to either the new variable or the old variable will be reflected in the value of both.
So far, so good. You’re probably wondering, “What’s the big deal here? What difference does it make whether PHP copies or makes a reference to a variable, as long as we get what we expected?” For variables passed around a procedural program, you hardly ever need to worry about references. However, when it comes to objects interacting with one another, if you don’t pass an object by reference, you may well get results you weren’t expecting.
The Importance of References
Imagine you have a mechanism on your site that allows visitors to change the look and feel of the site—a user “control panel.” It’s likely that, to implement this sort of functionality, you’d have code that acts on a set of variables containing “look and feel” data, to modify them independently of the rest of the application’s logic.
Representing this simply with classes, first, let’s see the class that will store data-related to look and feel:
Example 2.8. 5.php (excerpt)
<?php
// Look and feel contains $color and $size
class LookAndFeel {
var $color;
var $size;
function LookAndFeel()
{
$this->color = 'white';
$this->size = 'medium';
}
function getColor()
{
return $this->color;
}
function getSize()
{
return $this->size;
}
function setColor($color)
{
$this->color = $color;
}
function setSize($size)
{
$this->size = $size;
}
}
Next, we have a class that deals with rendering output:
Example 2.9. 5.php (excerpt)
// Output deals with building content for display
class Output {
var $lookandfeel;
var $output;
// Constructor takes LookAndFeel as its argument
function Output($lookandfeel)
{
$this->lookandfeel = $lookandfeel;
}
function buildOutput()
{
$this->output = 'Color is ' . $this->lookandfeel->getColor() .
' and size is ' . $this->lookandfeel->getSize();
}
function display()
{
$this->buildOutput();
return $this->output;
}
}
Notice the constructor for the Output class. It takes an instance of LookAndFeel as its argument so that, later, it can use this to help build the output for the page. We’ll talk more about the ways classes interact with each other later in this chapter.
Here’s how we use the classes:
Example 2.10. 5.php (excerpt)
// Create an instance of LookAndFeel
$lookandfeel = new LookAndFeel();
// Pass it to an instance of Output
$output = new Output($lookandfeel);
// Display the output
echo $output->display();
?>
This displays the following message:
Color is white and size is medium
Now, let’s say that, in response to one of the options on your user control panel, you want to make some changes to the look and feel of the site. Let’s put this into action:
Example 2.11. 6.php (excerpt)
$lookandfeel = new LookAndFeel(); // Create a LookAndFeel
$output = new Output($lookandfeel); // Pass it to an Output
// Modify some settings
$lookandfeel->setColor('red');
$lookandfeel->setSize('large');
// Display the output
echo $output->display();
Using the setColor and setSize methods, we change the color to “red” and the size to “large,” right? Well, in fact, no. The output display still says:
Color is white and size is medium
Why is that? The problem is that we’ve only passed a copy of the LookAndFeel object to $output. So the changes we make to $lookandfeel have no effect on the copy that $output uses to generate the display.
To fix this we have to modify the Output class so that it uses a reference to the LookAndFeel object it is given. We do this by altering the constructor:
Example 2.12. 7.php (excerpt)
function Output(&$lookandfeel)
{
$this->lookandfeel = &$lookandfeel;
}
Notice that we have to use the reference operation twice here. This is because the variable is being passed twice—first to the constructor function, then again, to place it in a member variable.
Once we’ve made these changes, the display looks like this:
Color is red and size is large
In summary, passing by reference keeps the target variable “linked” to the source variable, so that if one changes, so does the other.