Phpdefine's second parameter usage _ PHP Tutorial

Source: Internet
Author: User
How to use the second parameter of phpdefine. According to the manual, only constants defined by define are allowed: scalar and null. The scalar type is integer, float, string, or boolean. You can also define the constant value type as resource. Read the manual and say that the constants defined by define are only allowed:
Only scalar and null are allowed. The scalar type is integer, float, string, or boolean. It can also define the type of constant value as resource, but it is not recommended to do so, it may cause unknown conditions.
Today, I read the php source code and found that the second parameter of define can also be an object.
First paste an example:

The code is as follows:


Class {
Public function _ toString (){
Return 'bar ';
}
}

$ A = new ();
Define ('foo', $ );
Echo foo;
// Output bar


Next let's take a look at how define is implemented in php:

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;

// Receives three parameters: string, zval, and bool.
If (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "sz | B", & name, & name_len, & val, & non_cs) = FAILURE ){
Return;
}

// Case sensitive
If (non_cs ){
Case_sensitive = 0;
}

// If The define class constant is used, an error is returned.
If (zend_memnstr (name, ":", sizeof (":")-1, name + name_len )){
Zend_error (E_WARNING, "Class constants cannot be defined or redefined ");
RETURN_FALSE;
}

// Obtain 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_OBJ_HT_P (val)-> get (val TSRMLS_CC );
Goto repeat;
} 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;
}
}
}
/* No break */
Default:
Zend_error (E_WARNING, "Constants may only evaluate to scalar values ");
If (val_free ){
Zval_ptr_dtor (& val_free );
}
RETURN_FALSE;
}

// Build a 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 a 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 role of this code is:
For int, float, string, bool, resource, null, these values are directly used for actually defined constants.
For an object, you need to convert the object to one of the above six types (if it is still an object after the transformation, the transformation will continue)
How can we convert an object into one of six types? There are two methods in 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 the macro is expanded, it is (* val). value. obj. handlers-> get
2. Z_OBJ_HT_P (val)-> cast_object. after the macro is expanded, it is (* val). value. obj. handlers-> cast_object
Handlers is a struct containing many function pointers. for specific definitions, see _ zend_object_handlers. The function pointers in this struct are used to operate objects, such as reading/modifying object attributes, obtaining/calling object methods, and so on... Get and cast_object are also one of 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:

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 _ toString is defined in the user class, call
If (ce->__ tostring &&
(Zend_call_method_with_0_params (& readobj, ce, & ce->__ tostring, "_ tostring", & retval) | EG (exception ))){
......

}
Return FAILURE;
......
}
Return FAILURE;
}


From the specific implementation above, the default cast_object is to find the _ tostring method in the class and then call...
Return to the initial example, define ('foo', $ a), because $ a is an instance of A, and class A defines _ toString, therefore, the foo constant is equal to the return value bar of toString.

Scalar only allows scalar and null. The scalar type is integer, float, string, or boolean. You can also define the constant value type as resource ,...

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.