Object handlers¶
Nearly all operations on objects in PHP go through object handlers and every magic method or magic interface is implemented with an object or class handler internally. Furthermore there are quite a few handlers which are not exposed to userland PHP. For example internal classes can have custom comparison and cast behavior.
An Overview¶
Here are all the object handlers with their signature and a small description.
-
zval *read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv)¶
-
zval *write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot)¶
-
int has_property(zend_object *zobj, zend_string *name, int has_set_exists, void **cache_slot)¶
-
void unset_property(zend_object *zobj, zend_string *name, void **cache_slot)¶
-
zval *get_property_ptr_ptr(zend_object *zobj, zend_string *name, int type, void **cache_slot)¶
These handlers correspond to the
__get
,__set
,__isset
and__unset
methods.get_property_ptr_ptr
is the internal equivalent of__get
returning by reference.cache_slot
is used to store the property offset andzend_property_info
.read_property
may directly return a zval owned by the object, in which case its reference count should not be modified byread_property
, and the caller should not release it. Alternatively, it may returnrv
for temporary zvals (e.g. result of call to__get
), in which case the refcount should be incremented, and the caller is responsible for releasing the value.
-
zval *read_dimension(zend_object *object, zval *offset, int type, zval *rv)¶
-
void write_dimension(zend_object *object, zval *offset, zval *value)¶
-
int has_dimension(zend_object *object, zval *offset, int check_empty)¶
-
void unset_dimension(zend_object *object, zval *offset)¶
This set of handlers is the internal representation of the
ArrayAccess
interface.zval *rv
inread_dimension
is used for temporary values returned fromoffsetGet
andoffsetExists
.
-
HashTable *get_properties(zend_object *zobj)¶
-
HashTable *get_debug_info(zend_object *object, int *is_temp)¶
Used to get the object properties as a hashtable. The former is more general purpose, for example it is also used for the
get_object_vars
function. The latter on the other hand is used exclusively to display properties in debugging functions likevar_dump
. So even if your object does not provide any formal properties you can still have a meaningful debug output.
-
zend_function *get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key)¶
The
get_method
handler fetches thezend_function
used to call a certain method. Optionallykey
can be passed as an optimization to avoid lowercasingmethod_name
in case it is already present.
-
zend_function *get_constructor(zend_object *zobj)¶
Like
get_method
, but getting the constructor function. The most common reason to override this handler is to disallow manual construction by throwing an error in the handler.
-
zend_result count_elements(zend_object *object, zend_long *count)¶
This is just the internal way of implementing the
Countable::count
method. The function returns azend_result
and assigns the value to thezend_long *count
pointer.
-
int compare(zval *o1, zval *o2)¶
The
compare
handler is a required handler that computes equality of the given object and another value. Note that the other value isn’t necessarily an object of the same class, or even an object at all. The handler should return negative numbers if the lhs is smaller, 0 if they are equal, or a positive number is the lhs is larger. If the values are uncomparableZEND_UNCOMPARABLE
should be returned.
-
zend_result cast_object(zend_object *readobj, zval *writeobj, int type)¶
Internal classes have the ability to implement a custom compare behavior and override casting behavior for all types. Userland classes on the other hand only have the ability to override object to string casting through
__toString
.
-
zend_result get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only)¶
This handler is invoked when the object is used as a function, i.e. it is the internal version of
__invoke
. The name derives from the fact that its main use is for the implementation of closures (theClosure
class).
-
zend_string *get_class_name(const zend_object *zobj)¶
This handler is used to get the class name from an object for debugging contexts. There should be little reason to overwrite it.
-
zend_object *clone_obj(zend_object *old_object)¶
The
clone_obj
handler is called when executingclone $old_object
. By default PHP performs a shallow clone on objects, which means properties containing objects are not be cloned but both the old and new object will point to the same object. Theclone_obj
allows for this behavior to be customized. It’s also used to inhibitclone
altogether.
-
HashTable *get_gc(zend_object *zobj, zval **table, int *n)¶
The
get_gc
handler should return all variables that are held by the object, so cyclic dependencies can be properly collected. If the object doesn’t maintain a property hashmap (because it doesn’t store any dynamic properties) it can usetable
to store a pointer directly into the list of zvals, along with a count of properties.
-
void dtor_obj(zend_object *object)¶
-
void free_obj(zend_object *object)¶
dtor_obj
is called beforefree_obj
. The object must remain in a valid state after dtor_obj finishes running. Unlikefree_obj
, it is run prior to deactivation of the executor during shutdown, which allows user code to run. This handler is not guaranteed to be called (e.g. on fatal error), and as such should not be used to release resources or deallocate memory. Furthermore, releasing resources in this handler can break detection of memory leaks, as cycles may be broken early.dtor_obj
should be used only to call user destruction hooks, such as__destruct
.free_obj
should release any resources the object holds, without freeing the object structure itself. The object does not need to be in a valid state afterfree_obj
finishes running.free_obj
will always be invoked, even if the object leaks or a fatal error occurs. However, during shutdown it may be called once the executor is no longer active, in which case execution of user code may be skipped.
-
zend_result do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2)¶
do_operation
is an optional handler that will be invoked for various arithmetic and binary operations on instances of the given class. This allows for operator overloading semantics to be implemented for custom classes. Examples for overloadable operators are+
,-
,*
,/
,++
,--
,!
.
-
zend_array *get_properties_for(zend_object *object, zend_prop_purpose purpose)¶
The
get_properties_for
can be used to customize the list of object properties returned for various purposes. The purposes are defined inzend_prop_purpose
, which currently entailsprint_r
,var_dump
, the(array)
cast,serialize
,var_export
andjson_encode
.