OOP is an indispensable development thought for PHPer, but how much do you know about the underlying implementation of php classes and objects?In the spirit of knowing what it is and knowing what it is, let's find the answer together. ~
The underlying implementation of a class can be considered as a set of knowledge about variables, functions, etc. as we mentioned earlier. So if you want to understand more deeply, you'd better check out my previous articles on introducing variables and functions.
Data structure of class
Both ordinary and abstract classes and interfaces are stored in a unified structure, and when intermediate code is generated, such classes are added to the global class list. Of course, at this point, the class name is used to determine whether the class already exists, and if it exists, the addition fails.
struct _zend_class_entry { char type; // Like functions, classes are split into two types: ZEND_INTERNAL_CLASS internal type and ZEND_USER_CLASS user-defined type. char *name;// Class name zend_uint name_length; // That is sizeof(name) - 1 struct _zend_class_entry *parent; // Inherited parent class int refcount; // Reference number zend_bool constants_updated; zend_uint ce_flags; //Class types, which are distinguished during compilation, are common classes, interfaces, and abstract classes. HashTable function_table; // Static class methods and common class methods store collections HashTable default_properties; // Default properties store collections HashTable properties_info; // Attribute Information Storage Set HashTable default_static_members;// Static Variables Storage Collection of Classes HashTable *static_members; // When type = ZEND_USER_CLASS, take & default_static_members; // When type = ZEND_INTERAL_CLASS, set it to NULL HashTable constants_table; // Constant storage set struct _zend_function_entry *builtin_functions;// Method Definition Entry /* Magic Methods */ //All magic methods are stored separately and initialized as 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;// iteration /* Class handle */ 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); /* Interfaces for class declarations */ int(*interface_gets_implemented)(zend_class_entry *iface, zend_class_entry *class_type TSRMLS_DC); /* Serialized callback function pointer */ 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; // Class Implementation Interface zend_uint num_interfaces; // Number of interfaces implemented by class char *filename; // Address Absolute Address of Class Storage File zend_uint line_start; // Starting line of class definition zend_uint line_end; // End line of class definition char *doc_comment; zend_uint doc_comment_len; struct _zend_module_entry *module; // The module entry where the class is located: EG(current_module) };
As can be seen from the above code, the member variables and member methods of the class are stored in their respective structures. The data structure of the structure is the same as the data structure of the function explained before, except that the compiled member variables and member methods are stored in the class structure.
Object Generation
As we all know, objects are new, but at the bottom, object generation is divided into three steps
Step 1: Find out if the class exists in the global class list according to the class name, and if it exists, get the variables of the storage class.
Step 2: Determine whether the class is a common class (non-abstract class or interface); if it is a common class, allocate memory to the zval container where the object needs to be created, and set the container type IS_OBJECT?
Step 3: Perform object initialization and add objects to the global object list (object pool)
The data structure of the attached object:
typedef struct _zend_object { zend_class_entry *ce; //Class structure of objects HashTable *properties; //Object attribute HashTable *guards; /* protects from __get/__set ... recursion */ } zend_object;
Get and set member variables
Get member variables:
The first step is to get the attributes of the object and find out whether there are attributes corresponding to the name from the properties of the object. If there are returned results, if not, go to the second step.
The second step, if there is a get magic method, calls this method to get the variable, and if there is no, the error is reported.
Set member variables:
The first step is to get the attributes of the object and find out whether there are attributes corresponding to the name from the properties of the object. If there are and the existing values are the same as the values that need to be set, no operation will be performed. Otherwise, variable assignment will be performed. If there are no attributes, go to the second step.
The second step, if there is a _set magic method, calls this method to set variables. If not, go to the third step.
Third, if the member variable has never been set, add it directly to the HashTable where the properties field of the object is located.
summary
So far, we've almost gone through the underlying principles of php. Of course, during this period, many students told me that they have gradually started to use php7. What you are talking about now is still php5. Will it be out of date? In fact, I explained PHP5 to prepare for php7. After all, php7 is an extension of php5. After knowing php5, it will be easier to understand php7. And PHP is gradually improved from the beginning of php5, we need to understand the content of php5. But starting next week, we will start to compare the differences between php7 and PHP5 from the bottom. Please look forward to it.~