Statement: This article is an original article by the author, all of which have been analyzed by the author one by one. I hope you can give me some advice if there is something wrong with it.
You are welcome to reprint it. Please indicate the source for reprinting.
Address: http://imsiren.com/archives/593
What should we do if we want to inherit a class?
For example, the siren class inherits the secure class.
class Secure{ public function test(){ echo "this is Secure::test"; }}class Siren extends Secure{ }
What should I do for such a class?
In fact, there is no big difference. It is the same as creating a common class, but there are some slight changes ..
1. Declare the method in the header file
zend_class_entry *secure_ce;zend_class_entry *siren_ce; PHP_METHOD(Secure,__construct); PHP_METHOD(Secure,__destruct); PHP_METHOD(Secure,test); PHP_METHOD(Siren,__construct); PHP_METHOD(Siren,__destruct);
2. Create a method pointer in the C file. Note that the. secure_method and siren_method must be one-to-one matched and cannot be placed in a pointer.
const zend_function_entry secure_methods[]={ PHP_ME(Secure,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(Secure,__destruct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_DTOR) PHP_ME(Secure,test,NULL,ZEND_ACC_PUBLIC) PHP_FE_END};const zend_function_entry siren_methods[]={ PHP_ME(Siren,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(Siren,__destruct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_DTOR) PHP_FE_END};
3. register two classes in php_minit_function. Here is the focus.
Php_minit_function (secure) {zend_class_entry secure; zend_class_entry siren; init_class_entry (secure, "secure", secret); // initialize a sequence (siren, "siren", siren_methods ); // initialize secure_ce = secure (& secure, null, null tsrmls_dc); secure_ce-> ce_flags = signature; siren_ce = Signature (& siren, secure_ce, null tsrmls_dc); Return success ;};
Row 2-3 // create objects... secure and siren
Line 4-5 initializes two objects.
6th-row Registration
In row 7th, you must declare secure_ce as a common class. You must set it here. Otherwise, it will be a final class by default. In this way, an error will be reported when inheritance is performed.
In addition to zend_acc_implicit_public, there are many macros with similar functions.
ZEND_ACC_ABSTRACTZEND_ACC_ALLOW_STATICZEND_ACC_CALL_VIA_HANDLERZEND_ACC_CHANGEDZEND_ACC_CLONEZEND_ACC_CLOSUREZEND_ACC_CTORZEND_ACC_DEPRECATEDZEND_ACC_DTORZEND_ACC_EXPLICIT_ABSTRACT_CLASSZEND_ACC_FINALZEND_ACC_FINAL_CLASSZEND_ACC_IMPLEMENTED_ABSTRACTZEND_ACC_IMPLEMENT_INTERFACESZEND_ACC_IMPLICIT_ABSTRACT_CLASSZEND_ACC_IMPLICIT_PUBLICZEND_ACC_INTERACTIVEZEND_ACC_INTERFACEZEND_ACC_PPP_MASKZEND_ACC_PRIVATEZEND_ACC_PROTECTEDZEND_ACC_PUBLICZEND_ACC_SHADOWZEND_ACC_STATIC
We can see it by name. We will not introduce it here.
The second parameter of zend_register_internal_class_ex should be noted when siren is registered to our hash table in row 8th.
Zend_register_internal_class_ex ('', '<zend_class_entry * parent_ce>', '<char * parent_name tsrmls_dc> ')
The second parameter is the pointer of the parent class.
This function will call zend_do_inheritance to copy the parent_ce attribute class to the class_entry.
The definition is as follows:
ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */{ if ((ce->ce_flags & ZEND_ACC_INTERFACE) && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) { zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name); } if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) { zend_error(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ce->name, parent_ce->name); } ce->parent = parent_ce; /* Copy serialize/unserialize callbacks */ if (!ce->serialize) { ce->serialize = parent_ce->serialize; } if (!ce->unserialize) { ce->unserialize = parent_ce->unserialize; } /* Inherit interfaces */ zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC); /* Inherit properties */ zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0); if (parent_ce->type != ce->type) { /* User class extends internal class */ zend_update_class_constants(parent_ce TSRMLS_CC); zend_hash_apply_with_arguments(CE_STATIC_MEMBERS(parent_ce) TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members); } else { zend_hash_apply_with_arguments(&parent_ce->default_static_members TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members); } zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce); zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0); zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce); do_inherit_parent_constructor(ce); if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) { ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } else if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES)) { /* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */ zend_verify_abstract_class(ce TSRMLS_CC); }}
4. Add a method body
PHP_METHOD(Secure,__construct){ php_printf("construct is running");};PHP_METHOD(Secure,__destruct){ };PHP_METHOD(Secure,test){ php_printf("this is Secure::test");};PHP_METHOD(Siren,__construct){ };PHP_METHOD(Siren,__destruct){ };
In this way, the siren class inherits the secure class.
Execute in PHP
$ A = new siren ();
$ A-> test ();
"This is secure: Test" is output"
Source: http://imsiren.com/archives/593