PHP V5 and object-oriented programming
When PHP V5 was released in 2004, it was a giant leap forward compared to what PHP V4 provided in regards to object-oriented programming (OOP) and design. It added several needed improvements, such as class visibility, proper constructors and destructors, type hinting, and a class-reflection API. It opened the door for advanced objected-oriented programming in PHP, and allowed you to implement many design patterns much easier, along with better design classes and APIs.
In PHP V5.3, many incremental additions have been made to enhance OOP. These improvements have been in the realm of syntax additions and performance improvements. To begin, let's look at the new features available with static methods and members.
Improved static method and member handling
One useful addition made in PHP V5 was the ability to specify a method or member of a class as static (PHP V4 did support static access to methods and members of class, but not the ability to specify that the method or member is designed for static access). Static access is especially useful for implementing the singleton design pattern, where only one instance of class exists.
PHP V5.3 has added several features to enhance the support for static members and methods within a class. First, we'll look at a newly added magic method: __callStatic().
The _callStatic() magic method
PHP V5 has several specially defined methods that can be used inside classes known as magic methods. When defined in the class, these methods provide special functionality, and enable overloading (the ability to allow a method to accept different types of parameters) and polymorphism (the ability to allow different data types to use the same interface). They also open the door to using different types of OOP programming methods and design patterns with PHP easily.
In PHP V5.3, a new magic method is added: __callStatic(). This works similar to the __call() magic method, which is designed to handle method calls for methods that aren't defined or visible in the class. However, __callStatic() is designed for handling static method calls, which gives us the ability to better design our method overloading. An example of how to use this method is below.
Listing 1. Example of using
__callStatic() vs. __call()
class Foo
{
public static function __callStatic(
$name,
$args
)
{
echo "Called method $name statically";
}
public function __call(
$name,
$args
)
{
echo "Called method $name";
}
}
Foo::dog(); // outputs "Called method dog statically"
$foo = new Foo;
$foo->dog(); // outputs "Called method dog"
|
One thing to note is PHP does enforce the definition of the __callStatic() method; it must be public, and it must be declared static. Likewise, the __call() magic method must also be defined public, just as all magic methods must be.
One nice feature of PHP is variable variables. What this means is you can use the string value of a variable to specify the name of another variable. In other words, you could do something like what is shown below.
Listing 2. Variable variables
$x = 'y';
$$x = 'z';
echo $x; // outputs 'y'
echo $y; // outputs 'z'
echo $$x; // outputs 'z'
|
The same concept can be used with functions, or even class methods, as shown below.
Listing 3. Variable function and class method names
class Dog
{
public function bark()
{
echo "Woof!";
}
}
$class = 'Dog'
$action = 'bark';
$x = new $class(); // instantiates the class 'Dog'
$x->$action(); // outputs "Woof!"
|
New to PHP V5.3 is the ability to have the name of the class when specified be a variable when making a static call. This opens up a few new possibilities, as shown below.
Listing 4. Variable class naming
class Dog
{
public static function bark()
{
echo "Woof!";
}
}
$class = 'Dog';
$action = 'bark';
$class::$action(); //outputs "Woof!"
|
This addition makes the variable-variables feature of PHP complete, allowing them to be used in just about every situation with PHP.
Let's look at one more useful enhancement to using static methods and members: late static binding.
One of the more annoying things about PHP before V5.3 is how static methods and members are dealt with. Up until now, static references, such as those made with self or __CLASS__, are resolved in the class scope in which the function was defined. The problem is that the reference would be incorrect if the class was extended and the call was made from the new child class. Late static binding has been added in PHP V5.3 to alleviate this problem. To better illustrate, let's create a class with a static method below.
Listing 5. Class
Foo with static method test()
class Foo
{
protected static $name = 'Foo';
public static function test()
{
return self::$name;
}
}
|
Let's extend this class. We'll redefine the member $name in this child class.
Listing 6. Child class
Bar that extends parent class Foo
class Bar extends Foo
{
protected static $name = 'Bar';
}
|
We make the static call in Listing 7.
Listing 7. Static method call
test()echo Bar::test(); |
What is output from that call would be the string Foo. This is because the self::$name reference made in the test() method is done with the Foo class. The binding occurs this way because this is where the function is defined.
PHP V5.3 has added the keyword static to allow you to make a reference against the current class. So you will change the Foo class above to use this keyword in Listing 8, and we'll see that Bar will instead be output.
Listing 8. Using the static keyword
class Foo
{
protected static $name = 'Foo';
public static function test()
{
return static::$name;
}
}
class Bar
{
protected static $name = 'Bar';
}
echo Bar::test(); // outputs 'Bar'
|
One thing to note about the static keyword is that it doesn't work the same as how this works in the nonstatic context. This means that the normal inheritance rules do not apply to static calls. The static keyword will simply try to resolve the call in the current class instead of the class the function was defined in. This is an important thing to note.
Now that we have seen some enhancements with static methods and members, let's take a look at some new classes added to a very useful part of PHP V5: the Standard PHP Library.
The Standard PHP Library (SPL) is a collection of interfaces and classes added in PHP V5 designed to solve standard problems. These problems include having an object be iterateable, letting an object behave as if it was an array, or implementing a linked list. The advantage of using these classes and methods is that they are native to PHP, which means they are faster than if they were implemented in PHP itself. They also, in many instances, allow many of the internal functions of PHP to use these objects directly, such as how the Iterator interface allows you to use the foreach construct to iterate over the object.
PHP V5.3 adds a few more classes to SPL. One we referenced earlier is the implementation of a doubly linked list in the SPL class SplDoublyLinkedList. It is used by two other new SPL classes: SplStack, which implements a stack, and SplQueue, which implements a queue.
Let's take a look at how you can use the SplStack class to implement a stack.
Listing 9. Using
SplStack
$stack = new SplStack();
// push a few new items on the stack
$stack->push('a');
$stack->push('b');
$stack->push('c');
// see how many items are on the stack
echo count($stack); // returns 3
// iterate over the items in the stack
foreach ( $stack as $item )
echo "[$item],";
// the above outputs: [c],[b],[a]
// pop an item off the stack
echo $stack->pop(); // returns 'c'
// now see how many items are on the stack
echo count($stack); // returns 2
|
The SqlQueue works in a similar fashion, but it works like a queue would (first item in, first item out; instead of last item in, first item out, like the stack). In addition, a heap implementation exists (SplHeap), as well as specific queue and heap implementations for certain situations (SplMinHeap, SplMaxHeap, and SplPriorityQueue).
Another useful addition is the SplFixedArray class, which, as the name implies, is a fixed-size array implementation. It is, however, rather fast — actually so fast that it's been benchmarked to be 10-30 percent faster than the built-in array implementation in PHP. This speedup is due to the fact that the array is a fixed size, not a variable-sized one like the default PHP one is, and that non-numeric indexes are not allowed. Listing 10 shows how it's used.
Listing 10.
SplFixedArray
$array = new SplFixedArray(3);
$array[0] = 'dog';
$array[1] = 'cat';
$array[2] = 'bird';
$a->setSize(4); // increase the size on the fly
$array[3] = 'mouse';
foreach ( $array as $value )
echo "[$value],";
Output:
[dog],[cat],[bird],[mouse]
|
In addition, a few new iterator classes have been added: FilesystemIterator and GlobIterator. These work the same as the other iterator classes in PHP, but they are specially designed for certain instances.
One other change with SPL is that it is always enabled now in PHP V5.3. In previous versions of PHP V5, you could disable SPL at compile time, but as of PHP V5.3, this is no longer possible.
The new additions to SPL add some useful functionality to PHP that is easy to use, as well as implementations of data structures, such as doubly linked lists, stacks, heaps, and queues. These classes can be used to replace user space implementations you may have, which will gain increased speed and better integration with various PHP functions and constructs.
Now that we have seen some new additions to SPL, let's see how OOP in PHP V5.3 has gained an important performance and memory usage improvement with the addition of circular garbage collection.
One problem PHP developers run into from a performance standpoint is garbage collection. PHP has a pretty simple garbage collector, which basically will garbage collect an object when it no longer is in scope. The way it does this internally is by using a reference counter, so that when the counter reaches zero (meaning no more references to this object are available), the object will be garbage collected and expunged from memory.
This works fairly well, but can become a problem in situations where one object references another in a parent-child relationship. In this situation, the reference counter for those object are not collected, so the memory used by these objects stays in unreferenced memory and is not unallocated until the end of the request. Let's take a look at an example of when this problem occurs.
Listing 11. Parent-child class relationship not properly garbage collected in PHP V5.2 and earlier
class Parent
{
public function __construct()
{
$this->child = new Child($this);
}
}
class Child
{
public function __construct(
Parent $parent
)
{
$this->parent = $parent;
}
}
|
In this instance, every time you create an instance of the Parent class and then subsequently the instance goes out of scope, the memory is never released, so the script will grow and grow in memory usage. There are a few user space solutions to this problem, such as creating a destructor for the parent class that will release the child object directly. This destructor would have to be called specifically before unsetting the parent class reference. While doing all of this works, it complicates your code quite a bit.
In PHP V5.3, the garbage collector will detect these circular references and is able to free up the memory used by them, so the PHP memory usage will remain flat as the script is executed. As each reference to the Parent class is removed, the Child class reference inside the Parent class will also be garbage collected.
PHP has came a long way in the way of object-oriented programming support, from the weak support in the PHP V4 days to the much-improved additions in PHP V5 and tweaks with subsequent versions. Now, PHP V5.3 has gained some exciting improvements, including syntax enhancements such as the new __callStatic() magic methods, dynamic static calls, late static binding, static method, and member support. The new additions to SPL with the implementations of doubly linked lists, stacks, heaps, and queues, puts some common data structures at your fingertips and make them easy to use. Finally, the long-awaited circular garbage collector fixes memory and performance issues with self-referencing classes by implementing a much-improved garbage collector that properly releases memory for these circular instances. All of these features make PHP V5.3 a much stronger language for object-oriented programming.
Learn
-
Continue this series with "What's new in PHP V5.3, Part 2, Part 3, and Part 4.
-
The Zend Developer Zone has documentation for memory manager functions.
-
Read "A PHP V5 migration guide" to learn how to migrate code developed in PHP V4 to V5.
-
"Connecting PHP Applications to Apache Derby" shows you how to install and configure PHP on Windows® (some steps are applicable to Linux®).
-
PHP.net is the central resource for PHP developers.
-
Check out the "Recommended PHP reading list."
-
Browse all the PHP content on developerWorks.
-
Expand your PHP skills by checking out IBM developerWorks' PHP project resources.
-
To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.
-
Using a database with PHP? Check out the Zend Core for
IBM, a seamless, out-of-the-box, easy-to-install PHP development and production environment that supports IBM DB2 V9.
-
Stay current with developerWorks' Technical events and webcasts.
-
Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.
-
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
-
Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.
Get products and technologies
-
Innovate your next open source development project with IBM trial software, available for download or on DVD.
-
Download IBM product evaluation versions, and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
-
Participate in developerWorks blogs and get involved in the developerWorks community.
-
Participate in the developerWorks PHP Forum: Developing PHP applications with IBM Information Management products (DB2, IDS).




