2008-08-31 147 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');

這次我沒有收到錯誤,它甚至沒有調用我的自定義錯誤函數。該腳本死在同一行上。

有沒有人有線索爲什麼以及如何去解決這個問題?