php擴展開發-面向對象

在zval變量裏IS_OBJECT類型使用zend_object_value來保存變量的,咱們看一下他的具體結果。php

typedef struct _zend_object_value {
    zend_object_handle handle;
    const zend_object_handlers *handlers; } zend_object_value;

在擴展中建立一個咱們本身的類函數

zend_class_entry *myext_class_ce;//保存咱們建立的對象實例

static zend_function_entry myext_class_method[] = {//函數的屬性和方法都在這裏定義
    {NULL, NULL, NULL}//固定語法
};

//在MINIT函數裏
PHP_MINIT_FUNCTION(myext)
{
    zend_class_entry tmp_myext_class_ce;//臨時變量
    INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);//臨時變量,類名稱,類屬性和方法
    myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);//在內核中註冊咱們的類
}

/*

$class = new myext_example_class();

  var_dump($class);this

  object(myext_example_class)#6 (0) {
  }spa

  */code

建立類的第一個函數對象

ZEND_METHOD(myext_example_class,hello);

//ZEND_ME爲方法註冊,每一個方法使用一個ZEND_ME
//參數說明
//1,類名稱
//2,方法名稱
//3,參數,跟普通函數的同樣,也是ZEND_END_ARG_INFO
//4,修飾方法或屬性,後面會專門講到
static zend_function_entry myext_class_method[] = {
    ZEND_ME(myext_example_class,hello,NULL,ZEND_ACC_PUBLIC)
    {NULL, NULL, NULL}//固定語法
};

//函數定義,參數說明:
//類名稱
//類方法名稱
ZEND_METHOD(myext_example_class,hello){
    php_printf("hello");
}

建立一個構造函數__construct()blog

ZEND_METHOD(myext_example_class,__construct);

//建立構造方法同普通方法基本同樣,惟一的差異在於第四個參數,ZEND_ACC_CTOR,表示它是構造方法
static zend_function_entry myext_class_method[] = { ZEND_ME(myext_example_class,hello,NULL,ZEND_ACC_PUBLIC) ZEND_ME(myext_example_class,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) {NULL, NULL, NULL}//固定語法 }; ZEND_METHOD(myext_example_class,__construct){ php_printf("我是__construct函數"); }

如今來看一下修飾方法和屬性的常量,經過他們能夠定義方法的訪問權限,是不是抽獎函數,是不是FINAL屬性等等繼承

下面詳細的羅列出了全部常量,fn_flags表明能夠在定義方法時使用,zend_property_info.flags表明能夠在定義屬性時使用,ce_flags表明在定義zend_class_entry時候可用。當須要用到多個常量的時候,咱們能夠採用或運算的形式,在定義構造函數的時候,咱們已經遇到了,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR接口

#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 */

如今咱們爲這個類增長一些屬性。添加屬性變量須要在MINIT函數中實現,在類建立完成以後,咱們就能夠添加屬性了get

    zend_class_entry tmp_myext_class_ce;
    INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);
    myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);
//上面是建立類,下面是添加屬性
//建立普通屬性和靜態屬性的方法是同樣,只須要在第四個參數中增長ZEND_ACC_STATIC即爲靜態屬性
//建立類常量是另一組的函數,和普通屬性不同 zend_declare_property_null(myext_class_ce,
"private_prop",sizeof("private_prop")-1,ZEND_ACC_PRIVATE TSRMLS_CC);//私有權限,默認值爲NULL zend_declare_property_string(myext_class_ce,"protected_prop",sizeof("protected_prop")-1,"我是默認值",ZEND_ACC_PROTECTED TSRMLS_CC);//protected權限,默認值是"我是默認值" zend_declare_property_long(myext_class_ce,"public_prop",sizeof("public_prop")-1,100,ZEND_ACC_PUBLIC TSRMLS_CC);//public,默認值是100 zend_declare_property_string(myext_class_ce,"static_prop",sizeof("static_prop")-1,"我是靜態變量",ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_CC);//靜態變量,默認值是"我是靜態變量" zend_declare_class_constant_string(myext_class_ce,"CONSTANT_PROP",sizeof("CONSTANT_PROP") - 1,"我是類常量" TSRMLS_CC);//類常量,默認值是"我是類常量"
/*

$class = new myext_example_class();
var_dump($class);
$class->hello();
var_dump(myext_example_class::$static_prop);
var_dump(myext_example_class::CONSTANT_PROP);

 

object(myext_example_class)#6 (3) {
["private_prop":"myext_example_class":private]=>
NULL
["protected_prop":protected]=>
string(15) "我是默認值"
["public_prop"]=>
int(100)
}
hello

string(18) "我是靜態變量"
string(15) "我是類常量"

*/

