Freunde, heute sprechen wir über etwas, das jeden, der schon einmal in fremdem PHP-Code herumgestochert hat, zur Weißglut bringt. Sie öffnen eine Website, und da ist nichts. Ein leerer Bildschirm. Kein Fehler, kein Hinweis darauf, was schiefgelaufen ist.
Kommt Ihnen das bekannt vor?
Dies ist der klassische Fall eines schwerwiegenden PHP-Fehlers, der das Skript einfach tötet und verschwindet, ohne sich zu verabschieden. Heute lernen wir, wie wir PHP zum Sprechen bringen, Logs aktivieren und genau jene fatalen Fehler finden, die sich hinter dem "Weißen Bildschirm des Todes" verstecken.
Warum PHP schweigt: Ein wenig Theorie
Lassen Sie uns zunächst verstehen, wie PHP Fehler grundsätzlich behandelt. Es ist nicht nur "Fehler -> Log". Es gibt eine ganze Hierarchie.
In PHP 7+ implementiert alles, was schiefgehen kann, die Schnittstelle Throwable. Sie hat zwei Hauptzweige: - Error — interne PHP-Fehler (fatal, Parse, Typenfehler) - Exception — Ausnahmen, die mit try-catch abgefangen werden können
Schwerwiegende Fehler (E_ERROR, E_PARSE, E_CORE_ERROR) sind der schlimmste Albtraum eines jeden Entwicklers. Sie töten das Skript sofort, und standardmäßige Behandler via set_error_handler() fangen sie nicht ab . Der einzige Weg, einen fatalen Fehler abzufangen, ist die Verwendung von register_shutdown_function().
Aber gehen wir Schritt für Schritt vor. Zuerst müssen wir das Logging aktivieren, damit Fehler überhaupt irgendwo geschrieben werden.
Schritt 1: Logging über php.ini aktivieren
Der korrekteste Weg, Logs zu konfigurieren, ist die Bearbeitung der PHP-Konfigurationsdatei. Wo sie sich befindet, hängt von Ihrem System ab :
| System | Pfad zu 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 oder /etc/php.d/ |
| Windows (XAMPP) | C:\xampp\php\php.ini |
| Windows (WAMP) | C:\wamp\bin\php\phpX.X.X\php.ini |
In dieser Datei interessieren uns die folgenden Direktiven :
```ini ; Schreiben von Fehlern in eine Logdatei aktivieren (zwingend erforderlich!) log_errors = On
; Pfad zur Logdatei angeben error_log = /var/log/php_errors.log
; Anzeige von Fehlern auf dem Bildschirm deaktivieren (für Produktion!) display_errors = Off
; Für die Entwicklung können Sie dies aktivieren, aber später wieder deaktivieren display_startup_errors = Off
; Fehlerberichtsebene — alle Fehler error_reporting = E_ALL ```
Wichtig: Die Kommandozeile (CLI) verwendet ihre eigene php.ini, und Logs können an einem anderen Ort geschrieben werden . Wenn Sie ein Skript in der Konsole testen, überprüfen Sie bitte separat.
Nach Änderungen müssen Sie den Webserver neu starten :
bash
sudo systemctl restart apache2 # für Apache
sudo systemctl restart php7.4-fpm # für PHP-FPM
Was diese Einstellungen bedeuten
- log_errors = On — aktiviert das Schreiben von Fehlern in eine Datei. Ohne dies schweigt PHP wie ein Grab .
- error_log — der Pfad zur Datei, in die alles geschrieben wird. Es ist entscheidend, dass der Webserver-Benutzer (normalerweise
www-dataoderapache) Schreibrechte für diese Datei und ihr Verzeichnis hat . - display_errors = Off — in Produktion unbedingt deaktivieren, um keine Details an Benutzer preiszugeben .
- error_reporting = E_ALL — alle Fehlertypen protokollieren. Für die Produktion können Sie dies einschränken, aber zum Debuggen ist es besser, alles zu sehen.
Schritt 2: Alternative: Logging direkt im Code aktivieren
Wenn Sie keinen Zugriff auf die php.ini haben (z.B. bei Shared Hosting), können Sie versuchen, das Logging direkt in Ihrem Skript mit der Funktion ini_set() zu aktivieren.
Fügen Sie dies ganz an den Anfang der problematischen Datei ein:
```php
/dev/null ``` Oder erstellen Sie eine PHP-Datei mit `phpinfo();` und suchen Sie nach dem Abschnitt **error_log**. ## Schritt 4: Logs lesen: Werkzeuge und Techniken Sobald Logs geschrieben werden, müssen Sie wissen, wie Sie sie schnell anzeigen und filtern können. ### tail — Die letzten Ereignisse anzeigen ```bash # Letzte 50 Zeilen tail -n 50 /var/log/php_errors.log # In Echtzeit folgen (wie docker logs -f) tail -f /var/log/php_errors.log ``` ### grep — Nach bestimmten Fehlern suchen ```bash # Nur fatale Fehler grep "Fatal error" /var/log/php_errors.log # Parse-Fehler (Syntaxfehler) grep "Parse error" /var/log/php_errors.log # Groß-/Kleinschreibung ignorieren grep -i "warning" /var/log/php_errors.log ``` ### less — Komfortable Ansicht mit Navigation ```bash less /var/log/php_errors.log ``` In less können Sie `/` drücken und ein Wort zur Suche eingeben, `n` für den nächsten Treffer, `N` für den vorherigen. ### Kombinationen — Eine mächtige Pipeline ```bash # Die letzten 100 Zeilen anzeigen und nach Fehlern suchen tail -n 100 /var/log/php_errors.log | grep -i fatal # In Echtzeit folgen und sofort filtern tail -f /var/log/php_errors.log | grep --line-buffered "error" # Fehler nach Typ zählen grep -o "PHP [A-Za-z]* error" /var/log/php_errors.log | sort | uniq -c ``` ## Schritt 5: Fehler entschlüsseln: Was ist was Ein typischer Logeintrag sieht so aus : ``` [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 ``` Wir analysieren ihn: - **Datum und Uhrzeit** — wann es passiert ist - **PHP Fatal error** — die Fehlerstufe - **Uncaught Error: Call to undefined function foo()** — die Meldung - **/var/www/html/index.php:10** — die Datei und Zeilennummer Wichtigste Fehlerstufen : | Stufe | Bedeutung | Beispiel | |-------|-----------|----------| | **E_ERROR** / **Fatal error** | Schwerwiegender Fehler, Skript stirbt | Aufruf einer nicht existierenden Funktion, Speichermangel | | **E_WARNING** / **Warning** | Warnung, aber Skript läuft weiter | `include` einer nicht existierenden Datei | | **E_PARSE** / **Parse error** | Syntaxfehler, Skript startet nicht | Fehlendes Semikolon | | **E_NOTICE** / **Notice** | Hinweis, meist nicht kritisch | Zugriff auf undefinierte Variable | | **E_DEPRECATED** | Veraltete Konstruktion | Verwendung von `mysql_connect()` | ## Schritt 6: Fatale Fehler abfangen (Der interessante Teil) Fatale Fehler sind diejenigen, die nicht vom standardmäßigen `set_error_handler()` abgefangen werden können. Sie töten das Skript sofort, und der Standardbehandler hat einfach keine Zeit mehr, ausgeführt zu werden . Aber es gibt einen Weg! Verwenden Sie `register_shutdown_function()` — diese Funktion wird auf jeden Fall aufgerufen, selbst bei einem fatalen Fehler . ### Einfacher Behandler für fatale Fehler ```php getMessage()." | ".$e->getFile().":".$e->getLine()." | $url\n"; file_put_contents($logFile, $msg, FILE_APPEND); }); // Behandler für fatale Fehler 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); } }); ``` Sie können einen solchen Code ganz an den Anfang Ihrer Hauptdatei (z.B. `index.php` oder `header.php`) einfügen, und er wird absolut alles abfangen . ## Schritt 7: Logs in gängigen Frameworks Wenn Sie ein modernes Framework verwenden, ist das Logging bereits eingerichtet, aber die Pfade zu den Logs sind anders. ### Laravel Logs werden in `storage/logs/laravel.log` gespeichert. Standardmäßig wird Monolog verwendet; das Format kann Text oder JSON sein. So sehen Sie Fehler: ```bash tail -f storage/logs/laravel.log ``` ### Symfony Standard-Logs: `var/log/dev.log` und `var/log/prod.log`. Verwendet ebenfalls Monolog, hochgradig konfigurierbar. ### WordPress Standardmäßig schreibt WordPress keine Logs, aber Sie können sie aktivieren, indem Sie dies in `wp-config.php` einfügen: ```php define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false); ``` Die Logs befinden sich dann in `/wp-content/debug.log`. ## Schritt 8: Häufige Probleme und ihre Lösungen ### Problem: Logs werden überhaupt nicht geschrieben Was ist zu überprüfen: 1. Ist `log_errors = On` definitiv gesetzt? 2. Bestehen Schreibrechte für die Datei und ihr Verzeichnis? 3. Haben Sie die richtige php.ini bearbeitet (mit `phpinfo()` prüfen)? 4. Haben Sie den Webserver nach den Änderungen neu gestartet? ### Problem: Fatale Fehler werden nicht abgefangen Selbst bei aktiviertem Logging werden fatale Fehler manchmal nicht geschrieben, wenn sie sehr früh auftreten (z.B. ein Parse-Fehler in genau der Datei, in der Sie das Logging aktivieren). Die einzige Lösung ist die richtige Platzierung — ganz am Anfang, vor allem anderen . ### Problem: Zu viele Logs Wenn `E_ALL` in der Produktion aktiviert ist, wachsen die Logs schnell. Konfigurieren Sie `error_reporting` sinnvoll : ```ini error_reporting = E_ALL & ~E_DEPRECATED & ~E_NOTICE ``` ### Problem: Logs füllen die Festplatte Richten Sie die Log-Rotation mit `logrotate` ein. Eine Konfiguration für PHP-Logs: ``` /var/log/php_errors.log { daily rotate 30 compress delaycompress missingok notifempty create 644 www-data www-data } ``` ## Schritt 9: Praxisbeispiel: Eine leere Seite untersuchen Stellen Sie sich vor: Sie öffnen eine Website, und sie ist leer. Was tun Sie Schritt für Schritt? 1. **Überprüfen Sie die Webserver-Logs** (Apache/Nginx) — oft gibt es dort einen Hinweis 2. **Überprüfen Sie die PHP-Logs** — suchen Sie nach Einträgen der letzten Minuten ```bash tail -n 50 /var/log/php_errors.log | grep -A5 -B5 "$(date +%Y-%m-%d)" ``` 3. **Finden Sie den Fehler** : ``` [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. **Öffnen Sie die Datei**, überprüfen Sie Zeile 12 — tatsächlich, Sie haben vergessen, die Klasse einzubinden. 5. **Korrigieren Sie es**, testen Sie — die Website funktioniert! Magie! ## Kurzreferenz: Spickzettel | Aktion | Befehl / Code | |--------|---------------| | Logging in php.ini aktivieren | `log_errors = On` + `error_log = /pfad/zur/datei` | | Im Code aktivieren | `ini_set('log_errors', 'On');` | | Letzte Zeilen anzeigen | `tail -f /var/log/php_errors.log` | | Nach fatalen Fehlern suchen | `grep "Fatal error" /var/log/php_errors.log` | | Fatale Fehler abfangen | `register_shutdown_function()` + `error_get_last()` | | Wo sind Laravel-Logs? | `storage/logs/laravel.log` | | Wo sind Symfony-Logs? | `var/log/dev.log` und `var/log/prod.log` | ## Statt eines Nachworts PHP ist nicht so beängstigend, wie es oft gemacht wird. Ja, der Weiße Bildschirm des Todes ist furchterregend, aber dahinter steckt immer ein konkreter Fehler, der nur nicht sprechen will. Lernen Sie, Logs zu aktivieren, und PHP wird anfangen zu reden. Die Hauptregeln: - In Produktion **immer** `log_errors` aktivieren und `display_errors` deaktivieren - Logs in eine dedizierte Datei schreiben, nicht nach syslog — so ist die Suche einfacher - Verwenden Sie `register_shutdown_function`, um fatale Fehler abzufangen - Überprüfen Sie Ihre Logs regelmäßig — mindestens einmal täglich Und denken Sie daran: Perfekter Code schreibt keine Fehler. Aber wenn ein Fehler auftritt, soll er wenigstens eine Notiz hinterlassen. ?>