用Php扩展实现的简单框架 - 3

来源:互联网 发布:中国单挑全世界知乎 编辑:程序博客网 时间:2024/05/22 15:23
kiss.c:


#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "ext/standard/php_string.h"
#include "ext/standard/url.h"
#include "SAPI.h"
#include "php_kiss.h"

#include "kiss_const.c"
#include "kiss_inner.c"

// #define KISS_DEPS /** HAVE_SIMPLEXML */


#ifdef KISS_DEPS /** HAVE_SIMPLEXML */
static zend_module_dep kiss_deps[] = {
    // ZEND_MOD_REQUIRED("libxml")

    // ZEND_MOD_REQUIRED("simplexml")

    {NULL, NULL, NULL}
};
#endif

/* True global resources - no need for thread safety here */
// static HashTable hosts_rw;


ZEND_DECLARE_MODULE_GLOBALS(kiss)



zend_function_entry action_mtds[] = {

    PHP_ME(KissAction, __construct, NULL, ZEND_ACC_PUBLIC)

    // PHP_ME(KissAction, init, NULL, ZEND_ACC_PUBLIC)


    // PHP_ABSTRACT_ME(KissAction, init, NULL)


    {NULL, NULL, NULL}

};



zend_function_entry listener_mtds[] = {

    PHP_ME(KissListener, __construct, NULL, ZEND_ACC_PUBLIC)

    PHP_ME(KissListener, preDispatch, NULL, ZEND_ACC_PUBLIC)

    PHP_ME(KissListener, postDispatch, NULL, ZEND_ACC_PUBLIC)

    {NULL, NULL, NULL}

};




zend_function_entry kiss_functions[] = {

    PHP_FE(kiss_cli_test,    NULL)
    PHP_FE(kiss_status,    NULL)

    PHP_FE(kiss_front_start,    NULL)
    PHP_FE(kiss_eval, NULL)
    PHP_FE(kiss_forward, NULL)
    PHP_FE(kiss_redirect, NULL)
    PHP_FE(kiss_request_get, NULL)
    PHP_FE(kiss_request_query, NULL)
    PHP_FE(kiss_request_post, NULL)
    PHP_FE(kiss_request_params, NULL)
    PHP_FE(kiss_set_rule, NULL)
    PHP_FE(kiss_clear_rules, NULL)
    PHP_FE(kiss_set_listener, NULL)
    {NULL, NULL, NULL}
};

zend_module_entry kiss_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
#ifdef KISS_DEPS /** HAVE_SIMPLEXML */
    STANDARD_MODULE_HEADER_EX, NULL,
    kiss_deps,
#else
    STANDARD_MODULE_HEADER,
#endif
#endif
    "kiss",
    kiss_functions,
    PHP_MINIT(kiss),
    PHP_MSHUTDOWN(kiss),
    PHP_RINIT(kiss),
    PHP_RSHUTDOWN(kiss),
    PHP_MINFO(kiss),
#if ZEND_MODULE_API_NO >= 20010901
    KISS_VERSION,
#endif
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_KISS
ZEND_GET_MODULE(kiss)
#endif

PHP_INI_BEGIN()
    STD_PHP_INI_ENTRY(CFG_FILE_ENTRY, DEFAULT_CFG_FILE, PHP_INI_SYSTEM, /
        OnUpdateString, cfg_file, zend_kiss_globals, kiss_globals)
PHP_INI_END()

/** co: zval **, var: global-var, type of zval* */
#define clear_var_pzval(co, var) { /
    (co) = &KISS_G(var); if(*(co)) zval_ptr_dtor((co)); *(co) = NULL; /
}

static void php_kiss_init_globals(zend_kiss_globals *kiss_globals)
{
    zend_hash_init(&kiss_globals->hosts_rw, 0 , NULL, (void (*)(void *)) kiss_rule_free, 1);
    zend_hash_init(&kiss_globals->hosts_ls, 0 , NULL, NULL/*(void (*)(void *)) kiss_ls_free*/, 1);
}
static void php_kiss_destroy_globals(zend_kiss_globals *kiss_globals)
{
    zend_hash_destroy(&kiss_globals->hosts_rw);
    zend_hash_destroy(&kiss_globals->hosts_ls);
}

