Get your FREE 30 page Developing SOLID Applications guide!

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.

Learning design patterns doesn't have to suck.

Design patterns open a whole new world of possibilities. So why are you avoiding them? This brand new book will help you finally understand these wonderful programming techiques!

Learn design patterns TODAY »

James wrote at 4/12/2010 11:53 am:

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__.

Gargoyle wrote at 4/12/2010 4:32 pm:

Nice and simple way to show an example of LSB…

till (@klimpong) wrote at 4/13/2010 6:26 am:

Great example, but better yet an example of why singletons are to be avoided – always.

Sebs wrote at 4/14/2010 7:19 am:

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