error_reporting()
Scopri come PHP gestisce la segnalazione degli errori con error_reporting(), display_errors e log_errors per sviluppo e produzione.
Introduzione
Questo capitolo illustra come PHP segnala gli errori: la funzione error_reporting() che controlla quali errori PHP genera, le direttive display_errors e log_errors che controllano dove vengono inviati, e le funzioni di supporto per gestirli e registrarli. Al termine saprai come configurare la segnalazione degli errori in modo diverso per lo sviluppo e la produzione, e perché configurarla in modo errato è uno degli errori di sicurezza e debug più comuni in PHP.
Perché la segnalazione degli errori è importante
PHP è un linguaggio dinamicamente tipizzato e permissivo: molti errori che bloccherebbero la compilazione in altri linguaggi emergono invece a runtime come avvisi, notifiche o messaggi di deprecazione. Se li sopprimi, comportamenti errati possono arrivare silenziosamente in produzione. Se li mostri agli utenti finali, rischi di rivelare percorsi di file, SQL e stack trace agli aggressori.
Una buona segnalazione degli errori trova il giusto equilibrio per ciascun ambiente:
- In sviluppo — mostra tutto, chiaramente, così individui i bug mentre scrivi.
- In produzione — non mostrare nulla all'utente, ma registra tutto in un file per analisi successive.
Livelli di errore e costanti
Gli errori PHP sono classificati per livello. Ogni livello è una costante predefinita e si combinano con gli operatori bit a bit. I livelli più comuni:
| Costante | Significato |
|---|---|
E_ERROR | Errore fatale a runtime; l'esecuzione dello script si interrompe. |
E_WARNING | Avviso a runtime; lo script continua. |
E_NOTICE | Notifica (ad es. uso di una variabile non definita). |
E_DEPRECATED | Uso di una funzionalità che sarà rimossa in una futura versione di PHP. |
E_USER_ERROR / E_USER_WARNING / E_USER_NOTICE | Livelli che puoi generare tu stesso con trigger_error(). |
E_ALL | Tutti gli errori, avvisi e notifiche. |
Poiché sono flag bit, si combinano con | (inclusione), & (maschera) e ~ (negazione):
// All errors EXCEPT notices and deprecation messages
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
// Only fatal errors and warnings
error_reporting(E_ERROR | E_WARNING);Nota sulla versione: Da PHP 8.0 il livello predefinito di
error_reportingèE_ALL.E_STRICTè stato deprecato in 8.0 e rimosso in 8.4, e le sue notifiche sono ora incluse inE_ALL, quindi non è più necessario aggiungerlo separatamente.
Segnalazione vs. visualizzazione: due impostazioni distinte
Una fonte frequente di confusione è che due interruttori indipendenti decidono se un errore viene effettivamente mostrato:
error_reporting()— decide quali livelli PHP genera.display_errors— decide se gli errori generati vengono stampati nell'output.
Devi attivare entrambi per vedere un errore sullo schermo. L'esempio seguente genera una notifica di livello E_ALL e la stampa perché entrambi gli interruttori sono attivi:
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
echo $undefined; // Warning: Undefined variable $undefinedSe display_errors fosse disattivato, la stessa notifica verrebbe comunque generata (e potrebbe essere registrata), ma non apparirebbe nell'output della pagina.
Le funzioni principali per la segnalazione degli errori
error_reporting()
Imposta quali livelli di errore vengono segnalati a runtime e restituisce il livello precedente. Chiamala senza argomenti per leggere l'impostazione corrente.
<?php
$old = error_reporting(E_ALL & ~E_NOTICE);
echo "Now reporting all errors except notices.\n";
echo "Previous level was: " . $old . "\n";ini_set()
Sovrascrive una direttiva di php.ini per la durata dello script corrente. È l'equivalente a runtime della modifica di php.ini, ed è il modo per attivare display_errors, display_startup_errors e log_errors dall'interno del codice.
<?php
// Development setup: show everything on screen
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);Nota: display_errors non può intercettare gli errori fatali di parsing nello stesso file, perché l'intero file non riesce a compilarsi prima che ini_set() venga eseguita. Per questi casi, imposta la direttiva direttamente in php.ini.
set_error_handler()
Registra un callback che viene eseguito ogni volta che viene generato un errore (non fatale), permettendoti di sostituire il comportamento predefinito di PHP — ad esempio per convertire gli avvisi in eccezioni o per formattarli come JSON per un'API. Il callback riceve il livello di errore, il messaggio, il file e la riga.
<?php
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {
echo "[$errno] $errstr in " . basename($errfile) . " on line $errline\n";
return true; // true = we handled it; PHP's internal handler is skipped
});
echo $undefined; // routed to our handler instead of the default messageVedi set_error_handler() per la firma completa e come ripristinare il gestore precedente.
error_log() e trigger_error()
error_log()invia un messaggio al log configurato di PHP, a un file specifico o a un indirizzo email — mai all'output della pagina. Questo è il modo sicuro per la produzione di registrare i problemi.trigger_error()genera un errore definito da te (livelliE_USER_*), che poi scorre attraverso la stessa pipeline dierror_reporting/gestore degli errori integrati.
<?php
// Append a message to a specific log file (message type 3)
error_log("Payment gateway timed out", 3, "/var/log/php_errors.log");
// Raise a user-level warning that your handler / log can pick up
trigger_error("Cache miss for product 42", E_USER_WARNING);Approfondisci in error_log() e trigger_error().
Configurazione consigliata per ambiente
Anziché distribuire le impostazioni ovunque, inseriscile in cima al file di bootstrap.
<?php
// --- Development ---
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');<?php
// --- Production ---
error_reporting(E_ALL); // still GENERATE everything...
ini_set('display_errors', '0'); // ...but never show it to users...
ini_set('log_errors', '1'); // ...log it instead.
ini_set('error_log', '/var/log/php_errors.log');Il blocco di produzione mantiene la piena visibilità tramite i log senza esporre nulla ai visitatori — la configurazione che quasi sempre si desidera su un server live.
Best practice
- Non eseguire mai in produzione con
display_errorsattivo. Percorsi e stack trace esposti costituiscono un rischio di divulgazione di informazioni. - Segnala sempre con
E_ALLovunque. Segnalazione e visualizzazione sono separate; sopprimere i livelli nasconde solo i bug. - Evita l'operatore di soppressione degli errori
@. Nasconde gli errori nel punto di chiamata e rende il debug molto più difficile; gestisci esplicitamente la condizione. - Cattura ciò che puoi come eccezioni. Per i fallimenti recuperabili, preferisci
try/catchai gestori di errori. Vedi PHP Exceptions. - Usa una libreria di logging nelle app più grandi. Strumenti come Monolog offrono livelli di log, rotazione e destinazioni multiple su
error_log().
Conclusione
La segnalazione degli errori in PHP si articola in tre livelli: scegliere i livelli con error_reporting(), scegliere la destinazione con display_errors / log_errors, e facoltativamente personalizzare la gestione con set_error_handler() e trigger_error(). Configurali deliberatamente — verbosi sullo schermo durante lo sviluppo, silenziosi ma registrati in produzione — e otterrai un debug rapido senza esporre l'applicazione a utenti o aggressori.
Letture correlate: PHP Error handling · error_get_last() · try…catch.