我正在迈出一步:我的PHP脚本将全部失败!
至少,这就是我所希望的......“
我不想(实际上)在try...catch
语句中包含(实际上)每一行,所以我认为最好的办法是为我的文件开头创建一个自定义错误处理程序。
我正在练习页面上测试它:
function customError($level,$message,$file,$line,$context) {
echo "Sorry, an error has occured on line $line.<br />";
echo "The function that caused the error says $message.<br />";
die();
}
set_error_handler("customError");
echo($imAFakeVariable);
这很好用,返回:
抱歉,第17行发生错误。导致该功能的功能 错误表示未定义的变量:imAFakeVariable。
但是,此设置不适用于未定义的函数。
function customError($level,$message,$file,$line,$context) {
echo "Sorry, an error has occured on line $line.<br />";
echo "The function that caused the error says $message.<br />";
die();
}
set_error_handler("customError");
imAFakeFunction();
返回:
致命错误:调用未定义的函数:imafakefunction()in 第17行的/Library/WebServer/Documents/experimental/errorhandle.php
为什么我的自定义错误处理程序没有捕获未定义的函数?这会导致其他问题吗?
答案 0 :(得分:11)
set_error_handler
旨在处理代码为E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE
的错误。这是因为set_error_handler
是一种报告用户错误函数trigger_error
引发的错误的方法。
但是,我确实在手册中找到了可能对您有用的评论:
“使用用户定义的函数无法处理以下错误类型:
E_ERROR
,E_PARSE
,E_CORE_ERROR
,E_CORE_WARNING
,E_COMPILE_ERROR
,{{1在E_COMPILE_WARNING
被调用的文件中引发了大多数E_STRICT
。“这不完全正确。
set_error_handler()
无法处理它们,但set_error_handler()
至少可以处理ob_start()
。E_ERROR
实际上,例如,应该在文件中静默报告这些错误。希望您的项目中不会出现很多<?php
function error_handler($output)
{
$error = error_get_last();
$output = "";
foreach ($error as $info => $string)
$output .= "{$info}: {$string}\n";
return $output;
}
ob_start('error_handler');
will_this_undefined_function_raise_an_error();
?>
错误! : - )
对于一般错误报告,坚持使用Exceptions(我发现将它们与我的MVC系统联系起来很有帮助)。您可以构建一个非常通用的Exception来通过按钮提供选项并添加大量描述以让用户知道错误。
答案 1 :(得分:6)
我猜您还需要使用register_shutdown_function
例如:
register_shutdown_function( array( $this, 'customError' ));.
function customError()
{
$arrStrErrorInfo = error_get_last();
print_r( $arrStrErrorInfo );
}
答案 2 :(得分:2)
从documentation(强调添加):
使用用户定义的函数处理以下错误类型 :E_ERROR,E_PARSE,E_CORE_ERROR,E_CORE_WARNING,E_COMPILE_ERROR,E_COMPILE_WARNING,以及调用set_error_handler()的文件中引发的大部分E_STRICT。
调用未定义的函数会触发E_ERROR,因此错误回调(或异常处理程序)无法处理它。您可以做的就是将error_reporting设置为0。
PS,如果你正在滚动自己的错误处理程序,你应该注意正确处理@运算符。从文档(重点添加):
重要的是要记住标准的PHP错误处理程序是完全被绕过的。 error_reporting()设置将不起作用,无论如何都将调用您的错误处理程序 - 但是您仍然可以读取error_reporting的当前值并采取适当的操作。 特别值得注意的是,如果导致错误的语句由@ error-control运算符预先添加,则此值将为0.
答案 3 :(得分:1)
为什么我的自定义错误处理程序没有捕获未定义的函数?这会导致其他问题吗?
猜测,我会说未定义的函数错误通过与其他错误类型不同的执行路径。也许PHP设计师可以告诉你更多,除了我怀疑PHP是以任何方式设计的。
如果您希望脚本在仍然以PHP风格编写时优雅地失败,请尝试将整个页面放在一个函数中,然后在try..catch
块中调用它。
答案 4 :(得分:0)
今天我发现非常有趣的事情,因为我遇到了类似的问题。如果您使用以下内容 - 它将使用您的自定义错误处理函数/方法捕获错误:
ini_set('display_errors', 'Off');
error_reporting(-1);
set_error_handler(array("Cmd\Exception\Handler", "getError"), -1 & ~E_NOTICE & ~E_USER_NOTICE);
通过将'display_errors'设置为'Off',您可以捕获仍然使用处理程序捕获它们。
答案 5 :(得分:0)
我已经玩错误处理了一段时间,似乎它在大多数情况下都有效。
function fatalHandler() {
global $fatalHandlerError, $fatalHandlerTitle;
$fatalHandlerError = error_get_last();
if( $fatalHandlerError !== null ) {
print($fatalHandlerTitle="{$fatalHandlerTitle} | ".join(" | ", $fatalHandlerError).
(preg_match("/memory/i", $fatalHandlerError["message"]) ? " | Mem: limit ".ini_get('memory_limit')." / peak ".round(memory_get_peak_usage(true)/(1024*1024))."M" : "")."\n".
"GET: ".var_export($_GET,1)."\n".
"POST: ".var_export($_POST,1)."\n".
"SESSION: ".var_export($_SESSION,1)."\n".
"HEADERS: ".var_export(getallheaders(),1));
}
return $fatalHandlerTitle;
}
function fatalHandlerInit($title="phpError") {
global $fatalHandlerError, $fatalHandlerTitle;
$fatalHandlerTitle = $title;
$fatalHandlerError = error_get_last();
set_error_handler( "fatalHandler" );
}
现在我遇到一个问题,如果内存耗尽,每次都不会报告。看起来它取决于使用了多少内存。 我做了一个脚本来加载一个大文件(需要大约6.6M的内存)在一个无限循环中。 设置1:
ini_set('memory_limit', '296M');
fatalHandlerInit("testing");
$file[] = file("large file"); // copy paste a bunch of times
在这种情况下,我得到错误报告,并在45文件加载时死亡。
Setup2 - 相同但更改: ini_set(&#39; memory_limit&#39;,&#39; 299M&#39;);
这次我没有收到错误,甚至没有调用我的自定义错误功能。脚本死在同一条线上。
有没有人知道为什么以及如何解决这个问题?