您好,欢迎访问一九零五行业门户网

PHP如何自定义扩展(二)之钩子功能

php自定义扩展(二)接着上篇来讲php生命周期,看看扩展哪些钩子做哪些事,php生命周期大概5个阶段,模块初始化阶段php_module_startup,请求初始化阶段php_request_startup,脚本执行阶段php_execute_script,请求关闭阶段php_request_shutdown,模块关闭阶段php_module_shutdown,下面以cli模式介绍。
php_module_startup
先看看这个阶段做了什么,如果不知道php入口文件在哪,用gdb看看调用栈,gdb ./php
在php_module_startup打断点,执行,在看下调用栈,
b php_module_startup(gdb) r test.phpbtphp_module_startup (sf=0x1406460 <cli_sapi_module>,     additional_modules=0x0, num_additional_modules=0)    at /www/test/php/php-7.4.3/main/main.c:2098#1  0x00000000008bae7c in php_cli_startup (    sapi_module=0x1406460 <cli_sapi_module>)    at /www/test/php/php-7.4.3/sapi/cli/php_cli.c:407#2  0x00000000008bcc80 in main (argc=2, argv=0x1425af0)    at /www/test/php/php-7.4.3/sapi/cli/php_cli.c:1323
在调用栈可以清楚看到执行流程,现在到/main/main.c文件看看做了哪些事情,也可以用gdb一步一步的看,这里就讲与php扩展有关的几个地方,这里做的初始化工作,像垃圾回收,请求初始化,注册常量,php.ini配置文件加载等,
先来看看怎么加载模块的
/* startup extensions statically compiled in */    if (php_register_internal_extensions_func() == failure) {        php_printf(unable to start builtin modules\n);        return failure;    }
这里是加载php内置的模块,这里只贴出核心功能,先检查依赖
/* check module dependencies */    if (module->deps) {        const zend_module_dep *dep = module->deps;        while (dep->name) {            if (dep->type == module_dep_conflicts) {                name_len = strlen(dep->name);                lcname = zend_string_alloc(name_len, 0);                zend_str_tolower_copy(zstr_val(lcname), dep->name, name_len);                if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {                    zend_string_efree(lcname);                    /* todo: check version relationship */                    zend_error(e_core_warning, cannot load module '%s' because conflicting module '%s' is already loaded, module->name, dep->name);                    return null;                }                zend_string_efree(lcname);            }            ++dep;        }    }
if (module->functions && zend_register_functions(null, module->functions, null, module->type)==failure) {        zend_hash_del(&module_registry, lcname);        zend_string_release(lcname);        eg(current_module) = null;        zend_error(e_core_warning,%s: unable to register functions, unable to load, module->name);        return null;    }
这是内置模块加载原理,现在看看ini里的扩展怎么加载
php_ini_register_extensions();
zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb);
利用这个函数加载
php_load_extension(char *filename, int type, int start_now)
这里面也执行了加载内置模块的功能。
是调用了module->functions,进行模块功能函数注册,现在知道了为什么功能函数要写在helloworld_functions这里吧
zend_module_entry helloworld_module_entry = {    standard_module_header,    helloworld,                    /* extension name */    helloworld_functions,            /* zend_function_entry */    php_minit(helloworld),                            /* php_minit - module initialization */    null,                            /* php_mshutdown - module shutdown */    php_rinit(helloworld),            /* php_rinit - request initialization */    null,                            /* php_rshutdown - request shutdown */    php_minfo(helloworld),            /* php_minfo - module info */    php_helloworld_version,        /* version */    php_module_globals(pib),    null,    null,    null,    standard_module_properties_ex};
现在看看扩展的几个钩子函数
/* start zend extensions */    zend_startup_extensions();
这里的核心就是func(element->data)也就是执行扩展
php_minit函数
element=l->head;    while (element) {        next = element->next;        if (func(element->data)) {            del_llist_element(element, l);        }        element = next;    }
现在就知道php_minit钩子可以做很多初始化的功能,怎么注册一个自定义扩展的功能类,怎么把扩展的变量写到php.ini里面,怎么重写php内置函数,
original = zend_hash_str_find_ptr(cg(function_table), var_dump, sizeof(var_dump)-1);    if (original != null) {        original->internal_function.handler = my_overwrite_var_dump;    }    zend_class_entry person;    init_class_entry(person,class_name,person_functions);    zend_register_internal_class_ex(&person,null);
这里就是重写var_dump函数,注册了一个person类,先介绍到这里,下篇就介绍怎么把php代码通过词法分析语法分析生成ast,然后编译opcode指令,供zend虚拟机调用。
推荐学习:《php视频教程》
以上就是php如何自定义扩展(二)之钩子功能的详细内容。
其它类似信息

推荐信息