ahxxx 2019-07-05
baiyan
class A{
const PI = 3.14;
}struct _zend_class_entry {
...
HashTable constants_table; //常量哈希表,key为常量名,value为常量值
...
};class A{
public $name = 'jby';
}struct _zend_class_entry {
...
int default_properties_count; //普通属性的数量总和
...
zval *default_properties_table; //存放普通属性的初始化值的数组
...
HashTable properties_info; //存储对象属性的信息哈希表,key为属性名,value为zend_property_info结构体
...
}typedef struct _zend_property_info {
uint32_t offset; //表示普通属性的内存偏移值或静态属性的数组索引
uint32_t flags; //属性掩码,如public、private、protected及是否为静态属性
zend_string *name; //属性名
zend_string *doc_comment; //文档注释信息
zend_class_entry *ce; //所属类
} zend_property_info;
//flags标识位
#define ZEND_ACC_PUBLIC 0x100
#define ZEND_ACC_PROTECTED 0x200
#define ZEND_ACC_PRIVATE 0x400
#define ZEND_ACC_STATIC 0x01class A{
static $instance = null;
}struct _zend_class_entry {
...
int default_static_members_count; //静态属性数量总和
...
zval *default_static_members_table; //存放静态属性初始化值的数组
zval *static_members_table; //存放静态属性值的数组
...
HashTable properties_info; //存储对象属性的信息哈希表,key为属性名,value为zend_property_info结构体
...
}struct _zend_class_entry {
...
HashTable function_table; //成员方法哈希表
...
}struct _zend_class_entry {
char type; //类的类型:内部类ZEND_INTERNAL_CLASS(1)、用户自定义类ZEND_USER_CLASS(2)
zend_string *name; //类名
struct _zend_class_entry *parent; //父类指针
int refcount; //引用计数
uint32_t ce_flags; //类掩码,如普通类、抽象类、接口等等
int default_properties_count; //普通属性的数量总和
int default_static_members_count; //静态属性数量总和
zval *default_properties_table; //存放普通属性初始化值的数组
zval *default_static_members_table; //存放静态属性初始化值的数组
zval *static_members_table; //存放静态属性值的数组
HashTable function_table; //成员方法哈希表
HashTable properties_info; //存储对象属性的信息哈希表,key为属性名,value为zend_property_info结构体
HashTable constants_table; //常量哈希表,key为常量名,value为常量值
//构造函数、析构函数以及魔术方法的指针
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 *__callstatic;
union _zend_function *__tostring;
union _zend_function *__debugInfo;
union _zend_function *serialize_func;
union _zend_function *unserialize_func;
zend_class_iterator_funcs iterator_funcs;
//自定义的钩子函数,通常是定义内部类时使用,可以灵活的进行一些个性化的操作
//用户自定义类不会用到,暂时忽略即可
zend_object* (*create_object)(zend_class_entry *class_type);
zend_object_iterator *(*get_iterator)(zend_class_entry *ce, zval *object, int by_ref);
int (*interface_gets_implemented)(zend_class_entry *iface, zend_class_entry *class_type); /* a class implements this interface */
union _zend_function *(*get_static_method)(zend_class_entry *ce, zend_string* method);
/* serializer callbacks */
int (*serialize)(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data);
int (*unserialize)(zval *object, zend_class_entry *ce, const unsigned char *buf, size_t buf_len, zend_unserialize_data *data);
uint32_t num_interfaces; //实现的接口数量总和
uint32_t num_traits; //使用的trait数量总和
zend_class_entry **interfaces; //实现的接口,可以理解为它指向一个一维数组,一维数组里全部存放的都是类结构的指针,指向它所实现的接口类
zend_class_entry **traits; //所使用的trait,理解方法同上
zend_trait_alias **trait_aliases; //trait别名,解决多个trait中方法重名冲突的问题
zend_trait_precedence **trait_precedences;
union {
struct {
zend_string *filename;
uint32_t line_start;
uint32_t line_end;
zend_string *doc_comment;
} user;
struct {
const struct _zend_function_entry *builtin_functions;
struct _zend_module_entry *module; //所属扩展
} internal;
} info;
}struct _zend_object {
zend_refcounted_h gc; //内部存有引用计数
uint32_t handle;
zend_class_entry *ce; //所属的类
const zend_object_handlers *handlers;
HashTable *properties; //存储动态属性值
zval properties_table[1]; //柔性数组,每一个单元都是zval类型,用来存储普通属性值,offset就是相对于当前字段首地址的偏移量
};- 通过指针ce找到当前对象对应的类结构zend_class_entry - 取出当前类结构中的Hashtable property_info字段,这个字段是一个哈希表,存有属性的信息。 - 将要查找的属性名作为key,到哈希表中找到对应的value,即zend_property_info结构体,并取出结构体中的offset字段 - 到当前对象zend_object结构体中,通过内存地址计算(柔性数组的起始地址+offset)就可以得到所要访问的当前对象的某个普通属性的值了
struct _zend_object_handlers {
int offset;
zend_object_free_obj_t free_obj; //释放对象
zend_object_dtor_obj_t dtor_obj; //销毁对象
zend_object_clone_obj_t clone_obj;//复制对象
zend_object_read_property_t read_property; //读取成员属性
zend_object_write_property_t write_property;//修改成员属性
...
}
//处理对象的handler
ZEND_API zend_object_handlers std_object_handlers = {
0,
zend_object_std_dtor, /* free_obj */
zend_objects_destroy_object, /* dtor_obj */
zend_objects_clone_obj, /* clone_obj */
zend_std_read_property, /* read_property */
zend_std_write_property, /* write_property */
zend_std_read_dimension, /* read_dimension */
zend_std_write_dimension, /* write_dimension */
zend_std_get_property_ptr_ptr, /* get_property_ptr_ptr */
NULL, /* get */
NULL, /* set */
zend_std_has_property, /* has_property */
zend_std_unset_property, /* unset_property */
zend_std_has_dimension, /* has_dimension */
zend_std_unset_dimension, /* unset_dimension */
zend_std_get_properties, /* get_properties */
zend_std_get_method, /* get_method */
NULL, /* call_method */
zend_std_get_constructor, /* get_constructor */
zend_std_object_get_class_name, /* get_class_name */
zend_std_compare_objects, /* compare_objects */
zend_std_cast_object_tostring, /* cast_object */
NULL, /* count_elements */
zend_std_get_debug_info, /* get_debug_info */
zend_std_get_closure, /* get_closure */
zend_std_get_gc, /* get_gc */
NULL, /* do_operation */
NULL, /* compare */
}class A{
public $name = 'jby';
}
$a = new A();
$a->age = 18;- 通过指针ce找到当前对象对应的类结构zend_class_entry - 取出当前类结构中的Hashtable property_info字段,这个字段是一个哈希表,存有属性的信息。 - 将要查找的属性名作为key,到哈希表中找到对应的value,即zend_property_info结构体,并取出结构体中的offset字段 - 到当前对象zend_object结构体中,通过内存地址计算(柔性数组的起始地址+offset)就可以得到所要访问的当前对象的某个普通属性的值 - 如果以上都没有找到,说明它是一个动态属性,那么就去zend_object下的properties哈希表中查找,属性名作为key,到这个哈希表中查找对应的value即可