PHP Define Constants Detailed

Source: Internet
Author: User
    1. Class A {
    2. Public Function __tostring () {
    3. return ' bar ';
    4. }
    5. }
    6. $a = new A ();
    7. Define (' foo ', $a);
    8. echo foo;
    9. Output bar
Copy Code

How the Define in PHP is implemented:

  1. Zend_function (define)

  2. {
  3. Char *name;
  4. int Name_len;
  5. Zval *val;
  6. Zval *val_free = NULL;
  7. Zend_bool non_cs = 0;
  8. int case_sensitive = Const_cs;
  9. Zend_constant C;

  10. Receive 3 parameters, String,zval,bool

  11. if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "Sz|b", &name, &name_len, &val, &non_cs) = = FAILURE) {
  12. Return
  13. }

  14. is case sensitive

  15. if (Non_cs) {
  16. case_sensitive = 0;
  17. }

  18. If the Define class constant, the error

  19. if (ZEND_MEMNSTR (Name, "::", sizeof ("::")-1, name + Name_len)) {
  20. Zend_error (e_warning, "Class constants cannot be defined or redefined");
  21. Return_false;
  22. }

  23. Get the real value, save it with Val

  24. Repeat
  25. Switch (Z_type_p (val)) {
  26. Case Is_long:
  27. Case Is_double:
  28. Case is_string:
  29. Case Is_bool:
  30. Case Is_resource:
  31. Case Is_null:
  32. Break
  33. Case Is_object:
  34. if (!val_free) {
  35. if (Z_obj_ht_p (val)->get) {
  36. Val_free = val = z_obj_ht_p (val)->get (Val tsrmls_cc);
  37. Goto repeat;
  38. } else if (Z_obj_ht_p (val)->cast_object) {
  39. Alloc_init_zval (Val_free);
  40. if (Z_obj_ht_p (Val)->cast_object (Val, Val_free, is_string tsrmls_cc) = = SUCCESS) {
  41. val = val_free;
  42. Break
  43. }
  44. }
  45. }
  46. /* No Break */
  47. Default
  48. Zend_error (e_warning, "Constants may be evaluate to scalar values");
  49. if (Val_free) {
  50. Zval_ptr_dtor (&val_free);
  51. }
  52. Return_false;
  53. }
  54. Building constants
  55. C.value = *val;
  56. Zval_copy_ctor (&c.value);
  57. if (Val_free) {
  58. Zval_ptr_dtor (&val_free);
  59. }
  60. C.flags = case_sensitive; /* Non Persistent *///If case is not sensitive, then 0, sensitivity is 1
  61. C.name = zend_strndup (name, Name_len);
  62. C.name_len = name_len+1;
  63. C.module_number = php_user_constant; Label non-kernel constants, but user-defined constants
  64. Register constants
  65. if (Zend_register_constant (&c tsrmls_cc) = = SUCCESS) {
  66. Return_true;
  67. } else {
  68. Return_false;
  69. }
  70. }

Copy Code

Note that a loop that starts with repeat also uses a goto statement t_t

The purpose of this code is: for Int,float,string,bool,resource,null, the actual defined constants are used directly for object, you need to convert the object to one of the above 6 types (if it is still object after transformation, Continue to transform) how do I make an object into one of 6 types? There are 2 ways to look at the code:

    1. if (Z_obj_ht_p (val)->get) {
    2. Val_free = val = z_obj_ht_p (val)->get (Val tsrmls_cc);
    3. Goto repeat;
    4. }
    5. The __tostring () method is called in the Cast_object
    6. else if (Z_obj_ht_p (val)->cast_object) {
    7. Alloc_init_zval (Val_free);
    8. if (Z_obj_ht_p (Val)->cast_object (Val, Val_free, is_string tsrmls_cc) = = SUCCESS)
    9. {
    10. val = val_free;
    11. Break
    12. }
    13. }
Copy Code

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:

    1. Zend_api int zend_std_cast_object_tostring (zval *readobj, zval *writeobj, int type TSRMLS_DC)/* {{* * *

    2. {
    3. Zval *retval;
    4. Zend_class_entry *ce;

    5. Switch (type) {

    6. Case is_string:
    7. CE = z_objce_p (readobj);
    8. If __tostring is defined in the user's class, an attempt is made to invoke the
    9. if (ce->__tostring &&
    10. (Zend_call_method_with_0_params (&readobj, CE, &ce->__tostring, "__tostring", &retval) | | EG (Exception))) {
    11. ......
    12. }
    13. return FAILURE;
    14. ......
    15. }
    16. return FAILURE;
    17. }
Copy Code

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.

PS: Keep digging a little bit of detail.

1,define has a return value that is usually written directly in our definition constants: Define (' foo ', 123); However, from the implementation of define, it has a return value. According to the description in the manual:

Returns TRUE on success, or FALSE on failure.

Under what circumstances will define fail? As an example:

    1. Define (' Php_int_max ', 1); Returns false

    2. Define (' FOO ', 1); Returns True

    3. Define (' FOO ', 2); Returns false
Copy Code

The above code contains two cases where we try to redefine the predefined constants of the PHP kernel, such as Php_int_max, which will obviously fail. The second scenario is that we've defined a constant foo somewhere in the code, and then we define it again in the next program, which can also lead to failure. Therefore, it is best to write all constants that need to be defined when coding, so as not to cause name duplication.

2, constant name No limit again review the implementation of define, which only determines if name is xxx::yyy this form.

In other words, define almost no requirement for its name, and of course it does not require that name be a valid PHP variable name. Therefore, we can let define's constants take some strange names. For example:

    1. Define (' >_< ', 123); Returns True
    2. Echo >_<; Syntax error
Copy Code

However, if such constants are defined, they cannot be used directly and will be reported as grammatical errors. The correct method of use is as follows:

    1. Define (' >_< ', 123); Returns True
    2. ECHO constant (' >_< '); Output 123
Copy Code
  • 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.