2008-08-31 120 views
11

我正在飞跃:我的PHP脚本将全部失败优雅!set_error_handler不工作我想如何工作

至少,这就是我希望的......

我不想换行(几乎)在尝试... 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); 

这工作正常,返回:

Sorry, an error has occured on line 17. The function that caused the error says Undefined variable: 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(); 

这将返回:

Fatal error: Call to undefined function: imafakefunction() in /Library/WebServer/Documents/experimental/errorhandle.php on line 17

为什么我的自定义错误处理程序捕获未定义的功能?这会造成其他问题吗?

回答

9

set_error_handler被设计的代码来处理错误:E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE。这是因为set_error_handler是为了报告用户错误功能trigger_error所引发的错误的方法。

不过,我的确发现手册中此评论,可以帮助你:

"The following error types cannot be handled with a user defined function: E_ERROR , E_PARSE , E_CORE_ERROR , E_CORE_WARNING , E_COMPILE_ERROR , E_COMPILE_WARNING , and most of E_STRICT raised in the file where set_error_handler() is called."

This is not exactly true. set_error_handler() can't handle them, but ob_start() can handle at least 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(); 

?> 

但实际上这些错误应该默默报告在一个文件中,例如。希望你的项目中不会有太多错误E_PARSE! :-)

至于一般错误报告,坚持例外(我发现它有助于使他们与我的MVC系统配合)。您可以构建一个功能非常丰富的Exception,通过按钮提供选项并添加大量描述,以便让用户知道哪里出了问题。

1

Why isn't my custom error handler catching undefinedd functions? Are there other problems that this will cause?

在猜测,我会说,未定义的函数错误通过不同的执行路径比其他错误类型。也许PHP设计者可以告诉你更多,除非我怀疑PHP是以任何方式设计的。

如果您希望脚本在写入PHP风格时仍然优雅地失败,请尝试将整个页面放在一个函数中,然后在try..catch块中调用它。

1

documentation(强调):

The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.

调用未定义功能触发E_ERROR,因此其不能由错误回调来处理(或由异常处理程序的这个问题)。你所能做的就是将error_reporting设置为0.

PS,如果你在滚动你自己的错误处理程序,你应该小心地正确处理@操作符。从文档(强调):

It is important to remember that the standard PHP error handler is completely bypassed. 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. Of particular note is that this value will be 0 if the statement that caused the error was prepended by the @ error-control operator.

6

我猜你需要使用register_shutdown_function

例如:

register_shutdown_function(array($this, 'customError'));. 

    function customError() 
    { 

    $arrStrErrorInfo = error_get_last(); 

    print_r($arrStrErrorInfo); 

    } 
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”为“关”你可以捕捉仍与处理程序赶上他们。

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文件加载。设置2 - 相同但改变: ini_set('memory_limit','299M');

这次我没有收到错误,它甚至没有调用我的自定义错误函数。该脚本死在同一行上。

有没有人有线索为什么以及如何去解决这个问题?