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.
Related
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.
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.
I have question. I have some app on facebook and getting this error
Fatal error: Uncaught OAuthException: An active access token must be used to query
information about the current user. thrown in
/home/xxx/public_html/domain/lib/base_facebook.php on line 1024
but no matter at this time.. the matter is that, is it possible to change/hide this "xxx" name? you understand? for example, instead this I would have /public_html/domain/...
OR completely hide the path ??
thanks in advance =)
The recommended action would be to disable the public display of all PHP errors when you are in production mode.
To do that, edit your php.ini file and set display_errors to 0. You can still set the error_reporting level to something suitable and all errors will be logged to the error_log file, but the actual errors themselves are not visible to the end user.
Otherwise, there is no way to modify PHP's built in error messages to hide the path. Doing so would render the error message much less helpful.
See display_errors and error_reporting PHP directives.
EDIT: In the case of the exact error message in your question, you could handle the error (try/catch) and then display a more friendly error that helps you but also doesn't expose your path. The reason it is displaying like that is because an exception that was thrown was uncaught.
No. If you don't want the complete debug backtrace in case of an uncaught exception, you'll need to catch it every time. There are no shortcuts here.
I have recently taken over development of a legacy system and want to be able to turn on logging of PHP E_NOTICE's on the deployment environment. The deployment environment ini has the following directives...
error_reporting = E_ALL & ~E_DEPRECATED
display_errors = Off
log_errors = On
I have compared the error_reporting bitmask by using echo (E_ALL & ~E_DEPRECATED).' = '.error_reporting();, and both match, so I know the error_reporting level isn't changed within the system itself, and if I turn display_errors = On notices are displayed, but not logged.
So how can I start logging PHP E_NOTICE's?
Update:
According to #m.p.c in the comments on this answer, errors are being displayed in the browser when display_errors is on, but they aren't appearing in the log. I was assuming errors weren't appearing at all.
Are E_NOTICE errors the only ones that aren't appearing in the log, or are all error types affected? If it's all error types, then the first thing I would check is whether or not error logging is even enabled. Try setting ini_set('log_errors', 'On'); at the top of your script. If that doesn't work, then try setting your log file to something you're sure your server can write to by calling ini_set('error_log', 'your_file_path');. If neither of these work, then I think something is seriously wrong with your PHP install. If either of these fixes work, you can put them into your actual php.ini if you have access.
Original Answer:
Based on the error_reporting level in your question, your PHP install should already be setup to report E_NOTICE errors. If it's not logging these errors, something is wrong. I would suggest turning on display_errors to see if any E_NOTICE errors are displayed. If you can't change the php.ini file, try running ini_set('display_errors', 'On'); at the top of your script. Obviously, these errors will only show up and/or be logged if you trigger one, so you should double check that you're actually doing that somewhere.
One caveat is that the E_DEPRECATED error level was only introduced with PHP 5.3. When I just tested setting E_DEPRECATED on a PHP 5.2 install, PHP responded with errors, and set the error_reporting level to 0, which means it reports no errors at all. While it makes no sense for a pre-5.3 php.ini file to use this setting, I feel it's important to at least raise the possibility that you're using E_DEPRECATED on a server that doesn't support it. If you're not sure of your version, you can run phpinfo() and it will display a page with lots and lots of information, including the version number for your install.
Notwithstanding the above, if I've misunderstood your question and you're only talking about creating your own custom logging, then you need to create a function to run when an error occurs and assign it as the error handler using the set_error_handler() function.
It's important to note that when you use set_error_handler(), you bypass PHP's default error handler entirely. This means that your error_handler level becomes meaningless. All errors, regardless of their severity, will be passed to the error handler function you've created. The first parameter passed to this function by PHP will be the error number, which is the numeric value of the E_xxx constant of the error that was found. You'll need to write custom code to catch only the errors you want.
For example, to catch only E_NOTICE errors, your function would look like this:
function my_error_handler($errno, $errstr, $errfile, $errline) {
if ($errno == E_NOTICE) {
// handle/log the error
}
}
set_error_handler("my_error_handler");
Turns out the system has a custom Apache ErrorLog directive defined, and I have been tail -f ... the default Apache error_log.
Note to self: always check the web server setup first before posting silly questions on SO!
You can create your own handler
<?php
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
if ($errno == E_USER_NOTICE){
/* log actions here */
}
}
set_error_handler("myErrorHandler");
Since updating my testing server to PHP 5.3.3 (Debian Squeeze) I encountered strange behaviour regarding the error reporting in PHP.
I set error_reporting like this:
error_reporting(E_ALL);
and checked the setting via
echo error_reporting();
which echoes 30719. According to php.net this means "All errors and warnings, as supported, except of level E_STRICT.".
But in the very next line (a class definition abstract class formInputContainer extends formContainer implements formElementValueable { ... }) this results in the message:
Strict (2048): Declaration of formInputContainer::addElement() should be compatible with that of formContainer::addElement()
Why is the E_STRICT message echoed though it's not set? Even changing to E_ALL & ~E_STRICT does not help.
The reason you're seeing them even though they are not set, is that these are thrown at compile time (well, parse time). That means the errors are triggered before your error_reporting() call is made. The real fix is to change the php.ini setting to remove E_STRICT from the definition. To make sure you're editing the correct file, check phpinfo().
If this is a custom error handler (set via set_error_handler()), you'll have to check the current error_reporting level by yourself. A custom error handler gets all error messages:
The manual says:
It is important to remember that the standard PHP error handler is completely bypassed for the error types specified by error_types unless the callback function returns FALSE. error_reporting() settings will have no effect and your error handler will be called regardless - however you are still able to read the current value of error_reporting and act appropriately.