set_exception_handler()
Come set_exception_handler() di PHP registra un gestore globale per eccezioni non catturate, con firma, valore restituito, esempio pratico e best practice.
Introduzione
set_exception_handler() registra una funzione che PHP chiama ogni volta che un'eccezione non catturata raggiunge il livello più alto dello script. Normalmente un'eccezione non catturata produce un errore fatale e uno stack trace predefinito; un gestore globale consente di sostituire tutto ciò con una registrazione consistente, una pagina di errore amichevole o un sistema di notifica — in un unico punto, per l'intera applicazione. Questa pagina tratta la firma della funzione, il valore restituito, un esempio eseguibile, i casi che non gestisce e le insidie da conoscere.
Se hai bisogno prima delle basi su come lanciare e catturare eccezioni, inizia con Eccezioni PHP e il capitolo try/catch.
Quando viene chiamato il gestore?
Una normale eccezione viene catturata dal primo blocco catch corrispondente. Il gestore globale viene eseguito solo quando nessun blocco catch corrisponde — l'eccezione "sfugge" fino in cima allo script:
try {
throw new RuntimeException('handled here');
} catch (RuntimeException $e) {
// caught locally — the global handler never runs
}
throw new RuntimeException('nothing catches this'); // → global handler runs, then script endsDopo che il gestore ritorna, l'esecuzione non riprende — lo script termina. Il gestore è quindi la tua ultima possibilità per registrare e presentare l'errore in modo pulito, non un modo per recuperare e continuare.
Firma e valore restituito
set_exception_handler(?callable $callback): ?callable$callback— un callable che accetta l'oggetto lanciato come unico argomento. Da PHP 7 ogni eccezione ed errore implementaThrowable, quindi è consigliabile usareThrowablecome type-hint del parametro (non soloException) per catturare anche le istanze diErrorcomeTypeError.- Restituisce il gestore registrato in precedenza (o
nullse nessuno era impostato), che puoi conservare per ripristinarlo in seguito. Passarenullrimuove il gestore.
Esempio eseguibile
Lo script seguente registra un gestore, lo attiva con un'eccezione non catturata e stampa un messaggio formattato. Scrive sull'errore standard tramite error_log() senza destinazione, quindi è completamente portabile:
<?php
function appExceptionHandler(Throwable $e): void
{
$message = sprintf(
"Uncaught %s: %s in %s on line %d",
get_class($e),
$e->getMessage(),
$e->getFile(),
$e->getLine()
);
error_log($message); // goes to the SAPI error log / stderr
echo "Something went wrong.\n"; // user-facing message
}
set_exception_handler('appExceptionHandler');
throw new RuntimeException('Database is unreachable');Output (la riga error_log va a stderr, echo a stdout):
Something went wrong.con una riga come Uncaught RuntimeException: Database is unreachable in /path/to/script.php on line 19 nel log degli errori.
Cosa NON gestisce
set_exception_handler() intercetta solo le eccezioni non catturate. Non cattura:
- Errori fatali, errori di analisi o avvisi — questi passano attraverso
set_error_handler()(per gli errori catturabili) oregister_shutdown_function()(per i fatali). - Le eccezioni già catturate da un blocco
try/catchlocale.
Per errori non-eccezione come avvisi e notifiche, registra un gestore separato con set_error_handler().
Ripristino del gestore precedente
restore_exception_handler() ripristina il gestore che era attivo prima dell'ultima chiamata a set_exception_handler(). Usalo quando un gestore personalizzato deve applicarsi solo a un blocco di codice specifico:
<?php
set_exception_handler(function (Throwable $e) {
echo "Custom: {$e->getMessage()}\n";
});
// ... code that should use the custom handler ...
restore_exception_handler(); // back to the default behaviorImportante: il tuo gestore non deve lanciare una nuova eccezione. In caso contrario, PHP non può distribuirla nuovamente e genera invece un errore fatale.
Best Practice per l'uso di set_exception_handler
Quando si utilizza set_exception_handler, ci sono alcune best practice da seguire per garantire che l'applicazione gestisca gli errori in modo efficace:
- Usa
Throwablecome type-hint del parametro del gestore in modo da catturare sia i sottotipi diExceptionche diError(PHP 7+). - Assicurati che il gestore non lanci mai una nuova eccezione — ciò causerebbe un errore fatale non recuperabile.
- Registra abbastanza contesto per diagnosticare il problema: classe dell'eccezione, messaggio, file, riga e lo stack trace da
$e->getTraceAsString(). - Mantieni il messaggio rivolto all'utente generico; non esporre mai stack trace o messaggi agli utenti finali in produzione.
- Registra il gestore il prima possibile (ad es. in un file di bootstrap) in modo che copra l'intera richiesta.
- Abbinalo a
set_error_handler()eregister_shutdown_function()per coprire anche avvisi, notifiche ed errori fatali. - Usa
restore_exception_handler()per ripristinare il gestore precedente quando uno personalizzato deve essere limitato a un blocco di codice.
Conclusione
set_exception_handler() ti fornisce un unico punto per gestire tutte le eccezioni non catturate in un'applicazione — trasformando un errore fatale grezzo in una registrazione consistente e un messaggio pulito per l'utente. Ricorda i suoi limiti: viene eseguito solo per le eccezioni non catturate, l'esecuzione si interrompe dopo, e il gestore stesso non deve mai lanciare eccezioni. Combinalo con set_error_handler() per gli avvisi, trigger-error per segnali di errore personalizzati e restore_exception_handler() per la gestione con ambito limitato, per costruire un sistema di segnalazione degli errori robusto.