Created
March 3, 2012 16:03
-
-
Save ircmaxell/1966809 to your computer and use it in GitHub Desktop.
Scalar Casting Patch, Version 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: Zend/zend.h | |
=================================================================== | |
--- Zend/zend.h (revision 323850) | |
+++ Zend/zend.h (working copy) | |
@@ -486,6 +486,10 @@ | |
union _zend_function *__call; | |
union _zend_function *__callstatic; | |
union _zend_function *__tostring; | |
+ union _zend_function *__toint; | |
+ union _zend_function *__tofloat; | |
+ union _zend_function *__toarray; | |
+ union _zend_function *__toscalar; | |
union _zend_function *serialize_func; | |
union _zend_function *unserialize_func; | |
Index: Zend/zend_object_handlers.c | |
=================================================================== | |
--- Zend/zend_object_handlers.c (revision 323850) | |
+++ Zend/zend_object_handlers.c (working copy) | |
@@ -1482,6 +1482,49 @@ | |
} | |
/* }}} */ | |
+ZEND_API int zend_std_cast_object(zval *readobj, zval *writeobj, int type TSRMLS_DC) /* {{{ */ | |
+{ | |
+ zend_class_entry *ce = Z_OBJCE_P(readobj); | |
+ zval *retval = NULL; | |
+ switch (type) { | |
+ case IS_LONG: | |
+ if (ce->__toint) { | |
+ zend_call_method_with_0_params(&readobj, ce, &ce->__toint, "__toint", &retval); | |
+ } | |
+ break; | |
+ case IS_DOUBLE: | |
+ if (ce->__tofloat) { | |
+ zend_call_method_with_0_params(&readobj, ce, &ce->__tofloat, "__tofloat", &retval); | |
+ } | |
+ break; | |
+ case IS_ARRAY: | |
+ if (ce->__toarray) { | |
+ zend_call_method_with_0_params(&readobj, ce, &ce->__toarray, "__toarray", &retval); | |
+ } | |
+ break; | |
+ } | |
+ if (retval) { | |
+ ZVAL_ZVAL(writeobj, retval, 1, 1); | |
+ return SUCCESS; | |
+ } | |
+ return zend_std_cast_object_tostring(readobj, writeobj, type TSRMLS_CC); | |
+ | |
+} | |
+/* }}} */ | |
+ | |
+ZEND_API zval *zend_std_cast_object_get(zval *readobj TSRMLS_DC) /* {{{ */ | |
+{ | |
+ zval *retval; | |
+ zend_class_entry *ce = Z_OBJCE_P(readobj); | |
+ ALLOC_INIT_ZVAL(retval); | |
+ if (ce->__toscalar && zend_call_method_with_0_params(&readobj, ce, &ce->__toscalar, "__toscalar", &retval)) { | |
+ return retval; | |
+ } | |
+ ZVAL_NULL(retval); | |
+ return retval; | |
+} | |
+/* }}} */ | |
+ | |
ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC) /* {{{ */ | |
{ | |
zval *retval; | |
@@ -1589,7 +1632,7 @@ | |
zend_std_read_dimension, /* read_dimension */ | |
zend_std_write_dimension, /* write_dimension */ | |
zend_std_get_property_ptr_ptr, /* get_property_ptr_ptr */ | |
- NULL, /* get */ | |
+ zend_std_cast_object_get, /* get */ | |
NULL, /* set */ | |
zend_std_has_property, /* has_property */ | |
zend_std_unset_property, /* unset_property */ | |
@@ -1602,7 +1645,7 @@ | |
zend_std_object_get_class, /* get_class_entry */ | |
zend_std_object_get_class_name, /* get_class_name */ | |
zend_std_compare_objects, /* compare_objects */ | |
- zend_std_cast_object_tostring, /* cast_object */ | |
+ zend_std_cast_object, /* cast_object */ | |
NULL, /* count_elements */ | |
NULL, /* get_debug_info */ | |
zend_std_get_closure, /* get_closure */ | |
Index: Zend/zend_compile.c | |
=================================================================== | |
--- Zend/zend_compile.c (revision 323850) | |
+++ Zend/zend_compile.c (working copy) | |
@@ -1617,6 +1617,22 @@ | |
if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { | |
zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static"); | |
} | |
+ } else if ((name_len == sizeof(ZEND_TOINT_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOINT_FUNC_NAME, sizeof(ZEND_TOINT_FUNC_NAME)-1))) { | |
+ if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { | |
+ zend_error(E_WARNING, "The magic method __toInt() must have public visibility and cannot be static"); | |
+ } | |
+ } else if ((name_len == sizeof(ZEND_TOFLOAT_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOFLOAT_FUNC_NAME, sizeof(ZEND_TOFLOAT_FUNC_NAME)-1))) { | |
+ if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { | |
+ zend_error(E_WARNING, "The magic method __toFloat() must have public visibility and cannot be static"); | |
+ } | |
+ } else if ((name_len == sizeof(ZEND_TOARRAY_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOARRAY_FUNC_NAME, sizeof(ZEND_TOARRAY_FUNC_NAME)-1))) { | |
+ if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { | |
+ zend_error(E_WARNING, "The magic method __toArray() must have public visibility and cannot be static"); | |
+ } | |
+ } else if ((name_len == sizeof(ZEND_TOSCALAR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSCALAR_FUNC_NAME, sizeof(ZEND_TOSCALAR_FUNC_NAME)-1))) { | |
+ if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { | |
+ zend_error(E_WARNING, "The magic method __toScalar() must have public visibility and cannot be static"); | |
+ } | |
} | |
} else { | |
char *class_lcname; | |
@@ -1673,6 +1689,26 @@ | |
zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static"); | |
} | |
CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array); | |
+ } else if ((name_len == sizeof(ZEND_TOINT_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOINT_FUNC_NAME, sizeof(ZEND_TOINT_FUNC_NAME)-1))) { | |
+ if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { | |
+ zend_error(E_WARNING, "The magic method __toInt() must have public visibility and cannot be static"); | |
+ } | |
+ CG(active_class_entry)->__toint = (zend_function *) CG(active_op_array); | |
+ } else if ((name_len == sizeof(ZEND_TOFLOAT_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOFLOAT_FUNC_NAME, sizeof(ZEND_TOFLOAT_FUNC_NAME)-1))) { | |
+ if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { | |
+ zend_error(E_WARNING, "The magic method __toFloat() must have public visibility and cannot be static"); | |
+ } | |
+ CG(active_class_entry)->__tofloat = (zend_function *) CG(active_op_array); | |
+ } else if ((name_len == sizeof(ZEND_TOARRAY_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOARRAY_FUNC_NAME, sizeof(ZEND_TOARRAY_FUNC_NAME)-1))) { | |
+ if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { | |
+ zend_error(E_WARNING, "The magic method __toArray() must have public visibility and cannot be static"); | |
+ } | |
+ CG(active_class_entry)->__toarray = (zend_function *) CG(active_op_array); | |
+ } else if ((name_len == sizeof(ZEND_TOSCALAR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSCALAR_FUNC_NAME, sizeof(ZEND_TOSCALAR_FUNC_NAME)-1))) { | |
+ if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) { | |
+ zend_error(E_WARNING, "The magic method __toScalar() must have public visibility and cannot be static"); | |
+ } | |
+ CG(active_class_entry)->__toscalar = (zend_function *) CG(active_op_array); | |
} else if (!(fn_flags & ZEND_ACC_STATIC)) { | |
CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC; | |
} | |
@@ -2839,6 +2875,18 @@ | |
if (!ce->__tostring) { | |
ce->__tostring = ce->parent->__tostring; | |
} | |
+ if (!ce->__toint) { | |
+ ce->__toint = ce->parent->__toint; | |
+ } | |
+ if (!ce->__tofloat) { | |
+ ce->__tofloat = ce->parent->__tofloat; | |
+ } | |
+ if (!ce->__toarray) { | |
+ ce->__toarray = ce->parent->__toarray; | |
+ } | |
+ if (!ce->__toscalar) { | |
+ ce->__toscalar = ce->parent->__toscalar; | |
+ } | |
if (!ce->clone) { | |
ce->clone = ce->parent->clone; | |
} | |
@@ -3734,6 +3782,14 @@ | |
ce->__callstatic = fe; | |
} else if (!strncmp(mname, ZEND_TOSTRING_FUNC_NAME, mname_len)) { | |
ce->__tostring = fe; | |
+ } else if (!strncmp(mname, ZEND_TOINT_FUNC_NAME, mname_len)) { | |
+ ce->__toint = fe; | |
+ } else if (!strncmp(mname, ZEND_TOFLOAT_FUNC_NAME, mname_len)) { | |
+ ce->__tofloat = fe; | |
+ } else if (!strncmp(mname, ZEND_TOARRAY_FUNC_NAME, mname_len)) { | |
+ ce->__toarray = fe; | |
+ } else if (!strncmp(mname, ZEND_TOSCALAR_FUNC_NAME, mname_len)) { | |
+ ce->__toscalar = fe; | |
} else if (ce->name_length + 1 == mname_len) { | |
char *lowercase_name = emalloc(ce->name_length + 1); | |
zend_str_tolower_copy(lowercase_name, ce->name, ce->name_length); | |
@@ -6742,6 +6798,10 @@ | |
ce->__call = NULL; | |
ce->__callstatic = NULL; | |
ce->__tostring = NULL; | |
+ ce->__toint = NULL; | |
+ ce->__tofloat = NULL; | |
+ ce->__toarray = NULL; | |
+ ce->__toscalar = NULL; | |
ce->create_object = NULL; | |
ce->get_iterator = NULL; | |
ce->iterator_funcs.funcs = NULL; | |
Index: Zend/zend_object_handlers.h | |
=================================================================== | |
--- Zend/zend_object_handlers.h (revision 323850) | |
+++ Zend/zend_object_handlers.h (working copy) | |
@@ -154,6 +154,8 @@ | |
ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC); | |
ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC); | |
ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC); | |
+ZEND_API zval *zend_std_cast_object_get(zval *readobj TSRMLS_DC); | |
+ZEND_API int zend_std_cast_object(zval *readobj, zval *writeobj, int type TSRMLS_DC); | |
ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC); | |
ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, const struct _zend_literal *key TSRMLS_DC); | |
ZEND_API void rebuild_object_properties(zend_object *zobj); | |
Index: Zend/zend_compile.h | |
=================================================================== | |
--- Zend/zend_compile.h (revision 323850) | |
+++ Zend/zend_compile.h (working copy) | |
@@ -829,6 +829,10 @@ | |
#define ZEND_CALL_FUNC_NAME "__call" | |
#define ZEND_CALLSTATIC_FUNC_NAME "__callstatic" | |
#define ZEND_TOSTRING_FUNC_NAME "__tostring" | |
+#define ZEND_TOINT_FUNC_NAME "__toint" | |
+#define ZEND_TOFLOAT_FUNC_NAME "__tofloat" | |
+#define ZEND_TOARRAY_FUNC_NAME "__toarray" | |
+#define ZEND_TOSCALAR_FUNC_NAME "__toscalar" | |
#define ZEND_AUTOLOAD_FUNC_NAME "__autoload" | |
/* The following constants may be combined in CG(compiler_options) | |
Index: Zend/zend_API.c | |
=================================================================== | |
--- Zend/zend_API.c (revision 323850) | |
+++ Zend/zend_API.c (working copy) | |
@@ -27,6 +27,7 @@ | |
#include "zend_constants.h" | |
#include "zend_exceptions.h" | |
#include "zend_closures.h" | |
+#include "zend_interfaces.h" | |
#ifdef HAVE_STDARG_H | |
#include <stdarg.h> | |
@@ -368,9 +369,25 @@ | |
convert_to_long_ex(arg); | |
*p = Z_LVAL_PP(arg); | |
break; | |
- | |
+ case IS_OBJECT: | |
+ { | |
+ zend_class_entry *ce = Z_OBJCE_PP(arg); | |
+ zval *tmp = NULL; | |
+ if (ce->__toint) { | |
+ if (Z_ISREF_PP(arg)) { | |
+ zend_spprintf(error, 0, "to be an int, cannot cast referenced parameter from object"); | |
+ return "long"; | |
+ } | |
+ zend_call_method_with_0_params(arg, ce, &ce->__toint, "__toint", &tmp); | |
+ if (tmp && Z_TYPE_P(tmp) == IS_LONG) { | |
+ *p = Z_LVAL_P(tmp); | |
+ zval_ptr_dtor(&tmp); | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ /* Fall through intentional */ | |
case IS_ARRAY: | |
- case IS_OBJECT: | |
case IS_RESOURCE: | |
default: | |
return "long"; | |
@@ -402,9 +419,25 @@ | |
convert_to_double_ex(arg); | |
*p = Z_DVAL_PP(arg); | |
break; | |
- | |
+ case IS_OBJECT: | |
+ { | |
+ zend_class_entry *ce = Z_OBJCE_PP(arg); | |
+ zval *tmp = NULL; | |
+ if (ce->__tofloat) { | |
+ if (Z_ISREF_PP(arg)) { | |
+ zend_spprintf(error, 0, "to be a float, cannot cast referenced parameter from object"); | |
+ return "double"; | |
+ } | |
+ zend_call_method_with_0_params(arg, ce, &ce->__tofloat, "__tofloat", &tmp); | |
+ if (tmp && Z_TYPE_P(tmp) == IS_DOUBLE) { | |
+ *p = Z_DVAL_P(tmp); | |
+ zval_ptr_dtor(&tmp); | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ /* Fall through intentional */ | |
case IS_ARRAY: | |
- case IS_OBJECT: | |
case IS_RESOURCE: | |
default: | |
return "double"; | |
@@ -506,6 +539,23 @@ | |
} | |
if (Z_TYPE_PP(arg) == IS_ARRAY || (c == 'A' && Z_TYPE_PP(arg) == IS_OBJECT)) { | |
*p = *arg; | |
+ } else if (Z_TYPE_PP(arg) == IS_OBJECT) { | |
+ zend_class_entry *ce = Z_OBJCE_PP(arg); | |
+ zval *tmp = NULL; | |
+ if (ce->__toarray) { | |
+ if (Z_ISREF_PP(arg)) { | |
+ zend_spprintf(error, 0, "to be an array, cannot cast referenced parameter from object"); | |
+ return "array"; | |
+ } | |
+ zend_call_method_with_0_params(arg, ce, &ce->__toarray, "__toarray", &tmp); | |
+ if (tmp && Z_TYPE_P(tmp) == IS_ARRAY) { | |
+ SEPARATE_ZVAL_IF_NOT_REF(arg); | |
+ ZVAL_ZVAL(*arg, tmp, 1, 1) ; | |
+ *p = *arg; | |
+ break; | |
+ } | |
+ } | |
+ return "array"; | |
} else { | |
return "array"; | |
} | |
@@ -526,6 +576,19 @@ | |
if(*p == NULL) { | |
return "array"; | |
} | |
+ } else if (Z_TYPE_PP(arg) == IS_OBJECT) { | |
+ zend_class_entry *ce = Z_OBJCE_PP(arg); | |
+ zval *tmp = NULL; | |
+ if (ce->__toarray) { | |
+ zend_call_method_with_0_params(arg, ce, &ce->__toarray, "__toarray", &tmp); | |
+ if (tmp && Z_TYPE_P(tmp) == IS_ARRAY) { | |
+ SEPARATE_ZVAL_IF_NOT_REF(arg); | |
+ ZVAL_ZVAL(*arg, tmp, 1, 1); | |
+ *p = HASH_OF(*arg); | |
+ break; | |
+ } | |
+ } | |
+ return "array"; | |
} else { | |
return "array"; | |
} | |
@@ -1930,7 +1993,7 @@ | |
int count=0, unload=0, result=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, *__callstatic = NULL, *__tostring = NULL; | |
+ zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL, *__toint = NULL, *__tofloat = NULL, *__toarray = NULL, *__toscalar = NULL; | |
const char *lowercase_name; | |
int fname_len; | |
const char *lc_class_name = NULL; | |
@@ -2065,6 +2128,14 @@ | |
__callstatic = reg_function; | |
} else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME))) { | |
__tostring = reg_function; | |
+ } else if ((fname_len == sizeof(ZEND_TOINT_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOINT_FUNC_NAME, sizeof(ZEND_TOINT_FUNC_NAME))) { | |
+ __toint = reg_function; | |
+ } else if ((fname_len == sizeof(ZEND_TOFLOAT_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOFLOAT_FUNC_NAME, sizeof(ZEND_TOFLOAT_FUNC_NAME))) { | |
+ __tofloat = reg_function; | |
+ } else if ((fname_len == sizeof(ZEND_TOARRAY_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOARRAY_FUNC_NAME, sizeof(ZEND_TOARRAY_FUNC_NAME))) { | |
+ __toarray = reg_function; | |
+ } else if ((fname_len == sizeof(ZEND_TOSCALAR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSCALAR_FUNC_NAME, sizeof(ZEND_TOSCALAR_FUNC_NAME))) { | |
+ __toscalar = reg_function; | |
} else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) { | |
__get = reg_function; | |
} else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) { | |
@@ -2107,6 +2178,10 @@ | |
scope->__call = __call; | |
scope->__callstatic = __callstatic; | |
scope->__tostring = __tostring; | |
+ scope->__toint = __toint; | |
+ scope->__tofloat = __tofloat; | |
+ scope->__toarray = __toarray; | |
+ scope->__toscalar = __toscalar; | |
scope->__get = __get; | |
scope->__set = __set; | |
scope->__unset = __unset; | |
@@ -2150,6 +2225,30 @@ | |
} | |
__tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; | |
} | |
+ if (__toint) { | |
+ if (__toint->common.fn_flags & ZEND_ACC_STATIC) { | |
+ zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __toint->common.function_name); | |
+ } | |
+ __toint->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; | |
+ } | |
+ if (__tofloat) { | |
+ if (__tofloat->common.fn_flags & ZEND_ACC_STATIC) { | |
+ zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __tofloat->common.function_name); | |
+ } | |
+ __tofloat->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; | |
+ } | |
+ if (__toarray) { | |
+ if (__toarray->common.fn_flags & ZEND_ACC_STATIC) { | |
+ zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __toarray->common.function_name); | |
+ } | |
+ __toarray->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; | |
+ } | |
+ if (__toscalar) { | |
+ if (__toscalar->common.fn_flags & ZEND_ACC_STATIC) { | |
+ zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __toscalar->common.function_name); | |
+ } | |
+ __toscalar->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; | |
+ } | |
if (__get) { | |
if (__get->common.fn_flags & ZEND_ACC_STATIC) { | |
zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name); | |
Index: Zend/zend_operators.c | |
=================================================================== | |
--- Zend/zend_operators.c (revision 323850) | |
+++ Zend/zend_operators.c (working copy) | |
@@ -30,6 +30,7 @@ | |
#include "zend_strtod.h" | |
#include "zend_exceptions.h" | |
#include "zend_closures.h" | |
+#include "zend_interfaces.h" | |
#if ZEND_USE_TOLOWER_L | |
#include <locale.h> | |
@@ -640,6 +641,7 @@ | |
case IS_OBJECT: | |
{ | |
zval *tmp; | |
+ zend_class_entry *ce = Z_OBJCE_P(op); | |
HashTable *ht; | |
ALLOC_HASHTABLE(ht); | |
@@ -651,6 +653,15 @@ | |
FREE_HASHTABLE(ht); | |
return; | |
} | |
+ } else if (ce->__toarray) { | |
+ zend_call_method_with_0_params(&op, ce, &ce->__toarray, "__toarray", &tmp); | |
+ if (tmp && Z_TYPE_P(tmp) == IS_ARRAY) { | |
+ ZVAL_ZVAL(op, tmp, 1, 1); | |
+ zend_hash_destroy(ht); | |
+ FREE_HASHTABLE(ht); | |
+ return; | |
+ } | |
+ zend_error(E_WARNING, "%s::__toArray() must return an array", ce->name); | |
} else if (Z_OBJ_HT_P(op)->get_properties) { | |
HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC); | |
if (obj_ht) { | |
Index: Zend/zend_API.h | |
=================================================================== | |
--- Zend/zend_API.h (revision 323850) | |
+++ Zend/zend_API.h (working copy) | |
@@ -186,6 +186,10 @@ | |
class_container.__call = handle_fcall; \ | |
class_container.__callstatic = NULL; \ | |
class_container.__tostring = NULL; \ | |
+ class_container.__toint = NULL; \ | |
+ class_container.__tofloat = NULL; \ | |
+ class_container.__toarray = NULL; \ | |
+ class_container.__toscalar = NULL; \ | |
class_container.__get = handle_propget; \ | |
class_container.__set = handle_propset; \ | |
class_container.__unset = handle_propunset; \ |
I'm interested in this too. I think it is the perfect moment for this to be included in PHP core.
Why would you choose a separate function for each class instead of a more general __toType(string $type)
?
Please release.
When doing $obj + 123
, $obj
shouldn't be treated as a string. Adding __toscalar
is handy for solving this.
I created php/php-src#14073
Please vote.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Cool for now, but i'm also interested in __toBool and a __toClass or __toObject magic to perform object-to-object casts, something like:
Same should be possible for parameters in functions/methods like:
I think much more sexy is using angle brackets, in my opinien... See: