php / php-src

The PHP Interpreter
https://www.php.net
Other
38.15k stars 7.74k forks source link

Feature Request: new `phpinfo_array()` function #16560

Open bkdotcom opened 3 days ago

bkdotcom commented 3 days ago

Description

phpinfo() contains a fair amount of information that is only obtainable via phpinfo()

phpinfo() outputs as either plain-text or html depending on if called via CLI or web process

To obtain a value, one must wrap phpinfo in ob_start() and then parse the text or html that it returns, or extract the specific desired value(s)

A new phpinfo_array() function that returns the "raw" information would be helpful

return

array(
    INFO_GENERAL => array(
        'PHP Version' => '8.5.0-dev',
        'System' => string,
        'Build Date' => string,
        ...
        //  this license info is output as a "keyless" value as text/html... assigned to "info" here
        'info' => 'This program makes use of the Zend Scripting Language Engine:.... ',
    ),
    INFO_CREDITS => array(
        'PHP Group' => string,
        'Language Design & Concept' => string,
        'PHP Authors' => array(
            'Zend Scripting Language Engine' => string,
            'Extension Module API' => string,
            ...
        ),
        ...
    ),
    INFO_CONFIGURATION => array(
        'allow_url_fopen' => ['On', 'On'],
        ...
    ),
    INFO_MODULES => array(
        //    all module keys lowercase for consistancy
        'bcmath' => array(
            'BCMath support' => enabled,
            'bcmath.scale' => ['0', '0'],
            ...
         ),
        ...
        'phar' => array(
            'Phar: PHP Archive support' => 'enabled',
            ...
           // phar, xdebug, and others output "keyless" "information/license/disclaimer".   I've assigned to "info" here
            'info' => 'Phar based on pear/PHP_Archive, original concept by Davey Shafik. Phar fully realized by Gregory Beaver and Marcus Boerger. Portions of tar implementation Copyright (c) 2003-2009 Tim Kientzle.'
            ...
            'phar.cache_list' => [null, null], //   html and text output 'no value'
            ...
        ),
        'additional modules' => [], // list of lowercase strings 
    ),
    INFO_ENVIRONMENT => array(
        'TERM_PROGRAM' => string,
        ...
    ),
    INFO_VARIABLES => array(
         //   the values...    not the flattened /+print_r output that text/html gives
         '$_COOKIE' => array(),
         '$_SERVER' => array(),
         ....
    ),
    INFO_LICENSE => string,
)

If a single category flag is passed to phpinfo_array(), the topmost category level keys could be omitted

phpinfo_array(INFO_GENERAL)

return

array(
    'PHP Version' => '8.5.0-dev',
    'System' => string,
    'Build Date' => string,
    ...
),
NattyNarwhal commented 3 days ago

What data are you interested in from phpinfo? Some of the critical ones are available as constants at runtime.

iluuu1994 commented 3 days ago

This would be a relatively big change, given phpinfo() is currently entirely hard-coded to print the given information in HTML or text form. I'm guessing the easier approach is if you elaborate which information is missing, so that it can be exposed as usual. (@NattyNarwhal beat me to it)

bkdotcom commented 3 days ago

In my current use-case I'm simply after the "Build Date" (output with phpinfo(INFO_GENERAL)) Noticed that most of the comments on phpinfo's documentation are poorly implemented parsers... that only parse the html output

to get build date:

\ob_start();
\phpinfo(INFO_GENERAL);
$phpInfo = \ob_get_clean();
$phpInfo = \strip_tags($phpInfo);
\preg_match('/Build Date (?:=> )?([^\n]*)/', $phpInfo, $matches);
$buildDate = $matches[1];

Nice to have: $buildDate = phpinfo_array(INFO_GENERAL)['Build Date'];

cmb69 commented 3 days ago

Nicer to have:

$buildDate = PHP_BUILD_DATE;
bkdotcom commented 2 days ago

On the topic of build date:

php -v

PHP 8.3.10 (cli) (built: Aug 1 2024 08:18:25) (NTS)

php -i | grep "Build Date"

Build Date => Aug 1 2024 08:16:34

^ 111 second discrepency


php -v

PHP 8.4.0-dev (cli) (built: Oct 18 2024 00:15:08) (NTS)

php -i | grep "Build Date"

Build Date => Oct 18 2024 00:13:23

^ 105 second discrepency

NattyNarwhal commented 2 days ago

I believe it's because it just uses __DATE__ and __TIME__, which are set for each translation unit separately. Since phpinfo lives in info.c and -v lives in main/main.c, if there's any disparity between when it compiles those files, it'll show up.

