2011-12-14 13 views
7

odbc_errormsg no informa los mensajes de error odbc_execute de la forma en que se supone que debe. Simplemente lanza una advertencia. Así que me han obligado a escribir un truco para analizar el mensaje de error a través del error_get_last.error_get_last() y controlador de error personalizado

estoy usando set_error_handler y error_get_last vuelve NULL a menos que sea:

  1. desactivo mi gestor de errores,

  2. o hacerlo volver FALSE.

yo supongo que esto se debe al controlador de errores incorporado de PHP teniendo cuidado de almacenar los detalles del error en algún lugar para que puedan ser recuperados más tarde.

¿Hay alguna forma de emular dicho comportamiento en mi controlador de error personalizado para que error_get_last() se pueda usar con normalidad?

Tenga en cuenta que ya sé varias formas de recuperar la información de error en cualquier momento. Mi pregunta es cómo hacer que error_get_last sea utilizable.


Actualización: creo que será mejor que publicar algo de código.

PHP tiene error_get_last(), lo que permite hacer esto:

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

... y conseguir esto:

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) 
} 

Esto rompe si se reemplaza el controlador de errores incorporado:

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 

Si conserva ambos controladores de errores ...

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; 

... sufre efectos adversos:

[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 

... en lugar de simplemente:

[Error happened: Undefined variable: foo] 

Quiero a mi manejador de error personalizado para interactuar correctamente con error_get_last. Quiero que error_get_last funcione bien.

+0

¿Aceptarías utilizar una función diferente (definida por el usuario)? Porque si lo hiciera, podría almacenar el último error en una var global y tener una función que simplemente 'devuelva $ GLOBALS ['varname'];' – DaveRandom

+0

¿No es aceptable devolver 'falso '? Si es así, ¿por qué? – Jon

+0

Además, ¿ha intentado asignar un valor a ['$ php_errormsg'] (http://uk.php.net/manual/en/reserved.variables.phperrormsg.php)? No tengo idea de si esto lograría (o incluso afectaría) a algo, pero podría valer la pena intentarlo ... – DaveRandom

Respuesta

5

Derecho, esta es una solución extraña, pero creo que se adaptará a sus propósitos.

Después de un poco de jugar un rato, he descubierto que esto:

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()); 

Resultados en esto:

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) 
} 

Calling @trigger_error() desde dentro de su gestor de errores, y no volver FALSE, provoca error_get_last() para devolver algo que no sea NULL, pero debido a que el error se suprime con @, PHP no genera nada. Parece que para evitar una recursión infinita, llamar al trigger_error() desde la función del manejador de errores registrado no llama al manejador de errores, lo cual funciona a nuestro favor aquí.

Obviamente, el código de error ha sido modificado, pero puede convertirlo al código E_USR_* relevante si lo necesita, pero sospecho que lo que realmente quiere es el valor de cadena, que este método le permitirá obtener. Desgraciadamente, también ha perdido el número de línea y la información del archivo, aunque es posible recuperarlo haciendo algo relacionado con un seguimiento de la pila dentro del controlador de errores o, como mínimo, incluyéndolo en la cadena de los argumentos aprobados.

Esto es horrible, horrible, horrible, pero como no hay una forma oficial de hacerlo, un pirateo es esencialmente lo que estás pidiendo.

+0

Ingenioso ... Necesito estudiarlo cuidadosamente :) –

+0

@ ÁlvaroG.Vicario, tan ingenioso como http: //ioccc.org ..... – Pacerier

0

Puede cambiar su controlador de error personalizado para que devuelva falso, justo cuando se ignora el error (@ -operador utilizado).

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