Amici, oggi parliamo di qualcosa che fa impazzire chiunque abbia mai dovuto scavare nel codice PHP di qualcun altro. Apri un sito web e non c'è niente. Una schermata bianca. Nessun errore, nessun indizio su cosa sia andato storto.

Vi suona familiare?

Questo è il caso classico di un errore fatale di PHP che uccide semplicemente lo script e scompare nel nulla senza salutare. Oggi impareremo come far parlare PHP, attivare i log e trovare quegli errori fatali che si nascondono dietro la "schermata bianca della morte".

Perché PHP tace: un po' di teoria

Per prima cosa, cerchiamo di capire come PHP gestisce gli errori in generale. Non è solo "errore -> log". C'è un'intera gerarchia.

In PHP 7+, tutto ciò che può andare storto implementa l'interfaccia Throwable. Ha due eredi principali: - Error — errori interni di PHP (fatali, di parse, di tipo) - Exception — eccezioni che possono essere catturate con try-catch

Gli errori fatali (E_ERROR, E_PARSE, E_CORE_ERROR) sono l'incubo peggiore di ogni sviluppatore. Uccidono lo script all'istante, e i gestori standard tramite set_error_handler() non li catturano . L'unico modo per intercettare un errore fatale è usare register_shutdown_function().

Ma procediamo passo dopo passo. Prima di tutto, dobbiamo attivare il logging in modo che gli errori vengano effettivamente scritti da qualche parte.

Passo 1: Attivare il logging tramite php.ini

Il modo più corretto per configurare i log è modificare il file di configurazione di PHP. Dove si trova dipende dal vostro sistema :

| Sistema | Percorso per php.ini | |---------|----------------------| | Ubuntu/Debian (Apache) | /etc/php/7.x/apache2/php.ini | | Ubuntu/Debian (CLI) | /etc/php/7.x/cli/php.ini | | Ubuntu/Debian (PHP-FPM) | /etc/php/7.x/fpm/php.ini | | CentOS/RHEL | /etc/php.ini o /etc/php.d/ | | Windows (XAMPP) | C:\xampp\php\php.ini | | Windows (WAMP) | C:\wamp\bin\php\phpX.X.X\php.ini |

In questo file, ci interessano le seguenti direttive :

```ini ; Abilita la scrittura degli errori in un file di log (obbligatorio!) log_errors = On

; Specifica il percorso del file di log error_log = /var/log/php_errors.log

; Disabilita la visualizzazione degli errori sullo schermo (per la produzione!) display_errors = Off

; Per lo sviluppo, puoi abilitarlo, ma disabilitalo dopo display_startup_errors = Off

; Livello di segnalazione errori — tutti gli errori error_reporting = E_ALL ```

Importante: L'interfaccia a riga di comando (CLI) usa il proprio php.ini, e i log potrebbero essere scritti in un luogo diverso . Se state testando uno script nella console, verificate separatamente.

Dopo aver apportato le modifiche, è necessario riavviare il server web : bash sudo systemctl restart apache2 # per Apache sudo systemctl restart php7.4-fpm # per PHP-FPM

Cosa significano queste impostazioni

  • log_errors = On — abilita la scrittura degli errori in un file. Senza questo, PHP rimarrà muto come una tomba .
  • error_log — il percorso del file in cui verrà scritto tutto. È fondamentale che l'utente del server web (di solito www-data o apache) abbia i permessi di scrittura per questo file e la sua directory .
  • display_errors = Off — disabilitare assolutamente in produzione per non esporre dettagli agli utenti .
  • error_reporting = E_ALL — registra tutti i tipi di errori. Per la produzione, potete limitarlo, ma per il debug è meglio vedere tutto.

Passo 2: Alternativa: Attivare il logging direttamente nel codice

Se non avete accesso a php.ini (ad esempio, in un hosting condiviso), potete provare ad attivare il logging direttamente nel vostro script usando la funzione ini_set().

Inserite questo all'inizio del file problematico:

