发布扩展信息

扩展可以通过 phpinfo() 或 Reflection API 发布所需的信息。让我们一起来看看吧。

本章不会太长,因为实际上没有什么难度。

MINFO() 钩子

一切都发生在您声明的 MINFO() 钩子中(如果您声明了一个)。如果您未声明任何内容,则引擎将运行默认函数来打印有关扩展的信息。该函数将仅打印扩展的版本和您最终声明的 INI 条目。如果您想参与此类过程,则必须在扩展结构中声明一个 MINFO() 钩子。

一切都发生在 ext/standard/info.c 中,你可以阅读该文件。打印有关 PHP 扩展的信息由引擎通过调用 php_info_print_module() 来完成。

下面是一个简单的 MINFO() 示例:

#include "php/main/SAPI.h"
#include "ext/standard/info.h"

#define PIB_TXT  "PHPInternalsBook Authors"
#define PIB_HTML "<h3>" PIB_TXT "</h3>"

PHP_MINFO_FUNCTION(pib)
{
    time_t t;
    char cur_time[32];

    time(&t);
    php_asctime_r(localtime(&t), cur_time);

    php_info_print_table_start();
        php_info_print_table_colspan_header(2, "PHPInternalsBook");
        php_info_print_table_row(2, "Current time", cur_time);
    php_info_print_table_end();

    php_info_print_box_start(0);
        if (!sapi_module.phpinfo_as_text) {
            php_write(PIB_HTML, strlen(PIB_HTML));
        } else {
            php_write(PIB_TXT, strlen(PIB_TXT));
        }
    php_info_print_box_end();
}

zend_module_entry pib_module_entry = {
    STANDARD_MODULE_HEADER,
    "pib",
    NULL, /* Function entries */
    NULL, /* Module init */
    NULL, /* Module shutdown */
    NULL, /* Request init */
    NULL, /* Request shutdown */
    PHP_MINFO(pib), /* Module information */
    "0.1", /* Replace with version number for your extension */
    STANDARD_MODULE_PROPERTIES
};
image 2024 07 21 23 17 50 616

您基本上要做的是处理 php_info_print_*() API,该 API 允许打印到生成的输出流中。如果您想打印一些原始信息,一个简单的 php_write() 就足够了。php_write() 只是将您作为参数传递的内容写入 SAPI 输出流,而 php_info_print_*() API 也一样,但如果输出预期为 HTML,则使用 HTML table-tr-td 标签格式化内容,如果不是,则使用简单的空格。

如您所见,您需要包含 ext/standard/info.h 才能访问 php_info_print_*() API,并且您将需要 php/main/SAPI.h 来访问 sapi_module 符号。该符号是全局的,它代表 PHP 进程使用的当前 SAPI。phpinfo_as_text 字段会告知您是要使用 “Web” SAPI(例如 php-fpm f.e)还是 “文本” SAPI(例如 php-cli)进行写入。

触发 MINFO() 钩子的方法是:

  • 调用用户空间的 phpinfo() 函数

  • php -iphp-cgi -iphp-fpm -i。更一般地,<SAPI_binary> - i

  • php --ri 或用户空间的 ReflectionExtension::info()

注意输出格式。如果您需要在文本和 HTML 格式之间切换,请探测 sapi_module.phpinfo_as_text。您不知道用户空间将如何调用扩展的信息。

如果您需要显示 INI 设置,只需在 MINFO() 中调用 DISPLAY_INI_ENTRIES() 宏即可。此宏解析为 display_ini_entries()

关于 Reflection API 的说明

Reflection 大量使用 zend_module_entry 结构。例如,当您调用 ReflectionExtension::getVersion() 时,API 只会读取 zend_module_entry 结构的版本字段。

与发现函数相同,您的 zend_module_entry 有一个 const struct _zend_function_entry *functions 成员,用于注册 PHP 函数。

基本上,PHP 用户空间 Reflection API 只会读取您的 zend_module_entry 结构并发布这些信息。它还可能使用您的 module_number 来收集您在引擎不同位置注册的扩展的信息。例如,ReflectionExtension::getINIentries()ReflectionExtension::getClasses() 使用此结构。