>  기사  >  백엔드 개발  >  원본: 다음과 같은 멤버 속성 및 메서드에 대한 PHP 커널 연구

원본: 다음과 같은 멤버 속성 및 메서드에 대한 PHP 커널 연구

黄舟
黄舟원래의
2016-12-22 09:58:271260검색

이 글에서는 PHP 클래스의 멤버 속성과 메서드에 대해 자세히 설명하겠습니다.
이전 글에서는 zend_class_entry를 생성하고 초기화하는 데 사용되는 zend_do_begin_class_declaration 함수를 소개했습니다.
클래스가 저장되는 구조입니다.


1

2

3

classPerson{

public$name;

}

또한 이전 글에서 언급한 zend_initialize_class_data 함수를 기억해두셔도 상관없습니다.
zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

ZEND_APIvoidzend_initialize_class_data(zend_class_entry *ce , zend_bool nullify_handlers TSRMLS_DC)/ * {{ { */

{

          zend_bool persist_hashes = (ce->type == ZEND_INTERNAL_CLASS) ?ZVAL_INTERNAL_PTR_DTOR: ZVAL_PTR_ DTOR) ;

ce->refcount = 1;

ce->constants_updated = 0;

ce->ce_fla gs = 0 ;

ash_init_ex(&ce ->default_properties, 0, NULL, zval_ptr_dtor_func, persist_hashes, 0);

zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (percious_hashes ? ternal: zend_destroy_property_info) , 영구_해시, 0);

zend_hash_init_ex(&ce->default_static_members, 0, NULL, zval_ptr_dtor_func, persist_hashes, 0); zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persist_hashes, 0);

zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persist_hashes, 0);

if(ce->type == ZEND_INTERNAL_CLASS) {

# ifdef ZTS

intn = zend_hash_num_elements(CG(class_table));

if(CG(static_members) && n >= CG(last_static_member)) {

                                                                   /* 런타임 선언 지원: dl()                             ​ ​ CG(static_members) =realloc(CG(static_members), (n+1)*sizeof(HashTable*));

CG(static_members)[n] = NULL;

}

ce->static_members = (HashTable *)(zend_intptr_t)n;

#else

            ce->static_members = NULL 🎜> ce->static_members = &ce->default_static_members;

}

        if(nullify_handlers) {

              ce->constructor = NULL;

               ce->destructor = NULL;

                ce->clone = NULL;

               ce->__get = NULL;

               ce->__set = NULL;

               ce->__unset = NULL;

                ce- >__isset = NULL;

               ce->__call = NULL;

              ce->__callstatic = NULL;

               ce->__ tostring = NULL;

               ce->create_object = NULL;

               ce->get_iterator = NULL;

               ce->iterator_funcs.funcs = NULL;

                ce- >interface_gets_implemented = NULL;

               ce->get_static_method = NULL;

              ce->parent = NULL;

                ce->num_interfaces = 0;

               ce->인터페이스 = NULL;

               ce->모듈 = NULL;

               ce->serialize = NULL;

                ce-> unserialize = NULL;

               ce->serialize_func = NULL;

              ce->unserialize_func = NULL;

               ce->builtin_functions = NULL;

        }

}

   

zend_bool persist_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
普什么会有区别呢???我还没来得及研究哦..^.^
注意看13-1 6행.
zend_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persist_hashes, 0);
zend_hash_init_ex(&ce->default_static_members, 0, NULL, zval_ptr_dtor_func, persist_hashes, 0);
zend _hash_init_ex(&ce- >constants_table, 0, NULL, zval_ptr_dtor_func, persist_hashes, 0);
zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persist_hashes, 0);
如果你看过之前的文章,那么你肯 정정지식은 HashTable을 기반으로 합니다.
是的..确实是这样,
default_properties,default_static_members等TU是HashTable은 指针.所以初始化当然要zend_h ash_init了.
第36-61行初始化魔术방법
不过这里只是初始化哦..好image并没有设置属性.$name属性是如何添加到属性表里的呢???

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

   

unticked_class_declaration_statement:

               class_entry_type T_STRING

에서

                       { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); }

                       implements_list

                     '{'

                              class_statement_list

                       '}'{ zend_do_end_class_declaration(&$1, &$2 TSRMLS_CC); }

        |       interface_entry T_STRING

                       { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); }

                       interface_extends_list

                     '{'

                               class_statement_list

                      '}'{ zend_do_end_class_declaration(&$1, &$2 TSRMLS_CC); }

;

class_statement:

               variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration';'

        |       class_constant_declaration';'

        |       method_modifiers 함수 is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); }'('

                       parameter_list')'method_body { zend_do_abstract_method(&$4, &$1, &$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }

;

class_variable_declaration:

              class_variable_declaration','T_VARIABLE                                  { _declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); }

        |       class_variable_declaration','T_VARIABLE'='static_scalar     { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); }

        |       T_VARIABLE                                           { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); }

        |       T_VARIABLE'='static_scalar    { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); }

;

   

这个还记得吧?
类初始化成功后类里平东西当然要执行class_statement _list这个啦.. ^.^
类体里会调사용 zend_do_declare_property处리.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

   

voidzend_do_declare_property(constznode *var_name,constznode *value, zend_uint access_type TSRMLS_DC)/* {{{ */

{

       zval *property;

        zend_property_info *exist ing_property_info;

        char*comment = NULL;

        intcomment_len = 0;

  

        if(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)

               zend_error(E_COMPILE_ERROR,"인터페이스에 멤버 변수가 포함될 수 없습니다.");

        }

  

        if(access_type & ZEND_ACC_ABSTRACT) {

                zend_error (E_COMPILE_ERROR,"속성은 추상적으로 선언할 수 없습니다.");

        }

  

        if(access_type & ZEND_ACC_FINAL) {

              zend _error(E_COMPILE_ERROR,"할 수 없습니다 %s::$%s final 속성을 선언하세요. final 수정자는 메서드 및 클래스에만 허용됩니다.",

                                  CG(active_class_entry)->name, var_name->u.constant.value.str. val);

        }

  

        if(zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name ->u.constant.value.str.len+1, (void**) &existing_property_info)==SUCCESS) {

               if(!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {

                     zend_error(E_COMPILE_ERROR,"%s::$%s을(를) 다시 선언할 수 없습니다", CG(active_class_entry)->name, var_name->u.constant.value.str.val);

                }

        }

        ALLOC_ZVAL(속성);

  

        if(값) {

              *적절 ty = 값 -> u. 상수;

        }else{

                INIT_PZVAL(속성);

              Z_TYPE_P(속성) = IS_NULL;

        }

  

>                CG(doc_comment) = NULL ;

               CG(doc_comment_len) = 0;

        }

  

        zend_declare_property_ex(CG(active_class_entry), var_name->u.constant.value. str.val, var_name->u.constant.value.str.len, 속성, access_type, comment, comment_len TSRMLS_CC);

        efree(var_name->u.constant.value.str.val) ;

}

   

