PHP define the second parameter using _php tutorial

Source: Internet
Author: User
Tags php define php source code scalar
Read the manual that define defines constants that allow only:
Only scalar and null are allowed. The type of scalar is integer, Float,string, or Boolean. It is also possible to define a constant value of type resource, but it is not recommended to do so, which can lead to the occurrence of an unknown condition.
Read the PHP source code today, found that the second parameter of define can actually be an object.
Put a sample first:
Copy CodeThe code is as follows:
Class A {
Public Function __tostring () {
return ' bar ';
}
}

$a = new A ();
Define (' foo ', $a);
echo foo;
Output bar

Then let's look at how the Define in PHP is implemented:
Copy CodeThe 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
}

is case sensitive
if (Non_cs) {
case_sensitive = 0;
}

If the Define class constant, the error
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, 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 be evaluate to scalar values");
if (Val_free) {
Zval_ptr_dtor (&val_free);
}
Return_false;
}

Building constants
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 constants
if (Zend_register_constant (&c tsrmls_cc) = = SUCCESS) {
Return_true;
} else {
Return_false;
}
}

Note that a loop that starts with repeat also uses a goto statement t_t
The function of this code is:
For Int,float,string,bool,resource,null, these values are used directly when the constants are actually defined
For object, you need to convert the object to one of the above 6 types (if it is still object after transformation, continue with the transformation)
How do I put an object into one of 6 types? There are 2 ways to look at the code:
Copy CodeThe 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;
}
The __tostring () method is called in the 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 (*val). Value.obj.handlers->get
2,z_obj_ht_p (Val)->cast_object, after the macro is expanded (*val). Value.obj.handlers->cast_object
Handlers is a struct with many function pointers, as defined in _zend_object_handlers. The function pointers in the struct are used to manipulate objects, such as reading/modifying object properties, getting/calling object methods, and so on ... Get and Cast_object are also one of them.
For generic objects, PHP provides the standard Cast_object function zend_std_cast_object_tostring, which is located in PHP-SRC/ZEND/ZEND-OBJECT-HANDLERS.C:
Copy CodeThe 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's class, an attempt is made to invoke the
if (ce->__tostring &&
(Zend_call_method_with_0_params (&readobj, CE, &ce->__tostring, "__tostring", &retval) | | EG (Exception))) {
......

}
return FAILURE;
......
}
return FAILURE;
}

From the above specific implementation, the default cast_object is to find the class __tostring method and then call ...
Back to the first example, define (' foo ', $a), since $ A is an instance of a and __tostring is defined in Class A, the Foo constant is actually equal to the return value of ToString bar.

http://www.bkjia.com/PHPjc/825008.html www.bkjia.com true http://www.bkjia.com/PHPjc/825008.html techarticle the manual says that the constants defined by define are allowed only: scalar and null are allowed only. The type of scalar is integer, Float,string, or Boolean. It is also possible to define a constant value of type 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.