Writing PHP Extensions1. Setting up Your PHP Build Environment on Linux2. Generating a PHP Extension Skeleton3. Building and Installing a PHP Extension4. Rebuilding Extensions for Production5. Extension Skeleton File Content6. Running PHP Extension Tests7. Adding New Functionality8. Basic PHP Structures9. PHP Arrays10. Catching Memory Leaks11. PHP Memory Management12. PHP References13. Copy on Write14. PHP Classes and Objects15. Using OOP in our Example Extension16. Embedding C Data into PHP Objects17. Overriding Object Handlers18. Answers to Common Extension Questions14. PHP Classes and ObjectsObjects in PHP are represented by zend_object structure immediately followed by plain array of properties (zvals). The first word of object is defined by zend_refcounted structure and used for reference-counting, then there is a pointer to class entry structure, then pointer to object handlers table (similar to Virtual Methods Table) and HashTable of undeclared properties. All the declared properties are followed and may be accessed by offset. There are two important dependent structures -zend_class_entry and zend_object_handlers. The first one keeps all the static information about the class, including its name, parent, methods, constants, properties — and their default values, values of static properties, etc. Here you can also see, a callback function “create_object”, that may be overridden to create something custom.typedef struct zend_class_entry { char type; zend_string *name; 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; HashTable constants_table; zend_property_info **properties_info_table; ... zend_object* (*create_object)(zend_class_entry *class_type); ... } zend_class_entry;The second contains callback functions that determine the object behavior. We may create objects with custom behavior overriding this table and then changing some specific functions. This is advanced PHP internals knowledge. Now you can just read the list of handler names and guess what they are going to do.typedef struct _zend_object_handlers { /* offset of real object header (usually zero) */ int offset; /* object handlers */ zend_object_free_obj_t free_obj; /* required */ zend_object_dtor_obj_t dtor_obj; /* required */ zend_object_clone_obj_t clone_obj; /* optional */ zend_object_read_property_t read_property; /* required */ zend_object_write_property_t write_property; /* required */ zend_object_read_dimension_t read_dimension; /* required */ zend_object_write_dimension_t write_dimension; /* required */ zend_object_get_property_ptr_ptr_t get_property_ptr_ptr; /* required */ zend_object_get_t get; /* optional */ zend_object_set_t set; /* optional */ zend_object_has_property_t has_property; /* required */ zend_object_unset_property_t unset_property; /* required */ zend_object_has_dimension_t has_dimension; /* required */ zend_object_unset_dimension_t unset_dimension; /* required */ zend_object_get_properties_t get_properties; /* required */ zend_object_get_method_t get_method; /* required */ zend_object_call_method_t call_method; /* optional */ zend_object_get_constructor_t get_constructor; /* required */ zend_object_get_class_name_t get_class_name; /* required */ zend_object_compare_t compare_objects; /* optional */ zend_object_cast_t cast_object; /* optional */ zend_object_count_elements_t count_elements; /* optional */ zend_object_get_debug_info_t get_debug_info; /* optional */ zend_object_get_closure_t get_closure; /* optional */ zend_object_get_gc_t get_gc; /* required */ zend_object_do_operation_t do_operation; /* optional */ zend_object_compare_zvals_t compare; /* optional */ zend_object_get_properties_for_t get_properties_for; /* optional */ } zend_object_handlers;There are few APIs to work with PHP objects and classes. They are not compact, are not always consistent, and not well organized. I tried to collect the most important groups. The first one is the group of simple getter macros for basic internal object fields: Z_OBJ(zv) – returns pointer to zend_object structure from the zval (the type must be IS_OBJECT). Z_OBJCE(zv) – returns pointer to class entry of the given PHP object zval. Z_OBJ_HANDLE(zv) – returns object handle (unique number) of the given PHP object zval. Z_OBJ_HT(zv) – returns object handlers table of the given PHP object zval. Z_OBJ_HANDLER(zv, name) – returns named object handler from the table of the given PHP object zval. Z_OBJPROP(zv) – returns a HashTable with all properties (both declared and undeclared). Declared properties are stored as zvals of type IS_INDIRECT and the pointer to real value may be retrieved though Z_INDIRECT(zv) macro.Few useful macros and functions to work with object or static class members: ZVAL_OBJ(zv, obj) – initializes zval with IS_OBJECT type and given zen_object. object_init(zv) – creates a new empty stdClass object and store it in zv. object_init_ex(zv, ce) – creates a new empty object of given class and store it in zv. zend_objects_new(ce) – creates and return object of the given class. zend_object_alloc(hdr_size, ce) – allocates a memory block for object with all the properties declared in given class. To create regular PHP objects, hdr_size must be equal to sizeof(zend_object). However, it’s possible to request more memory and use it for keeping additional C data (this will be discussed later). zend_object_std_init(obj, ce) – initializes fields of the given zend_object as an object of given class. zend_object_release(obj) – releases object (decrements reference-counter and destroy object if it reaches zero). add_property_...(zv, name, value) – a family of functions to add named property of different values to the given object. zend_read_property(ce, zv, name, len, silent, ret) – reads the value of static property, and returns pointer to zval or NULL. “ret“ is an address of zval where the property value should be stored (but not necessary). zend_read_static_property(ce, name, len, silent) – reads the value of static property, and returns pointer to zval or NULL. zend_update_property...(ce, zv, name, len, value) – a family of functions to assign values of different types to object property. zend_update_static_property...(ce, name, len, value) – a family of functions to assign values of different types to static property. Here are a few functions to declare internal classes and their elements: INIT_CLASS_ENTRYce, name, functions) – initializes class entry structure with given name and list of methods. zend_register_internal_class(ce) – registers the given class entry in the global class table and returns the address of the real class entry. zend_register_internal_class_ex(ce, parent_ce) – similar to zend_register_internal_class(), but also perform inheritance from the given “parent_ce”. zend_register_internal_interface(ce) – similar to zend_register_internal_class(ce), but registers interface instead. zend_class_implements(ce, num_interfaces, …) – makes class to implement given interfaces. zend_declare_class_constant_...(ce, name, len, value) – a family of function to declare class constants with different value types. zend_declare_property_...(ce, name, name, len, flags, value) – a family of functions to declare properties with different default value types. The “flags” argument may be used to declare public, protected, private and static properties.Request PDF VersionBook traversal links for 14. PHP Classes and Objects‹ 13. Copy on WriteWriting PHP Extensions15. Using OOP in our Example Extension ›