A Lesson In Static Methods And Late Static Binding
Out Of Date Warning
Languages change. Perspectives are different. Ideas move on. This article was published on April 12, 2010 which is more than two years ago. It may be out of date. You should verify that technical information in this article is still current before relying upon it for your own purposes.
Until 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
<span id="more-1264"></span>
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.

Write better object
oriented PHP today.
A brand new book on object oriented PHP that will leave you an object oriented master.
Learn more about the book »Nice 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


Imagine if you could write clear, compelling code each and every time you sat down to work. You can do this. I'll show you how with The Ten Commandments of Clean Code.
Brandon Savage has been a software developer since 2003. Ever since discovering that he could use software to automate routine tasks, he's been hooked. Brandon is passionate about perfecting the art of software development.
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__.