2011-12-14 15 views
7

odbc_errormsg non segnala i messaggi di errore da odbc_execute nel modo previsto. Si limita a lanciare un avvertimento. Quindi sono stato costretto a scrivere un trucco per analizzare il messaggio di errore tramite error_get_last.error_get_last() e gestore di errori personalizzato

sto usando set_error_handler e error_get_last ritorna NULL a meno che non sia:

  1. a disattivare il mio gestore di errori,

  2. o farla tornare FALSE.

avrei Suppongo che questo è dovuto al gestore di errore built-in di PHP avendo cura di memorizzare i dettagli di errore da qualche parte in modo che possano essere recuperati in seguito.

C'è un modo per emulare tale comportamento nel mio gestore degli errori personalizzato in modo che error_get_last() può essere utilizzato normalmente?

Nota: conosco già diversi modi per recuperare le informazioni di errore in qualsiasi momento. La mia domanda è come rendere utilizzabile error_get_last.


Aggiornamento: Penso meglio che postare un certo codice.

PHP ha error_get_last(), che permette di fare questo:

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

... e ottenere questo:

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

Questo rompe se si sostituisce il gestore degli errori incorporato:

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 

Se mantieni entrambi i gestori degli errori ...

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; 

... si ottiene effetti collaterali:

[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 

... invece di:

[Error happened: Undefined variable: foo] 

Voglio il mio gestore di errore personalizzato per interfacciarsi correttamente con error_get_last. Voglio che error_get_last funzioni correttamente.

+0

Accetteresti di utilizzare una funzione diversa (definita dall'utente)? Perché se lo si volesse, si potrebbe semplicemente archiviare l'ultimo errore in una variabile globale e avere una funzione che restituisce semplicemente $ GLOBALS ['varname']; ' – DaveRandom

+0

Il ritorno' false' non è accettabile? Se è così, perché? – Jon

+0

Inoltre, hai provato ad assegnare un valore a ['$ php_errormsg'] (http://uk.php.net/manual/en/reserved.variables.phperrormsg.php)? Non ho idea se questo potrebbe raggiungere (o addirittura influenzare) qualcosa, ma potrebbe valere la pena di provare ... – DaveRandom

risposta

5

Giusto, questa è una soluzione bizzarra, ma io penso che soddisferà i tuoi scopi.

Dopo un po 'di suonare in giro, ho scoperto che questo:

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

risultati in questo:

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() all'interno del tuo gestore degli errori, e non tornare FALSE, provoca error_get_last() per restituire qualcosa di diverso da NULL, ma poiché l'errore è soppresso con @, PHP non emette nulla. Sembra che nell'interesse di evitare una ricorsione infinita, chiamare trigger_error() dall'interno della funzione di gestione degli errori registrata non chiami il gestore degli errori, che funziona a nostro vantaggio qui.

Ovviamente, il codice di errore è stato modificato, ma è possibile convertirlo nel relativo codice E_USR_* se necessario, ma ho il sospetto che ciò che si desidera veramente sia il valore stringa, che questo metodo consente di ottenere. Purtroppo, hai anche perso il numero di riga e le informazioni sui file, anche se è possibile recuperarlo eseguendo qualcosa che coinvolge una traccia di stack all'interno del gestore degli errori o, per lo meno, includendolo nella stringa dagli argomenti passati.

Questo è un attacco orribile, orribile, orribile, ma dal momento che non esiste un modo ufficialmente approvato per farlo, un trucco è essenzialmente quello che stai chiedendo.

+0

Witty ... Ho bisogno di studiarlo attentamente :) –

+0

@ ÁlvaroG.Vicario, spiritoso come http: //ioccc.org ..... – Pacerier

0

È possibile modificare il gestore errori personalizzato per restituire false, solo quando l'errore viene ignorato (@ -operator utilizzato).

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