2011-12-14 90 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; 
}