Capitolo 15. Gestione degli errori

In PHP sono presenti diversi tipi di errori e avvertimenti (warning):

Tabella 15-1. PHP - Tipi di errore

valoresimbolodescrizionenote
1E_ERRORErrore run-time fatale 
2E_WARNINGWarning run-time(errore non fatale) 
4E_PARSEErrore nel parsing in compilazione 
8E_NOTICE Notifiche run-time (meno serie dei warning)  
16E_CORE_ERRORErrore fatale nella fase di startup inizale di PHPSolo PHP 4
32E_CORE_WARNING Warning (errore non fatale) nella fase di startup inizale di PHP Solo PHP 4
64E_COMPILE_ERRORErrore fatale in fase di compilazioneSolo PHP 4
128E_COMPILE_WARNINGWarning (errore non fatale) in fase di compilazioneSolo PHP 4
256E_USER_ERRORMessagio di errore generato dall'utenteSolo PHP 4
512E_USER_WARNINGMessaggio di avvertimento (warning) generato dall'utenteSolo PHP 4
1024E_USER_NOTICEMessagio di notifica generato dall'utenteSolo PHP 4
 E_ALLTutti i precedentiSolo PHP 4

I valori presenti nella tabella (sia numerici che simbolici) sono utilizzati per creare delle bitmask per specificare quali errori segnalare. Si possono usare gli operatori sui bit '|','&' e '~' per combinare questi valori e mascherare certi tipi di errori. Nota che solo '|', '~', '!', e '&' verranno interpretati correttamente all'interno del file php.ini e che gli operatori sui bit non saranno interpretati nel file php3.ini.

Nel PHP 4 la configurazione predefinita di error_reporting è E_ALL & ~E_NOTICE che fa si che vengano visualizzati tutti gli errori e avvertimenti che non siano di livello E_NOTICE. Nel PHP 3 la configurazione predefinita è (E_ERROR | E_WARNING | E_PARSE), che ha lo stesso effetto. Si noti che, dato che le costanti non sono supportate nel file php3.ini presente nel PHP 3, la configurazione di error_reporting va effettuata usando un valore numerico, ad esempio 7.

Le configurazioni predefinite possono essere cambiate nel file ini con la direttiva error_reporting. Si può anche utilizzare il file di configurazione di Apache httpd.conf con la direttiva php_error_reporting (php3_error_reporting per PHP 3) oppure ancora in fase di esecuzione di uno script con la funzione error_reporting().

Attenzione

Quando si esegue un upgrade del codice o dei server da PHP3 a PHP4 è necessario controllare questi settaggi e le chiamate a error_reporting() oppure potrebbe disabilitarsi il report dei nuovi tipi di errore, specialmente E_COMPILE_ERROR. Questo potrebbe portare a documenti vuoti senza alcun feedback sulle cause o dove guardare per trovare il problema.

Tutte le espressioni PHP possono anche venir chiamate con il prefisso "@", che disabilita il report degli errori per quella particolare espressione. Se capita un errore in una di queste espressioni e l'opzione track_errors è attivata, si può trovare il messaggio d'errore nella variabile globale $php_errormsg.

Nota: Il prefisso @ non disabilita i messaggi che sono il risultato di errori di parsing.

Attenzione

Attualmente il prefisso @ disabilita anche il report per gli errori critici che terminano l'esecuzione dello script. Fra le altre cose, questo significa che se si usa @ per sopprimere gli errori di una determinata funzione e questa è ad esempio non disponibile oppure è stata chiamata in maniera non corretta, lo script terminerà e non ci sarà nessuna indicazione del perché.

Di seguito si può vedere un esempio di come si possono usare le possibilità di gestione degli errori del PHP. Definiamo una funzione per la gestione degli errori che registra le informazioni in un file (utilizzando un formato XML) e invia una email allo sviluppatore quando si verifica un errore critico nella logica.

Esempio 15-1. Usare la gestione degli errori in uno script

<?php
// sviluppiamo la nostra gestione degli errori
error_reporting(0);

// funzione per la gestione degli errori definita dall'utente
function userErrorHandler ($errno, $errmsg, $filename, $linenum, $vars) {
    // data e ora della annotazione dell'errore
    $dt = date("Y-m-d H:i:s (T)");

    // define an assoc array of error string
    // in reality the only entries we should
    // consider are 2,8,256,512 and 1024
    $errortype = array (
                1   =>  "Error",
                2   =>  "Warning",
                4   =>  "Parsing Error",
                8   =>  "Notice",
                16  =>  "Core Error",
                32  =>  "Core Warning",
                64  =>  "Compile Error",
                128 =>  "Compile Warning",
                256 =>  "User Error",
                512 =>  "User Warning",
                1024=>  "User Notice"
                );
    // set of errors for which a var trace will be saved
    $user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);
    
    $err = "<errorentry>\n";
    $err .= "\t<datetime>".$dt."</datetime>\n";
    $err .= "\t<errornum>".$errno."</errornum>\n";
    $err .= "\t<errortype>".$errortype[$errno]."</errortype>\n";
    $err .= "\t<errormsg>".$errmsg."</errormsg>\n";
    $err .= "\t<scriptname>".$filename."</scriptname>\n";
    $err .= "\t<scriptlinenum>".$linenum."</scriptlinenum>\n";

    if (in_array($errno, $user_errors))
        $err .= "\t<vartrace>".wddx_serialize_value($vars,"Variables")."</vartrace>\n";
    $err .= "</errorentry>\n\n";
    
    // for testing
    // echo $err;

    // save to the error log, and e-mail me if there is a critical user error
    error_log($err, 3, "/usr/local/php4/error.log");
    if ($errno == E_USER_ERROR)
        mail("phpdev@example.com","Critical User Error",$err);
}


function distance ($vect1, $vect2) {
    if (!is_array($vect1) || !is_array($vect2)) {
        trigger_error("Incorrect parameters, arrays expected", E_USER_ERROR);
        return NULL;
    }

    if (count($vect1) != count($vect2)) {
        trigger_error("Vectors need to be of the same size", E_USER_ERROR);
        return NULL;
    }

    for ($i=0; $i<count($vect1); $i++) {
        $c1 = $vect1[$i]; $c2 = $vect2[$i];
        $d = 0.0;
        if (!is_numeric($c1)) {
            trigger_error("Coordinate $i in vector 1 is not a number, using zero", 
                            E_USER_WARNING);
            $c1 = 0.0;
        }
        if (!is_numeric($c2)) {
            trigger_error("Coordinate $i in vector 2 is not a number, using zero", 
                            E_USER_WARNING);
            $c2 = 0.0;
        }
        $d += $c2*$c2 - $c1*$c1;
    }
    return sqrt($d);
}

$old_error_handler = set_error_handler("userErrorHandler");

// undefined constant, generates a warning
$t = I_AM_NOT_DEFINED;

// define some "vectors"
$a = array(2,3,"foo");
$b = array(5.5, 4.3, -1.6);
$c = array (1,-3);

// generate a user error
$t1 = distance($c,$b)."\n";

// generate another user error
$t2 = distance($b,"i am not an array")."\n";

// generate a warning
$t3 = distance($a,$b)."\n";

?>
Questo è un semplice esempio che mostra come usare le funzioni per la gestione degli errori e per loggare.

Vedere anche error_reporting(), error_log(), set_error_handler(), restore_error_handler(), trigger_error(), user_error()