在php內核中,因爲操做變量的類型不一樣,一般一樣一個功能,會有一組函數,上面咱們提到的建立類屬性和類常量也是有一組操做。

//如下操做都是在zend_API.h
//定義類屬性
ZEND_API int zend_declare_property(zend_class_entry *ce, const 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, const char *doc_comment, int doc_comment_len TSRMLS_DC); ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, int name_length, double value, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, int name_length, const char *value, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, int value_len, int access_type TSRMLS_DC); //定義類常量 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_class_entry *myext_interface_ce;

static zend_function_entry myext_interface_method[] = {
    ZEND_ABSTRACT_ME(myext_interface_ce,int_func,NULL)//定義一個抽獎方法,這個方法能夠不實現,也就是不須要存在一個ZEND_ME(myext_interface_ce,int_func)
    {NULL, NULL, NULL}//固定語法
};

    zend_class_entry tmp_myext_interface_ce;
    INIT_CLASS_ENTRY(tmp_myext_interface_ce,"myext_example_interface",myext_interface_method);
    myext_interface_ce = zend_register_internal_interface(&tmp_myext_interface_ce TSRMLS_CC);//註冊接口的函數與註冊類的不同

/*

class interface_class implements myext_example_interface{
public function int_func(){
echo "我繼承了接口\n";
}
}

$interface_class = new interface_class();
$interface_class->int_func();

 

我繼承了接口

*/

咱們在擴展的代碼裏實現繼承,讓myext_example_class繼承myext_example_interface

ZEND_METHOD(myext_example_class,int_func);//php_myext.h

//抽象函數int_func的實現
ZEND_METHOD(myext_example_class,int_func){
php_printf("我是class繼承了接口interface");
}


static zend_function_entry myext_class_method[] = {
    ZEND_ME(myext_example_class,hello,NULL,ZEND_ACC_PUBLIC)
    ZEND_ME(myext_example_class,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
    ZEND_ME(myext_example_class,int_func,NULL,ZEND_ACC_PUBLIC)
    {NULL, NULL, NULL}//固定語法
};


    zend_class_entry tmp_myext_interface_ce;
    INIT_CLASS_ENTRY(tmp_myext_interface_ce,"myext_example_interface",myext_interface_method);
    myext_interface_ce = zend_register_internal_interface(&tmp_myext_interface_ce TSRMLS_CC);

    zend_class_entry tmp_myext_class_ce;
    INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);
    myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);
    zend_declare_property_null(myext_class_ce,"private_prop",sizeof("private_prop")-1,ZEND_ACC_PRIVATE TSRMLS_CC);
    zend_declare_property_string(myext_class_ce,"protected_prop",sizeof("protected_prop")-1,"我是默認值",ZEND_ACC_PROTECTED TSRMLS_CC);
    zend_declare_property_long(myext_class_ce,"public_prop",sizeof("public_prop")-1,100,ZEND_ACC_PUBLIC TSRMLS_CC);
    zend_declare_property_string(myext_class_ce,"static_prop",sizeof("static_prop")-1,"我是靜態變量",ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_CC);
    zend_declare_class_constant_string(myext_class_ce,"CONSTANT_PROP",sizeof("CONSTANT_PROP") - 1,"我是類常量" TSRMLS_CC);
    zend_class_implements(myext_class_ce TSRMLS_CC,1,myext_interface_ce);//這句話表示myext_class_ce繼承接口myext_interface_ce

/*

$class = new myext_example_class();

$class->int_func();

我是class繼承了接口interface

*/

咱們再來實現一個類繼承的例子

ZEND_METHOD(myext_example_class,class_func);//php_myext.h
ZEND_METHOD(myext_example_parent_class,class_func);//php_myext.h

zend_class_entry *myext_parent_class_ce;//保存父類的變量

