Home >Backend Development >PHP Tutorial >深入PHP内核之面向对象小结

深入PHP内核之面向对象小结

WBOY
WBOYOriginal
2016-06-13 12:28:261046browse

深入PHP内核之面向对象总结

很久以前看过的,今天总结一下

一、PHP中创建一个类

在PHP中创建一个简单的类是这样的:

<?php	$obj = new test($url)?>

二、zend_class_entry结构

zend_class_entry是内核中定义的一个结构体,是PHP中类与对象的基础结构类型。

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; // ZEND_ACC_IMPLICIT_ABSTRACT_CLASS: 类存在abstract方法    // ZEND_ACC_EXPLICIT_ABSTRACT_CLASS: 在类名称前加了abstract关键字    // ZEND_ACC_FINAL_CLASS    // ZEND_ACC_INTERFACE    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;// 方法定义入口      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)};

二、访问控制

//fn_flags代表可以在定义方法时使用,zend_property_info.flags代表可以在定义属性时使用,ce_flags代表在定义zend_class_entry时候可用//ZEND_ACC_CTOR 构造函数掩码 , ZEND_ACC_DTOR  析构函数掩码//ZEND_ACC_STATIC static函数掩码//ZEND_ACC_ABSTRACT abstract函数掩码#define ZEND_ACC_STATIC                     0x01     /* fn_flags, zend_property_info.flags */#define ZEND_ACC_ABSTRACT                   0x02     /* fn_flags */#define ZEND_ACC_FINAL                      0x04     /* fn_flags */#define ZEND_ACC_IMPLEMENTED_ABSTRACT       0x08     /* fn_flags */#define ZEND_ACC_IMPLICIT_ABSTRACT_CLASS    0x10     /* ce_flags */#define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS    0x20     /* ce_flags */#define ZEND_ACC_FINAL_CLASS                0x40     /* ce_flags */#define ZEND_ACC_INTERFACE                  0x80     /* ce_flags */#define ZEND_ACC_INTERACTIVE                0x10     /* fn_flags */#define ZEND_ACC_PUBLIC                     0x100    /* fn_flags, zend_property_info.flags */#define ZEND_ACC_PROTECTED                  0x200    /* fn_flags, zend_property_info.flags */#define ZEND_ACC_PRIVATE                    0x400    /* fn_flags, zend_property_info.flags */#define ZEND_ACC_PPP_MASK   (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE)#define ZEND_ACC_CHANGED                    0x800    /* fn_flags, zend_property_info.flags */#define ZEND_ACC_IMPLICIT_PUBLIC            0x1000   /* zend_property_info.flags; unused (1) */#define ZEND_ACC_CTOR                       0x2000   /* fn_flags */      #define ZEND_ACC_DTOR                       0x4000   /* fn_flags */     #define ZEND_ACC_CLONE                      0x8000   /* fn_flags */#define ZEND_ACC_ALLOW_STATIC               0x10000  /* fn_flags */#define ZEND_ACC_SHADOW                     0x20000  /* fn_flags */#define ZEND_ACC_DEPRECATED                 0x40000  /* fn_flags */#define ZEND_ACC_CLOSURE                    0x100000 /* fn_flags */#define ZEND_ACC_CALL_VIA_HANDLER           0x200000 /* fn_flags */

三、申明和更新类中的属性

ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC);  ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC);  ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC);  ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value TSRMLS_DC);  ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC);  ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length TSRMLS_DC);  ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC); ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC);ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC);ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC);ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC);ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value TSRMLS_DC);ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value, int value_length TSRMLS_DC);ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC);ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC);ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC);ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC);ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, const char *value TSRMLS_DC);ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, const char *value, int value_length TSRMLS_DC);

动态添加属性

#define add_property_long(__arg, __key, __n) add_property_long_ex(__arg, __key, strlen(__key)+1, __n TSRMLS_CC)#define add_property_null(__arg, __key) add_property_null_ex(__arg, __key, strlen(__key) + 1 TSRMLS_CC)#define add_property_bool(__arg, __key, __b) add_property_bool_ex(__arg, __key, strlen(__key)+1, __b TSRMLS_CC)#define add_property_resource(__arg, __key, __r) add_property_resource_ex(__arg, __key, strlen(__key)+1, __r TSRMLS_CC)#define add_property_double(__arg, __key, __d) add_property_double_ex(__arg, __key, strlen(__key)+1, __d TSRMLS_CC)#define add_property_string(__arg, __key, __str, __duplicate) add_property_string_ex(__arg, __key, strlen(__key)+1, __str, __duplicate TSRMLS_CC)#define add_property_stringl(__arg, __key, __str, __length, __duplicate) add_property_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate TSRMLS_CC)#define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key)+1, __value TSRMLS_CC)

四、一些其它的宏