8-25행:
클래스가 인터페이스를 선언하면 인터페이스는 속성을 가질 수 없으며 인터페이스는 멤버 변수를 포함할 수 없습니다.
클래스의 속성이 추상으로 설정되면 다음이 발생합니다. throw 속성은 추상으로 선언할 수 없습니다
클래스의 속성이 final로 설정되면 throw Cannot 선언 속성 %s::$%s final, final 수정자는 메서드 및 클래스에만 허용됩니다
모두 OK이면 zval 데이터가 할당됩니다.
속성에 초기 값이 있으면 데이터가 zval에 할당됩니다. 그렇지 않으면 INIT_PZVAL이 호출되어 zval을 초기화하고 유형이 IS_NULL로 설정됩니다.
마지막으로 zend_declare_property_ex가 호출됩니다. 지정된 active_class_entry에 zval을 추가합니다
클래스 메서드

1

2

3

4

5

classPerson{

publicfunctiontest(){

echo1;

}

}

메소드라면 어떻게 처리되나요?
규칙을 먼저 살펴보세요

1

2

3

4

5

class_statement:

CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration';'

gin_function_declaration(&$2, &$4, " RMLS_CC); }

첫 번째가 속성이고, 세 번째가 메소드...

zend_do_begin_function_declaration이 낯익은 것 같나요?

이전 내용을 읽어보셨다면 기사, 당신은 분명 친숙해 보인다

아직 읽지 않았다면 먼저 이 기사를 읽어보세요

여기서는 자세히 설명하지 않겠습니다.
무슨 내용인지만 이야기하겠습니다. 해당 글에는 언급되지 않았습니다
이 기능에는



1

2

3

4에 판단이 있습니다.

5

6

7

8

9

10

11

if (is_method) {

if(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {

if((Z_LVAL(fn_flags_znode-&g) t;u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC) :) .str.val);

                                                             나머지 파서 */

}

                          fn_flags = Z_LVAL( fn_flags_znode->u.constant);                            ​​fn_flags = 0;

}

물론, 그럼 그것

3-5줄: 인터페이스 클래스의 속성을 private 또는 protected로 설정하면 인터페이스 메서드 %s::%s()에 대한 액세스 유형을 생략해야 합니다

가 발생하고 그런 다음

if (zend_hash_add()가 호출됩니다 &CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {

zend_error(E_COMPILE_ERROR, “Cannot redeclare %s: :%s()”, CG(active_class_entry)->name, name);

}

function_table에 직접 메서드를 추가합니다.

다음 클래스 선언에 따라 다른 판단을 내리게 됩니다.

위 내용은 원본 내용입니다. PHP 커널 연구 및 기타 회원 속성 및 방법에 대한 자세한 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.