I work on a localhost. I have php 5.4.4. I Just read on php.net that since version 5.4 onwards E_STRICT became part of E_ALL.
So, i see in my php.ini file this.
error_reporting = E_ALL
So, i assume, it is the strictest Error reporting mode. So, i make a mistake intentionally to see if this works.
I set $_SESSION key to begin with a numerical value in my code. No error is reported. The program simply runs incorrectly.
I have also set: display_errors = On
So, i assume any error shall be reported in my browser, when the script is run. But, nothing happens.
One of the Fellow, Stackoverflow.com Members, was checking my code and found out the error, because his browser reported the error. But, nothing happens in mine.
You probably have your PHP configured to not output errors to screen, rather logging them to a log file.
That is, you have display_errors set to false, and log_errors set to true .
That is the common configuration for production websites, not echoing errors to screen (which could reveal important info for an attacker) but writing them to the web server log.
I suggest you install a global error handler, and do some formatting there, to get a nice result:
set_error_handler( 'error_handler' );
function error_handler( $errno, $errmsg, $filename, $linenum, $vars )
{
// error was suppressed with the #-operator
if ( 0 === error_reporting() )
return false;
printf( "Unrecoverable error in `%s' line %s: %s\n\n", $filename, $linenum, $errmsg );
exit( $errno );
}
The problem is a bit hard to track. If you want to see the actual error message with display errors, you have to keep the following in mind:
The display_errors directive works only as long as there is some display it could output to.
Normally the session is saved on disk at a time when your script has already finished and there is no output associated any longer to it.
Therefore you can not make the following notice visible with that setting:
Notice: Unknown: Skipping numeric key 0 in Unknown on line 0
The in Unknown on line 0 is a sign that this is not the normal PHP code. It's just when the PHP engine shuts down and saves the session data.
So you can never get this error message onto your display unless:
You track the error log or use the CLI environment which still has an output in shutdown phase (STDOUT)
You use session_write_close() to write the session while your script still runs:
Notice: session_write_close(): Skipping numeric key 0 in ... on line 12
Hope this helps and clarifies it fully.
Related
I have a PHP REST API endpoint that throws an error:
PHP message: PHP Fatal error: Uncaught Exception: Accessing static property...as non static in...
with the default error_reporting value but returns a correct value if error_reporting is set to 1, which I believe is E_ERROR.
Doesn't error_reporting just control the logging? This seems to control whether the exception is thrown as well, allowing the code to continue as normal.
I come from a Java background, used to using Logback and similar logging frameworks. In these frameworks, the log level refers to a filter for the recipient of the logs, commonly a log file. A log level X means that messages need to be at least level X (or lower than, I forget which) to be logged, but it doesn't affect whether the exception is thrown to begin with.
I had assumed that this was the case with PHP's error_reporting, however, based on the above behavior I am not sure.
I've looked through the PHP docs, but I haven't found a detailed explanationof how error_reporting works
So, my question: What does "reporting" mean here? Does error_reporting control more besides which exceptions/errors are logged?
error_reporting is a bit different with the log level, the argument is a set of toggles for each error type.
For example error_reporting(E_ERROR) only reports errors and error_reporting(E_NOTICE) only reports notices and error_reporting(E_ERROR|E_NOTICE) reports both errors and notices but doesn't report warnings.
FYI the error level of this message "Accessing static property...as non static in..." is E_STRICT in PHP 5 and E_NOTICE in PHP 7 by default.
This is weired because you got an exception, I guess the problem that changes the behaviour of the error is in your error handler.
I'm using NGINX with PHP-FPM in seperated Docker containers. I want to get errors only to stderr, so that I can collect them on a centralized log-server. Problem is: I'm using WP and seems to have some not well written plugins. They work but cause warnings like this:
2017/06/17 01:16:08 [error] 7#7: *1 FastCGI sent in stderr: "PHP
message: PHP Warning: Parameter 1 to wp_default_scripts() expected to
be a reference, value given in /www/wp-includes/plugin.php on line 601
Example script for testing, which should give me a fatal error in the stderr:
<?php
not_existing_func();
PHP-FPM was configured to log errors to stderr like this:
[global]
log_level = error
error_log = /proc/self/fd/2
I'm wondering that this gave me nothing in the script above. Just after I switched the log_level to at least notice, I got the exception on the console of the docker container:
[17-Jun-2017 01:45:35] WARNING: [pool www] child 8 said into stderr:
"NOTICE: PHP message: PHP Fatal error: Uncaught Error: Call to
undefined function not_existing_func() in /www/x.php:2"
Why the hell is this a notice? For me we've clearly a fatal error here like the message indicates, cause the script can't continue (and we get a 500 error in the browser, of course). It can't be true that I have to set log_level to notice so that I don't miss fatal errors which are delcared as warnings. And simultaneously, my logs get filled with trash warnings from wordpress themes, plugins and so on, that I haven't developed and I don't want to fix for update reasons...
I tried a bit and found out that log_errors in php.ini is essential for PHP-FPM to get any information. But the log level from error_reporting seems wired too. For testing purpose, I used the following configuration:
display_errors = Off
log_errors = On
error_log = /proc/self/fd/2
;error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR
error_reporting = 0
Result: I got notices, but NO info about my fatal error...
First of all, I learned that I was wrong: Wordpress is the root cause for this issue, not PHP directly. It's a known fact that WP manipulates the error_reporting when debugging is enabled, so I tried to define WP_DEBUG as false in my config; BUT even having this set, the documentation says
[...]
Except for 'error_reporting', WordPress will set this to 4983 if WP_DEBUG is defined as false.
[...]
So my settings into php.ini were correct and sufficient. I don't even need the php-fpm settings, when errors are redirected to stdout in the php.ini file.
How to prevent WordPress from manipulating the error reporting?
This is not so easy, too. Although the WordPress documentation says, that the wp-config.php is a good place to set global wide settings like the error reporting, they got overwritten later to 4983. I don't know where; maybe it's not even the Core of Wordpress, but rather some poor developed plugin or theme.
We can handle this by adding error_reporting to the disabled functions:
disable_functions = error_reporting
Now it's not possible to overwrite our error_reporting. I think this is the best solution to make sure that we don't get any other error reporting by external influence from plugins or themes. Also in the future, since PHP allows such chaos, we need to reckon with such things.
Basically, we could criticize that this prevent us from getting more logs by setting WP_DEBUG to true, that's right, but as we're on a production system, it seems wrong for me to do troubleshooting in such a way there. We shouldn't do this on an application base, especially without display_errors! Instead, the workflow to find problems should be to look at the error logs.
Fatal errors should always be logged and checked on a regular basis. If that is not enough, error_reporting could be set on a higher level to get information about possible problems like warnings.
in my php.ini the display_errors setting is set to Off by standard. Usually I started my index.php file with
ini_set('display_errors', 'On');
error_reporting(E_ALL & ~E_NOTICE);
which all worked fine for my needs.
Recently, the error reporting did not work anymore. notices have been thrown out though, so:
<?php echo $i ?>
throws a notice "undefined constant"
<?php badbadbad ?>
simply returns a blank page instead of a Fatal Error message.
Checking phpinfo() shows that the Master value for display_errors is Off, while the local value is set to On (as expected). Nevertheless I could not get any error message.
Changing my php.ini setting for display_errors = On gets me around this issue, but should not be a solution for ever.
Any hints?
Thanks & brgds
David
I think the reason your second example fails is that it's actually a Parse Error.
When executing code, PHP has to first parse and compile the whole file it's going to execute and then only after that it can run it. If there's a problem during parsing, even if the problem is at the end of the file, none of the file's code will be executed -- so neither will your ini_set() and error_reporting() statements.
If the erroneous code is in the same file as said statements, there's not much you can do. If it's in another file that is used with include or require, make sure that the including calls are made after setting the new error reporting values. At least that works for me with PHP >= 5.4.
I don't get any PHP error, just get a white page on Firefox, and
Server error
The website encountered an error while retrieving http://example.com/pruebas/prov.php. It may be down for maintenance or configured incorrectly
on Chrome.
This is the code:
if (!ini_get('display_errors')) {
ini_set('display_errors', 1);
}
echo "hola"
echo "hola2";
I intentionally made mistake in the echo "hola" (there's no ';').
I also tried adding to the end of my .htaccess file -> suPHP_ConfigPath /home/username/public_html replacing username with my current username, and then I created a php.ini in public_html with "display_errors = on;". But I'm still not able to get any PHP error.
Your script is dying due to the syntax error before it ever executes, so the ini_set() call is never executed and never takes effect. You'd have to change the setting in the appropriate php.ini.
The actual error message may be in a log file somewhere. Try Apache's error_log, or see if PHP's logging somewhere else.
Make sure that you also have the appropriate error_reporting ini value set as well. You can find more information on PHP.net
Set the error reporting level. The parameter is either an integer representing a bit field, or named constants. The error_reporting levels and constants are described in Predefined Constants, and in php.ini. To set at runtime, use the error_reporting() function. See also the display_errors directive.
In PHP 4 and PHP 5 the default value is E_ALL & ~E_NOTICE. This setting does not show E_NOTICE level errors. You may want to show them during development.
Source
Make sure the display_errors is set to on on your php.ini file.
Please tell me if this is correct. In my error handler, I need to be able to detect when the # error-control operator was used to suppress errors, because some external libraries (sadly) use it a lot. Execution of the script should continue, just like when you don't use custom error handlers.
When the at-sign is used, PHP temporarily sets error_reporting to 0. So at the start of a script we set error_reporting to any value but zero - we can now do some beautiful IF/ELSE magic. To avoid any errors being shown at the frontend, we also set display_errors to 0, this will override error_reporting (but we can still use it's value for magic).
<?php
ini_set('display_errors',0);
error_reporting(E_ALL);
function error_handler($errno, $errstr, $errfile, $errline)
{
if (error_reporting()===0) return;
else die();
}
set_error_handler('error_handler');
//This issues an error, but the handler will return and execution continues.
//Remove the at-sign and the script will die()
#file();
echo 'Execution continued, hooray.';
?>
So.. Are there no catches here? Except the one where the external library overrides my error handling.. (any tips on that?)
Considering what your script does, and some user notes on the # operator manual page, it seems what you are doing is OK.
For instance, taras says :
I was confused as to what the # symbol
actually does, and after a few
experiments have concluded the
following:
the error handler that is set gets called regardless of what level the
error reporting is set on, or whether
the statement is preceeded with #
it is up to the error handler to impart some meaning on the different
error levels. You could make your
custom error handler echo all errors,
even if error reporting is set to
NONE.
so what does the # operator do? It temporarily sets the error reporting
level to 0 for that line. If that line
triggers an error, the error handler
will still be called, but it will be
called with an error level of 0
And the set_error_handler manual page seems to confirm that :
Of particular note is that this value will be 0 if the statement
that caused the error was prepended by the # error-control operator.
Here too, there are some user notes that can be useful ; for instance, this one (see the begining of the code)
Still, if what you want is to "disable" the effect of the # operator (not sure I understood the question correctly ; this might help you anyway), to be able to get the error messages while you are on your development environment, you can install the scream extension (pecl, manual)
Provided you configure it the right way, setting this in your php.ini (after installating/loading the extension, of course) :
scream.enabled = 1
This extension will simply disable the # operator.
And here's an example (quoting the manual) :
<?php
// Make sure errors will be shown
ini_set('display_errors', true);
error_reporting(E_ALL);
// Disable scream - this is the default and produce an error
ini_set('scream.enabled', false);
echo "Opening http://example.com/not-existing-file\n";
#fopen('http://example.com/not-existing-file', 'r');
// Now enable scream and try again
ini_set('scream.enabled', true);
echo "Opening http://example.com/not-existing-file\n";
#fopen('http://example.com/another-not-existing-file', 'r');
?>
And this will output :
Opening http://example.com/not-existing-file
Opening http://example.com/not-existing-file
Warning: fopen(http://example.com/another-not-existing-file): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in example.php on line 14
I am not sure I would use this extension on a production server (where I never want errors displayed), but it is very useful on a development machine, when using old code, on an application/library that uses # operator extensivly...