首頁 >php教程 >php手册 >PHP内核中读取$

PHP内核中读取$

WBOY
WBOY原創
2016-06-06 19:54:511082瀏覽

一、内核中获取$_GET\$_POST\$_SERVER\$_FILES\$_COOKIE等全局变量 HashTable是PHP很多实现的基础,例如$_GET\$_POST等全局变量实现。 那么,在扩展中读取这些全局变量,当然还是操作HashTable。 内核中初始化环境变量的通过main/php_variables.c中php_hash_e

一、内核中获取$_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_POST		0
#define TRACK_VARS_GET		1
#define TRACK_VARS_COOKIE	2
#define TRACK_VARS_SERVER	3
#define TRACK_VARS_ENV		4
#define TRACK_VARS_FILES	5
#define TRACK_VARS_REQUEST	6

如果需要对环境变量进行修改,可以在全局作用域中搜索:
(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读取的是只读全局变量。


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn