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 0x01
class 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即可