PHP_MINIT_FUNCTION(kiss)
{

    zend_class_entry ce;
    zval * pzv;


    ZEND_INIT_MODULE_GLOBALS(kiss, php_kiss_init_globals, NULL);
    /* 第三个参数传入NULL将导致在非多线程的平台产生段错误,
     * 传入php_kiss_destroy_globals导致段错误。
     */

    REGISTER_INI_ENTRIES();

    KISS_EXPORT_CONST

    MAKE_STD_ZVAL(pzv);
    if(!zend_get_constant(DIR_SEP, DIR_SEP_LEN, pzv TSRMLS_CC)) {
        KISS_G(dir_sep) = Z_STRVAL_P(pzv)[0];
        zval_ptr_dtor(&pzv);
    } else KISS_G(dir_sep) = DEFAULT_DIR_SEP;


    INIT_CLASS_ENTRY(ce, "KissAction", action_mtds);

    KISS_G(action_ce) = zend_register_internal_class(&ce TSRMLS_CC);

    //KISS_G(action_ce)->ce_flags != ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;




    INIT_CLASS_ENTRY(ce, "KissListener", listener_mtds);

    KISS_G(listener_ce) = zend_register_internal_class(&ce TSRMLS_CC);

    //KISS_G(listener_ce)->ce_flags != ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;


    KISS_G(cfg_inited) = 0;
#ifndef PHP_WIN32
    kiss_init_cfg(KISS_G(cfg_file) TSRMLS_CC);
#endif


    return SUCCESS;
}

PHP_MSHUTDOWN_FUNCTION(kiss)
{
    UNREGISTER_INI_ENTRIES();
#ifdef ZTS
    zend_hash_destroy(&KISS_G(hosts_rw));
    zend_hash_destroy(&KISS_G(hosts_ls));
#else
    php_kiss_destroy_globals(&kiss_globals TSRMLS_CC);
#endif
    return SUCCESS;
}

PHP_RINIT_FUNCTION(kiss)
{
    zval **co;
 
    KISS_G(status) = kiss_status_init();
    if(!KISS_G(status)) return FAILURE;
    co = &KISS_G(obj_cache); MAKE_STD_ZVAL(*co); array_init(*co);
    co = &KISS_G(ls_called); MAKE_STD_ZVAL(*co); array_init(*co);
    KISS_G(ls_pre_disp) = NULL;
    KISS_G(ls_post_disp) = NULL;
    KISS_G(request) = NULL;
    // KISS_G(response) = NULL;

    return SUCCESS;
}

PHP_RSHUTDOWN_FUNCTION(kiss)
{
    char ** path;
    zval ** co;
    kiss_request ** req;
    // kiss_response ** resp;


    kiss_status_free(KISS_G(status));
    clear_var_pzval(co, obj_cache);
    clear_var_pzval(co, ls_called);
    clear_var_pzval(co, ls_pre_disp);
    clear_var_pzval(co, ls_post_disp);
    req = &KISS_G(request); if(*req) { kiss_request_free(*req); *req = NULL; }
    // resp = &KISS_G(response); if(*resp) { kiss_response_free(*resp); *resp = NULL; }


    return SUCCESS;
}

PHP_MINFO_FUNCTION(kiss)
{
    php_info_print_table_start();
    php_info_print_table_header(2, "kiss support", "enabled");
    php_info_print_table_end();

    // DISPLAY_INI_ENTRIES();

}


PHP_METHOD(KissAction, __construct) { }

// PHP_METHOD(KissAction, init) { }


PHP_METHOD(KissListener, __construct) { }

PHP_METHOD(KissListener, preDispatch) { }

PHP_METHOD(KissListener, postDispatch) { }

/** 包含并执行文件,参考include。
 * proto mixed kiss_eval(string src[, long type])
 * arg1 - 文件,
 * arg2 - eval的类型,缺省是KISS_REQUIRE,
 * return - 参考include,如有问题则返回NULL,
 * throw Exception(文件不存在) */

