• php扩展开发-INI配置


    php.ini文件是用来保存各项扩展配置的文件,每个扩展都或多或少需要有一个定制化的配置,ini文件是一个很好的保存配置的方式,我们来看下怎么在自己的扩展里,使用到ini的配置功能

    //创建ini的配置项
    #include "php_ini.h"
    //ini配置的创建和全局变量的类似,通过宏定义创建一个结构体,来保存INI的配置项
    //参数说明:
    //1,配置名称
    //2,配置值
    //3,作用域
    //4,修改时的回调函数,可以为NULL PHP_INI_BEGIN() PHP_INI_ENTRY(
    "myext.ini_string","我是ini的字符串",PHP_INI_ALL,myext_example_ini_callback) PHP_INI_ENTRY("myext.ini_long","100",PHP_INI_ALL,NULL) PHP_INI_END()
    //在入口增加PHP_MSHUTDOWN(myext)函数 zend_module_entry myext_module_entry
    = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "myext",//扩展名称 myext_functions,//zend_function_entry myext_functions 定义好的函数扩展变量 PHP_MINIT(myext),//MINIT_FUNCTION PHP_MSHUTDOWN(myext),//PHP_MSHUTDOWN(myext),//MSHUTDOWN_FUNCTION PHP_RINIT(myext),//RINIT_FUNCTION PHP_RSHUTDOWN(myext),//RSHUTDOWN_FUNCTION PHP_MINFO(myext),//MINFO_FUNCTION #if ZEND_MODULE_API_NO >= 20010901 PHP_MYEXT_VERSION, #endif STANDARD_MODULE_PROPERTIES }; PHP_MINIT_FUNCTION(myext) { //注册INI配置 REGISTER_INI_ENTRIES(); return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(myext) {
    //销毁INI配置 UNREGISTER_INI_ENTRIES();
    return SUCCESS; }

    //PHP_INI_ENTRY中的回调函数

    ZEND_INI_MH(myext_example_ini_callback){
    if(new_value_length == 0 || strcmp(new_value,"no_allow_string") == 0){
    return FAILURE;
    }
    return SUCCESS;
    }

    /*

    var_dump(ini_get('myext.ini_string'));
    ini_set('myext.ini_string','我是新的INI字符串');
    var_dump(ini_get('myext.ini_string'));
    var_dump(ini_get('myext.ini_long'));
    ini_set('myext.ini_long','101');
    var_dump(ini_get('myext.ini_long'));

    string(21) "我是ini的字符串"
    string(24) "我是新的INI字符串"
    string(3) "100"
    string(3) "101"

    */

    我们来看一下刚才PHP_INI_ENTRY函数中第三个参数作用域的问题

    参数       描述
    PHP_INI_PERDIR 指令可以在php.ini、httpd.conf或.htaccess文件中修改
    PHP_INI_SYSTEM 指令可以在php.ini 和 httpd.conf 文件中修改
    PHP_INI_USER 指令可以在用户脚本中修改
    PHP_INI_ALL 指令可以在任何地方修改

    怎么能在扩展中访问ini的配置项呢

    PHP_FUNCTION(myext_example_ini);//php_myext.c
    
    
    PHP_FE(myext_example_ini, NULL)//每个函数一行,第一个参数与PHP_FUNCTION(name)的name一样
    
    
    PHP_FUNCTION(myext_example_ini){
        const char * ini_string = INI_STR("myext.ini_string");//获取当前值
        long ini_long = INI_INT("myext.ini_long");
        php_printf("ini_string => %s
    ",ini_string);
        php_printf("ini_long => %ld
    ",ini_long);
        const char * orig_ini_string = INI_ORIG_STR("myext.ini_string");//获取默认值
        long orig_ini_long = INI_ORIG_INT("myext.ini_long");
        php_printf("orig_ini_string => %s
    ",orig_ini_string);
        php_printf("orig_ini_long => %ld
    ",orig_ini_long);
    }

    /*

    myext_example_ini();
    ini_set('myext.ini_string','我是新的INI字符串');
    ini_set('myext.ini_long','101');
    myext_example_ini();

     

    ini_string => 我是ini的字符串
    ini_long => 100
    orig_ini_string => 我是ini的字符串
    orig_ini_long => 100

    //上面是修改前,下面是修改后

    ini_string => 我是新的INI字符串
    ini_long => 101
    orig_ini_string => 我是ini的字符串
    orig_ini_long => 100


    */

    INI的配置项一共有四种类型,所有INI_STR和INI_ORIG_STR分别有四种不同类型的组合

    #define INI_INT(name) zend_ini_long((name), sizeof(name), 0)
    #define INI_FLT(name) zend_ini_double((name), sizeof(name), 0)
    #define INI_STR(name) zend_ini_string_ex((name), sizeof(name), 0, NULL)
    #define INI_BOOL(name) ((zend_bool) INI_INT(name))
    
    #define INI_ORIG_INT(name)  zend_ini_long((name), sizeof(name), 1)
    #define INI_ORIG_FLT(name)  zend_ini_double((name), sizeof(name), 1)
    #define INI_ORIG_STR(name)  zend_ini_string((name), sizeof(name), 1)
    #define INI_ORIG_BOOL(name) ((zend_bool) INI_ORIG_INT(name))

    在PHP_INI_ENTRY函数中第四个参数是一个回调函数,在ini配置项被修改的时候,这个函数会被调用,这个的作用在于,你可以对设置的值进行过滤,不符合要求的可以返回FAILER让本次修改不生效。

    ZEND_INI_MH(myext_example_ini_callback){//这个函数需要用ZEND_INI_MH来定义,跟ZEND_FUNCTION不一样
    if(new_value_length == 0 || strcmp(new_value,"no_allow_string") == 0)//如果字符串为空或字符串=no_allow_string就不允许设置
    {
    return FAILURE; //本次修改不会生效
    }
    return SUCCESS;
    }

    #define ZEND_INI_MH(name) int name(zend_ini_entry *entry, char *new_value, uint new_value_length, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage TSRMLS_DC)
    //宏展开以后这里有很多参数,这里面我们会用到的是修改值的new_value(字符串内容)和new_value_length(字符串长度),其余参数,内核会帮助我们自己补充,可以不需要关心

    我们经常需要通过phpinfo或php -i来查询当前有效的ini配置项目,所以当我们开发扩展的时候,最好也把当前配置的信息写到PHP_MINFO_FUNCTION的函数中,结合前面说的MINFO部分的知识,以及刚才说到读取INI配置项的知识,我们可以自己实现这个功能,幸运的是,Zend的内核以及帮我们考虑到了,所有我们只要用以下代码就可以做到了。

    PHP_MINFO_FUNCTION(myext){
        php_info_print_table_start();
        php_info_print_table_row(2, "version", PHP_MYEXT_VERSION);
        php_info_print_table_row(2, "writer", "zhangxiaomin");
        php_info_print_table_end();
    
        DISPLAY_INI_ENTRIES();//只要增加这一行就可以了/
    }

    /*
    php5.6 -i //命令行

    myext

    version => 1.0
    writer => zhangxiaomin

    Directive => Local Value => Master Value
    myext.ini_long => 100 => 100
    myext.ini_string => 我是ini的字符串 => 我是ini的字符串


    */

     到目前为止,我们已经能够在扩展中使用ini的配置了,但是实现起来不太理想,内核是用一个哈希表来保存配置项的数据的,每一次都需要一直zend_hash_find,然后保存的值都是字符串类型,查找到之后需要做类型转换,我们有什么方法来优化吗?如果你能想起全局变量,那就说明你慢慢对扩展有点感觉了。

    ZEND_BEGIN_MODULE_GLOBALS(myext)
        unsigned long counter;
        char * global_ini_string;
        char * global_ini_long;
    ZEND_END_MODULE_GLOBALS(myext)
    
    PHP_INI_BEGIN()
    PHP_INI_ENTRY("myext.ini_string","我是ini的字符串",PHP_INI_ALL,myext_example_ini_callback)
    PHP_INI_ENTRY("myext.ini_long","100",PHP_INI_ALL,NULL)
    
    STD_PHP_INI_ENTRY("myext.global_ini_string","i am global_ini_string",PHP_INI_ALL,OnUpdateString, global_ini_string, zend_myext_globals, myext_globals)
    STD_PHP_INI_ENTRY("myext.global_ini_long","10000",PHP_INI_ALL,OnUpdateLong, global_ini_long, zend_myext_globals, myext_globals)
    PHP_INI_END()   
    
    PHP_FUNCTION(myext_example_ini){
        const char * ini_string = INI_STR("myext.ini_string");
        long ini_long = INI_INT("myext.ini_long");
        php_printf("ini_string => %s
    ",ini_string);
        php_printf("ini_long => %ld
    ",ini_long);
        const char * orig_ini_string = INI_ORIG_STR("myext.ini_string");
        long orig_ini_long = INI_ORIG_INT("myext.ini_long");
        php_printf("orig_ini_string => %s
    ",orig_ini_string);
        php_printf("orig_ini_long => %ld
    ",orig_ini_long);
    
        php_printf("global_ini_string => %s
    ",MYEXT_G(global_ini_string));
        php_printf("global_ini_long => %ld
    ",MYEXT_G(global_ini_long));
    }
    
    /*
    这个地方有点问题,会导致php段错误,回头再查一下
    */
  • 相关阅读:
    Irrlicht_0.1源码学习(3)—Irrlicht.cpp & include/Irrlicht.h
    Irrlicht_0.1源码学习(2)—引擎目录结构
    Irrlicht_0.1源码学习(1)—Welcome to the Irrlicht Engine
    Visual Studio 2013 编译时 "error LNK2026:模块对于 SAFESEH 映像是不安全的" 解决方案
    Windows平台下Lua环境的搭建
    系统调用与API
    前端学习技巧分享
    简单的bootstarp项目实例
    js显示表单的提交验证
    拷贝一张图片,从一个目录到另外一个目录下(PS:是拷贝是不是移动)
  • 原文地址:https://www.cnblogs.com/wuhen781/p/6241321.html
Copyright © 2020-2023  润新知