```php

/dev/null ``` Oppure create un file PHP con `phpinfo();` e cercate la sezione **error_log**. ## Passo 4: Leggere i log: strumenti e tecniche Una volta che i log vengono scritti, dovete sapere come visualizzarli e filtrarli rapidamente. ### tail — Visualizzare gli ultimi eventi ```bash # Ultime 50 righe tail -n 50 /var/log/php_errors.log # Seguire in tempo reale (come docker logs -f) tail -f /var/log/php_errors.log ``` ### grep — Cercare errori specifici ```bash # Solo errori fatali grep "Fatal error" /var/log/php_errors.log # Errori di parse (errori di sintassi) grep "Parse error" /var/log/php_errors.log # Ignorare maiuscole/minuscole grep -i "warning" /var/log/php_errors.log ``` ### less — Visualizzazione comoda con navigazione ```bash less /var/log/php_errors.log ``` All'interno di less, potete premere `/` e digitare una parola per cercare, `n` per il risultato successivo, `N` per il precedente. ### Combinazioni — Una pipeline potente ```bash # Mostra le ultime 100 righe e cerca errori tail -n 100 /var/log/php_errors.log | grep -i fatal # Seguire e filtrare in tempo reale tail -f /var/log/php_errors.log | grep --line-buffered "error" # Contare gli errori per tipo grep -o "PHP [A-Za-z]* error" /var/log/php_errors.log | sort | uniq -c ``` ## Passo 5: Decifrare gli errori: cos'è cosa Una voce di log tipica assomiglia a questa : ``` [2026-03-04 14:35:22 UTC] PHP Fatal error: Uncaught Error: Call to undefined function foo() in /var/www/html/index.php on line 10 ``` Analizziamola: - **Data e Ora** — quando è successo - **PHP Fatal error** — il livello di errore - **Uncaught Error: Call to undefined function foo()** — il messaggio - **/var/www/html/index.php:10** — il file e il numero di riga Principali livelli di errore : | Livello | Significato | Esempio | |---------|-------------|---------| | **E_ERROR** / **Fatal error** | Errore fatale, lo script muore | Chiamata a funzione inesistente, memoria insufficiente | | **E_WARNING** / **Warning** | Avvertimento, ma lo script continua | `include` di un file inesistente | | **E_PARSE** / **Parse error** | Errore di sintassi, lo script non parte | Punto e virgola mancante | | **E_NOTICE** / **Notice** | Notifica, generalmente non critica | Accesso a variabile non definita | | **E_DEPRECATED** | Costrutto obsoleto | Uso di `mysql_connect()` | ## Passo 6: Catturare gli errori fatali (La parte interessante) Gli errori fatali sono quelli che non possono essere catturati dal `set_error_handler()` standard. Uccidono lo script all'istante, e il gestore predefinito semplicemente non fa in tempo a eseguirsi . Ma c'è un modo! Usate `register_shutdown_function()` — questa funzione viene chiamata in ogni caso, anche in caso di errore fatale . ### Semplice gestore di errori fatali ```php getMessage()." | ".$e->getFile().":".$e->getLine()." | $url\n"; file_put_contents($logFile, $msg, FILE_APPEND); }); // Gestore per errori fatali register_shutdown_function(function() use ($logFile) { $error = error_get_last(); if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { $url = ($_SERVER['HTTP_HOST'] ?? 'CLI') . ($_SERVER['REQUEST_URI'] ?? ''); $msg = "[".date('Y-m-d H:i:s')."] [FATAL] ".$error['message']." | ".$error['file'].":".$error['line']." | $url\n"; file_put_contents($logFile, $msg, FILE_APPEND); } }); ``` Potete inserire questo codice all'inizio del vostro file principale (ad esempio, `index.php` o `header.php`), e catturerà assolutamente tutto . ## Passo 7: Log nei framework popolari Se usate un framework moderno, il logging è già configurato, ma i percorsi dei log sono diversi. ### Laravel I log sono memorizzati in `storage/logs/laravel.log`. Di default, usa Monolog; il formato può essere testo o JSON. Per vedere gli errori: ```bash tail -f storage/logs/laravel.log ``` ### Symfony Log predefiniti: `var/log/dev.log` e `var/log/prod.log`. Usa anche Monolog, altamente configurabile. ### WordPress Di default, WordPress non scrive log, ma potete abilitarli aggiungendo questo a `wp-config.php`: ```php define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false); ``` I log saranno in `/wp-content/debug.log`. ## Passo 8: Problemi comuni e loro soluzioni ### Problema: I log non vengono scritti affatto Cosa verificare: 1. `log_errors = On` è sicuramente impostato? 2. Ci sono permessi di scrittura per il file e la sua directory? 3. Avete modificato il php.ini corretto (verificare con `phpinfo()`)? 4. Avete riavviato il server web dopo le modifiche? ### Problema: Gli errori fatali non vengono catturati Anche con il logging attivato, a volte gli errori fatali non vengono scritti se si verificano molto presto (ad esempio, un errore di parse nel file stesso in cui state attivando il logging). L'unica soluzione è il corretto posizionamento — all'inizio, prima di qualsiasi altra cosa . ### Problema: Troppi log Se `E_ALL` è attivato in produzione, i log cresceranno rapidamente. Configurate `error_reporting` in modo sensato : ```ini error_reporting = E_ALL & ~E_DEPRECATED & ~E_NOTICE ``` ### Problema: I log riempiono il disco Impostate la rotazione dei log con `logrotate`. Una configurazione per i log PHP: ``` /var/log/php_errors.log { daily rotate 30 compress delaycompress missingok notifempty create 644 www-data www-data } ``` ## Passo 9: Esempio pratico: Indagare su una pagina bianca Immaginiamo una situazione: aprite un sito web ed è bianco. Cosa fare passo dopo passo? 1. **Controllate i log del server web** (Apache/Nginx) — spesso contengono un indizio 2. **Controllate i log PHP** — cercate voci degli ultimi minuti ```bash tail -n 50 /var/log/php_errors.log | grep -A5 -B5 "$(date +%Y-%m-%d)" ``` 3. **Trovate l'errore** : ``` [2026-03-04 15:30:22] PHP Fatal error: Uncaught Error: Class 'DB' not found in /var/www/site/index.php on line 12 ``` 4. **Aprite il file**, controllate la riga 12 — effettivamente, avete dimenticato di includere la classe. 5. **Correggete**, testate — il sito funziona! Magia! ## Riferimento rapido: Prontuario | Azione | Comando / Codice | |--------|------------------| | Abilitare logging in php.ini | `log_errors = On` + `error_log = /percorso/del/file` | | Abilitare nel codice | `ini_set('log_errors', 'On');` | | Vedere le ultime righe | `tail -f /var/log/php_errors.log` | | Cercare errori fatali | `grep "Fatal error" /var/log/php_errors.log` | | Catturare errori fatali | `register_shutdown_function()` + `error_get_last()` | | Dove sono i log di Laravel? | `storage/logs/laravel.log` | | Dove sono i log di Symfony? | `var/log/dev.log` e `var/log/prod.log` | ## Invece di una conclusione PHP non è così spaventoso come spesso viene dipinto. Sì, la schermata bianca della morte è terrificante, ma dietro di essa c'è sempre un errore specifico che semplicemente non vuole parlare. Imparate ad attivare i log, e PHP inizierà a parlare. Le regole principali: - In produzione, **sempre** attivare `log_errors` e disattivare `display_errors` - Scrivere i log in un file dedicato, non in syslog — è più facile cercare - Usare `register_shutdown_function` per catturare gli errori fatali - Controllare i log regolarmente — almeno una volta al giorno E ricordate: il codice perfetto non scrive errori. Ma se si verifica un errore, che lasci almeno un biglietto. ?>