在PHP中,物件導向與Class是密切相關的,來看看在核心中如何?Class的介面、繼承、私人、受保護、公開等特性。
一、建立類
zend_class_entry是核心中定義的一個結構體,是PHP中類與對象的基礎結構類型。
如何在擴充中定義myclass類,並能夠在PHP中能夠執行個體化?
PHP中看起來像這樣:
<?php$obj = new myclass();?>
核心中:
zend_class_entry *myclass;//定義全域指標變數,指向myclass類。static zend_function_entry myclass_method[] = {//myclass中的方法{NULL, NULL, NULL}}PHP_MINIT_FUNCTION(extension_name){zend_class_entry class;INIT_CLASS_ENTRY(class, "myclass", myclass_method);myclass = zend_register_internal_class(&class TSRMLS_CC);return SUCCESS;}
某個類的zend_class_entry會經常用到,所以我們一般會把它儲存在一個全域變數裡,供擴充中其它地方的程式使用.
對應上述myclass類的實現,在PHP中的代碼:
<?phpclass myclass{}?>
這個類沒有任何屬性和方法。
二、建立類的屬性
在介紹類的屬性之前,先瞭解類中的public、protected、private在核心中的表示。
#define ZEND_ACC_STATIC 0x01 /* Static */#define ZEND_ACC_PUBLIC 0x100 /* Public */#define ZEND_ACC_PROTECTED 0x200 /* Protected */#define ZEND_ACC_PRIVATE 0x400 /* Private */
定義類的屬性可以使用核心提供的zend_declare_property_*系列函數,同時需要三個資訊:
屬性名稱、屬性預設值、屬性存取權限。
<?phpclass myclass{private my_var="this is property";}?>
核心中:
zend_class_entry *myclass;static zend_function_entry myclass_method[] = {{NULL, NULL, NULL}}PHP_MINIT_FUNCTION(extension_name){zend_class_entry class;INIT_CLASS_ENTRY(class, "myclass", myclass_method);myclass = zend_register_internal_class(&class TSRMLS_CC);zend_declare_property_string(myclass, "my_var", strlen("my_var"), "this is property", ZEND_ACC_PRIVATE TSRMLS_CC);}
//核心中提供了定義類屬性的宏ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC);ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC);ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC);ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC);ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC);ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC);ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC);ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC);
三、建立類中的方法
#define ZEND_ACC_STATIC 0x01 /* 靜態方法 */#define ZEND_ACC_ABSTRACT 0x02 /* 抽象方法 */#define ZEND_ACC_FINAL 0x04 /* 終態方法 */#define ZEND_ACC_IMPLEMENTED_ABSTRACT 0x08 /* fn_flags */#define ZEND_ACC_INTERACTIVE 0x10 /* fn_flags */#define ZEND_ACC_PUBLIC 0x100 /* PUBLIC */#define ZEND_ACC_PROTECTED 0x200 /* PROTECTED */#define ZEND_ACC_PRIVATE 0x400 /* PRIVATE */#define ZEND_ACC_CHANGED 0x800 /* fn_flags, zend_property_info.flags */#define ZEND_ACC_CTOR 0x2000 /* __construct */#define ZEND_ACC_DTOR 0x4000 /* __destruct */#define ZEND_ACC_CLONE 0x8000 /* __clone */#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_function_entry。
在建立的擴充中,有一個zend_function_entry,核心通過它把PHP語言中的函數和C語言編寫的函數串連,zend_function_entry相當於橋樑。
class中,同樣用它來串連PHP中類的方法與C語言編寫的方法。
<?phpclass myclass{public function __construct(){echo "init myclass!";}public function hello(){echo "hello";}}?>
核心中:
zend_class_entry *myclass;PHP_METHOD(myclass, __construct){php_printf("init myclass!");}PHP_METHOD(myclass, hello){php_printf("hello");}static zend_function_entry myclass_method[] = {ZEND_ME(myclass, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR);ZEND_ME(myclass, hello, NULL, ZEND_ACC_PUBLIC);{NULL, NULL, NULL}}PHP_MINIT_FUNCTION(extension_name){zend_class_entry class;INIT_CLASS_ENTRY(class, "myclass", myclass_method);myclass = zend_register_internal_class(&class TSRMLS_CC);return SUCCESS;}
四、建立類中的常量
使用核心提供的API即可。
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);
<?phpclass myclass{const class_name = "myclass";}?>
核心中:
zend_class_entry *myclass;static zend_function_entry myclass_method[] = {{NULL, NULL, NULL}}PHP_MINIT_FUNCTION(extension_name){zend_class_entry class;INIT_CLASS_ENTRY(class, "myclass", myclass_method);myclass = zend_register_internal_class(&class TSRMLS_CC);zend_declare_class_constant_stringl(myclass, "class_name", strlen("class_name"), "myclass", strlen("myclass") TSRMLS_CC);}