Les amis, aujourd'hui nous allons parler de ce qui rend fou quiconque a déjà fouillé dans du code PHP écrit par quelqu'un d'autre. Vous ouvrez un site web, et il n'y a rien. Un écran blanc. Pas d'erreur, pas d'indice sur ce qui a mal tourné.
Cela vous dit quelque chose ?
C'est le cas classique d'une erreur fatale PHP qui tue simplement le script et disparaît dans la nature sans dire au revoir. Aujourd'hui, nous allons apprendre à faire parler PHP, à activer les journaux et à trouver ces erreurs fatales qui se cachent derrière « l'écran blanc de la mort ».
Pourquoi PHP reste silencieux : un peu de théorie
Pour commencer, comprenons comment PHP gère les erreurs en général. Ce n'est pas juste « erreur -> journal ». Il y a toute une hiérarchie.
En PHP 7+, tout ce qui peut mal se passer implémente l'interface Throwable. Elle a deux héritiers principaux : - Error — les erreurs internes de PHP (fatales, de parse, de type) - Exception — les exceptions qui peuvent être attrapées avec try-catch
Les erreurs fatales (E_ERROR, E_PARSE, E_CORE_ERROR) sont le pire cauchemar de tout développeur. Elles tuent le script instantanément, et les gestionnaires standards via set_error_handler() ne les attrapent pas . La seule façon d'intercepter une erreur fatale est d'utiliser register_shutdown_function().
Mais procédons étape par étape. D'abord, nous devons activer la journalisation pour que les erreurs soient réellement écrites quelque part.
Étape 1 : Activer la journalisation via php.ini
La façon la plus correcte de configurer les journaux est de modifier le fichier de configuration PHP. Son emplacement dépend de votre système :
| Système | Chemin vers 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 ou /etc/php.d/ |
| Windows (XAMPP) | C:\xampp\php\php.ini |
| Windows (WAMP) | C:\wamp\bin\php\phpX.X.X\php.ini |
Dans ce fichier, les directives suivantes nous intéressent :
```ini ; Activer l'écriture des erreurs dans un journal (obligatoire !) log_errors = On
; Spécifier le chemin vers le fichier journal error_log = /var/log/php_errors.log
; Désactiver l'affichage des erreurs à l'écran (pour la production !) display_errors = Off
; Pour le développement, vous pouvez activer ceci, mais désactivez-le plus tard display_startup_errors = Off
; Niveau de rapport d'erreurs — toutes les erreurs error_reporting = E_ALL ```
Important : L'interface en ligne de commande (CLI) utilise son propre php.ini, et les journaux peuvent être écrits à un endroit différent . Si vous testez un script dans la console, vérifiez séparément.
Après avoir effectué les modifications, vous devez redémarrer le serveur web :
bash
sudo systemctl restart apache2 # pour Apache
sudo systemctl restart php7.4-fpm # pour PHP-FPM
Signification de ces paramètres
- log_errors = On — active l'écriture des erreurs dans un fichier. Sans cela, PHP restera muet comme une tombe .
- error_log — le chemin vers le fichier où tout sera écrit. Il est crucial que l'utilisateur du serveur web (généralement
www-dataouapache) ait les permissions d'écriture pour ce fichier et son répertoire . - display_errors = Off — désactivez impérativement cela en production pour éviter d'exposer des détails aux utilisateurs .
- error_reporting = E_ALL — journaliser tous les types d'erreurs. Pour la production, vous pouvez limiter cela, mais pour le débogage, il est préférable de tout voir.
Étape 2 : Alternative : Activer la journalisation directement dans le code
Si vous n'avez pas accès à php.ini (par exemple, sur un hébergement mutualisé), vous pouvez essayer d'activer la journalisation directement dans votre script en utilisant la fonction ini_set().
Insérez ceci au tout début du fichier problématique :
```php
/dev/null ``` Ou créez un fichier PHP avec `phpinfo();` et cherchez la section **error_log**. ## Étape 4 : Lire les journaux : outils et techniques Une fois que les journaux sont écrits, vous devez savoir comment les visualiser et les filtrer rapidement. ### tail — Voir les derniers événements ```bash # 50 dernières lignes tail -n 50 /var/log/php_errors.log # Suivre en temps réel (comme docker logs -f) tail -f /var/log/php_errors.log ``` ### grep — Rechercher des erreurs spécifiques ```bash # Uniquement les erreurs fatales grep "Fatal error" /var/log/php_errors.log # Erreurs de parse (erreurs de syntaxe) grep "Parse error" /var/log/php_errors.log # Ignorer la casse grep -i "warning" /var/log/php_errors.log ``` ### less — Visualisation pratique avec navigation ```bash less /var/log/php_errors.log ``` Dans less, vous pouvez appuyer sur `/` et taper un mot pour chercher, `n` pour le résultat suivant, `N` pour le précédent. ### Combinaisons — Un pipeline puissant ```bash # Afficher les 100 dernières lignes et rechercher des erreurs tail -n 100 /var/log/php_errors.log | grep -i fatal # Suivre et filtrer en temps réel tail -f /var/log/php_errors.log | grep --line-buffered "error" # Compter les erreurs par type grep -o "PHP [A-Za-z]* error" /var/log/php_errors.log | sort | uniq -c ``` ## Étape 5 : Déchiffrer les erreurs : qu'est-ce que c'est Une entrée de journal typique ressemble à ceci : ``` [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 ``` Détaillons-la : - **Date et Heure** — quand c'est arrivé - **PHP Fatal error** — le niveau d'erreur - **Uncaught Error: Call to undefined function foo()** — le message - **/var/www/html/index.php:10** — le fichier et le numéro de ligne Principaux niveaux d'erreur : | Niveau | Signification | Exemple | |--------|---------------|---------| | **E_ERROR** / **Fatal error** | Erreur fatale, le script meurt | Appel d'une fonction inexistante, mémoire insuffisante | | **E_WARNING** / **Warning** | Avertissement, mais le script continue | `include` d'un fichier inexistant | | **E_PARSE** / **Parse error** | Erreur de syntaxe, le script ne s'exécute pas | Point-virgule manquant | | **E_NOTICE** / **Notice** | Suggestion, généralement pas critique | Accès à une variable non définie | | **E_DEPRECATED** | Construction obsolète | Utilisation de `mysql_connect()` | ## Étape 6 : Attraper les erreurs fatales (la partie intéressante) Les erreurs fatales sont celles qui ne peuvent pas être attrapées par le `set_error_handler()` standard. Elles tuent le script instantanément, et le gestionnaire par défaut n'a tout simplement pas le temps de s'exécuter . Mais il y a un moyen ! Utilisez `register_shutdown_function()` — cette fonction est appelée quoiqu'il arrive, même en cas d'erreur fatale . ### Gestionnaire d'erreurs fatales simple ```php getMessage()." | ".$e->getFile().":".$e->getLine()." | $url\n"; file_put_contents($logFile, $msg, FILE_APPEND); }); // Gestionnaire pour les erreurs fatales 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); } }); ``` Vous pouvez insérer un tel code au tout début de votre fichier principal (par exemple, `index.php` ou `header.php`), et il attrapera absolument tout . ## Étape 7 : Journaux dans les frameworks populaires Si vous utilisez un framework moderne, la journalisation est déjà configurée, mais les chemins des journaux sont différents. ### Laravel Les journaux sont stockés dans `storage/logs/laravel.log`. Par défaut, il utilise Monolog ; le format peut être texte ou JSON. Pour voir les erreurs : ```bash tail -f storage/logs/laravel.log ``` ### Symfony Journaux par défaut : `var/log/dev.log` et `var/log/prod.log`. Utilise également Monolog, hautement configurable. ### WordPress Par défaut, WordPress n'écrit pas de journaux, mais vous pouvez les activer en ajoutant ceci dans `wp-config.php` : ```php define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false); ``` Les journaux seront dans `/wp-content/debug.log`. ## Étape 8 : Problèmes courants et leurs solutions ### Problème : Les journaux ne sont pas écrits du tout Que vérifier : 1. `log_errors = On` est-il bien défini ? 2. Y a-t-il des permissions d'écriture pour le fichier et son répertoire ? 3. Avez-vous modifié le bon php.ini (vérifiez via `phpinfo()`) ? 4. Avez-vous redémarré le serveur web après les modifications ? ### Problème : Les erreurs fatales ne sont pas attrapées Même avec la journalisation activée, les erreurs fatales ne sont parfois pas écrites si elles se produisent très tôt (par exemple, une erreur de parse dans le fichier même où vous activez la journalisation). La seule solution est un placement correct — au tout début, avant toute autre chose . ### Problème : Trop de journaux Si `E_ALL` est activé en production, les journaux grossiront rapidement. Configurez `error_reporting` de manière raisonnable : ```ini error_reporting = E_ALL & ~E_DEPRECATED & ~E_NOTICE ``` ### Problème : Les journaux remplissent le disque Configurez la rotation des journaux avec `logrotate`. Une configuration pour les journaux PHP : ``` /var/log/php_errors.log { daily rotate 30 compress delaycompress missingok notifempty create 644 www-data www-data } ``` ## Étape 9 : Exemple pratique : Enquêter sur une page blanche Imaginons une situation : vous ouvrez un site web, et il est blanc. Que faire étape par étape : 1. **Vérifiez les journaux du serveur web** (Apache/Nginx) — ils contiennent souvent un indice 2. **Vérifiez les journaux PHP** — cherchez des entrées des dernières minutes ```bash tail -n 50 /var/log/php_errors.log | grep -A5 -B5 "$(date +%Y-%m-%d)" ``` 3. **Trouvez l'erreur** : ``` [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. **Ouvrez le fichier**, vérifiez la ligne 12 — effectivement, on a oublié d'inclure la classe. 5. **Corrigez**, testez — le site fonctionne ! Magique ! ## Aide-mémoire : Fiche de révision | Action | Commande / Code | |--------|-----------------| | Activer la journalisation dans php.ini | `log_errors = On` + `error_log = /chemin/vers/fichier` | | Activer dans le code | `ini_set('log_errors', 'On');` | | Voir les dernières lignes | `tail -f /var/log/php_errors.log` | | Rechercher des erreurs fatales | `grep "Fatal error" /var/log/php_errors.log` | | Attraper les erreurs fatales | `register_shutdown_function()` + `error_get_last()` | | Où sont les journaux Laravel ? | `storage/logs/laravel.log` | | Où sont les journaux Symfony ? | `var/log/dev.log` et `var/log/prod.log` | ## En guise de conclusion PHP n'est pas aussi effrayant qu'on le dit souvent. Oui, l'écran blanc de la mort est terrifiant, mais derrière lui se cache toujours une erreur spécifique qui ne veut tout simplement pas parler. Apprenez à activer les journaux, et PHP commencera à parler. Les règles principales : - En production, **toujours** activer `log_errors` et désactiver `display_errors` - Écrire les journaux dans un fichier dédié, pas dans syslog — c'est plus facile pour chercher - Utiliser `register_shutdown_function` pour attraper les erreurs fatales - Vérifier vos journaux régulièrement — au moins une fois par jour Et souvenez-vous : le code parfait n'écrit pas d'erreurs. Mais si une erreur se produit, qu'elle laisse au moins un mot. ?>