ホームページ >バックエンド開発 >PHPチュートリアル >オリジナル: メンバーのプロパティとメソッドに関する PHP カーネルの研究
この記事では、PHP クラスのメンバー属性とメソッドについて詳しく説明します。
前の記事では、zend_class_entry の作成と初期化に使用される zend_do_begin_class_declaration 関数を紹介しました。
クラスのすべての情報はこの構造体に保存されます。 、次に属性 メソッドとメソッドはどのように保存されますか?覚えていませんね。この関数
14
15
16
17
18
19
20
21
22
23
24
25
495051525 354555657
585960
6162 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这个啦..^.^
234567891011121314 15161718 192021222324252627282930 31323334 35363738🎜
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;
}
}
メソッドだったらどうする?? 対処方法
まずはルールを見てください
zend_do_begin_function_declaration 見覚えがありますか?
前の記事を読んだことがあれば、間違いなく見覚えがあるでしょう 読んでいない場合読まないでください、まずこの記事を読んでください。 関数の定義
ここでは詳しく説明しません
その記事で言及されていないことについてのみ説明します
この関数には
の判定があります。
クラスのプロパティが 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) に注目してください。