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.

Frustrated with your company’s development practices? You don't have to be! No matter what the issues are, they can be fixed. You can begin to shed light on these issues with my handy checklist. Plus, I'll help you with strategies to approach the issues at the organization level and "punch above your weight."

Great! We'll be updating you soon on best practices for your team!

Brandon Savage is the author of Mastering Object Oriented PHP and Practical Design Patterns in PHP