PHP_FUNCTION(kiss_eval) {
    zval * ret, * source;
    ulong type;
    
    type = KISS_REQUIRE;

    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l!", &source, &type) == FAILURE) {
        RETURN_NULL();
    }
    if(Z_TYPE_P(source) != IS_STRING) RETURN_NULL();

    if(!kiss_eval(type, source, &ret TSRMLS_CC)) {
     zend_throw_exception_ex(NULL, KISS_E_READFILE TSRMLS_CC, "文件%s不存在或不可读。", Z_STRVAL_P(source));
     RETURN_NULL();
    }

    if(ret) {
        RETURN_ZVAL(ret, 0, 1);
    } else {
        RETURN_NULL();
    }
}

/** 设定运行状态,必须在kiss_front_start之前调用。
 * proto mixed kiss_status(long key[, zval * value])
 * arg1 - 代表状态字段的常量,
 * arg2 - 新值,
 * return - 旧值。 */

PHP_FUNCTION(kiss_status) {
    ulong k;
    zval * v = NULL;
    kiss_status * ks;

    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &k, &v)==FAILURE) {
        return;
    }
    ks = KISS_G(status);
#define status_bool(k) { /
    RETVAL_BOOL(ks->k); /
    if(v) ks->k = Z_BVAL_P(v); /
    return; /
}
#define status_string(k) { /
    if(ks->k) { /
        RETVAL_STRING(ks->k, 1); /
        efree(ks->k); /
    } /
    if(v) ks->k = estrdup(Z_STRVAL_P(v)); /
    return; /
}
    switch(k) {
    case KISS_STATUS_PREFIX_CTL: status_bool(prefix_ctl);
    case KISS_STATUS_SHARE_GP: status_bool(share_gp);
    case KISS_STATUS_USE_PORT: status_bool(use_port);
    case KISS_STATUS_USE_CACHE: status_bool(use_cache);
    case KISS_STATUS_DISPATCH_TYPE:
        RETVAL_LONG(ks->dispatch_type);
        if(v) ks->dispatch_type = Z_LVAL_P(v);
        return;
    case KISS_STATUS_CLI_ROOT: status_string(cli_root);
    case KISS_STATUS_EXT_PROC: status_string(ext_proc);
    case KISS_STATUS_EXT_PATH: status_string(ext_path);
    case KISS_STATUS_DEFAULT_MDL: status_string(default_mdl);
    case KISS_STATUS_DEFAULT_CTL: status_string(default_ctl);
    case KISS_STATUS_DEFAULT_ACT: status_string(default_act);
    case KISS_STATUS_POSTFIX_CTL: status_string(postfix_ctl);
    case KISS_STATUS_POSTFIX_ACT: status_string(postfix_act);
    default:
        return;
    }
}

/** 手工设定模块分发目录。
 * proto bool kiss_set_rule(string ctl_dir[, string mdl])
 * arg1 - 控制器目录,
 * arg2 - 模块名,不提供或NULL表示缺省(全局)模块(空字符串表示),
 * return - 是否成功。 */

PHP_FUNCTION(kiss_set_rule) {
    char * mdl_name = "", * ctl_dir;
    uint mdl_name_len = 0, ctl_dir_len;

    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!",
     &ctl_dir, &ctl_dir_len, &mdl_name, &mdl_name_len) == FAILURE) {
        RETURN_BOOL(0);
    }

    RETURN_BOOL(kiss_set_rule(mdl_name, ctl_dir, ctl_dir_len TSRMLS_CC));
}


/** 清除模块分发目录设置。
 * proto void kiss_clear_rules(void)
 * TODO: 需要有对应的init函数。 */

PHP_FUNCTION(kiss_clear_rules) {
    zend_hash_destroy(&KISS_G(hosts_rw));
}

/** 用于terminal调试。 */
PHP_FUNCTION(kiss_cli_test) {
    char * uri;
    uint uri_len;
    char * path = NULL;
    zend_bool flag;

    if(!sapi_module.name || strncmp(sapi_module.name, "cli", 3)) {
        kiss_e_throw("该函数只能用于CLI模式。", KISS_E_ONLYCLI);
        RETURN_FALSE;
    }

    if(!KISS_G(status)->cli_root || '/0'==*(KISS_G(status)->cli_root)) {
        kiss_e_throw("CLI模式需要kiss_status()提供基本目录。", KISS_E_NEEDROOT);
        RETURN_FALSE;
    }
    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &uri, &uri_len)==FAILURE) {
        RETURN_FALSE;
    }
    if(!uri || !uri_len) {
        kiss_e_throw("必须提供测试用的URI!", KISS_E_NEEDURI);
        RETURN_BOOL(0);
    }

