PHP 类底层数据结构为 zend_class_entry 结构体,下面是摘录源代码 稍微了解下即可。
可以看到 有类名、继承父类入口,函数表,静态资源,属性(资产),各种魔术方法,继承接口,构造/析构函数等。
//详情 Zend/zend.h
struct_zend_class_entry{
chartype;
char*name;
zend_uint name_length;
struct_zend_class_entry *parent;
intrefcount;
zend_bool constants_updated;
zend_uint ce_flags;
HashTable function_table;
HashTable default_properties;
HashTable properties_info;
HashTable default_static_members;
HashTable *static_members;
HashTable constants_table;
conststruct_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 *__callstatic;
union _zend_function *__tostring;
union _zend_function *serialize_func;
union _zend_function *unserialize_func;
zend_class_iterator_funcs iterator_funcs;
/* handlers */
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);/* a class implements this interface */
union _zend_function *(*get_static_method)(zend_class_entry *ce,char*method,intmethod_len TSRMLS_DC);
/* serializer callbacks */
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;
};
typedefstruct_zend_class_entry zend_class_entry;所以需要首先声明 类
//Tips: PHP源代码内 常见缩写为 xx_ce 即为某个类定义入口
zend_class_entry *demo_ce; 那么类的定义写在哪里呢?
这要看你所需要的初始化阶段,一般在 PHP_MINIT_FUNCTION 阶段或 ZEND_MINIT_FUNCTION 内,即 当扩展模块加载时(PHP 启动时/代码内手动load时)处理。
当然看业务需求 也可以在 每个Request请求时处理 PHP_RINIT_FUNCTION 内。
这里有个小技巧,如果可能尽量把类入口定义 抽出到公共区域,因为你在定义各种属性方法,使用函数时,都会需要类 ce 入口作为参数,这里我们建议写在文件尽量考前的位置(比如 include 之后)。
定义完 zend_class_entry 就完了?
当然不可能,你可能想到了 我 TM 类名还没设置呢就完了。。。。
//类内部方法声明、具体实现
PHP_METHOD(demo,foo){
php_printf("call method foo in class demo.\n");
}
//这一步是对应绑定到具体类 对应方法 类似 bind 动作
staticzend_function_entry demo_methods[]={
//参数: 类名,方法名,方法参数信息,方法访问权限,例如 public, privite, protected
ZEND_ME(demo, foo, NULL, ZEND_ACC_PUBLIC)
NULL,NULL,NULL
};
PHP_MINIT_FUNCTION(demo) //MINIT阶段
{
//再次定义一个类入口
zend_class_entry ce;
//初始化类
INIT_CLASS_ENTRY(ce,"demo",methods);
//把类注册到zend 内部, 并且把返回值 zend_class_entry 类型赋值给 上面注册的公共类变量
demo_ce=zend_register_internal_class(&ce TSRMLS_CC);
}
//Tips: 已上初始类的三句话,经常用到,可以自定义宏替换,避免过于麻烦。(本次不使用)
例如:
#define DEMO_INIT_CLASS(class_ce, class_name, functions) \
zend_class_entry ce;\
INIT_CLASS_ENTRY(ce,class_name,functions);\
class_ce=zend_register_internal_class(&ce TSRMLS_CC);接着重新编译ini引入扩展 就可以尝试 使用对象了
$obj=newdemo;
$obj->foo();
//call method foo in class demo.当然对类操作还有很多其他高级功能,比如说: 定义/初始化类属性,定义类常量,类方法互相调用,静态方法,类继承类/接口,类命名空间等等,后续一一讲解记录。