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:
1.2. 3.class My_Auth extends Zend_Auth4.{}5. 6.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:01./**02.* Returns an instance of Zend_Auth03.*04.* Singleton pattern implementation05.*06.* @return Zend_Auth Provides a fluent interface07.*/08.public static function getInstance()09.{10.if (null === self::$_instance) {11.self::$_instance = new self();12.}13. 14.return self::$_instance;15.}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.01.// Auth.php rewritten02. 03./**04.* Returns an instance of Zend_Auth05.*06.* Singleton pattern implementation07.*08.* @return Zend_Auth Provides a fluent interface09.*/10.public static function getInstance()11.{12.if (null === static::$_instance) {13.static::$_instance = new static();14.}15. 16.return static::$_instance;17.}18. 19.// My Auth class and sample code20.class My_Auth extends Zend_Auth21.{}22. 23.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.
No comments:
Post a Comment