#ifdef PHP_WIN32
    if(!KISS_G(cfg_inited)) kiss_init_cfg(KISS_G(cfg_file) TSRMLS_CC);
#endif
    if(!KISS_G(cfg_inited)) {
        kiss_e_throw("配置文件解析失败!", KISS_E_CFGFILE);
        RETURN_BOOL(0);
    }

    flag = kiss_request_init(uri, &path TSRMLS_CC);
    if(!flag) {
        if(path) efree(path);
        kiss_e_throw("初始化请求失败!", KISS_E_INITREQ);
        RETURN_BOOL(0);
    }

    flag = kiss_route_layer(path TSRMLS_CC);
    if(path) efree(path);
    if(!flag) {
        kiss_e_throw("路由失败!", KISS_E_ROUTE);
        RETURN_BOOL(0);
    }

    flag = kiss_dispatch(TSRMLS_C);
    if(!flag) {
        kiss_e_throw("分发失败!", KISS_E_DISPATCH);
        RETURN_BOOL(0);
    }

    RETURN_BOOL(1);
}

/** 启动前端控制器,如果未初始化,则用当前参数初始化。
 * proto bool kiss_front_start(void)
 * throws Exception
 * return - 是否成功,
 * throws - 配置文件解析或路由或分发失败,
 * TODO: 加入更多的路由。 */


PHP_FUNCTION(kiss_front_start)

{
    zend_bool flag;
    char * path = NULL;

#ifdef PHP_WIN32
    if(!KISS_G(cfg_inited)) kiss_init_cfg(KISS_G(cfg_file) TSRMLS_CC);
#endif
    if(!KISS_G(cfg_inited)) {
        kiss_e_throw("配置文件解析失败!", KISS_E_CFGFILE);
        RETURN_BOOL(0);
    }

    flag = kiss_request_init(NULL, &path TSRMLS_CC);
    if(!flag) {
        if(path) efree(path);
        kiss_e_throw("初始化请求失败!", KISS_E_INITREQ);
        RETURN_BOOL(0);
    }

    flag = kiss_route_layer(path TSRMLS_CC);
    if(path) efree(path);
    if(!flag) {
        kiss_e_throw("路由失败!", KISS_E_ROUTE);
        RETURN_BOOL(0);
    }

    flag = kiss_dispatch(TSRMLS_C);
    if(!flag) {
        kiss_e_throw("分发失败!", KISS_E_DISPATCH);
        RETURN_BOOL(0);
    }

    RETURN_BOOL(1);
}

/** 设定Action或Controller的监听器,如果未初始化,则用当前参数初始化。
 * NOTE: 在Controller调用。
 * proto bool kiss_set_listener(string listener[, string item[, long type]])
 * arg1 - 监听器类的名字,
 * arg2 - 监听目标,应是Action,空表示对整个Controller,
 * arg3 - 监听器类型(现在只有分发前和分发后),缺省是分发前,
 * return - 是否成功。*/

PHP_FUNCTION(kiss_set_listener) {
    char * item = NULL, * ls = NULL;
    uint item_len, ls_len, str_len;
    ulong ls_type;
    zval ** lsco, * mco, * cco, * aco, ** value;
    kiss_request * req;

    ls_type = KISS_LS_PRE_DISPATCH;

    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sl!",
        &ls, &ls_len, &item, &item_len, &ls_type) == FAILURE) {
        RETURN_FALSE;
    }
    if(!ls || 0==ls_len) RETURN_BOOL(0);

    req = KISS_G(request);
    lsco = KISS_LS_PRE_DISPATCH==ls_type ?
        &KISS_G(ls_pre_disp) : &KISS_G(ls_post_disp);
    if(!*lsco) {
        MAKE_STD_ZVAL(*lsco);
        array_init(*lsco);
    }

    str_len = strlen(req->module);
    if(zend_hash_find(Z_ARRVAL_PP(lsco), req->module, str_len+1, (void**)&value) == FAILURE) {
        MAKE_STD_ZVAL(mco);
        array_init(mco);
        add_assoc_zval(*lsco, req->module, mco);
    } else mco = *value;
    str_len = strlen(req->controller);
    if(zend_hash_find(Z_ARRVAL_P(mco), req->controller, str_len+1, (void**)&value) == FAILURE) {
        MAKE_STD_ZVAL(cco);
        array_init(cco);
        add_assoc_zval(mco, req->controller, cco);
    } else cco = *value;
    if(!item || '/0' == *item) { // controller

        item = "";
        item_len = 0;
    }
    if(zend_hash_find(Z_ARRVAL_P(cco), item, item_len+1, (void**)&value) == FAILURE) {
        MAKE_STD_ZVAL(aco);
        array_init(aco);
        add_assoc_zval(cco, item, aco);
    } else aco = *value;
    if(!zend_hash_exists(Z_ARRVAL_P(aco), ls, ls_len+1)) {
        add_assoc_long(aco, ls, 0);
    }

    RETURN_BOOL(1);
}

