Menu

Mostrare gli errori in PHP: display_errors ed E_ALL

Per mostrare tutti gli errori PHP, metti ini_set('display_errors', '1'); ed error_reporting(E_ALL); in cima allo script, oppure imposta display_errors = On ed error_reporting = E_ALL in php.ini. In produzione registra gli errori in un log invece di mostrarli.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Per mostrare gli errori PHP, metti queste righe in cima allo script: ini_set('display_errors', '1'); e error_reporting(E_ALL);. La prima fa stampare a PHP i messaggi di errore, la seconda gli fa segnalare ogni tipo di errore, compresi warning e deprecazioni.

<?php
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

Con queste righe, un errore come leggere una variabile mai impostata stampa un messaggio con file e numero di riga invece di fallire in silenzio:

Warning: Undefined variable $total in /home/index.php on line 7

error_reporting() chiamata senza argomenti restituisce l'impostazione corrente come numero. Premi Run per impostare un livello e ritradurlo in nomi:

Ogni tipo di errore è un bit, quindi E_ALL & ~E_DEPRECATED significa "tutto tranne le deprecazioni". Cambia la prima riga in error_reporting(E_ERROR | E_WARNING); ed eseguilo di nuovo.

Mostrare gli errori in php.ini

Un'impostazione nello script vale solo dopo che lo script ha iniziato a girare. Per mostrare gli errori in ogni script, errori di sintassi compresi, modifica php.ini (lo trovi con php --ini):

; Development
display_errors = On
display_startup_errors = On
error_reporting = E_ALL

Riavvia Apache o PHP-FPM dopo la modifica. Il server integrato php -S e la riga di comando leggono il file a ogni avvio. Su un hosting condiviso senza accesso a php.ini, Apache con mod_php accetta anche righe in .htaccess:

php_flag display_errors on
php_value error_reporting -1

-1 imposta tutti i bit, che equivale a E_ALL.

I livelli di errore

CostanteCosa lo provocaFerma lo script
E_ERRORErrore fatale a runtime, come l'esaurimento della memoriasì
E_PARSEErrore di sintassi nel filesì
E_WARNINGVariabile o chiave di array non definita, file mancante in includeno
E_NOTICEProblemi minori (in PHP 8 ne restano pochi)no
E_DEPRECATEDCodice che una futura versione di PHP rifiuteràno
E_USER_*Errori che sollevi tu con trigger_error()solo E_USER_ERROR
E_ALLTutti i livelli, compresi errori del core e di compilazione non elencati qui

PHP 8.0 ha trasformato molti vecchi warning in eccezioni: dividere per zero con / e passare il tipo sbagliato a una funzione integrata ora lanciano una sottoclasse di Error, come succede da PHP 7 quando chiami una funzione non definita. Puoi catturarli tutti e tre:

Le eccezioni sono trattate in try e catch. Warning, notice e deprecazioni passano ancora dal sistema di segnalazione degli errori descritto qui.

Registrare gli errori nel log invece di mostrarli

Su un sito in produzione i visitatori non devono mai vedere messaggi di errore: rivelano percorsi, SQL e codice. Scrivili invece in un file di log:

; Production
display_errors = Off
log_errors = On
error_log = /var/log/php/app-errors.log
error_reporting = E_ALL

Mantieni error_reporting = E_ALL in produzione. Abbassarlo non fa sparire gli errori, impedisce solo che tu ne venga a sapere. Anche i tuoi messaggi possono finire nello stesso log con error_log():

<?php
error_log("Payment failed for order 1042");

Poi tieni d'occhio il file mentre fai i test: tail -f /var/log/php/app-errors.log.

Trasformare i warning in eccezioni con set_error_handler

set_error_handler sostituisce la gestione predefinita di warning, notice e deprecazioni con una tua funzione. Uno schema comune li converte tutti in ErrorException, così una chiave di array dimenticata ferma il codice come qualsiasi altra eccezione e può essere catturata:

Il gestore riceve il livello dell'errore come primo argomento, quindi può trattare i livelli in modo diverso. Questo registra solo le deprecazioni e trasforma tutto il resto in un'eccezione:

Gli errori fatali e gli errori di sintassi non arrivano mai al gestore, perché dopo di essi lo script non può continuare. Per registrarli, registra una funzione di shutdown che legge error_get_last().

Leggere l'ultimo errore con error_get_last

Alcune funzioni restituiscono false e riportano il motivo solo come warning, per esempio file_get_contents su un file mancante. error_get_last() restituisce quel warning come array, utile quando vuoi mostrare un tuo messaggio:

L'operatore @ davanti alla chiamata sopprime il messaggio per quella sola espressione. Usalo con parsimonia e solo quando controlli il risultato subito dopo, come qui; una @ da sola nasconde soltanto i bug.

Errore comune: gli errori sono attivi, ma la pagina è ancora bianca

Se hai aggiunto ini_set('display_errors', '1') e vedi ancora una pagina bianca, probabilmente l'errore è di sintassi. PHP analizza tutto il file prima di eseguire la prima riga, quindi un ; o una } mancanti fermano tutto prima che ini_set venga eseguita. Controlla il file dal terminale, che stampa sempre il messaggio:

php -l index.php
Errors parsing index.php
PHP Parse error:  syntax error, unexpected token "," in index.php on line 2

Il numero di riga indica dove PHP si è arreso, che spesso è la riga dopo l'errore vero. Correggilo, esegui di nuovo php -l finché non dice No syntax errors detected, poi ricarica la pagina.

Domande frequenti

Come mostro tutti gli errori in PHP?

Aggiungi ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); error_reporting(E_ALL); proprio in cima allo script, oppure imposta display_errors = On ed error_reporting = E_ALL in php.ini e riavvia il web server o PHP-FPM.

Perché la mia pagina PHP mostra una schermata bianca?

Un errore fatale ha fermato lo script mentre display_errors è disattivato, quindi non è stato stampato nulla. Attiva gli errori (oppure leggi il log degli errori, per esempio con tail -f sul file indicato da error_log) per vedere il messaggio e il numero di riga.

Perché ini_set('display_errors', 1) non mostra il mio errore di sintassi?

Un errore di sintassi ferma PHP prima che venga eseguita qualsiasi riga del file, quindi la chiamata a ini_set non avviene mai. Imposta display_errors in php.ini, oppure metti ini_set in un piccolo file che poi fa include di quello rotto.

display_errors deve essere attivo in produzione?

No. I messaggi di errore rivelano ai visitatori percorsi dei file e dettagli del codice. In produzione usa display_errors = Off, log_errors = On e un percorso per error_log, e mantieni error_reporting = E_ALL così i problemi vengono comunque registrati.

Cosa fa error_reporting(0)?

Disattiva la segnalazione di ogni tipo di errore per il resto dello script, quindi warning e persino errori fatali non producono alcun messaggio. Nasconde i problemi invece di risolverli; meglio registrare gli errori nel log che silenziarli.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA