[PATCH] late binding for parent (and other options) - Was Re: [PHP-DEV] late static binding php6

From: Date: Sun, 25 Nov 2007 22:11:52 +0000
Subject: [PATCH] late binding for parent (and other options) - Was Re: [PHP-DEV] late static binding php6
References: 1 2 3 4 5 6 7 8 9 10  Groups: php.internals 
Request: Send a blank email to internals+get-33432@lists.php.net to get a copy of this message
I have come up with three different patches that allow us to work around the issue of parent:: being considered an 'explicit class reference' and thus disallowing static:: to effectively used. The patches are against 5.3. I also have patches against HEAD but I was having problems getting run-tests.php to run against that code base (it would hang on the first test no matter which set of tests I ws running.) All three patches have different levels of intrusiveness to the engine and all three patches have been tested against (and pass) the existing lsb tests in Zend/tests/lsb_*.phpt 1.) lsb.parent-forwarding.patch This patch modifies the behavior of only parent:: to not change EG(called_class) to the parent of the current scope. With this change. <?php class A { public static function test() { echo get_called_class()."\n"; } } class B extends A { public static function test() { parent::test(); } } A::test(); B::test(); ?> will output: A B It should be noticed that with this patch parent:: will always resolve to the parent of the current scope, it will just not make any changes to the called_scope (effectively) 2.) lsb.new-keyword.patch This patch effectively does the same thing as the parent forwarding patch, but does it by introducing a new keyword. I had no idea what to call this keyword so for the time being I am using '__parentf'. If this is a direction people want to go this can of course be changed with a relatively simple search & replace in the patch file. The code above would need to be changed to: <?php class A { public static function test() { echo get_called_class()."\n"; } } class B extends A { public static function test() { __parentf::test(); } } A::test(); B::test(); ?> This patch carries the same costs as the parent forwarding patch with the additional costs of having to check for a new keyword when declaring classes/namespaces/interfaces and calling static methods. Perhaps someone knows a cheaper way to do this? 3.) lsb.forward_static_call.patch This patch implements my desired functionality by using two new functions: forward_static_call() and forward_static_call_array(). These functions ares similar to the call_user_func*() functions however the first parameter is not a callback but a string specifying the desired static method that exists in the current scope's parent class. The function will error out with messages similar to parent:: if called from outside of a class or from within a class that does not have a parent. So with this patch the code would change to: <?php class A { public static function test() { echo get_called_class()."\n"; } } class B extends A { public static function test() { forward_static_call(__FUNCTION__); } } A::test(); B::test(); ?> This patch is completely outside of the Zend engine and as such existing lsb functionality is not affected at all. So, with these three options on the table I think it is very clear that what we are asking for can be done with varying levels of 'intrusiveness', so what does everyone think? If one of these options looks worth pursuing I can put together the tests I have written for all of them, cleanup the code, help with documentation, etc. - Mike Lively http://www.digitalsandwich.com

« previous php.internals (#33432) next »