/** 服务器内跳转到其他的Action,如果是相同的控制器,则不再初始化,使用同一实利。
 * 因为是函数调用方式,所以会返回调用点。
 * proto bool kiss_forward(string action[, string controller[, string module[, array params]]])
 * throws Exception
 * arg1 - Action,
 * arg2 - Controller,缺省为当前的控制器,
 * arg3 - Module,缺省为当前模块,
 * arg4 - 参数数组,
 * return - 是否成功,
 * throws - Action初始化或分发失败。 */

PHP_FUNCTION(kiss_forward) {
    char * action = NULL, * controller = NULL, * module = NULL;
    char * action2 = NULL, * controller2 = NULL, * module2 = NULL;
    uint act_len, ctl_len, mdl_len;
    zval * params = NULL;
    kiss_request * req;
    zval ** co;

    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ssz",
     &action, &act_len, &controller, &ctl_len, &module, &mdl_len, &params) == FAILURE) {
        RETURN_FALSE;
    }
    if(!action || '/0' == action[0]) RETURN_BOOL(0);

    req = KISS_G(request);
    // efree(req->action);

    action2 = req->action;
    req->action = estrdup(action);

    if(controller && '/0' != controller[0]) {
        // efree(req->controller);

        controller2 = req->controller;
        req->controller = estrdup(controller);
    }

    if(module) {
        // efree(req->module);

        module2 = req->module;
        req->module = estrdup(module);
    }

    if(params && IS_ARRAY == Z_TYPE_P(params))
        php_array_merge(Z_ARRVAL_P(req->query), Z_ARRVAL_P(params), 0 TSRMLS_CC);

    kiss_dispatch(TSRMLS_C);
    if(module2) { efree(req->module); req->module = module2; }
    if(controller2) { efree(req->controller); req->controller = controller2; }
    efree(req->action); req->action = action2;
}

/** 重定向到其他的地址。
 * proto bool kiss_redirect(string action[, string controller[, string module[, long code]]])
 * throws Exception
 * arg1 - Action或绝对路径,
 * arg2 - Controller,缺省为当前的控制器,
 * arg3 - Module,缺省为当前模块,
 * arg4 - 响应代码,
 * return - 是否成功,
 * throws - Action初始化或分发失败。
 * TODO: 对于相对路径,需要加入参数。 */

PHP_FUNCTION(kiss_redirect) {
    // zend_bool replace = 1;

    sapi_header_line ctr = {0};
    char * act = NULL, * ctl = NULL, * mdl = NULL, * lc_word;
    char * p1 = "http://", * p2 = "https://"/*, * protocol, url[1024]*/;
    uint a_len, c_len = 0, m_len = 0;
    kiss_request * req;

    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ssl",
        &act, &a_len, &ctl, &c_len, &mdl, &m_len, &ctr.response_code) == FAILURE) {
        RETURN_FALSE;
    }
    if(!act || !a_len) RETURN_BOOL(0);

    req = KISS_G(request);
    /*protocol = zend_getenv(SERVER_PROTOCOL, sizeof(SERVER_PROTOCOL)-1 TSRMLS_CC);
    if(!protocol || !*protocol) protocol = DEFAULT_SERVER_PROTOCOL;*/


    lc_word = (char*)do_alloca(a_len + 1);
    zend_str_tolower_copy(lc_word, act, a_len);
    if(PATH_SEP == *act || !strncmp(p1, lc_word, sizeof(p1)) || !strncmp(p2, lc_word, sizeof(p2))) {
    // 绝对路径

     ctr.line_len = spprintf(&(ctr.line), 0, "Location: %s", act);
    } else { // 相对路径

        if(!mdl || !m_len) {
            mdl = req->module;
        }
        if(!ctl || !c_len) {
            ctl = req->controller;
        }
        ctr.line_len = spprintf(&(ctr.line), 0, "Location: /%s/%s/%s", mdl, ctl, act);
    }
    free_alloca(lc_word);
    sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
    efree(ctr.line);
    RETURN_BOOL(1);
}

