起步
Zend引擎提供了另种管理设置值(INI)的途径。现在弄个简单的,我们经常看到php.ini里有诸如 display_errors = On
这样的全局设置。假设我们需要为我们扩展定义一个值: hello.greeting
并用函数 hello_ini()
返回它的内容。
在php.ini:
[hello]
hello.greeting=1
为了避免命名空间的冲突,我们扩展的名字作为所有值的前缀。仅仅是一种约定,一个句点用来分隔扩展名和说明性的初始设定名字。
声明变量 php_hello.h
用ext_skel
工具初始化的扩展有个好处就是它能帮我们在特定的位置写上注释。
/*
Declare any global variables you may need between the BEGIN
and END macros here:
ZEND_BEGIN_MODULE_GLOBALS(hello)
zend_long global_value;
char *global_string;
ZEND_END_MODULE_GLOBALS(hello)
*/
这是说如果我们需要声明全局变量,需要将放置在 宏
BEBIN与END之间。并提供了示例,因此在这边添加:
ZEND_BEGIN_MODULE_GLOBALS(hello)
zend_long greeting;
ZEND_END_MODULE_GLOBALS(hello)
ZEND_BEGIN_MODULE_GLOBALS()
和ZEND_END_MODULE_GLOBALS()
用来创建一个名为zend_hello_globals
的结构,它包含一个long型的变量。然后有条件地将HELLO_G()
定义为从线程池中取得数值,或者从全局作用域中得到-如果你编译的目标是非多线程环境。
工具还为我生成了:
/* Always refer to the globals in your function as HELLO_G(variable).
You are encouraged to rename these macros something shorter, see
examples in any other php module directory.
*/
#define HELLO_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(hello, v)
#if defined(ZTS) && defined(COMPILE_DL_HELLO)
ZEND_TSRMLS_CACHE_EXTERN()
#endif
#endif
这是一个简化变量获取操作的宏设置,可以使用 HELLO_G(greeting)
来获得全局设置的变量。
源码实现 hello.c
/* {{{ PHP_INI
*/
/* Remove comments and fill if you need to have entries in php.ini
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("hello.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_hello_globals, hello_globals)
STD_PHP_INI_ENTRY("hello.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_hello_globals, hello_globals)
PHP_INI_END()
*/
/* }}} */
注释说明可以自己看一下,在这下方添加:
ZEND_DECLARE_MODULE_GLOBALS(hello)
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("hello.greeting","0", PHP_INI_ALL, OnUpdateLong, greeting, zend_hello_globals, hello_globals)
PHP_INI_END()
用ZEND_DECLARE_MODULE_GLOBALS()
宏来例示zend_hello_globals
结构.初始值 "0"
是在php.ini里没有对应实体的时候生效的。
全局初始函数:
static void php_hello_init_globals(zend_hello_globals *hello_globals)
{
//hello_globals->global_value = 0;
//hello_globals->global_string = NULL;
}
php_hello_init_globals()
实际上什么也没做,却得多声明个RINIT将变量greeting初始化为0,为什么?
关键在于这两个函数何时调用。php_hello_init_globals()只是在一个新的进程或线程时被调用;然而,每个进程都能处理多个请求,所以这个函数将变量初始化为0将只在第一个页面请求时运行。
接下来就是hello_ini()函数的实现了:
PHP_FUNCTION(hello_ini)
{
RETURN_LONG(HELLO_G(greeting));
}
const zend_function_entry hello_functions[] = {
PHP_FE(hello, NULL)
PHP_FE(hello_ini, NULL) /*添加到编译中去*/
PHP_FE(confirm_hello_compiled, NULL)
PHP_FE_END
};
一些诸如PHP_MINIT_FUNCTION
也要修改,这些函数目前不知道作用是什么:
PHP_MINIT_FUNCTION(hello)
{
REGISTER_INI_ENTRIES();
return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(hello)
{
UNREGISTER_INI_ENTRIES();
return SUCCESS;
}
修改配置
写个hello_change_ini()
来修改配置项:
PHP_FUNCTION(hello_change_ini)
{
HELLO_G(greeting) ++;
}
同样要加到 hello_functions[]
中。
测试
<?php
echo hello_ini(); //1
hello_change_ini();
echo "<br>";
echo hello_ini(); //2
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。