php 类

php类的内部结构

struct _zend_class_entry {
char type; // 类型:ZEND_INTERNAL_CLASS / ZEND_USER_CLASS
char *name;// 类名称
zend_uint name_length; // 即sizeof(name) - 1
struct _zend_class_entry *parent; // 继承的父类
int refcount; // 引用数
zend_bool constants_updated;
zend_uint ce_flags; // ZEND_ACC_IMPLICIT_ABSTRACT_CLASS: 类存在abstract方法
// ZEND_ACC_EXPLICIT_ABSTRACT_CLASS: 在类名称前加了abstract关键字
// ZEND_ACC_FINAL_CLASS
// ZEND_ACC_INTERFACE
HashTable function_table; // 方法
HashTable default_properties; // 默认属性
HashTable properties_info; // 属性信息
HashTable default_static_members;// 类本?所具有的静态变量
HashTable *static_members; // type == ZEND_USER_CLASS时,取
&default_static_members;
// type == ZEND_INTERAL_CLASS时,设为NULL
HashTable constants_table; // 常量
struct _zend_function_entry *builtin_functions;// 方法定义入?
union _zend_function *constructor;
union _zend_function *destructor;
union _zend_function *clone;
/* 魔术方法 */
union _zend_function *__get;
union _zend_function *__set;
union _zend_function *__unset;
union _zend_function *__isset;
union _zend_function *__call;
union _zend_function *__tostring;
union _zend_function *serialize_func;
union _zend_function *unserialize_func;
zend_class_iterator_funcs iterator_funcs;// 迭代
/* 类句柄 */
zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC);
zend_object_iterator *(*get_iterator)(zend_class_entry *ce, zval *object,
intby_ref TSRMLS_DC);
/* 类声明的接? */
int(*interface_gets_implemented)(zend_class_entry *iface,
zend_class_entry *class_type TSRMLS_DC);
/* 序列化回调函数指针 */
int(*serialize)(zval *object, unsignedchar**buffer, zend_uint *buf_len,
zend_serialize_data *data TSRMLS_DC);
int(*unserialize)(zval **object, zend_class_entry *ce,
constunsignedchar*buf,
zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
zend_class_entry **interfaces; // 类实现的接?
zend_uint num_interfaces; // 类实现的接?数
char *filename; // 类的存放?件地址 绝对地址
zend_uint line_start; // 类定义的开始行
zend_uint line_end; // 类定义的结束行
char *doc_comment;
zend_uint doc_comment_len;
struct _zend_module_entry *module; // 类所在的模块入口:EG(current_module)
};

魔术方法在初始化时都是null

成员变量:这里我们以标准的操作函数为例说明成员变量的读取和获取。成员变量的获取最终调用的是

zend_std_read_property函数。 这个函数的流程是这样的:
第一步,获取对象的属性,如果存在,转第二步;如果没有相关属性,转第三步
第二步,从对象的properties查找是否存在与名称对应的属性存在,如果存在返回结果,如果不存
在,转第三步
第三步,如果存在__get魔术方法,则调用此方法获取变量,如果不存在,转第四步
第四步,如果type=BP_VAR_IS,返回 &EG(uninitialized_zval_ptr),否则报错
成员变量的设置最终调用的是zend_std_write_property函数。整个执行流程如下:
.3
第一步,获取对象的属性,如果存在,转第二步;如果没有相关属性,转第四步
第二步,从对象的properties查找是否存在与名称对应的属性存在,如果存在,转第三步,如果不存
在,转第四步
第三步,如果已有的值和需要设置的值相同,则不执行任何操作,否则执行变量赋值操作, 此处的
变量赋值操作和常规的变量赋值类似,有一些区别,这里只处理了是否引用的问题
第四步,如果存在__set魔术方法,则调用此方法设置变量,如果不存在,转第五步
第五步,如果成员变量一直没有被设置过,则直接将此变量添加到对象的properties字段所在
HashTable中。

成员方法:

举个例子

第一步,处理调用的方法名,获取其值,并做检验处理:如果不是字符串,则报错
第二步,如果第一个操作数是对象,则转第三步,否则报错 Call to a member function t on a nonobject
第三步,调?对象的get_method函数获取成员方法
第四步,其它处理,包括静态方法,this变量等。
而get_method函数一般是指标准实现中的get_method函数,其对应的具体函数为
Zend/zend_object_handlers.c?件中zend_std_get_method函数。 zend_std_get_method函数的流程如
下:
第一步,从zobj->ce->function_table中查找是否存在需要调?的函数,如果不存在,转第二步,如
果存在,转第三步
第二步,如果__call函数存在,则调用zend_get_user_call_function函数获取并返回,如果不存在,
则返回NULL
第三步,检查方法的访问控制,如果为私有函数,转第四步,否则转第五步
第四步,如果为同一个类或父类和这个方法在同一个作用域范围,则返回此方法,否则判断__call函
数是否存在,存在则调用此函数,否则报错
第五步,处理函数重载及访问控制为protected的情况。 转第六步
第六步,返回fbc

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。