ホームページ  >  記事  >  バックエンド開発  >  オリジナル: メンバーのプロパティとメソッドに関する PHP カーネルの研究

オリジナル: メンバーのプロパティとメソッドに関する PHP カーネルの研究

黄舟
黄舟オリジナル
2016-12-22 09:58:271224ブラウズ

この記事では、PHP クラスのメンバー属性とメソッドについて詳しく説明します。
前の記事では、zend_class_entry の作成と初期化に使用される zend_do_begin_class_declaration 関数を紹介しました。
クラスのすべての情報はこの構造体に保存されます。 、次に属性 メソッドとメソッドはどのように保存されますか?覚えていませんね。この関数

zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC) を詳しく見てみましょう。


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

5 3

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_boolpersistent_hashes = (ce->type = = ZEND_INTERNAL_CLASS) 1 : 0;

dtor_func_t zval_pt r_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR) ;

ce->refcount = 1;

ce->constants_updated = 0;

ce-> ;ce_flags = 0;

ce->doc_comment = NULL; doc_comment_len = 0;

zend_hash_init_ex(&ce-&g t;default_properties, 0, NULL, zval_ptr_dtor_func,persistent_hashes, 0); Zen d_hash_init_ex(&ce->default_static_members, 0, NULL, zval_ptr_ dtor_func、persistent_hashes、0) ; zend_hash_init_ex( &ce->constants_table, 0, NULL, zval_ptr_dtor_func,persistent_hashes, 0); ;

if(ce-> ;type == ZEND_INTERNAL_CLASS) {

#ifdef ZTS

intn = zend_hash_num_elements(CG(class_table)) ; t;= CG(last_static_member)) {

実行時宣言用: dl() */

CG(last_static_member) CG(static_members) );

CG(static_members)[n] = NULL;

# else

ce-> static_members = null;

if(nullify_handlers) {

ce->constructor = NULL;

ce->destructor = NULL;

ce ->クローン = 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->inter顔 = NULL;

ce->module = NULL;

ce->serialize = NULL;

ce->unserialize = NULL;

ce->serialize_func = NULL;

ce->un Serialize_func = NULL;

ce->builtin_functions = NULL;

}

}

zend_boolpersistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
普通用户類と内部類の割り当て内存方式が異なります….何会有区别呢???我还没来得及研究哦..^.^
注意看13-16行.
zend_hash_init_ex(&ce- >default_properties、0、NULL、zval_ptr_dtor_func、persistent_hashes、0);
zend_hash_init_ex(&ce->default_static_members、0、NULL、zval_ptr_dtor_func、persistent_hashes、0);
zend_hash_init_ex(&ce->const ants_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);
如果你看​​过前の文章,那么你肯定知道这是在初化HashTable.
是的..确实これは、
default_properties,default_static_members などの HashTable タイプの指针です。プロパティ表里に追加しました

12

13

14

15

16

17

18

19

20

21

22

23

24

2 5

26

unticked_class_declaration_statement:

class_entry_type T_STRING extends_from

{ 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 { zend_do_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这个啦..^.^

类体里会调用destroy_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 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,"インターフェイスには次のものが含まれていない可能性があります)メンバー変数");

}

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(値) {

* property = value->u.constant;

}else{

INIT_PZVAL(プロパティ);

Z_TYPE_P(プロパティ) = IS_NULL;

}

if(CG(doc_comment)) {

コメント = CG(doc_comment);

comment_len = CG(doc_comment_len);

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, property, access_type, comment, comment_len TSRMLS_CC);

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

}

8 ~ 25 行目:
クラスがインターフェイスを宣言している場合、インターフェイスはプロパティを持つことができず、インターフェイスにはメンバー変数が含まれていない可能性があります。
クラスのプロパティが abstract に設定されている場合、プロパティはスローされません。抽象宣言されました
クラスのプロパティがfinalに設定されている場合、プロパティ%s::$%sを宣言できません。finalがスローされます。final修飾子はメソッドとクラスにのみ許可されます
すべて問題なく、zvalデータは割り当てられています。
属性に初期値がある場合、データは zval に割り当てられます。そうでない場合は、INIT_PZVAL が呼び出されて zval が初期化され、型が IS_NULL に設定されます。
最後に、zend_declare_property_ex が呼び出されて zval が追加されます。指定された active_class_entry
クラスのメソッド

1

2

3

4

5

classperson{

public functiontest(){

echo1;

}

}

メソッドだったらどうする?? 対処方法
まずはルールを見てください

1

2

3

4

5

class_stateメント:

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

) }'('

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

1 つ目は属性、3 つ目はメソッドです...

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

zend_error(E _COMPILE_ERROR,"インターフェイス メソッド %s::%s() のアクセス タイプは省略する必要があります", CG(active_class_entry)->name, function_name->u.constant.value .str.val); (fn_flags_znode->u .constant) |= ZEND_ACC_ABSTRACT;/* パーサーの残りの部分に伝播します */

*/

クラスのプロパティが 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 中国語 Web サイト (www.php.cn) に注目してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。