我如何处理解析&使用自定义错误处理程序错误致命错误?
答案 0 :(得分:68)
实际上你可以处理解析和致命错误。确实,用set_error_handler()定义的错误处理函数不会被调用。这样做的方法是使用register_shutdown_function()定义一个关闭函数。以下是我在我的网站上工作的内容:
文件 prepend.php (此文件将自动添加到所有php脚本中)。有关将文件预先添加到PHP的提示,请参见下文。
set_error_handler("errorHandler");
register_shutdown_function("shutdownHandler");
function errorHandler($error_level, $error_message, $error_file, $error_line, $error_context)
{
$error = "lvl: " . $error_level . " | msg:" . $error_message . " | file:" . $error_file . " | ln:" . $error_line;
switch ($error_level) {
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_PARSE:
mylog($error, "fatal");
break;
case E_USER_ERROR:
case E_RECOVERABLE_ERROR:
mylog($error, "error");
break;
case E_WARNING:
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_USER_WARNING:
mylog($error, "warn");
break;
case E_NOTICE:
case E_USER_NOTICE:
mylog($error, "info");
break;
case E_STRICT:
mylog($error, "debug");
break;
default:
mylog($error, "warn");
}
}
function shutdownHandler() //will be called when php script ends.
{
$lasterror = error_get_last();
switch ($lasterror['type'])
{
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
case E_RECOVERABLE_ERROR:
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_PARSE:
$error = "[SHUTDOWN] lvl:" . $lasterror['type'] . " | msg:" . $lasterror['message'] . " | file:" . $lasterror['file'] . " | ln:" . $lasterror['line'];
mylog($error, "fatal");
}
}
function mylog($error, $errlvl)
{
...do whatever you want...
}
如果他在任何脚本中捕获错误,PHP将调用函数errorHandler()。如果错误强制脚本立即关闭,则错误由函数shutdownHandler()处理。
这正在我正在开发的网站上运行。我还没有在生产中测试它。但它目前正在捕捉我在开发过程中发现的所有错误。
我相信存在两次捕获相同错误的风险,每次执行一次。如果我在函数shutdownHandler()中处理的错误也被函数errorHandler()捕获,则可能发生这种情况。
<强> TODO的:强>
1 - 我需要使用更好的log()函数来优雅地处理错误。因为我还在开发中,所以我基本上将错误记录到数据库并将其回显到屏幕上。
2 - 为所有MySQL调用实现错误处理。
3 - 为我的javascript代码实现错误处理。
重要说明:
1 - 我在php.ini中使用以下行自动将上述脚本添加到所有php脚本中:
auto_prepend_file = "/homepages/45/d301354504/htdocs/hmsee/cgi-bin/errorhandling.php"
效果很好。
2 - 我正在记录并解决所有错误,包括E_STRICT错误。我相信开发一个干净的代码。在开发过程中,我的php.ini文件包含以下行:
track_errors = 1
display_errors = 1
error_reporting = 2147483647
html_errors = 0
当我上线时,我会将display_errors更改为0,以降低用户看到丑陋的PHP错误消息的风险。
我希望这有助于某人。
答案 1 :(得分:30)
您可以使用以下代码跟踪这些错误:
(解析错误只有在其他脚本文件中通过include()
或require()
发生,或者将此代码放入auto_prepend_file
时才会被捕获其他答案都提到了。)
function shutdown() {
$isError = false;
if ($error = error_get_last()){
switch($error['type']){
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
$isError = true;
break;
}
}
if ($isError){
var_dump ($error);//do whatever you need with it
}
}
register_shutdown_function('shutdown');
答案 2 :(得分:27)
简单回答:你做不到。请参阅manual:
以下错误类型不能 使用用户定义的函数处理: E_ERROR,E_PARSE,E_CORE_ERROR, E_CORE_WARNING,E_COMPILE_ERROR, E_COMPILE_WARNING,以及大部分内容 E_STRICT在文件中引发了 调用set_error_handler()。
对于其他每个错误,您都可以使用set_error_handler()
编辑:
由于似乎有关于此主题的讨论,关于使用register_shutdown_function
,我们应该看看处理的定义:对我来说,处理错误意味着捕获错误并做出反应用户和基础数据(数据库,文件,Web服务等)的“好”方式。
使用register_shutdown_function
您无法在调用它的代码中处理错误,这意味着代码仍然会在发生错误时停止工作。但是,您可以向用户显示错误消息而不是白页,但例如,您不能回滚代码在失败之前执行的任何操作。
答案 3 :(得分:11)
来自页面http://www.php.net/manual/en/function.set-error-handler.php
上的PHP.net评论我意识到这里有一些人提到你无法捕获解析错误(类型4,E_PARSE)。这不是真的。这是我的方式。我希望这可以帮助别人。
1)在Web根目录中创建一个“auto_prepend.php”文件并添加:
<?php
register_shutdown_function('error_alert');
function error_alert()
{
if(is_null($e = error_get_last()) === false)
{
mail('your.email@example.com', 'Error from auto_prepend', print_r($e, true));
}
}
?>
2)然后添加这个“php_value 的auto_prepend_file /www/auto_prepend.php“给你的 Web根目录中的.htaccess文件。
- 确保更改电子邮件地址和文件路径。
答案 4 :(得分:5)
根据我的经验,您可以捕获所有类型的错误,隐藏默认错误消息并显示您自己的错误消息(如果您愿意)。下面列出了您需要的东西。
1)初始/顶级脚本,我们将其称为index.php
,您可以在其中存储自定义错误处理函数。自定义错误函数处理程序必须保持在顶部,以便它们捕获低于它们的错误,“低于”我的意思是在包含文件中。
2)假设这个顶级脚本没有错误必须是真的!这非常重要,当您在index.php
中找到自定义错误处理函数时,无法在index.php
中捕获致命错误。
3)Php指令(也必须在index.php
中找到)
set_error_handler("myNonFatalErrorHandler");
#为了捕获非致命错误
register_shutdown_function('myShutdown');
#为了捕捉致命错误
ini_set('display_errors', false);
#为了隐藏php向用户显示的错误
ini_set('log_errors',FALSE);
#assuming我们自己记录错误
ini_set('error_reporting', E_ALL);
#我们想报告所有错误
在制作中(如果我没有错)我们可以保留ini_set('error_reporting', E_ALL);
以便能够记录错误,同时ini_set('display_errors', false);
将确保没有错误显示到用户。
至于我所说的两个函数myNonFatalErrorHandler
和myShutdown
的实际内容,我不会在此处放置详细内容以简化操作。此外,其他访客已经提供了很多例子。我只是表现出一个非常简单的想法。
function myNonFatalErrorHandler($v, $m, $f, $l, $c){
$some_logging_var_arr1[]="format $v, $m, $f, ".$err_lvl[$l].", $c the way you like";
//You can display the content of $some_logging_var_arr1 at the end of execution too.
}
function myShutdown()
{
if( ($e=error_get_last())!==null ){
$some_logging_var_arr2= "Format the way you like:". $err_level[$e['type']].$e['message'].$e['file'].$e['line'];
}
//display $some_logging_var_arr2 now or later, e.g. from a custom session close function
}
至于$ err_lvl,它可以是:
$err_lvl = array(E_ERROR=>'E_ERROR', E_CORE_ERROR=>'E_CORE_ERROR', E_COMPILE_ERROR=>'E_COMPILE_ERROR', E_USER_ERROR=>'E_USER_ERROR', E_PARSE=>'E_PARSE', E_RECOVERABLE_ERROR=>'E_RECOVERABLE_ERROR', E_WARNING=>'E_WARNING', E_CORE_WARNING=>'E_CORE_WARNING', E_COMPILE_WARNING=>'E_COMPILE_WARNING',
E_USER_WARNING=>'E_USER_WARNING', E_NOTICE=>'E_NOTICE', E_USER_NOTICE=>'E_USER_NOTICE',E_STRICT=>'E_STRICT');
答案 5 :(得分:4)
带有解析错误的脚本总是被中断,无法处理。因此,如果直接调用脚本或通过include / require调用脚本,则无法执行任何操作。但如果它是通过AJAX,flash或任何其他方式调用的, 是一种解决方法,如何检测解析错误。
我需要这个来处理swfupload脚本。 Swfupload是一个处理文件上传和每次上传文件的flash,它调用PHP处理脚本来处理filedata - 但是没有浏览器输出,所以PHP处理脚本需要这些设置用于调试目的:
if(!isset($_SESSION["swfupload"])) echo "parse error";
注1 null
表示is not set
至isset()