% git grep __DATE__  
Zend/zend_system_id.c:          PHP_MD5Update(&context, __DATE__, sizeof(__DATE__)-1);
ext/standard/info.c:            php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
main/main.c:            PHP_VERSION, sapi_module->name, __DATE__, __TIME__,
cmb69 commented 2 days ago
 ext/standard/info.c |   2 +-
 main/main.c         |   6 ++++--
 main/main.stub.php  |   7 +++++++
 main/main_arginfo.h | Bin 6887 -> 6966 bytes
 main/php.h          |   2 ++
 5 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/ext/standard/info.c b/ext/standard/info.c
index 8a706ef62e..aa03be761c 100644
--- a/ext/standard/info.c
+++ b/ext/standard/info.c
@@ -801,7 +801,7 @@ PHPAPI ZEND_COLD void php_print_info(int flag)
        php_info_print_box_end();
        php_info_print_table_start();
        php_info_print_table_row(2, "System", ZSTR_VAL(php_uname));
-       php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
+       php_info_print_table_row(2, "Build Date", php_build_date);
 #ifdef PHP_BUILD_SYSTEM
        php_info_print_table_row(2, "Build System", PHP_BUILD_SYSTEM);
 #endif
diff --git a/main/main.c b/main/main.c
index 0b38f303c5..0f422fd397 100644
--- a/main/main.c
+++ b/main/main.c
@@ -97,6 +97,8 @@ PHPAPI size_t core_globals_offset;

 #define SAFE_FILENAME(f) ((f)?(f):"-")

+const char php_build_date[] = __DATE__ " " __TIME__;
+
 PHPAPI const char *php_version(void)
 {
    return PHP_VERSION;
@@ -110,8 +112,8 @@ PHPAPI unsigned int php_version_id(void)
 PHPAPI char *php_get_version(sapi_module_struct *sapi_module)
 {
    char *version_info;
-   spprintf(&version_info, 0, "PHP %s (%s) (built: %s %s) (%s)\nCopyright (c) The PHP Group\n%s%s",
-       PHP_VERSION, sapi_module->name, __DATE__, __TIME__,
+   spprintf(&version_info, 0, "PHP %s (%s) (built: %s) (%s)\nCopyright (c) The PHP Group\n%s%s",
+       PHP_VERSION, sapi_module->name, php_build_date,
 #ifdef ZTS
        "ZTS"
 #else
diff --git a/main/main.stub.php b/main/main.stub.php
index b5f848dacc..3359d4a1cd 100644
--- a/main/main.stub.php
+++ b/main/main.stub.php
@@ -34,6 +34,13 @@
  * @cvalue PHP_VERSION_ID
  */
 const PHP_VERSION_ID = UNKNOWN;
+
+/**
+ * @var string
+ * @cvalue php_build_date
+ */
+const PHP_BUILD_DATE = UNKNOWN;
+
 /**
  * @var bool
  * @cvalue PHP_ZTS
diff --git a/main/main_arginfo.h b/main/main_arginfo.h
index 28a7d15f89..f0d2599baf 100644
Binary files a/main/main_arginfo.h and b/main/main_arginfo.h differ
diff --git a/main/php.h b/main/php.h
index c00777a1b4..0859afca93 100644
--- a/main/php.h
+++ b/main/php.h
@@ -272,6 +272,8 @@ END_EXTERN_C()
 extern char **environ;
 #endif /* ifndef PHP_WIN32 */

+extern const char php_build_date[];
+
 #ifdef PHP_PWRITE_64
 ssize_t pwrite(int, void *, size_t, off64_t);
 #endif
$ nmake /nologo run ARGS=-v
          "C:\php-sdk\phpdev\vs17\x64\php-src\x64\Debug\php.exe" -n -c "C:\php-sdk\phpdev\vs17\x64\php-src\x64\Debug\tmp-php.ini" -v
PHP 8.5.0-dev (cli) (built: Oct 24 2024 18:11:24) (NTS Visual C++ 2022 x64 DEBUG)
Copyright (c) The PHP Group
Zend Engine v4.5.0-dev, Copyright (c) Zend Technologies
    with Zend OPcache v8.5.0-dev, Copyright (c), by Zend Technologies

C:\php-sdk\phpdev\vs17\x64\php-src
$ nmake /nologo run ARGS=-i|grep "Build Date"
Build Date => Oct 24 2024 18:11:24

C:\php-sdk\phpdev\vs17\x64\php-src
$ nmake /nologo run ARGS="-r ""var_dump(PHP_BUILD_DATE);"""
          "C:\php-sdk\phpdev\vs17\x64\php-src\x64\Debug\php.exe" -n -c "C:\php-sdk\phpdev\vs17\x64\php-src\x64\Debug\tmp-php.ini" -r "var_dump(PHP_BUILD_DATE);"
string(20) "Oct 24 2024 18:11:24"