您的位置:首页 > 编程语言 > PHP开发

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

2008-03-24 15:03 866 查看
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, ¶ms) == 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);
}
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: