baiyanphp
所有視頻:https://segmentfault.com/a/11...segmentfault
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便可