php扩展练习-类

本文通过实现一个PHP扩展,展示了如何创建抽象类及其子类,并通过具体示例介绍了如何使用这些类来设置和获取动作名称,以及如何判断请求是否来自CLI环境。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

  本篇博文是对PHP扩展开发及内核应用第10-11章的学习、练习、总结。
  

练习习题

  用php扩展实现

        abstract class My_Yaf_Request_Abstract
        {
            protected $action;
            public function __construct()
            {
                echo "I am My_Yaf_Request_Abstract\n";
            }
            public function setActionName($action_name)
            {
                $this->action = $action_name;
            }
            public function getActionName()
            {
                return $this->action;
            }
            public abstract function isCli();
        }
        class My_Yaf_Request_Http extends My_Yaf_Request_Abstract
        {
            public function __construct()
            {
                echo("I am My_Yaf_Request_Http\n");
            }
            public function isCli()
            {
                return false;
            }
        }
        class My_Yaf_Request_Simple extends My_Yaf_Request_Abstract
        {
            public function __construct()
            {
                echo("I am My_Yaf_Request_Simple\n");
            }
            public function isCli()
            {
                return true;
            }
        }

实现

  PHP扩展开发及内核应用中对类的实现已经讲得十分详细,直接贴上我的实现吧。

    //myyaf.c
    #include "myyaf.h"
    //module entry
    #ifdef COMPILE_DL_MYYAF
    zend_class_entry *my_yaf_request_abstract;
    zend_class_entry *my_yaf_request_http;
    zend_class_entry *my_yaf_request_simple;
    ZEND_METHOD(My_Yaf_Request_Abstract, __construct)
    {
            php_printf("I am My_Yaf_Request_Abstract\n");    
    }
    ZEND_METHOD(My_Yaf_Request_Abstract, isCli)
    {
    }
    ZEND_METHOD(My_Yaf_Request_Abstract, setActionName)
    {
            zval *action;
            zend_class_entry *ce;
            ce = Z_OBJCE_P(getThis());
            if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &action) == FAILURE )
            {   
                printf("Error\n");
                RETURN_NULL();
            }
            zend_update_property(ce, getThis(), "action", sizeof("action")-1, action TSRMLS_CC);
    }
    ZEND_METHOD(My_Yaf_Request_Abstract, getActionName)
    {
            zval *action;
            zend_class_entry *ce;
            ce = Z_OBJCE_P(getThis());
            action = zend_read_property(ce, getThis(), "action", sizeof("action")-1, 1 TSRMLS_DC);
            RETVAL_ZVAL(action,1,0);
    }

    ZEND_METHOD(My_Yaf_Request_Http, __construct)
    {
            php_printf("I am My_Yaf_Request_Http\n");
    }
    ZEND_METHOD(My_Yaf_Request_Http, isCli)
    {
            RETVAL_BOOL(0);
    }
    ZEND_METHOD(My_Yaf_Request_Simple, __construct)
    {
            php_printf("I am My_Yaf_Request_Simple\n");
    }
    ZEND_METHOD(My_Yaf_Request_Simple, isCli)
    {
            RETVAL_BOOL(1);
    }
    static zend_function_entry my_yaf_request_abstract_method[] = {
            ZEND_ME(My_Yaf_Request_Abstract, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
            ZEND_ME(My_Yaf_Request_Abstract, getActionName, NULL, ZEND_ACC_PUBLIC)
            ZEND_ME(My_Yaf_Request_Abstract, setActionName, NULL, ZEND_ACC_PUBLIC)
            ZEND_ME(My_Yaf_Request_Abstract, isCli, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT)
            ZEND_ME(My_Yaf_Request_Abstract, isCli, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT)
            {NULL, NULL, NULL}
    };
    static zend_function_entry my_yaf_request_http_method[] = {
            ZEND_ME(My_Yaf_Request_Http, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
            ZEND_ME(My_Yaf_Request_Http, isCli, NULL, ZEND_ACC_PUBLIC)
            {NULL, NULL, NULL}
    };
    static zend_function_entry my_yaf_request_simple_method[] = {
            ZEND_ME(My_Yaf_Request_Simple, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
            ZEND_ME(My_Yaf_Request_Simple, isCli, NULL, ZEND_ACC_PUBLIC)
            {NULL, NULL, NULL}
    };

    ZEND_MINIT_FUNCTION(myyaf)
    {
            zend_class_entry ce, http_ce, simple_ce;
            INIT_CLASS_ENTRY(ce, "My_Yaf_Request_Abstract", my_yaf_request_abstract_method);
            my_yaf_request_abstract = zend_register_internal_class(&ce TSRMLS_CC);
            zend_declare_property_null(my_yaf_request_abstract, "action", strlen("action"), ZEND_ACC_PROTECTED TSRMLS_CC);
            INIT_CLASS_ENTRY(http_ce, "My_Yaf_Request_Http", my_yaf_request_http_method);
            my_yaf_request_http = zend_register_internal_class_ex(&http_ce, my_yaf_request_abstract, "My_Yaf_Request_Abstract" TSRMLS_CC);
            my_yaf_request_http->ce_flags |= ZEND_ACC_FINAL_CLASS;
            INIT_CLASS_ENTRY(simple_ce, "My_Yaf_Request_Simple", my_yaf_request_simple_method);
            my_yaf_request_simple = zend_register_internal_class_ex(&simple_ce, my_yaf_request_abstract, "My_Yaf_Request_Abstract" TSRMLS_CC);
            my_yaf_request_simple->ce_flags |= ZEND_ACC_FINAL_CLASS;
            return SUCCESS;
    }
    zend_module_entry myyaf_module_entry = {
    #if ZEND_MODULE_API_NO >= 20010901
            STANDARD_MODULE_HEADER,
    #endif
            "myyaf", //这个地方是扩展名称,往往我们会在这个地方使用一个宏。
            NULL, /* Functions */
            ZEND_MINIT(myyaf), /* MINIT */
            NULL, /* MSHUTDOWN */
            NULL, /* RINIT */
            NULL, /* RSHUTDOWN */
            NULL, /* MINFO */
    #if ZEND_MODULE_API_NO >= 20010901
            "2.1", //这个地方是我们扩展的版本
    #endif
            STANDARD_MODULE_PROPERTIES
    };
    ZEND_GET_MODULE(myyaf)
    #endif
myyaf.h

    //php_myyaf.h
    #ifndef MYYAF_H
    #define MYYAF_H
    //加载config.h,如果配置了的话
    #ifdef HAVE_CONFIG_H
    #include "config.h"
    #endif
    //加载php头文件
    #include "php.h"
    #define phpext_myyaf_ptr &myyaf_module_entry
    extern zend_module_entry myyaf_module_entry; 
    #endif

测试用例

    <?php
    $obj_http = new My_Yaf_Request_Http();
    $obj_simple = new My_Yaf_Request_Simple();
    $obj_http->setActionName("action_http");
    var_dump($obj_http->getActionName());
    $obj_http->setActionName("action_simple");
    var_dump($obj_http->getActionName());
    var_dump($obj_http->isCli());
    var_dump($obj_simple->isCli());

存疑

  5.4.33的zend引擎只显式提供了zend_register_internal_classzend_register_internal_class_ex分别表示类和子类,并没有提供Abstract类的注册方法。关于如何注册Abstract类,这部分作为后续存疑查找。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值