/** 获取查询参数。
 * proto mixed kiss_request_query([string key])
 * arg1 - 参数的键,不提供则返回全部参数数组,
 * return - 键对应的值。 */

PHP_FUNCTION(kiss_request_query) {
    char * key = NULL;
    uint key_len;

    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &key, &key_len) == FAILURE) {
        RETURN_FALSE;
    }

    kiss_request_query(key, KISS_G(request)->query, &return_value TSRMLS_CC);
}

/** 获取POST参数。
 * proto mixed kiss_request_post([string key])
 * arg1 - 参数的键,不提供则返回全部参数数组,
 * return - 键对应的值。 */

PHP_FUNCTION(kiss_request_post) {
    char * key = NULL;
    uint key_len;

    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &key, &key_len) == FAILURE) {
        RETURN_FALSE;
    }

    kiss_request_query(key, KISS_G(request)->post, &return_value TSRMLS_CC);
}

/** 获取请求(QUERY+POST)参数,QUERY优先。
 * proto mixed kiss_request_params([string key])
 * arg1 - 参数的键,不提供则返回全部参数数组,
 * return - 键对应的值。 */

PHP_FUNCTION(kiss_request_params) {
    char * key = NULL;
    uint key_len;

    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &key, &key_len) == FAILURE) {
        RETURN_FALSE;
    }

    kiss_request_query(key, KISS_G(request)->query, &return_value TSRMLS_CC);
    if(key && IS_NULL != Z_TYPE_P(return_value)) return;
    kiss_request_query(key, KISS_G(request)->post, &return_value TSRMLS_CC);
    //PHP_FN(kiss_request_query)(INTERNAL_FUNCTION_PARAM_PASSTHRU);

    //if(IS_NULL != Z_TYPE_P(return_value)) return;

    //PHP_FN(kiss_request_post)(INTERNAL_FUNCTION_PARAM_PASSTHRU);

}

/** 获取请求的信息。
 * proto mixed kiss_request_query([long type])
 * arg1 - 所需信息的类型常量,可组合,
 * return - 信息的数组,如需要的项不存在则为空字符串或空数组。
 * TODO: 以后考虑接受任意数量参数。 */

PHP_FUNCTION(kiss_request_get) {
    ulong arg1;
    zval * ret;
    kiss_request * req;
    
    arg1 = KISS_REQ_ALL;
    
    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &arg1) == FAILURE) {
        RETURN_FALSE;
    }
    
    req = KISS_G(request);

    array_init(return_value);
    ret = return_value;
    if(KISS_REQ_METHOD & arg1) {
        add_assoc_string(ret, "method", req->method?req->method:"", 1);
    }
    if(KISS_REQ_HOST & arg1) {
        add_assoc_string(ret, "host", req->host?req->host:"", 1);
    }
    if(KISS_REQ_MODULE & arg1) {
        add_assoc_string(ret, "module", req->module?req->module:"", 1);
    }
    if(KISS_REQ_CONTROLLER & arg1) {
        add_assoc_string(ret, "controller", req->controller?req->controller:"", 1);
    }
    if(KISS_REQ_ACTION & arg1) {
        add_assoc_string(ret, "action", req->action?req->action:"", 1);
    }
    if(KISS_REQ_FRAGMENT & arg1) {
        add_assoc_string(ret, "fragment", req->fragment?req->fragment:"", 1);
    }
    if(KISS_REQ_QUERY & arg1) {
        ZVAL_ADDREF(req->query); // 引用

        add_assoc_zval(ret, "query", req->query);
    }
    if(KISS_REQ_POST & arg1) {
        ZVAL_ADDREF(req->post); // 引用

        add_assoc_zval(ret, "post", req->post);
    }
}

 
原创粉丝点击