Home >Backend Development >PHP Tutorial >How to use the second parameter of php define_PHP tutorial

How to use the second parameter of php define_PHP tutorial

WBOY
WBOYOriginal
2016-07-13 10:25:37866browse

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:

Copy the code The code is as follows:

class A {
public function __toString( ) {
                                                    . ;
// Output bar


Let’s take a look at how define in php is implemented:



Copy code

The code is as follows:

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 ,...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn