[PHP-DEV] __call_static() Magic Method
Attached is a patch which exports an internals hook in zend_class_entry for fetching function pointers similar to the object hook get_method() available to instance methods. This patch also exports a userspace hook __call_static() which operates in the fashion of the current __call() magic method, but for static calls. Wez called for some functionality like this a few weeks ago for a COM wrapper (or something similar), and I noticed there was actually a comment in the engine about how this should eventually be done anyway... Usage example: class foo { public static function __call_static($fname, $args) { echo "foo::{$fname}() called staticly with ", count($args), " parameters\n"; } } foo::randomMethod(1,2,3); I considered setting get_static_method to zend_std_get_static_method() by default (avoiding the if set check during runtime), but all the other hoooks follow this pattern so I went with consistency. If noone comments to the negative, I'll commit next friday (7/20)... -Sara Index: Zend/zend.h === RCS file: /repository/ZendEngine2/zend.h,v retrieving revision 1.334 diff -u -p -r1.334 zend.h --- Zend/zend.h 26 Apr 2007 19:08:24 - 1.334 +++ Zend/zend.h 14 Jul 2007 00:42:05 - @@ -378,6 +378,7 @@ struct _zend_class_entry { union _zend_function *__unset; union _zend_function *__isset; union _zend_function *__call; + union _zend_function *__call_static; union _zend_function *__tostring; union _zend_function *serialize_func; union _zend_function *unserialize_func; @@ -388,6 +389,7 @@ struct _zend_class_entry { zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC); zend_object_iterator *(*get_iterator)(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); int (*interface_gets_implemented)(zend_class_entry *iface, zend_class_entry *class_type TSRMLS_DC); /* a class implements this interface */ + union _zend_function *(*get_static_method)(zend_class_entry *ce, zstr method, int method_len TSRMLS_DC); /* serializer callbacks */ int (*serialize)(zval *object, int *type, zstr *buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC); Index: Zend/zend_API.c === RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.439 diff -u -p -r1.439 zend_API.c --- Zend/zend_API.c 13 Jul 2007 23:51:51 - 1.439 +++ Zend/zend_API.c 14 Jul 2007 00:42:05 - @@ -2026,6 +2026,9 @@ ZEND_API void zend_check_magic_method_im } else if (lcname_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1) && fptr->common.num_args != 2) { zend_error(error_type, "Method %v::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME); + } else if (lcname_len == sizeof(ZEND_CALL_STATIC_FUNC_NAME) - 1 && + ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_CALL_STATIC_FUNC_NAME, sizeof(ZEND_CALL_STATIC_FUNC_NAME)-1) && fptr->common.num_args != 2) { + zend_error(error_type, "Method %v::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_STATIC_FUNC_NAME); } else if (lcname_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 && ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0) { zend_error(error_type, "Method %v::%s() cannot take arguments", ce->name, ZEND_TOSTRING_FUNC_NAME); @@ -2043,7 +2046,7 @@ ZEND_API int zend_register_functions(zen int count=0, unload=0; HashTable *target_function_table = function_table; int error_type; - zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__tostring = NULL; + zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__call_static = NULL, *__tostring = NULL; char *lowercase_name; int fname_len; zstr lc_class_name = NULL_ZSTR; @@ -2186,6 +2189,8 @@ ZEND_API int zend_register_functions(zen clone = reg_function; } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) { __call = reg_function; + } else if ((fname_len == sizeof(ZEND_CALL_STATIC_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_STATIC_FUNC_NAME, sizeof(ZEND_CALL_STATIC_FUNC_NAME))) { + __call_static = reg_function; } else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_
Re: [PHP-DEV] __call_static() Magic Method
Sara Golemon kirjoitti: Attached is a patch which exports an internals hook in zend_class_entry for fetching function pointers similar to the object hook get_method() available to instance methods. This patch also exports a userspace hook __call_static() which operates in the fashion of the current __call() magic method, but for static calls. Wez called for some functionality like this a few weeks ago for a COM wrapper (or something similar), and I noticed there was actually a comment in the engine about how this should eventually be done anyway... Usage example: class foo { public static function __call_static($fname, $args) { echo "foo::{$fname}() called staticly with ", count($args), " parameters\n"; } } foo::randomMethod(1,2,3); I considered setting get_static_method to zend_std_get_static_method() by default (avoiding the if set check during runtime), but all the other hoooks follow this pattern so I went with consistency. If noone comments to the negative, I'll commit next friday (7/20)... As long as you MFH, I don't mind. --Jani -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] __call_static() Magic Method
Jani Taskinen schrieb: > As long as you MFH, I don't mind. Yeah, I would love to have this in PHP_5_2, too. :) -- Sebastian Bergmann http://sebastian-bergmann.de/ GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] __call_static() Magic Method
I'm afraid this change is binary incompatible - it changes class structure, which is in use by extensions. So you'd need 5.3 for that. Sebastian Bergmann wrote: Jani Taskinen schrieb: As long as you MFH, I don't mind. Yeah, I would love to have this in PHP_5_2, too. :) -- Stanislav Malyshev, Zend Software Architect [EMAIL PROTECTED] http://www.zend.com/ (408)253-8829 MSN: [EMAIL PROTECTED] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] __call_static() Magic Method
And there is no reason not to release 5.3 is there? I'd also like to MFH the namespace patch for PHP 5. well, that's topic for another discussion, I just wanted to remind that it can't be in PHP_5_2. -- Stanislav Malyshev, Zend Software Architect [EMAIL PROTECTED] http://www.zend.com/ (408)253-8829 MSN: [EMAIL PROTECTED] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] __call_static() Magic Method
And there is no reason not to release 5.3 is there? I'd also like to MFH the namespace patch for PHP 5. --Jani Stanislav Malyshev kirjoitti: I'm afraid this change is binary incompatible - it changes class structure, which is in use by extensions. So you'd need 5.3 for that. Sebastian Bergmann wrote: Jani Taskinen schrieb: As long as you MFH, I don't mind. Yeah, I would love to have this in PHP_5_2, too. :) -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] __call_static() Magic Method
This is actually a very good idea. I had to put a hook into the opcode handler for static method calls to get the same result which is not really elegant. I was waiting for this feature for a couple month. Also I found out that the names of the static methods are already lowercase when it comes to the handler, i don't know if that is fixed in the meanwhile. On Saturday 14 July 2007 02:53:44 Sara Golemon wrote: > Attached is a patch which exports an internals hook in zend_class_entry > for fetching function pointers similar to the object hook get_method() > available to instance methods. > > This patch also exports a userspace hook __call_static() which operates > in the fashion of the current __call() magic method, but for static calls. > > Wez called for some functionality like this a few weeks ago for a COM > wrapper (or something similar), and I noticed there was actually a > comment in the engine about how this should eventually be done anyway... > > Usage example: > > class foo > { > public static function __call_static($fname, $args) > { > echo "foo::{$fname}() called staticly with ", > count($args), " parameters\n"; > } > } > > foo::randomMethod(1,2,3); > > > I considered setting get_static_method to zend_std_get_static_method() > by default (avoiding the if set check during runtime), but all the other > hoooks follow this pattern so I went with consistency. > > If noone comments to the negative, I'll commit next friday (7/20)... > > -Sara -- Thomas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] __call_static() Magic Method
Thomas Moenicke wrote: This is actually a very good idea. I had to put a hook into the opcode handler for static method calls to get the same result which is not really elegant. I was waiting for this feature for a couple month. Also I found out that the names of the static methods are already lowercase when it comes to the handler, i don't know if that is fixed in the meanwhile. Not fixed yet, but it certainly is fixable. Good catch. Please bring up any other brokennesses you notice... -Sara -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php