Although PHP didn't start out as an object-oriented language, growing interest in building object-oriented PHP applications led the development team to reconsider PHP's initially weak OOP implementation, making a much more capable and mature set of features available with the version 5 release. These vast improvements opened up an entirely new set of opportunities for the PHP community, including most notably the development of advanced frameworks such as the Zend Framework, CakePHP, and Symfony.
In this article I'll introduce you to three of PHP's advanced object-oriented features which seem to not have garnered the attention they deserve. The topics discussed here should be useful whether you're a relative newcomer to object-oriented development and are looking to expand your knowledge, or have a background using languages such as Java or C# and are trying to learn more about what PHP has to offer.

Reflection

Reflection is a powerful feature which allows you to learn more about class properties using metadata. This ability to dynamically learn more about class internals can prove very useful when creating general solutions for documenting (see PHPDoc) and testing (see PHPUnit) code. PHP's reflection API provides a large number of methods capable of retrieving information about practically every aspect of a class, including class comments, methods, information about any parent classes, properties, and property scope. Consider for instance the following class:
<?php class Account { private $_name; private $_ssn; private $_city; public function setName($name) { $this->_name = $name; } public function getName() { return $this->_name; } } $reflection = new ReflectionClass('Account'); $methods = $reflection->getMethods(); foreach ($methods AS $method) { echo "Method: {$method->name}<br />"; } ?>
Executing this script produces the following output:
Method: setName Method: getName 
Understanding how easy it is to obtain class information using the reflection API gives you a pretty good idea of how solutions such as the aforementioned PHPDoc and PHPUnit are possible! See the PHP manual for more information about what's possible.

The Standard PHP Library

Introduced in PHP 5.0, the Standard PHP Library (SPL) extension provides a series of object-oriented interfaces to common programming tasks. One of the most interesting features is the ArrayAccess interface, which you can use to manipulate objects using PHP's native array syntax. For instance, a typical PHP class implementation will involve using a number of mutator and accessor methods to manipulate and retrieve object data, respectively:
$account = new Account(); $name = $account->findUsernameById(45); 
You can streamline this syntax by implementing the ArrayAccess interface, as demonstrated here:
<?php class Account implements ArrayAccess { function offsetExists($id) { return true; } function offsetGet($id) { return "Jason"; } function offsetSet($name, $id) { return true; } function offsetUnset($name) { return "Account deleted"; } } ?>
Of course, in a real-world situation you'll likely implement each of the four interface methods offsetExists(), offsetGet(), offsetSet(), and offsetUnset()) by interacting with a database containing the account records. Either way, once implemented, you'll be able to treat your class as an array, as demonstrated here:
<php $account = new Account(); if (isset($account[45])) { echo $account[45]; } ?> 
The SPL offers quite a few other interfaces which allow you to endow your classes with a variety of useful behaviors. See the PHP manual for all of the details.
In addition to these convenient object-oriented language enhancements, SPL significantly expands PHP's datatype support by implementing advanced data structures such as heaps, queues, and stacks.

Late Static Binding

New to PHP 5.3, late static binding is a feature which can prove quite useful when working with class hierarchies, because it significantly streamlines the amount of code one had to write when using earlier versions of PHP in order to determine where exactly in the class hierarchy a static method call originated. Consider the following example, which loosely resembles a basic Active Record implementation. What do you think $table will be assigned following the call to Account::getTableName()?
class Record { protected static $tableName = "base"; public static function getTableName() { return self::$tableName; } } class Account extends Record { protected static $tableName = "accounts"; } $table = Account::getTableName();
In versions of PHP earlier than 5.3, $table would be assigned base because the self keyword was unable to determine that a child class originated the call to getTableName()! As of 5.3, this major inconvenience has been resolved, allowing PHP to bind to the originating caller at runtime, thereby setting $table to accounts.

Conclusion

I always recommend that newcomers to PHP take the time early on to get acquainted with the language's object-oriented features, as it will inevitably lead to more maintainable, extensible code. However, only by diving into the more esoteric details of PHP's object-oriented implementation will you really be able to stretch the language to its furthest capabilities. What other advanced PHP features interest you? Tell us about them in the comments!

About the Author

Jason Gilmore is the founder of EasyPHPWebsites.com and the author of several popular books, including "Easy PHP Web sites with the Zend Framework" and "Beginning PHP and MySQL: From Novice to Professional" (currently in its third edition). Check out his new DZone reference card, titled "Getting Started with the Zend Framework."