A Lesson In Static Methods And Late Static Binding
April 12th, 2010 @ 7:00 amUntil last week, I had never experienced what must have been incredibly frustrating to most developers: the fact that the self keyword in PHP refers to the class it is located in, and not necessarily a class that extends it. I personally ran into this problem when trying to extend Zend_Auth. Being a singleton, the constructor in Zend_Auth is protected, and the static method Zend_Auth::getInstance() instantiates itself. The problem is, when extended, My_Auth::getInstance() still returns an instance of Zend_Auth. The solution was to duplicate the static method in my My_Auth class, which worked properly. For example:
<?php
class My_Auth extends Zend_Auth
{}
echo get_class(My_Auth::getInstance());
What did I get as a return value? Zend_Auth – because here is the source code of the getInstance() method in Zend Framework’s Zend_Auth class:
/**
* Returns an instance of Zend_Auth
*
* Singleton pattern implementation
*
* @return Zend_Auth Provides a fluent interface
*/
public static function getInstance()
{
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
Why didn’t I get an instance of My_Auth instead of Zend_Auth? Well, that’s because PHP determines the meaning of the self keyword at compile time, meaning that when you call a function that makes use of it later, you’ll get whatever it’s been defined to mean when it was compiled.
PHP 5.3 provides a workaround for this, called late static binding. Simply put, PHP 5.3 introduces a new use of the keyword static, that allows you to avoid this define-at-compile-time problem. Using PHP 5.3 with the same example, and the static keyword, here is what happens.
// Auth.php rewritten
/**
* Returns an instance of Zend_Auth
*
* Singleton pattern implementation
*
* @return Zend_Auth Provides a fluent interface
*/
public static function getInstance()
{
if (null === static::$_instance) {
static::$_instance = new static();
}
return static::$_instance;
}
// My Auth class and sample code
class My_Auth extends Zend_Auth
{}
echo get_class(My_Auth::getInstance());
The result here is now that an instance of My_Auth is returned. Late static bindings make working with static methods much easier. For this feature alone I believe PHP 5.3 is a worthwhile upgrade.
The original work of Brandon Savage.
Related posts:
Categories: Object-Oriented Development, PHP 5, Zend FrameworkNice and simple way to show an example of LSB…
Great example, but better yet an example of why singletons are to be avoided – always.
I wonder what kind of language this is, where we need stuff like that. There is a Quadrupzillion Solutions that wont hurt your mind when you think about em. This is what OOP and PHP where about in the first place.
If someone says to me: late static binding, my brain goes into a “does not compute” mode and I ask the person to explain the problem that needs to be solved. If the solution is a technical solution that only solves a problem that another technical solution brought up …. you either see the recursion already or you learn late static binding.
2 cents
Web developer, amateur photographer, lover of the outdoors and travel. Expect to find me writing code, hiking or visiting new places. I own Blueprint DC and live in Washington, DC. Follow Me On Twitter!- July Slides
- Some Thoughts On Software Licensing
- Interfaces Make Testing Easier
- Revisiting: Why Every Developer Should Write Their Own Framework
- The Fallacy of Sunk Cost
- PHP: The Good Parts – Book Review
- 1st Amendment, Meet 4th Amendment: The Gizmodo Search Warrant
- A Closer Look At ArrayObject
- TEK Webcast Notes
- Caching For WordPress – A TEK-X Webinar

Just though I would point out the get_called_class function. It provides access to the name of the called class, not just a reference to it:
http://us.php.net/manual/en/function.get-called-class.php
You can think of it as the late-static-binding equivalent to __CLASS__.