2011-12-14 87 views
7

odbc_errormsg 不按照應該的方式報告odbc_execute的錯誤消息。它只是發出警告。所以我不得不通過error_get_last寫一個黑客來解析錯誤信息。error_get_last()和自定義錯誤處理程序

我使用set_error_handlererror_get_last回報NULL,除非我可以:

  1. 禁用我的錯誤處理程序,

  2. 或使其返回FALSE

我想這是由於PHP的內置錯誤處理程序負責將錯誤細節存儲在某處,以便稍後可以檢索它們。

有沒有辦法在我的自定義錯誤處理程序中模擬這種行爲,所以error_get_last()可以正常使用?

請注意我已經知道幾種方法隨時檢索錯誤信息。我的問題是如何使error_get_last可用。


更新:我想我應該張貼一些代碼。

PHP有error_get_last(),這使得要做到這一點:

@fopen('xxx'); 
var_dump(error_get_last()); 

...並得到這樣的:

array(4) { 
    ["type"]=> 
    int(2) 
    ["message"]=> 
    string(46) "fopen() expects at least 2 parameters, 1 given" 
    ["file"]=> 
    string(69) "C:\Documents and Settings\ALVARO.GONZALEZ\Mis documentos\tmp\test.php" 
    ["line"]=> 
    int(3) 
} 

如果更換內置的錯誤處理這打破:

function custom_error_handler($errno, $errstr, $errfile, $errline){ 
    $ignore = ($errno & error_reporting()) == 0; 
    if(!$ignore){ 
     echo "[Error happened: $errstr]\n"; 
    } 
    return TRUE; 
} 
set_error_handler('custom_error_handler'); 

@fopen('xxx'); 
var_dump(error_get_last()); // NULL 

如果您保留兩個錯誤處理程序...

function custom_error_handler($errno, $errstr, $errfile, $errline){ 
    $ignore = ($errno & error_reporting()) == 0; 
    if(!$ignore){ 
     echo "[Error happened: $errstr]\n"; 
    } 
    return FALSE; 
} 
set_error_handler('custom_error_handler'); 

error_reporting(E_ALL); 
echo $foo; 

...你得到的副作用:

[Error happened: Undefined variable: foo] 

Notice: Undefined variable: foo in C:\Documents and Settings\ALVARO.GONZALEZ\Mis documentos\tmp\test.php on line 15 

Call Stack: 
    0.0004  329720 1. {main}() C:\Documents and Settings\ALVARO.GONZALEZ\Mis documentos\tmp\test.php:0 

...而不是隻是:

[Error happened: Undefined variable: foo] 

我想我的自定義錯誤處理程序與error_get_last正確連接。我想error_get_last工作正常。

+0

您是否接受使用不同的(用戶定義的)功能?因爲如果你願意,你可以將最後一個錯誤存儲在一個全局變量中,並且有一個函數,它只是返回$ GLOBALS ['varname'];' – DaveRandom 2011-12-14 12:17:23

+0

返回'false'是不可接受的?如果是這樣,爲什麼? – Jon 2011-12-14 12:20:18

回答

5

對,這是一個奇怪的解決方案,但我認爲它會適合你的目的。

有點打轉轉後,我發現這一點:

function my_error_handler ($errno, $errstr, $errfile = '', $errline = 0, $errcontext = array()) { 

    // Handle the error here 

    @trigger_error($errstr); 
    return TRUE; 

} 

// Just to make sure PHP is not outputting anything 
error_reporting(-1); 
ini_set('display_errors',1); 

set_error_handler('my_error_handler'); 

// An E_USR error... 
trigger_error('Some error'); 
var_dump(error_get_last()); 

// ...and a native one 
$key = count(); 
var_dump(error_get_last()); 

結果在此:

array(4) { 
    ["type"]=> 
    int(1024) 
    ["message"]=> 
    string(10) "Some error" 
    ["file"]=> 
    string(69) "C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\test.php" 
    ["line"]=> 
    int(7) 
} 
array(4) { 
    ["type"]=> 
    int(1024) 
    ["message"]=> 
    string(45) "count() expects at least 1 parameter, 0 given" 
    ["file"]=> 
    string(69) "C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\test.php" 
    ["line"]=> 
    int(7) 
} 

調用從您的錯誤處理程序中@trigger_error(),也不回FALSE,導致error_get_last()返回除NULL以外的內容,但由於錯誤被@壓制,PHP不會輸出任何內容。似乎爲了避免無限遞歸,從註冊的錯誤處理函數中調用trigger_error()不會調用錯誤處理程序 - 這對我們來說很有用。

很顯然,錯誤代碼已被修改,但如果需要的話,您可以將其轉換爲相關的E_USR_*代碼 - 但我懷疑您真正想要的是字符串值,該方法將允許您獲取該值。不幸的是,你也失去了行號和文件信息 - 儘管你可能會通過在錯誤處理程序中執行一些涉及堆棧跟蹤的事情,或至少在傳入的參數中包括字符串中的內容來恢復它。

這是一個可怕的,可怕的,可怕的黑客 - 但由於沒有官方認可的方式來做到這一點,黑客基本上是你要求的。

0

只要忽略錯誤(@ -operator used),您可以更改自定義錯誤處理程序以返回false。

function custom_error_handler($errno, $errstr, $errfile, $errline){ 
    $ignore = ($errno & error_reporting()) == 0; 
    if ($ignore) { 
     return FALSE; 
    } 
    echo "[Error happened: $errstr]\n"; 
    return TRUE; 
}