static zend_function_entry myext_parent_class_method[] = {
    ZEND_ME(myext_example_parent_class,class_func,NULL,ZEND_ACC_PUBLIC)
    {NULL, NULL, NULL}//固定語法
};

    zend_class_entry tmp_myext_parent_class_ce;
    INIT_CLASS_ENTRY(tmp_myext_parent_class_ce,"myext_example_parent_class",myext_parent_class_method);
    myext_parent_class_ce = zend_register_internal_class(&tmp_myext_parent_class_ce TSRMLS_CC);//註冊一個myext_example_parent_class

    zend_class_entry tmp_myext_class_ce;
    INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);
    //myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);//正常註冊類
    myext_class_ce = zend_register_internal_class_ex(&tmp_myext_class_ce,myext_parent_class_ce,"myext_example_parent_class" TSRMLS_CC);//繼承註冊類,第一個參數是同樣的,第二個是繼承父類的變量,第三個是父類的名稱
    zend_declare_property_null(myext_class_ce,"private_prop",sizeof("private_prop")-1,ZEND_ACC_PRIVATE TSRMLS_CC);
    zend_declare_property_string(myext_class_ce,"protected_prop",sizeof("protected_prop")-1,"我是默認值",ZEND_ACC_PROTECTED TSRMLS_CC);
    zend_declare_property_long(myext_class_ce,"public_prop",sizeof("public_prop")-1,100,ZEND_ACC_PUBLIC TSRMLS_CC);
    zend_declare_property_string(myext_class_ce,"static_prop",sizeof("static_prop")-1,"我是靜態變量",ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_CC);
    zend_declare_class_constant_string(myext_class_ce,"CONSTANT_PROP",sizeof("CONSTANT_PROP") - 1,"我是類常量" TSRMLS_CC);
    zend_class_implements(myext_class_ce TSRMLS_CC,1,myext_interface_ce);


ZEND_METHOD(myext_example_parent_class,class_func){
    php_printf("我是父類的class_func\n");
}

ZEND_METHOD(myext_example_class,class_func){
    php_printf("我是子類的class_func\n");
}

/*

$parent_class = new myext_example_parent_class();
$parent_class->class_func();
$class = new myext_example_class();
$class->class_func();

 

我是父類的class_func
我是__construct函數
我是子類的class_func

*/              

接着咱們來看一下怎麼樣在類方法中使用類的屬性變量

ZEND_METHOD(myext_example_class,read_property){
zval *private_prop,*protected_prop,$public_prop;
zval *static_prop;
zend_class_entry *ce;

ce = Z_OBJCE_P(getThis());

private_prop = zend_read_property(myext_class_ce,getThis(),"private_prop",sizeof("private_prop") - 1,0 TSRMLS_CC);//獲取private_prop的屬性值,至關於php的$this->private_prop
php_var_dump(&private_prop,1 TSRMLS_CC);
protected_prop = zend_read_property(myext_class_ce,getThis(),"protected_prop",sizeof("protected_prop") - 1,0 TSRMLS_CC);
php_var_dump(&protected_prop,1 TSRMLS_CC);

static_prop = zend_read_static_property(ce,"static_prop",sizeof("static_prop") - 1,0 TSRMLS_CC);//獲取靜態屬性static_prop的屬性值,至關於php的self::$static_prop
php_var_dump(&static_prop,1 TSRMLS_CC);

zend_update_property_string(myext_class_ce,getThis(),"protected_prop",sizeof("protected_prop") - 1,"更新protected_prop的值" TSRMLS_CC);//設置protected_prop的屬性值,至關於php的$this->protected_prop = "更新protected_prop";
protected_prop = zend_read_property(myext_class_ce,getThis(),"protected_prop",sizeof("protected_prop") - 1,0 TSRMLS_CC);
php_var_dump(&protected_prop,1 TSRMLS_CC);

zend_update_static_property_string(myext_class_ce,"static_prop",sizeof("static_prop") - 1,"更新static_prop的值" TSRMLS_CC);//設置靜態屬性static_prop的屬性值,至關於php的self::$static_prop = "更新static_prop的值";
static_prop = zend_read_static_property(ce,"static_prop",sizeof("static_prop") - 1,0 TSRMLS_CC); 

php_var_dump(
&static_prop,1 TSRMLS_CC); }
//zend_update_property*的一組函數
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC); ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC); ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC); ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC); ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC); ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC); ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, int value_length TSRMLS_DC); //zend_update_static_property*的一組函數
ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC); 
ZEND_API
int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
ZEND_API
int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
ZEND_API
int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC);
ZEND_API
int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC);
ZEND_API
int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, int value_length TSRMLS_DC);
ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC);
相關文章
相關標籤/搜索