# Errori ed eccezioni in PHP

> Errori ed eccezioni in PHP: Throwable, Error ed Exception, try/catch/finally, handler globali e impostazioni sicure per la visualizzazione degli errori e i log.

Fonte: https://phpsos.de/it/php/fehler-und-exceptions/  
Stato: 25/10/2026  
Fornitore: PHP SOS, Assistenza di emergenza PHP e sicurezza dei server. Assistenza immediata su WhatsApp: https://wa.me/491736494914?text=Buongiorno%20PHP%20SOS%2C%20abbiamo%20bisogno%20di%20aiuto%20con%20il%20nostro%20server%20PHP.%20Azienda%3A%20%E2%80%A6%20Sito%20web%3A%20%E2%80%A6

**In breve:** PHP segnala i problemi in due modi: come errori classici, ad esempio avvisi e notifiche, controllati tramite `error_reporting`, e come eccezioni, che si possono intercettare con `try` e `catch`. Da PHP 7 anche molti errori interni generano un oggetto della classe `Error`; insieme a `Exception` implementa l'interfaccia `Throwable`. In produzione vale la regola: registrare gli errori nel log, non mostrarli mai nel browser. Su PHP 8.5, a causa di PHP2Shell, tra le misure transitorie c'è inoltre `fatal_error_backtraces=0`.

## Due mondi: errori classici ed eccezioni

PHP nasce in un'epoca in cui gli errori venivano emessi soprattutto come messaggi: notifiche (`E_NOTICE`), avvisi (`E_WARNING`), funzioni obsolete (`E_DEPRECATED`) ed errori fatali (`E_ERROR`). Molti di questi messaggi lasciano proseguire lo script, spesso con dati errati o vuoti.

Le eccezioni funzionano diversamente. Interrompono il flusso normale e saltano al successivo blocco `catch` adatto. Se non ne viene trovato nessuno, lo script termina. Per chi decide la differenza è importante: un avviso silenzioso può far sì che un ordine venga salvato in modo incompleto senza che nessuno se ne accorga. Un'eccezione rende il problema visibile e gestibile.

Un vantaggio sottovalutato dei messaggi classici sono le notifiche di tipo `E_DEPRECATED`. Annunciano che uno strumento del linguaggio verrà eliminato in una futura versione di PHP. Chi le raccoglie nel log e le analizza con regolarità sa, prima di un upgrade, quali punti vanno adeguati, e in caso di vulnerabilità urgente non deve prima testare a lungo.

## La gerarchia di Throwable

Tutto ciò che si può lanciare con `throw` e intercettare con `catch` implementa `Throwable`. Al di sotto ci sono due rami:

| Classe | Scopo | Esempi di sottoclassi |
|---|---|---|
| `Exception` | errori prevedibili dell'applicazione e delle estensioni | `ErrorException`, `PDOException`, classi proprie |
| `Error` | errori interni di PHP | `TypeError`, `ValueError`, `ArgumentCountError`, `ArithmeticError`, `DivisionByZeroError`, `UnhandledMatchError` |

Le classi di errore proprie derivano da `Exception`, non da `Error`. Da PHP 8.0 la maggior parte delle funzioni interne, con parametri non validi, lancia un `TypeError` o un `ValueError` invece di emettere soltanto un avviso. `strlen([])` ne è un esempio.

## try, catch e finally nella pratica

```php
<?php
declare(strict_types=1);

final class ZahlungFehlgeschlagen extends RuntimeException {}

function bezahlen(Bestellung $b, Zahlungsdienst $dienst, LoggerInterface $log): bool
{
    try {
        $dienst->belasten($b->betrag(), $b->referenz());
        return true;
    } catch (ZahlungFehlgeschlagen $e) {
        $log->warning('Zahlung abgelehnt', ['bestellung' => $b->id(), 'exception' => $e]);
        return false;
    } catch (TimeoutException | VerbindungsFehler) {
        // da PHP 8.0 la variabile nel catch è facoltativa
        $log->error('Zahlungsdienst nicht erreichbar', ['bestellung' => $b->id()]);
        return false;
    } finally {
        $dienst->verbindungSchliessen();
    }
}
```

Più classi si possono riunire in un unico `catch` con `|`. Il blocco `finally` viene eseguito sempre, che si sia verificato un errore o no. Da PHP 8.0 `throw` è inoltre un'espressione e può comparire, ad esempio, dopo `??`: `$id = $_GET['id'] ?? throw new InvalidArgumentException('id fehlt');`.

## Handler globali: set_error_handler e set_exception_handler

Due funzioni intercettano ciò che altrimenti sfuggirebbe. `set_exception_handler()` registra una funzione per i Throwable non intercettati. Secondo il manuale, dopo la sua chiamata lo script termina; è quindi adatta per la registrazione nel log e per una pagina di errore neutra, non per proseguire il lavoro.

Si è rivelato valido un handler che scrive nel log l'errore completo con data e ora e un identificativo casuale, mostrando al visitatore solo una pagina neutra con tale identificativo. Il supporto può così ritrovare il caso nel log, senza che dettagli interni trapelino all'esterno.

`set_error_handler()` intercetta gli errori classici. Il manuale mostra come trasformarli in una `ErrorException`, in modo che gli avvisi vengano trattati come eccezioni:

```php
<?php
set_error_handler(function (int $nr, string $text, string $datei, int $zeile): bool {
    if (!(error_reporting() & $nr)) {
        return false; // esclusa da error_reporting
    }
    if ($nr === E_DEPRECATED || $nr === E_USER_DEPRECATED) {
        return false; // non trasformare in eccezioni le segnalazioni di funzioni obsolete
    }
    throw new ErrorException($text, 0, $nr, $datei, $zeile);
});
```

