可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is it possible to have PHP stop execution upon a notice/warning, globally?
We run a development server with a lot of sites on, but want to force our developers to fix these warnings/notices (or ask for help with them at least) instead of ignoring and moving on.
回答1:
Yes, it is possible. This question speaks to the more general issue of how to handle errors in PHP. You should define and register a custom error handler using set_error_handler
docs to customize handling for PHP errors.
IMHO it's best to throw an exception on any PHP error and use try/catch blocks to control program flow, but opinions differ on this point.
To accomplish the OP's stated goal you might do something like:
function errHandle($errNo, $errStr, $errFile, $errLine) {
$msg = "$errStr in $errFile on line $errLine";
if ($errNo == E_NOTICE || $errNo == E_WARNING) {
throw new ErrorException($msg, $errNo);
} else {
echo $msg;
}
}
set_error_handler('errHandle');
The above code will throw an ErrorException
any time an E_NOTICE
or E_WARNING
is raised, effectively terminating script output (if the exception isn't caught). Throwing exceptions on PHP errors is best combined with a parallel exception handling strategy (set_exception_handler
) to gracefully terminate in production environments.
Note that the above example will not respect the @
error suppression operator. If this is important to you, simply add a check with the error_reporting()
function as demonstrated here:
function errHandle($errNo, $errStr, $errFile, $errLine) {
if (error_reporting() == 0) {
// @ suppression used, don't worry about it
return;
}
// handle error here
}
回答2:
You can globally configure this within your php.ini fileDocs.
You do this by specifying a file that is being included by all PHP processes with the auto_prepend_file
directiveDocs:
auto_prepend_file "/full/path/to/a/prepend-file.php"
Doing that inside you global php.ini file will ensure that the code inside the prepend file will be always exectued. You can use it then to register a global error handler that will turn all errors into exceptionsDocs:
<?php
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");
This little script will turn all errors/warnings/notices etc. into an ErrorException
.
Combine it with the error_reporting
ini directiveDocs, the values are describe in your php.ini file.
Throwing an exception is a very strict thing. Your programmers will be forced to deal with warnings and errors otherwise the code won't not work.
Probably this is too much for your programmers and not socially acceptable within your company. Instead you can also log all errors and add them at the end of the output (or at the top so it's more visible) by making use of output buffering.
Another alternative is to log errors and warnings to the logfile and then monitor that file with another process and aggregate the information. You could create a scoreboard that display the number of warnings per application and make this visible in the office so everybody sees how well a team performs or some fun like that.
What I try to say is: Next to the technical problem, it's a social problem you need to be creative with and actually talk the problem out of your developers. You need to make clear why it's important to fix warnings and errors and how their coding and skills will benefit from that.
回答3:
As of PHP 5.3.0:
set_error_handler(
function(int $nSeverity, string $strMessage, string $strFilePath, int $nLineNumber){
if(error_reporting()!==0) // Not error suppression operator @
throw new \ErrorException($strMessage, /*nExceptionCode*/ 0, $nSeverity, $strFilePath, $nLineNumber);
},
/*E_ALL*/ -1
);
回答4:
If you are in a development environment, you might consider installing the module Xdebug and set xdebug.halt_level=E_WARNING|E_NOTICE|E_USER_WARNING|E_USER_NOTICE
somewhere in your PHP ini files. The developer can reset xdebug.halt_level
, but we have the same issue with the answer based on set_error_handler
, because we can restore the handler to its original value.
回答5:
The other solutions implement a custom error handler which overrides the default error logging mechanism. That means when we set a custom error handler, the notice / warning is not printed anymore in the default way, so we change more than just "stop script execution upon notice / warning".
However, I needed a way to still print the message - in my case in PHP CLI - since the output is then parsed by another program. So I didn't want to print the message in some way but in the exact same way than PHP usually does it. I just wanted to stop the PHP CLI process with an exit code of != 0
right after a notice / warning was printed, and do not change anything else.
Unfortunately, there does not seem to be a default way of exiting the script without changing the whole error handling. So I needed to reimplement the default error handler (which is implemented in C) in PHP.
For this, I looked into the default error printing mechanism in PHP's source code and ported the relevant pieces from C to PHP to get the following error handler, which I want to share with you in case you need something similar:
set_error_handler(
function($errNo, $errStr, $errFile, $errLine) {
$error_type_str = 'Error';
// Source of the switch logic: default error handler in PHP's main.c
switch ($errNo) {
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
$error_type_str = "Fatal error";
break;
case E_RECOVERABLE_ERROR:
$error_type_str = "Recoverable fatal error";
break;
case E_WARNING:
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_USER_WARNING:
$error_type_str = "Warning";
break;
case E_PARSE:
$error_type_str = "Parse error";
break;
case E_NOTICE:
case E_USER_NOTICE:
$error_type_str = "Notice";
break;
case E_STRICT:
$error_type_str = "Strict Standards";
break;
case E_DEPRECATED:
case E_USER_DEPRECATED:
$error_type_str = "Deprecated";
break;
default:
$error_type_str = "Unknown error";
break;
}
fwrite(STDERR, "PHP $error_type_str: $errStr in $errFile on line $errLine\n");
exit(1);
},
E_ALL
);
回答6:
You can turn on the error_reporting to E_ALL in PHP Configuration file of your server.
In PHP 5 a new error level E_STRICT is available. As E_STRICT is not included within E_ALL you have to explicitly enable this kind of error level. Enabling E_STRICT during development has some benefits. STRICT messages will help you to use the latest and greatest suggested method of coding, for example warn you about using deprecated functions.
Reference: PHP Configuration Manual
The following settings guide you to output all the errors in a script. Please note that these will need to be included in the start of all your script files.
<?php
// Turn off all error reporting
error_reporting(0);
// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings ...)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// Report all errors except E_NOTICE
// This is the default value set in php.ini
error_reporting(E_ALL ^ E_NOTICE);
// Report all PHP errors (see changelog)
error_reporting(E_ALL);
// Report all PHP errors
error_reporting(-1);
// Same as error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
?>