Is there a way to determine, via enhanced error log message or output variable, the value of the CORE PHP DIRECTIVES' values used at run-time? This would be identical to a phpinfo() output for each error.
A basic example is the error_reporting variable. If the /etc/php.ini value is set at x, and the phpinfo() states that that php.ini file is in-fact the intended source of the ini variables. But if a user implements a run-time adjustment to that variable in their code, are we able to output the error_reporting variable at the time when an error is thrown.
Such as when the php.ini file has E_ALL & ~E_STRICT but E_STRICT errors are being reported in the log files, it would be great to have a way to enhance the output to the logfile that shows the "stacktrace" of all the system variables active, or at least modified, and their source for each error reported, perhaps via an error-id added to the httpd log that corresponds to an optional file that shows those run-time settings at the time of the error.
I do realize that a try/catch could be used for this, but I don't believe that could be implemented in practicality for a large deployment of mixed 3rd party code.
Does such a mechanism exist in PHP, or has anyone developed one (google says not likely)? This could be vary valuable for many other cases of errors, by helping expedite the merging of code-bases through relativity of variable settings to error message.
I hope that I'm just looking at this wrong and there is an easy fix I'm missing.
Thanks!
The ini_set() function allows you to change system attributes that affect the way your script is executed. Changes only affect the current script, and will revert back when the script ends. To use ini_set() , pass it the value you want to change as its first parameter, and the new value to use as its second parameter.
The phpinfo() function can be used to output a large amount of information about your PHP installation and can be used to identify installation and configuration problems. To run the function, just create a new file called test. php and place it into the root directory of your web server.
Check PHP Version by Running PHP Codephp echo 'PHP version: ' . phpversion(); Create the file using a text editor like gedit or Notepad, and upload it to your website's document root directory. Note: While phpinfo() is useful for debugging, the page features sensitive information about your system.
As we mentioned in Step 2, because your phpinfo. php file was placed in your public_html folder, it's now publically available.
I finally have a fully working example with "pecl runkit" as I had trouble installing apd
on a fresh distrib (it's an old library).
You can install runkit
it with PECL:
pecl install runkit
and add the following lines in your php.ini:
extension=runkit.so
runkit.internal_override=1
I forgot to mention that error_reporting
can be defined in different way using error_reporting()
function or ini_set
. So we have to care about each function.
First we copy the old ini_set
using runkit_function_copy
and then we redefine it using runkit_function_redefine
I use debug_bactrace(1)
to get the calling file and line number.
And finally to catch both non-fatal and fatal error, we have to use set_error_handler
and register_shutdown_function
.
The following code will output, after an error, where ini_set
was called and the filename/line.
Error (type=2): Division by zero in file /var/www/html/test.php line 47
INI SET stack
- error_reporting was defined here (in order):
- /var/www/html/test.php, line 16, value: 0
- /var/www/html/test.php, line 17, value: 2
- /var/www/html/test.php, line 18, value: 1
- /var/www/html/test.php, line 19, value: 32767
Code:
<?php
runkit_function_copy("ini_set", "old_ini_set");
runkit_function_redefine("ini_set", '$key,$value', '
global $iniset;
$trace=debug_backtrace(1);
$iniset[$key][]=$trace[0];
old_ini_set($key, $value);');
runkit_function_redefine("error_reporting", '$value', '
global $iniset;
$trace=debug_backtrace(1);
$iniset["error_reporting"][]=$trace[0];
old_ini_set($key, $value);');
// let test now
ini_set("error_reporting", 0);
ini_set("error_reporting", E_WARNING);
error_reporting(E_ERROR);
ini_set("error_reporting", E_ALL);
set_error_handler("custom_error_handler");
register_shutdown_function("custom_error_handler");
function custom_error_handler($errno=NULL, $errstr=NULL) {
global $iniset;
if (!($error=func_get_args())) {
$error=error_get_last();
if ($error!=E_ERROR) $error=NULL;
}
if ($error) {
echo "Error (type=$error[0]): $error[1]\n
in file $error[2] line $error[3]<br />\n";
echo "INI SET stack<br />\n";
echo "<ul>";
foreach ($iniset as $key=>$val) {
echo "<li>$key was defined here (in order):<ul>";
foreach ($val as $def) {
echo "<li>{$def['file']}, line {$def['line']},
value: ".array_pop($def['args'])."</li>";
}
echo "</li></ul>";
}
echo "</table>";
}
}
// division by 0
12/0;
Previous post:
You can get the value of all local and global configuration options with the ini_get_all()
function.
To retrieve the values of both local and global value, you can set the $details
parameter to true:
ini_get_all(NULL, true);
You can get the value for individual options with the ini_get()
(for runtime value) and get_cfg_var()
(for global php.ini value) functions.
$global_value=get_cfg_var("error_reporting");
$local_value=ini_get("error_reporting");
echo "Error reporting (Local value: $local_value, global value: $global_value)\n"
In order to see those results when an error occurs, you have to catch the errors.
For non fatal errors, you can use set_error_handler()
For fatal errors, you have to define a shutdown_function(), see How do I catch a PHP Fatal Error
You can use error_reporting()
without a parameter to return the current error reporting status. To test for particular features, do something like error_reporting() & (E_STRICT | E_COMPILE_WARNING)
, which would test if E_STRICT
and E_COMPILE_WARNING
are enabled.
If however, you really want that phpinfo()
detail, you can always capture the phpinfo output and log it to the error log (or somewhere else), complete with html formatting. For example:
ob_start();
phpinfo();
error_log(ob_get_clean());
Note that this will only write the phpinfo() to the log, and not output it in the response.
Also, you may want to consider using xdebug. If you're looking for a better stack trace, that may help.
The scope of your question is a bit unclear, so I write what I know about PHP's error handling and give the task making sense out of it back to you.
Part of your question suggest that you are running code that unexpectedly changes the settings from their default values, and you get error types that should have been disabled.
The solution for this would be to not change the settings in the code, and to find those places, there is a tool: PHP Code Sniffer. It has a rule "ForbiddenFunction" that can be customized to find calls to ini_set
, error_reporting
and others.
You'd scan the code for calls to these functions and then analyze why they are there. Simply removing them likely isn't the correct solution, because if code changes error settings, there is a reason. Maybe the code incorrectly sets the value back to the original.
You can register a callback that is executed during regular code execution with register_tick_function. It will be called every number of "ticks", which is the number of low level statements. Effectively, you can make the registered function jump in almost after every regular script statement - note that this will affect run time.
The function itself can try to analyze whatever you like, and react to changes.
You can register your own error and exception handler. set_error_handler accepts a callback that will be called with all information about any error that was triggered (not including fatal errors - if the PHP engine fails e.g. with syntax errors, nothing can be called anymore).
bool handler (
int $errno ,
string $errstr
[, string $errfile
[, int $errline
[, array $errcontext
]]]
)
The function will be called regardless of which setting of error_reporting()
was chosen, but it can also read the setting and ignore calls with disabled errors. So in your case, it could read the global php.ini setting (or get it hardcoded) and ignore all other errors. Or report these errors in a special log file. Returning false
from this function will call the regular error handling, returning true
will go on as if nothing happened.
Access to global variables are possible via the $GLOBALS
array.
Thrown exceptions that are not being catched will be handled by a callback registered with set_exception_handler. The callback will get the exception object, which has everything from message to stack trace.
What about repairing the code? The strict errors are there for a reason: Your code is likely to break when updating PHP. You are not giving details, so this has to be a generic suggestion, but I wonder what is the background of your question. I have a feeling of you asking the wrong question or trying to wipe code problems under the carpet. You can do that, but it will hurt eventually - and if the current situation already hurts, it will hurt even more later. Go for my first suggestion: Find the problems in the code and fix them appropriately. Everything else is not fixing code, but reducing it's error log footprint.
I too encountered this issue recently, so phpinfo()
was showing it had loaded the correct php.ini
but no matter what I do, it just won't use the values I set for the php directives it (PHP) just won't use it.
So I just searched the additional directory /etc/php/7.4/apache2/
for the string key of the directive (memory_limit
in my case) as follows
grep -r 'memory_limit' /etc/php/7.4/apache2/
I found that one of the "Additional .ini files parsed" was overriding my php.ini for that directive. Once I got rid of that override, my changes in php.ini
started reflecting correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With