Looking at the manual, it says that the constants defined by define are only allowed:
Only scalars and null are allowed. The type of scalar is integer, float, string or boolean. You can also define the type of the constant value as resource , but this is not recommended and may lead to unknown situations.
Reading the php source code today, I found that the second parameter of define can actually be an object.
Post an example first:
ZEND_FUNCTION(define)
{
char *name;
int name_len;
zval *val;
zval *val_free = NULL;
zend_bool non_cs = 0 ;
int case_sensitive = CONST_CS;
zend_constant c;
// Receive 3 parameters, string, zval, bool
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|b" , &name, &name_len, &val, &non_cs) == FAILURE) {
return;
}
// If define class constant, an error will be reported
if (zend_memnstr(name, "::", sizeof("::") - 1, name + name_len)) {
zend_error(E_WARNING, "Class constants cannot be defined or redefined");
RETURN_FALSE;
}
// Get the real value and save it with val
repeat:
switch (Z_TYPE_P(val)) {
case IS_LONG:
case IS_DOUBLE:
case IS_STRING:
case IS_BOOL:
case IS_RESOURCE:
case IS_NULL:
break;
case IS_OBJECT:
if (!val_free) {
if (Z_OBJ_HT_P(val)->get) {
val_free = val = Z_OB J_HT_P(val)->get(val TSRMLS_CC); Goto Repeat;
} else if (z_Obj_ht_p (Val)-& GT; Cast_object) {
Aloc_init_zval (Val_free); st_Object (VAL, VAL_FREE, IS_STRING TSRMLS_CC ) == SUCCESS) {
}
,"Constants may only evaluate to scalar values");
if (val_free) {
zval_ptr_dtor(&val_free);
}
RETURN_FALSE;
}
// Build Constant
c.value = *val;
zval_copy_ctor(&c.value);
if (val_free) {
zval_ptr_dtor(&val_free);
}
c.flags = case_sensitive; /* non persistent */
c.name = zend_strndup(name, name_len);
c.name_len = name_len+1;
c.module_number = PHP_USER_CONSTANT;
// Register constant
if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}
Note that a loop starting with repeat also uses the goto statement T_T
The function of this code is:
For int, float, string, bool, resource, null, the actual defined constants are directly Using these values
For object, you need to convert the object into one of the above 6 types (if it is still an object after the conversion, continue the conversion)
How to convert the object into one of the 6 types? From the code point of view, there are two methods:
Copy the code The code is as follows:
if (Z_OBJ_HT_P(val)-> get) {
val_free = val = Z_OBJ_HT_P(val)->get(val TSRMLS_CC);
goto repeat;
}
// __toString() method will be called in cast_object
else if (Z_OBJ_HT_P(val)->cast_object) {
ALLOC_INIT_ZVAL(val_free);
if (Z_OBJ_HT_P(val)->cast_object(val, val_free, IS_STRING TSRMLS_CC) == SUCCESS)
{
val = val_free;
break;
}
}
1, Z_OBJ_HT_P(val)->get, after macro expansion it is (*val). value.obj.handlers->get
2, Z_OBJ_HT_P(val)->cast_object, after macro expansion, it is (*val).value.obj.handlers->cast_object
handlers is a function that contains many Pointer structure, see _zend_object_handlers for specific definition. The function pointers in this structure are used to operate objects, such as reading/modifying object attributes, obtaining/calling object methods, etc... get and cast_object are also among them.
For general objects, PHP provides the standard cast_object function zend_std_cast_object_tostring. The code is located in php-src/zend/zend-object-handlers.c:
Copy code The code is as follows:
ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC) /* {{{ */
{
zval *retval;
Zend_Class_ENTRY *CE;
Switch (Type) {
Case is_String:
CE = z_objce_p (readObj);
// If the user's class is defined _ _Tostring, try to call
if (CE-& GT; __ Tostring &&
(ZEND_CALL_METHOD_WITH_0_PARAMS (& ReadObj, CE, & CE- & GT; __TOSTRING, & TVAL) || Eg (Exception))) {
……
}
. The default cast_object is to find the __tostring method in the class and then call...
Go back to the initial example, define('foo', $a), since $a is an instance of A, and class A defines _ _toString, so in fact the foo constant is equal to the return value bar of toString.
http://www.bkjia.com/PHPjc/825008.html
www.bkjia.com
true
http: //www.bkjia.com/PHPjc/825008.htmlTechArticleLooking at the manual, it says that the constants defined by define are only allowed: Only scalars and null are allowed. The type of scalar is integer, float, string or boolean. It is also possible to define the type of constant value as resource ,...