PHP Anthology, Volume 1, Chapter 2. Object Oriented PHP | 5
PHP Anthology, Volume 1, Chapter 2. Object Oriented PHP
Representing this simply with classes, first, let’s see the class that will store data-related to look and feel:
<?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:
// 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:
// 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:
$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:
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.
Let’s look at some other situations in which you might need to use references…
// Make sure $myObject is a reference to
// the variable created by the new keyword
$myObject = &new MyClass();
This looks odd at first, but remember, a variable created by the new keyword is being passed here—even if you can’t see it. The reference operator saves PHP from having to create a copy of the newly-created object to store in $myObject.
class Bar {
}
class Foo {
// Return by reference
function &getBar()
{
return new Bar();
}
}
// Instantiate Foo
$foo = &new Foo();
// Get an instance of Bar from Foo
$bar = &$foo->getBar();
In the above example, you’ll notice the getBar method in the Foo class. By preceding the function name with the reference operator, the value the function returns is passed by reference. Note that we also had to use a reference operator when assigning the return value of getBar to $bar. This technique is commonly used when a class method will return objects.
What’s bad practice is the following:
function display($message) {
echo $message;
}
$myMessage = 'Hello World!';
// Call time pass by reference - bad practice!
display(&$message);
That’s known as a call-time pass-by-reference , which PHP controls with the following setting in php.ini :
allow_call_time_pass_reference = Off
By default, in recent PHP releases the above setting should be switched to Off; turning it on is “frowned upon” by PHP’s makers. Switched off, PHP will generate warning errors every time a function call specifies an argument should be passed by reference. As such, it’s good practice to leave this setting off.
The reason why call time pass by reference is a “bad thing” is that call time passing by reference can make code extremely difficult to follow. I’ve occasionally seen PHP XML parsers written using a call-time pass-by-reference—it’s nearly impossible to gain any idea of what’s going on.
The “decision” as to whether a variable is passed by reference or not is one that belongs to the function being called, not the code that calls it. The above code written correctly would look like this:
// Accept by reference - good practice
function display(&$message)
{
echo $message;
}
$myMessage = 'Hello World!';
display($message);
In simple cases of copying one variable to another PHP's internal reference counting feature prevents unnecessary memory usage. For example,
$a = 'the quick brown fox'; $b = $a;
In the above example, the value of $b would not take up any extra memory, as PHP’s internal reference counting will implicitly reference $b and $a to the same location in memory, until their values become different. This is an internal feature of PHP and affects performance without affecting behavior. We don’t need to worry about it much.
In some cases, however, using a reference is faster, especially with large arrays and objects, where PHP's internal reference counting can’t be used. and the contents must therefore be copied.
So, for best performance, you should do the following:
-
With simple values such as integers and strings, avoid references whenever possible.
-
With complex values such as arrays and objects, use references whenever possible.
Essentially, the change brings PHP in line with the majority of object oriented programming languages like Java, and will certainly do a lot to reduce the confusion surrounding the subject. For now, though, and until PHP 5 has been widely adopted, knowing how references work is important.
The easiest way to see how inheritance works in PHP is by example. Let’s say we have this simple class:
Using the extends keyword, we can make a class that’s a child of Hello:
class Goodbye extends Hello {
function sayGoodbye()
{
return 'Goodbye World!';
}
}
Goodbye is now a child of Hello. Expressed the other way around, Hello is the parent or superclass of Goodbye. Now, we can simply instantiate the child class and have access to the sayHello and the sayGoodbye methods using a single object:
$msg = &new Goodbye(); echo $msg->sayHello() . '<br />'; echo $msg->sayGoodbye() . '<br />'; ?>
That example shows the basics of how inheritance works, but doesn’t demonstrate its real power… This comes with the addition of overriding.
Created: March 27 2003
Revised: January 2, 2004
URL: http://webreference.com/programming/phpanth2

Find a programming school near you