La programmazione è una tra le attività più complesse che esistano e come tante altre è soggetta ad errori. Di conseguenza è fondamentale imparare a gestire gli errori nel modo corretto.
In questa guida vedremo quali sono le tipologie di errori di PHP e impareremo ad utilizzare in modo efficiente le funzioni di gestione degli errori del linguaggio.
Indice dei contenuti
Esistono diversi motivi per cui un'applicazione genera errori, ad esempio:
Questi tipi di errori sono noti come errori a runtime, poiché si verificano nel momento in cui viene eseguito lo script. Gli errori di sintassi invece, come ad esempio l'omissione di un punto e virgola (;
) per indicare la fine di un'istruzione PHP, devono essere corretti prima che lo script possa essere eseguito.
Un'applicazione professionale deve avere le capacità per gestire tali errori, in modo tale da informare l'utente del problema nel modo più chiaro e preciso possibile.
PHP genera diverse tipologie di errore che possiamo suddividere in:
Gli errori fatali sono gli errori più gravi perché bloccano l'esecuzione dell'applicazione. Un tipico caso di errore fatale viene rilevato quando tentiamo di chiamare una funzione che non è stata definita:
<?php
$string = 'test';
echo test($string);
// Fatal error: Uncaught Error: Call to undefined function test()
I parse error, come gli errori fatali, bloccano l'esecuzione dello script e riguardano nello specifico un errore di sintassi. Riprendendo l'esempio precedente:
<?php
$string = 'test';
echo test($string)
// Parse error: syntax error, unexpected end of file, expecting ';' or ','
In questo caso manca il punto e virgola alla riga 4 che indica all'interprete PHP la fine dell'istruzione.
I warning error non bloccano l'esecuzione dello script. Questo tipo di errore può verificarsi ad esempio quando si cerca di includere un file inesistente:
<?php
include 'functions.php';
// Warning: include(functions.php): failed to open stream: No such file or directory
Di seguito è riportato l'elenco di tutte le tipologie di errori che possiamo riscontrare in PHP, a ciascuna costante corrisponde un valore numerico
Costante | Valore numerico | Descrizione |
---|---|---|
E_ERROR | 1 | Errore fatale a runtime. L'esecuzione dello script viene interrotta. |
E_WARNING | 2 | Warning a runtime. L'esecuzione dello script non viene interrotta. |
E_PARSE | 4 | Errore di sintassi. L'esecuzione dello script viene interrotta. |
E_NOTICE | 8 | Messaggio di errore a runtime, indica che l'interprete ha rilevato qualcosa che potrebbe essere un errore. Non blocca l'esecuzione dello script. |
E_CORE_ERROR | 16 | Errore fatale che si verifica durante l'avvio iniziale del motore PHP. |
E_CORE_WARNING | 32 | Warning che si verifica durante l'avvio iniziale del motore PHP. |
E_COMPILE_ERROR | 64 | Errore fatale generato dallo Zend Scripting Engine che si verifica durante la compilazione dello script. |
E_COMPILE_WARNING | 128 | Warning generato dallo Zend Scripting Engine che si verifica durante la compilazione dello script. |
E_USER_ERROR | 256 | Messaggio di errore generato dall'utente tramite la funzione trigger_error() piuttosto che dal motore PHP. |
E_USER_WARNING | 512 | Warning generato dall'utente tramite la funzione trigger_error() piuttosto che dal motore PHP. |
E_USER_NOTICE | 1024 | Notice generato dall'utente tramite la funzione trigger_error() piuttosto che dal motore PHP. |
E_STRICT | 2048 | Generato ogni volta che PHP incontra del codice che potrebbe causare problemi o incompatibilità |
E_RECOVERABLE_ERROR | 4096 | Un errore fatale recuperabile, ossia che può essere gestito a livello utente tramite la funzione set_error_handler() |
E_DEPRECATED | 8192 | Warning a runtime che indica l'utilizzo di una funzione deprecata, ossia che non funzionerà più nelle versioni future di PHP |
E_USER_DEPRECATED | 16384 | Warning generato a livello utente tramite trigger_error() per indicare l'utilizzo di funzioni deprecate |
E_ALL | 32767 | Tutti gli errori e gli avvisi di PHP |
Le costanti o i rispettivi valori numerici appena visti possono essere utilizzati come argomento per la funzione error_reporting()
del linguaggio. Questa funzione consente di configurare PHP per fare generare o meno una determinata tipologia di errori in base al valore passato. Un valore basso corrisponde ad un errore più critico.
Vediamo subito un esempio di utilizzo della funzione error_reporting()
:
<?php
error_reporting(E_NOTICE);
$number1 = 10;
echo $number2; //Notice: Undefined variable: number2
echo sum($number1, $number2);
L'esecuzione dello script genererà solamente un warning per la riga 5 poiché abbiamo abilitato la visualizzazione degli errori di tipo E_NOTICE
o superiori.
È possibile indicare una combinazione di costanti tramite l'and (&
) oppure l'or (|
), possiamo quindi scrivere
<?php
error_reporting(E_ERROR | E_WARNING);
per comunicare a PHP di abilitare solo errori fatali e warning.
Nota: la funzione error_reporting()
non consente di disabilitare gli errori di tipo E_PARSE
, poiché sono errori che vengono rilevati prima dell'esecuzione dello script (es. omissione del punto e virgola alla fine di un'istruzione).
Per disabilitare la visualizzazione degli errori all'utente è possibile impostare la variabile di configurazione display_errors
a false
oppure a 0
tramite la funzione ini_set()
:
ini_set("display_errors", false); // equivalente a ini_set("display_errors", 0);
Con questo codice gli errori non verranno mostrati nella pagina HTML. Ciò è molto importante in fase di produzione poiché evitiamo di mostrare all'utente informazioni sensibili, mentre in fase di sviluppo o testing lasciare abilitata la visualizzazione degli errori è utile per la fase di debugging.
Introduciamo adesso una delle funzioni PHP più utilizzate nelle applicazioni web, la funzione exit()
. Il suo utilizzo più comune è quello di mostrare un messaggio a video e terminare immediatamente l'esecuzione di dello script PHP, questo significa che qualsiasi ulteriore istruzione successiva non verrà eseguita.
exit($status)
Più precisamente si tratta di un costrutto del linguaggio, quindi può essere utilizzato anche senza parantesi se non viene specificato il parametro opzionale $status
.
Consideriamo adesso questo esempio di codice
<?php
// Proviamo ad aprire il file file.txt
$file = fopen("file.txt", "r");
Stiamo semplicemente tentando di aprire il file file.txt
in lettura. Se tale file non esiste, lo script genera il seguente avviso
Warning: fopen(file.txt): failed to open stream: No such file or directory in ... on line 3
Oltre a non fornire una buona esperienza d'uso all'utente, questa tipologia di errore mostra il percorso dove è memorizzato lo script, rivelando quindi un'informazione sensibile che rappresenta un potenziale problema dal punto di vista della sicurezza.
Vediamo adesso come la funzione exit()
può migliorare un pochino l'esperienza utente, partendo dall'esempio precedente possiamo scrivere
<?php
// Proviamo ad aprire il file file.txt
$file_path = "file.txt";
if (!file_exists($file_path)) {
exit("Il file $file_path non esiste");
}
$file = fopen("file.txt", "r");
In questo caso la funzione file_exists()
ci consente di verificare l'esistenza del file ritornando true
in caso di successo, false
altrimenti. L'utente quindi visualizza uno specifico errore impostato dal programmatore piuttosto che un errore di sistema contenente informazioni sensibili.
Nota: la funzione exit()
dovrebbe essere utilizzata dal programmatore prevalentemente per fare debugging in fase di sviluppo o testing.
Un altro utilizzo comune della funzione exit()
è insieme alla funzione header()
, in particolare nel redirezionare l'utente da una pagina all'altra.
Vediamo un esempio per capire meglio
<?php
session_start();
if (!isset($_SESSION['is_logged'])) {
header("Location: login.php");
exit;
}
Lo script verifica semplicemente se la variabile di sessione $_SESSION['is_logged']
è inizializzata, in caso contrario l'utente viene redirezionato alla pagina login.php
.
L'istruzione alla riga 6 consente di interrompere immediatamente l'esecuzione dello script, eventuali righe di codice successive alla riga 7 non vengono eseguite.
È possibile creare la propria funzione per gestire gli errori generati in fase di esecuzione dal motore PHP. Questo gestore di errori personalizzato offre una maggiore flessibilità e un migliore controllo sugli errori, è possibile ispezionare l'errore e decidere se mostrare un messaggio all'utente, registrare l'errore in un file o database o inviarlo tramite email. È inoltre possibile aggiungere ulteriori informazioni come la data e l'ora dell'evento.
La funzione di gestione degli errori definita dall'utente accetta diversi parametri tra cui due obbligatori, $errno
ed $errstr
e due opzionali, $errfile
e $errline
che vengono descritti di seguito:
Parametro | Descrizione |
---|---|
$errno |
Specifica il livello dell'errore, come numero intero corrispondente alla relativa costante (E_ERROR, E_WARNING, etc...) |
$errstr |
Specifica il messaggio di errore come stringa |
$errfile |
Specifica il nome file del file di script in cui si è verificato l'errore, sotto forma di stringa |
$errline |
Specifica il numero di riga in cui si è verificato l'errore, sotto forma di stringa |
Vediamo adesso un esempio di funzione di gestione degli errori personalizzata tramite l'utilizzo di set_error_handler()
, una funzione che consente di specificare un codice PHP alternativo per la gestione degli errori consentendo di personalizzare la risposta visualizzata dall'utente:
<?php
function my_custom_error($errno, $errstr, $errfile, $errline)
{
printf(
"%s<br>Errore [%s]: %s<br>Percorso file: %s<br>Riga n. %s",
date("d/m/Y H:i:s"),
$errno,
$errstr,
$errfile,
$errline
);
}
set_error_handler("my_custom_error");
echo $test;
Il codice precedente, salvato dentro un file error-handler.php
, genera l'errore
03/01/2023 13:44:14
Errore [8]: Undefined variable: test
Percorso file: C:\xampp\htdocs\error-handler.php
Riga n. 16
PHP può essere configurato in modo tale da memorizzare gli errori dentro un file di log specificato dal programmatore. Tale file è indicato nella direttiva error_log
del file php.ini, che di default risulta vuota.
Anche in questo caso possiamo utilizzare la funzione ini_set()
per impostare un file di log per la nostra applicazione.
Ad esempio, tramite il seguente codice:
<?php
ini_set('error_log', 'logs/error.log');
impostiamo logs/error.log
come percorso dove verranno salvati gli errori.
Ogni eventuale messaggio di errore, che sia un warning o un errore fatale, verrà riportato dentro il file error.log, a patto che la directory logs sia presente.
Eseguendo il seguente codice:
<?php
ini_set('error_log', 'logs/error.log');
echo $test;
dovremmo ottenere un notice dentro il file error.log che recita più o meno così
[02-Jan-2023 23:29:09 Europe/Rome] PHP Notice: Undefined variable: test in ... on line 4
Ulteriori errori generati dall'applicazione vengono accodati ai precedenti. Come possiamo notare, oltre alla a data e ora dell'evento abbiamo la timezone (Europe/Rome) che determina l'impostazione del fuso orario del server dove gira l'applicazione PHP.
Il file di log può essere utilizzato anche per memorizzare errori o messaggi generati dall'applicazione mediante l'uso della funzione error_log()
, la cui sintassi è la seguente:
error_log($message, $type, $dest, $headers)
$message
è il messaggio di errore, $type
è un numero intero che indica il canale dove inviare l'errore. I parametri $dest
e $headers
sono opzionali e il primo va usato nel caso in cui $type = 1
oppure 3
, il secondo nel caso in cui $type = 1
.
La seguente tabella elenca i possibili valori per il parametro $type
Valore | Descrizione |
---|---|
0 |
Il messaggio di errore viene salvato nel file di log di default. Nei sistemi operativi Unix si trova dentro /var/log/apache2/error.log |
1 |
Il messaggio di errore viene inviato per email. Il parametro $dest contiene l'indirizzo email di destinazione e $headers eventuali intestazioni da aggiungere all'email |
2 |
Non più utilizzabile |
3 |
Il messaggio di errore viene salvato nel file specificato nel parametro $dest . Ulteriori messaggi vengono accodati ai precedenti. |
4 |
Il messaggio di errore viene inviato al modulo SAPI del web server |
La funzione error_log()
ritorna true
in caso di successo, false
altrimenti.
Nota: $message
non può contenere il carattere null perché il messaggio verrà troncato, essendo questo carattere interpretato da PHP come terminatore. Per evitare questo inconveniente, prima di chiamare la funzione error_log()
, è possibile convertire il messaggio in base64 con la funzione base64_encode()
o in URL-encode tramite la funzione rawurlencode()
oppure utilizzare addlashes()
per effettuare un'escape dei seguenti caratteri: '
, "
, \
e carattere null.
Oltre alla funzione error_log()
, PHP mette a disposizione la funzione trigger_error()
che genera un messaggio di errore/avviso a livello utente.
La sintassi della funzione trigger_error()
è la seguente:
trigger_error($message, $error_level)
dove $message
è il messaggio di errore da generare e $error_level
è un intero che indica la tipologia dell'errore. Di default viene generato un errore di tipo utente E_USER_NOTICE
.
Nella prossima guida introdurremo le eccezioni, un modo per intercettare e gestire a livello di codice un possibile comportamento inatteso di un'applicazione.