Original : recherche du noyau PHP sur les propriétés et méthodes des membres telles que

黄舟
Libérer: 2023-03-03 21:06:02
original
1260 Les gens l'ont consulté

Cet article parlera en détail des attributs et méthodes des membres des classes PHP.
Dans l'article précédent, nous avons présenté la fonction zend_do_begin_class_declaration, qui est utilisée pour créer et initialiser un zend_class_entry
Toutes les informations du la classe est enregistrée dans Dans cette structure, comment les propriétés et les méthodes sont-elles stockées


1

2

3

classPerson{

public$name;

}

Vous vous souvenez également de la fonction zend_initialize_class_data mentionnée dans l'article précédent ? Peu importe si vous ne vous en souvenez pas. Regardons cette fonction de plus près

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 persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? ) ;

ce->refcount = 1;

ce->constants_updated = 0;

ce->ce_fla gs = 0 ;

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

zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? ternal : erty_info), persistent_hashes, 0); );

zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_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)) {

                                                                                                                                                                                                              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;

#endif

}else{

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-> unserialize = NULL;

                ce->serialize_func = NULL;

               ce->unserialize_func = NULL;

                 ce->builtin_functions = NULL;

        }

}

   

zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;

普通用户类与内部类 分配内存的方式不同…. ^.^

注意看13-16行.zend_hash_init_ex(&ce- >constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);

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

如果你看过之前的文章,那么你Il s'agit d'un HashTable.

是的..初始化当然要zend_hash_init了.
第36-61行初始化魔术方法
不过这里只是初始化哦..好像并没有设置属性.$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 extends_from

                        { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); antecedents _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 function 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                                                               e_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); antecedents Il s'agit d'un 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 *existing _property_info;

        char*comment = NULL;

        intcomment_len = 0;

  

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

               zend_error(E_COMPILE_ERROR, "Les interfaces ne peuvent pas inclure de variables membres");

        }

  

        if(access_type & ZEND_ACC_ABSTRACT {

                zend_error (E_COMPILE_ERROR,"Les propriétés ne peuvent pas être déclarées abstraites");

        }

  

        if(access_type & ZEND_ACC_FINAL) {

                zend_error(E_ COMPILE_ERROR,"Impossible déclarer la propriété %s::$%s final, le modificateur final n'est autorisé que pour les méthodes et les classes",

                                      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, "Impossible de redéclarer %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);

                }

        }

        ALLOC_ZVAL(propriété);

  

        si(valeur) {

                *propriété = valeur-> u.constant ;

        }else{

                INIT_PZVAL(propriété);

                Z_TYPE_P(propriété) = IS_NULL;

        }

  

        if(CG(doc_comment)) {

                comment = CG(doc_comment);

               comment_len = CG(doc_comment_len);

                CG(doc_comment) = NULL ; > .constant.value.str .val, var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC);

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

}

   

Ligne 8-25 :
Si votre classe déclare une interface, alors l'interface ne peut pas avoir d'attributs et lancera Les interfaces ne peuvent pas inclure de variables membres
Si les attributs de la classe sont définis sur abstrait, alors elle le fera throw Les propriétés ne peuvent pas être déclarées abstraites
Si les propriétés de la classe sont définies sur final, alors elle lancera Impossible de déclarer la propriété %s::$%s final, le modificateur final n'est autorisé que pour les méthodes et les classes
Tout c'est bien, une donnée zval sera allouée.
Si l'attribut a une valeur initiale, alors les données seront affectées au zval. Sinon, INIT_PZVAL sera appelé pour initialiser le zval et le type est défini sur IS_NULL ;
Enfin, zend_declare_property_ex sera appelé Ajouter le zval à l'active_class_entry spécifié
Méthodes de la classe

1

2

3

4

5

classPerson{

publicfunctiontest(){

echo1;

}

}

Et si c'est une méthode ? Comment est-elle gérée ?
Regardez d'abord les règles

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); }

Le premier est l'attribut, puis le troisième est la méthode...

Zend_do_begin_function_declaration vous semble-t-il familier ?

Si vous avez lu le précédent article, vous devez Cela vous semble familier

Si vous ne l'avez pas lu, allez d'abord lire cet article La définition de la fonction

Je n'entrerai pas dans les détails ici.
Je vais juste parler de ce qui était. non mentionné dans cet article
Dans cette fonction Il y a un jugement en



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);

                                                                                       reste de l'analyseur */

}

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

}

Si vous définissez les propriétés de la classe d'interface sur privée ou protégée, alors Type d'accès pour la méthode d'interface %s ::%s() doit être omis

sera lancé puis

if (zend_hash_add() sera appelé &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, "Impossible de redéclarer %s:: %s()", CG(active_class_entry)->name, name);

}

Ajoutez la méthode directement à la function_table.

Ce qui suit fera différents jugements basés sur différentes déclarations de classe.

Ce qui précède est le contenu original : recherche du noyau PHP et autres attributs et méthodes des membres. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (www.php.cn) !


Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!