#define INIT_CLASS_ENTRY(class_container, class_name, functions) INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, NULL, NULL, NULL)#define INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset)  INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, sizeof(class_name)-1, functions, handle_fcall, handle_propget, handle_propset, NULL, NULL)define INIT_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions) INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, NULL, NULL, NULL, NULL, NULL)define INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) {               const char *cl_name = class_name;           int _len = class_name_len;                  class_container.name = zend_new_interned_string(cl_name, _len+1, 0 TSRMLS_CC);    if (class_container.name == cl_name) {          class_container.name = zend_strndup(cl_name, _len);    }                                           class_container.name_length = _len;     INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \}#define INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) {                                   class_container.constructor = NULL;     class_container.destructor = NULL;          class_container.clone = NULL;               class_container.serialize = NULL;           class_container.unserialize = NULL;     class_container.create_object = NULL;       class_container.interface_gets_implemented = NULL;    class_container.get_static_method = NULL;    class_container.__call = handle_fcall;      class_container.__callstatic = NULL;        class_container.__tostring = NULL;          class_container.__get = handle_propget;    class_container.__set = handle_propset;    class_container.__unset = handle_propunset;    class_container.__isset = handle_propisset;    class_container.serialize_func = NULL;      class_container.unserialize_func = NULL;    class_container.serialize = NULL;           class_container.unserialize = NULL;     class_container.parent = NULL;              class_container.num_interfaces = 0;     class_container.traits = NULL;              class_container.num_traits = 0;             class_container.trait_aliases = NULL;       class_container.trait_precedences = NULL;    class_container.interfaces = NULL;          class_container.get_iterator = NULL;        class_container.iterator_funcs.funcs = NULL;    class_container.info.internal.module = NULL;    class_container.info.internal.builtin_functions = functions;}

五、PHP_METHOD

PHP_METHOD(test,__construct);PHP_METHOD(test,__destruct);PHP_METHOD(test,setproperty);PHP_METHOD(test,getproperty);

内核中的定义

#define PHP_METHOD  ZEND_METHOD#define ZEND_METHOD(classname, name)   ZEND_NAMED_FUNCTION(ZEND_MN(classname##_##name))#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_v    alue_used TSRMLS_DC//等价于void name(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_v    alue_used TSRMLS_DC )

六、zend_arg_info

typedef struct _zend_arg_info {    const char *name; //参数名称    zend_uint name_len;//长度    const char *class_name;  //所属类名    zend_uint class_name_len;  //类名长度    zend_bool array_type_hint;    zend_bool allow_null; //允许为空    zend_bool pass_by_reference;  //引用传值    zend_bool return_reference;   //引用返回    int required_num_args;   //参数个数} zend_arg_info;

接受参数.那么就要执行 

ZEND_BEGIN_ARG_INFO(test___construct_arginfo, 0)    ZEND_ARG_INFO(0, url)ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX定义在Zend/zend_API.h

define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args)       \    static const zend_arg_info name[] = {                                                                                                                                           \        { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },

ZEND_ARG_INFO(0,url)的定义如下

#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 },

最终是这样的

static const zend_arg_info name[] = {	{ NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },	{ #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 },};

七、定义一个类

1、申明

static zend_class_entry *test_ce;

2、添加方法

const zend_function_entry test_methods[] = {    PHP_ME(test, __construct, test___construct_arginfo, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)     PHP_ME(test, __destruct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_DTOR)    PHP_ME(test, __toString, NULL, ZEND_ACC_PUBLIC)    PHP_ME(test, getMeta, NULL, ZEND_ACC_PUBLIC)    PHP_ME(test, setMeta, NULL, ZEND_ACC_PUBLIC)    { NULL, NULL, NULL }};//ZEND_ACC_CTOR标示构造函数//ZEND_ACC_DTOR标示析构函数

3、PHP_MINIT_FUNCTION中初始化

PHP_MINIT_FUNCTION(test){    /*定义一个temp class*/    zend_class_entry ce;    /*初始化这个class,第二个参数是class name, 第三个参数是class methods*/    INIT_CLASS_ENTRY(ce, "test", test_methods);    /*注册这个class到zend engine*/    test_ce = zend_register_internal_class(&ce TSRMLS_CC);    return SUCCESS;}

4、定义参数

ZEND_BEGIN_ARG_INFO(test___construct_arginfo, 0)    ZEND_ARG_INFO(0, url)ZEND_END_ARG_INFO()

5、具体方法

static PHP_METHOD(test, __construct) {    char *url;    int url_len;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &url, &url_len, &age) == FAILURE) {        return;    }    zval *obj;    obj = getThis();    zend_update_property_stringl(test_ce, obj, "url", sizeof("url") -1, url, url_len TSRMLS_CC);}

 6、在PHP中访问

<?php    $c = new test('http://test.com');?>

 

可以参考的文章

http://www.phpinternalsbook.com/classes_objects/simple_classes.html

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn