|
一、内核中获取$_GET\$_POST\$_SERVER\$_FILES\$_COOKIE等全局变量
HashTable是PHP很多实现的基础,例如$_GET\$_POST等全局变量实现。
那么,在扩展中读取这些全局变量,当然还是操作HashTable。
内核中初始化环境变量的通过main/php_variables.c中php_hash_environment(TSRMLS_D)
PHP在初始化环境变量的同时,考虑到对大变量的读性能,会通过main/php_variables.c的php_startup_auto_globals来注册一份只读的环境变量。
void php_startup_auto_globals(TSRMLS_D)
{
zend_register_auto_global("_GET", sizeof("_GET")-1, NULL TSRMLS_CC);
zend_register_auto_global("_POST", sizeof("_POST")-1, NULL TSRMLS_CC);
zend_register_auto_global("_COOKIE", sizeof("_COOKIE")-1, NULL TSRMLS_CC);
zend_register_auto_global("_SERVER", sizeof("_SERVER")-1, php_auto_globals_create_server TSRMLS_CC);
zend_register_auto_global("_ENV", sizeof("_ENV")-1, php_auto_globals_create_env TSRMLS_CC);
zend_register_auto_global("_REQUEST", sizeof("_REQUEST")-1, php_auto_globals_create_request TSRMLS_CC);
zend_register_auto_global("_FILES", sizeof("_FILES")-1, NULL TSRMLS_CC);
}只读环境变量的读取方式:
&PG(http_globals)[TRACK_VARS_GET];
&PG(http_globals)[TRACK_VARS_POST];
&PG(http_globals)[TRACK_VARS_REQUEST];
&PG(http_globals)[TRACK_VARS_COOKIE];
&PG(http_globals)[TRACK_VARS_ENV];
&PG(http_globals)[TRACK_VARS_FILES];
其中用到的宏为内核提供
/*main/php_globals.h*/
#define TRACK_VARS_POST0
#define TRACK_VARS_GET1
#define TRACK_VARS_COOKIE2
#define TRACK_VARS_SERVER3
#define TRACK_VARS_ENV4
#define TRACK_VARS_FILES5
#define TRACK_VARS_REQUEST6
如果需要对环境变量进行修改,可以在全局作用域中搜索:
(void)zend_hash_find(&EG(symbol_table), ZEND_STRS("_GET"), (void **)&carrier);
(void)zend_hash_find(&EG(symbol_table), ZEND_STRS("_POST"), (void **)&carrier);
(void)zend_hash_find(&EG(symbol_table), ZEND_STRS("_REQUEST"), (void **)&carrier);
(void)zend_hash_find(&EG(symbol_table), ZEND_STRS("_COOKIE"), (void **)&carrier);
(void)zend_hash_find(&EG(symbol_table), ZEND_STRS("_FILES"), (void **)&carrier);
(void)zend_hash_find(&EG(symbol_table), ZEND_STRS("_ENV"), (void **)&carrier);
二、现在来看案例,定义一个类request,拥有方法getQuery与getPost.来读取$_GET和$_POST
/*
* fw_request.c
*
* Created on: 2012-6-19
* Author: jy
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "main/SAPI.h"
#include "Zend/zend_exceptions.h"
#include "Zend/zend_alloc.h"
#include "php_fw.h"
#include "fw_request.h"
zend_class_entry *request;
/**
*
class Request {
public mixed getLang ( void );
public mixed getQuery ( string $name = NULL );
}
*/
//定义类方法的参数类型,使内核自动校验参数类型
ZEND_BEGIN_ARG_INFO(getQueryArgs, 1)
ZEND_ARG_INFO(0, name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(getPostArgs, 1)
ZEND_ARG_INFO(0, name)
ZEND_END_ARG_INFO()
ZEND_METHOD(request, getQuery)
{
zval **carrier;
zval *key, *ret;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE){
RETURN_FALSE;
}
ret = request_query(TRACK_VARS_GET, Z_STRVAL_P(key), Z_STRLEN_P(key) TSRMLS_CC);
RETURN_ZVAL(ret, 0, NULL);
}
ZEND_METHOD(request, getPost)
{
zval **carrier;
zval *key, *ret;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE){
RETURN_FALSE;
}
ret = request_query(TRACK_VARS_POST, Z_STRVAL_P(key), Z_STRLEN_P(key) TSRMLS_CC);
RETURN_ZVAL(ret, 0, NULL);
}
zend_function_entry functions_entry[] = {
PHP_ME(request, getQuery, getQueryArgs, ZEND_ACC_PUBLIC)
PHP_ME(request, getPost, getPostArgs, ZEND_ACC_PUBLIC)
};
ZEND_MINIT_FUNCTION(fw_request)
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "request", functions_entry);
request = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
return SUCCESS;
}
/*
定义request_query来完成内核中读取$_GET\$_POST\$_SERVER\$_FILES\$_COOKIE\$_REQUEST
其中只有$_REQUEST的值是可修改的
*/
zval * request_query(uint type, char * name, uint len TSRMLS_DC) {
zval **carrier, **ret;
zend_bool jit_initialization = (PG(auto_globals_jit) && !PG(register_globals) && !PG(register_long_arrays));
switch (type) {
case TRACK_VARS_POST:
case TRACK_VARS_GET:
case TRACK_VARS_FILES:
case TRACK_VARS_COOKIE:
carrier = &PG(http_globals)[type];
break;
case TRACK_VARS_ENV:
if (jit_initialization) {
zend_is_auto_global(ZEND_STRL("_ENV") TSRMLS_CC);
}
carrier = &PG(http_globals)[type];
break;
case TRACK_VARS_SERVER:
if (jit_initialization) {
zend_is_auto_global(ZEND_STRL("_SERVER") TSRMLS_CC);
}
carrier = &PG(http_globals)[type];
break;
case TRACK_VARS_REQUEST:
if (jit_initialization) {
zend_is_auto_global(ZEND_STRL("_REQUEST") TSRMLS_CC);
}
(void)zend_hash_find(&EG(symbol_table), ZEND_STRS("_REQUEST"), (void **)&carrier);
break;
default:
break;
}
if (!carrier || !(*carrier)) {
zval *empty;
MAKE_STD_ZVAL(empty);
ZVAL_NULL(empty);
return empty;
}
if (!len) {
Z_ADDREF_P(*carrier);
return *carrier;
}
if (zend_hash_find(Z_ARRVAL_PP(carrier), name, len + 1, (void **)&ret) == FAILURE) {
zval *empty;
MAKE_STD_ZVAL(empty);
ZVAL_NULL(empty);
return empty;
}
Z_ADDREF_P(*ret);
return *ret;
}
三、网页访问PHP测试 访问网址http://localhost/test.php?get=test,这个网址由你本地环境决定
$_GET['test'] = "abc";
$obj = new request();
echo $obj->getQuery('test')."<br>";
echo $obj->getPost('test');
输出结果:
test
空
这也证明了,request_query读取的是只读全局变量。
|
|