|
| 1 | +Publishing extension informations |
| 2 | +================================= |
| 3 | + |
| 4 | +Extensions can publish informations asked by ``phpinfo()`` or the Reflection API. Let's see that together. |
| 5 | + |
| 6 | +This chapter won't be too long as there is really no difficulty. |
| 7 | + |
| 8 | +MINFO() hook |
| 9 | +------------ |
| 10 | + |
| 11 | +Everything takes place in the ``MINFO()`` hook you declared, if you declared one. If you declared none, then the engine |
| 12 | +will run a default function to print informations about your extension. That function will only print the version of |
| 13 | +your extension and the :doc:`INI entries <ini_settings>` you eventually declared. If you want to hook into such |
| 14 | +process, you must declare an ``MINFO()`` :doc:`hook <php_lifecycle>` in your extension structure. |
| 15 | + |
| 16 | +.. note:: Everything takes place in `ext/standard/info.c <https://github.com/php/php-src/blob/ |
| 17 | + ce64b82ebb2ac87e53cb85c312eafc8c5c37b112/ext/standard/info.c>`_ , you may read that file. Printing |
| 18 | + information about PHP extensions is done by the engine by calling `php_info_print_module() |
| 19 | + <https://github.com/php/php-src/blob/ce64b82ebb2ac87e53cb85c312eafc8c5c37b112/ext/standard/info.c#L139>`_ |
| 20 | + |
| 21 | +Here is a simple ``MINFO()`` example:: |
| 22 | + |
| 23 | + #include "php/main/SAPI.h" |
| 24 | + #include "ext/standard/info.h" |
| 25 | + |
| 26 | + PHP_MINFO_FUNCTION(pib) |
| 27 | + { |
| 28 | + time_t t; |
| 29 | + char cur_time[32]; |
| 30 | + |
| 31 | + time(&t); |
| 32 | + php_asctime_r(localtime(&t), cur_time); |
| 33 | + |
| 34 | + php_info_print_table_start(); |
| 35 | + php_info_print_table_colspan_header(2, "PHPInternalsBook"); |
| 36 | + php_info_print_table_row(2, "Current time", cur_time); |
| 37 | + php_info_print_table_end(); |
| 38 | + |
| 39 | + php_info_print_box_start(0); |
| 40 | + if (!sapi_module.phpinfo_as_text) { |
| 41 | + php_write(PIB_HTML, strlen(PIB_HTML)); |
| 42 | + } else { |
| 43 | + php_write(PIB_TXT, strlen(PIB_TXT)); |
| 44 | + } |
| 45 | + php_info_print_box_end(); |
| 46 | + } |
| 47 | + |
| 48 | + zend_module_entry pib_module_entry = { |
| 49 | + STANDARD_MODULE_HEADER, |
| 50 | + "pib", |
| 51 | + NULL, /* Function entries */ |
| 52 | + NULL, /* Module init */ |
| 53 | + NULL, /* Module shutdown */ |
| 54 | + NULL, /* Request init */ |
| 55 | + NULL, /* Request shutdown */ |
| 56 | + PHP_MINFO(pib), /* Module information */ |
| 57 | + "0.1", /* Replace with version number for your extension */ |
| 58 | + STANDARD_MODULE_PROPERTIES |
| 59 | + }; |
| 60 | + |
| 61 | +.. image:: ./images/php_minfo.png |
| 62 | + :align: center |
| 63 | + |
| 64 | +What you basically have to do is to deal with ``php_info_print_*()`` API, that allows to print into the output stream |
| 65 | +that is generated. If you want to print some raw informations, a simple ``php_write()`` is enough. ``php_write()`` just |
| 66 | +writes what you pass as argument onto the SAPI output stream, whereas ``php_info_print_*()`` API does as well, but |
| 67 | +before formats the content using HTML *table-tr-td* tags if the output is expected to be HTML, or simple spaces if not. |
| 68 | + |
| 69 | +Like you can see, you need to include *ext/standard/info.h* to access the ``php_info_print_*()`` API, and you will need |
| 70 | +*php/main/SAPI.h* to access the ``sapi_module`` symbol. That symbol is global, it represents the current *SAPI* used by |
| 71 | +the PHP process. The ``phpinfo_as_text`` field inform if you are going to write in a "Web" SAPI like *php-fpm* f.e, or |
| 72 | +in a "text" one, like *php-cli*. |
| 73 | + |
| 74 | +What will trigger your ``MINFO()`` hook are : |
| 75 | + |
| 76 | +* Calls to userland ``phpinfo()`` function |
| 77 | +* ``php -i``, ``php-cgi -i``, ``php-fpm -i``. More generaly ``<SAPI_binary> - i`` |
| 78 | +* ``php --ri`` or userland ``ReflectionExtension::info()`` |
| 79 | + |
| 80 | +.. note:: Take care of the output formating. Probe for ``sapi_module.phpinfo_as_text`` if you need to change between |
| 81 | + text and HTML formatting. You don't know how your extensions' infos will be called by userland. |
| 82 | + |
| 83 | +If you need to display your INI settings, just call for the ``DISPLAY_INI_ENTRIES()`` macro into your ``MINFO()``. This |
| 84 | +macro resolves to `display_ini_entries() |
| 85 | +<https://github.com/php/php-src/blob/4903f044d3a65de5b1c457d9eb618c9e247f7086/main/php_ini.c#L167>`_. |
| 86 | + |
| 87 | +A note about the Reflection API |
| 88 | +------------------------------- |
| 89 | + |
| 90 | +The Reflection heavilly uses your ``zend_module_entry`` structure. For example, when you call |
| 91 | +``ReflectionExtension::getVersion()``, the API just reads the version field of your ``zend_module_entry`` structure. |
| 92 | + |
| 93 | +Same to discover functions, your ``zend_module_entry`` has got a ``const struct _zend_function_entry *functions`` member |
| 94 | +which is used to register PHP functions. |
| 95 | + |
| 96 | +Basically, the PHP userland Reflection API just reads your ``zend_module_entry`` structure and publishes those |
| 97 | +informations. It may also use your ``module_number`` to gather back informations your extension registered at different |
| 98 | +locations against the engine. For example, ``ReflectionExtension::getINIentries()`` or |
| 99 | +``ReflectionExtension::getClasses()`` use this. |
0 commit comments