##For PHPer, OOP is indispensable Development thinking, but how much do you know about the underlying implementation of PHP classes and objects? Based on the idea of knowing what is happening and knowing why, let us find the answer together~The underlying implementation of the class can be regarded as the knowledge collection of variables, functions, etc. we have talked about before. Therefore, students who want to understand more deeply should check out my previous articles about introducing variables and functionsClass data structureWhether it is an ordinary class, an abstract class or an interface, all Stored in a unified structure, and when generating intermediate code, this class will be added to the global class list. Of course, at this time, the class name will be used to determine whether the class already exists. If it exists, the addition will fail
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; //类的类型,在编译阶段被区分是普通类,接口,抽象类 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;// 方法定义入口 /* 魔术方法 */ //所有魔术方法单独存放,初始化时被设置为null 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) };
The first step: Find whether the class exists in the global class list according to the class name. If If it exists, get the variable of the storage class
Step 2: Determine whether the class is a normal class (non-abstract class or interface); if it is a normal class, allocate memory to the zval container where the object to be created is stored, and set the container type For IS_OBJECT
Step 3: Perform object initialization operation and add the object to the global object list (object pool)
typedef struct _zend_object { zend_class_entry *ce; //对象的类结构 HashTable *properties; //对象属性 HashTable *guards; /* protects from __get/__set ... recursion */ } zend_object;
The first step is to get the properties of the object. Find whether there is an attribute corresponding to the name from the properties of the object. If it exists, return the result. If it does not exist, go to the second step
The second step, if there is a get magic method, call this method to get the variable. If it does not exist, an error will be reported.
The first step, get the properties of the object, from the object's properties looks up whether there is a property corresponding to the name. If it exists and the existing value is the same as the value that needs to be set, no operation is performed. Otherwise, the variable assignment operation is performed. If it does not exist, go to the second step
Step 2 , if the _set magic method exists, call this method to set the variable. If it does not exist, go to the third step
The third step, if the member variable has not been set, directly add this variable to the properties field of the object Located in HashTable.
For more PHP-related technical articles, please visit PHP Tutorial column to learn!
The above is the detailed content of PHP underlying principles, classes and objects. For more information, please follow other related articles on the PHP Chinese website!