Gli errori fatali, come un superamento della memoria, non si possono intercettare in questo modo. Che cosa accade internamente in caso di superamento lo spiega la pagina [memory_limit e Out-of-Memory](https://phpsos.de/it/php/out-of-memory/).

## Configurare la visualizzazione e la registrazione degli errori

Le impostazioni più importanti con i loro valori predefiniti secondo il manuale:

| Impostazione | Predefinito | Raccomandazione per la produzione |
|---|---|---|
| `error_reporting` | `E_ALL` da PHP 8.0.0 | `E_ALL` |
| `display_errors` | `1` | `Off` |
| `display_startup_errors` | `1` da PHP 8.0.0 | `Off` |
| `log_errors` | `0` | `On` |
| `error_log` | vuoto (log del server web o della SAPI) | file proprio fuori dal webroot |
| `fatal_error_backtraces` | `1`, nuova in PHP 8.5.0 | temporaneamente `0` (PHP2Shell) |

Da PHP 8.2.0 `error_log_mode` stabilisce i permessi del file di log, per impostazione predefinita `0644`. Se i log contengono dati personali o percorsi, è sensato un valore più restrittivo, perché gli altri utenti sul server non possano leggerli. Con `ignore_repeated_errors` si possono riunire i messaggi identici provenienti dallo stesso file e dalla stessa riga, perché un ciclo di errori non sommerga il log.

Il `php.ini-production` fornito con PHP imposta già `display_errors` su `Off`. Secondo il manuale `ini_set('display_errors', ...)` in fase di esecuzione non ha effetto sugli errori fatali, e gli errori di sintassi si verificano prima ancora che un `ini_set()` venga eseguito. Questi valori appartengono quindi alla configurazione del server. Gli approfondimenti si trovano nell'articolo [Disattivare la visualizzazione degli errori in produzione](https://phpsos.de/it/blog/display-errors-produktion/); come tenere i log senza fughe di dati, nell'articolo [Registrare i log in modo sicuro](https://phpsos.de/it/blog/sicher-loggen-php/).

## Gestione degli errori e PHP2Shell

Per PHP 8.5 php.net indica, tra le misure transitorie contro PHP2Shell, di impostare `fatal_error_backtraces=0` e di riavviare poi PHP. Le altre misure riguardano `memory_limit`, `post_max_size` e `session.upload_progress.enabled`. Nessuna di esse sostituisce l'aggiornamento a PHP 8.5.12, 8.4.27, 8.3.36 o 8.2.35.

```ini
; solo PHP 8.5, in php.ini o nel pool FPM, poi riavviare tutti i worker
fatal_error_backtraces = 0
```

Dopo PHP2Shell i log degli errori sono inoltre un'importante prova. Se dal 20/10/2026 si accumulano errori di memoria o worker interrotti, ciò può indicare tentativi di attacco, ma può avere anche cause innocue. Conservi i log e li analizzi insieme ai log degli accessi, come descritto nella guida [Analizzare i log del server web dopo un attacco](https://phpsos.de/it/ratgeber/logfiles-auswerten/).

## Come aiuta concretamente PHP SOS?

- Verifichiamo le impostazioni effettive per la visualizzazione degli errori e la registrazione per ogni sito web e le configuriamo in modo adatto alla produzione.
- Applichiamo le misure transitorie PHP2Shell in base alla versione di PHP e riavviamo tutti i worker.
- Mettiamo al sicuro i log degli errori e degli accessi dal 20/10/2026 e li analizziamo alla ricerca di anomalie.
- Nell'ambito del [monitoraggio della sicurezza](https://phpsos.de/it/leistungen/security-monitoring/) segnaliamo concentrazioni insolite di errori, invece di lasciarle disperdere nel log.


## Domande frequenti

**Qual è la differenza tra Error ed Exception?**  
Entrambe implementano l'interfaccia Throwable. Exception è pensata per gli errori che un'applicazione si aspetta e gestisce, ad esempio una connessione al database non riuscita. Error indica errori interni di PHP come un TypeError o una divisione per zero.

**display_errors dovrebbe essere attivo in produzione?**  
No. I messaggi di errore nel browser rivelano percorsi, query e talvolta credenziali. In produzione display_errors va impostato su Off e log_errors su On, così gli errori finiscono nel log e non davanti al visitatore.

**Si può intercettare un superamento della memoria con try/catch?**  
No. Se uno script supera memory_limit, PHP lo termina con un errore fatale che non può essere intercettato come eccezione. Compare solo nel log degli errori, se log_errors è attivo.

**Che cos'è fatal_error_backtraces?**  
Un'impostazione disponibile da PHP 8.5.0 che aggiunge un backtrace agli errori fatali. È attiva per impostazione predefinita. Come misura transitoria contro PHP2Shell, per PHP 8.5 php.net indica di impostarla su 0 e di riavviare poi PHP.

## Fonti

- [Manuale PHP: configurazione della gestione degli errori](https://www.php.net/manual/de/errorfunc.configuration.php)
- [Manuale PHP: classe Error](https://www.php.net/manual/de/class.error.php)
- [Manuale PHP: ErrorException](https://www.php.net/manual/en/class.errorexception.php)
- [Manuale PHP: set_exception_handler](https://www.php.net/manual/en/function.set-exception-handler.php)
- [php.net: bollettini di sicurezza](https://www.php.net/)
