Comment traiter les erreurs PHP qui ne peuvent être interceptées et gérées par script PHP? Impossible ? Pas si sûre !
? E_ERROR
? E_PARSE
? E_CORE_ERROR
? E_CORE_WARNING
? E_COMPILE_ERROR
? E_COMPILE_WARNING
? La plupart des E_STRICT
Attraper les erreurs de ce type est impossible dans un script PHP, puisque que l?interpréteur PHP est considéré instable et stoppé. PHP affiche par défaut un rapport d?erreur. Ces erreurs ne sont pas attrapables avec PHP.
Objectif :
? Comment être informer rapidement (mail par exemple) d'une erreur sur le site,
? Comment maitriser l'affichage du rapport d'erreur PHP, en pensant sécurité
Problématiques :
? La sécurité peut être compromise par l?affichage d?informations indésirables dans le rapport d?erreur de PHP.
? Pour l?aspect sécurité, la solution de désactiver le rapport d?erreur (display_errors = Off) est tout aussi risqué. Le client ne sera pas correctement informé qu?il y a une erreur. Soit la crédibilité du site en prend encor plus un coup que ce n?est déjà fait, soit il risque d?insister et provoquer plus de problèmes.
? Enfin, plus tôt on est informé de ce genre d?erreur, mieux c?est. Hors la configuration PHP propose uniquement un log des erreurs alors qu?un mail serait un minimum pour être informé rapidement.
? Le fichier php.ini peut être inaccessible (par exemple hébergement mutualisé)
Solution, résumé :
La solution que j?ai trouvé consiste à jouer sur la configuration des directives PHP (Rappel : le fichier php.ini, reconfigurable via htaccess ou script PHP), puis à l?aide d?une petite astuce HTML, poursuivre le traitement de l?erreur avec une redirection. Le système a ses limites mais fonctionne plus ou moins et ne demande qu?à être amélioré.
Note :
Il est fort possible que je puisse me tromper sur ces affirmations, et qu?il existe d?autres façons plus fiables et plus simples pour répondre à ces problèmes. Mais dans ce cas l?information est dure à trouver. N?hésitez pas à citer des références.
Source / Exemple :
<?php
/******************************************
Mise en place de la solution :
/******************************************
1) La configuration
?>
Modifier les directives PHP : Un fichier .htaccess est utilisable si php.ini n?est pas accessible. On peut garder sous la main deux versions de .htaccess : une pour l?environnement de développement et l?autre pour la production.
? display_errors = On : Il est indispensable de signaler l?erreur et, un rapport est nécessaire pour la redirection avec HTML.
? log_errors= On : Toujours écrire les messages d'erreur
? error_prepend_string et error_append_string : Pas d?influence sur le Log. C?est là, la clé de l?astuce : il faut fournir suffisamment de contenu (X)HTML pour obtenir une page qui convienne. La balise <meta http-equiv="refresh" content="0;URL=/err500.htm" /> redirige vers la page erreur.
? error_log : Indiquer un fichier commençant par « .ht » rend le fichier inaccessible
<?php /** Exemple .htaccess pour l?environnement « production » : */ ?>
php_value error_reporting 2147483647
php_flag display_errors on
php_flag display_startup_errors on
php_flag log_errors on
php_flag ignore_repeated_errors off
php_flag ignore_repeated_source off
php_flag report_memleaks on
php_flag html_errors off
php_flag track_errors on
php_value log_errors_max_len 4096
php_value docref_root off
php_value docref_ext off
php_value error_prepend_string '<html><head><meta http-equiv="refresh" content="0;URL=/err500.php" /></head><body>Erreur Critique.<div style="visibility:hidden">'
php_value error_append_string '</div></body></html>'
php_value error_log ./.ht_log_err_php.log
# // On peut éventuellement complèter avec :
ErrorDocument 500 ./ err500.php
<?php /** Exemple .htaccess pour l?environnement « développement » : */ ?>
php_value error_reporting 2147483647
php_flag display_errors on
php_flag display_startup_errors on
php_flag log_errors on
php_flag ignore_repeated_errors off
php_flag ignore_repeated_source off
php_flag report_memleaks on
php_flag html_errors on
php_flag track_errors on
php_value log_errors_max_len 4096
php_value docref_root
http://www.php.net/manual/fr/
php_value docref_ext .php
php_value error_prepend_string '<html><body>'
php_value error_append_string '</body></html>'
php_value error_log ./log_err_php.log
<?php
/******************************************
2) la page err500.php
?>
Puisque PHP avait stoppé l?exécution du script après l?erreur, il était impossible d?envoyer un mail par exemple. C?est avec la page err500.php que l?on va pouvoir le faire.
Exemple page de traitement :
<?php
header('HTTP/1.1 500 Internal Server Error');
// ?. Tout traitement pour l?erreur
//@mail('webmaster@localhost', 'Erreur critique sur site en prod', 'Must see the log');
?>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Internal Server Error</title></head><body>
<H1>Internal Server Error</H1>
<p>The server encountered an internal error or misconfiguration and was unable to complete your request.</p>
<p>Please contact the server administrator, webmaster@localhost and inform them of the time the error occurred, and anything you might have done that may have caused the error.</p>
<p>More information about this error may be available in the server error log.</p>
</body></html>
Conclusion :
-------------------------------------------------
Limitation de la solution :
-------------------------------------------------
Cette solution n?est absolument pas fiable et dépend fortement de la profondeur de l?erreur dans le code. La page renvoyée avec le rapport d?erreur n?est certainement pas conforme. L?astuce fonctionnera donc suivant l?interprétation du navigateur. En utilisant une bufferisation de sortie les chances sont fortement augmentées.
-------------------------------------------------
Appel à contribution :
-------------------------------------------------
Je n?ai pas poussé mes tests très loin, contribuez à cette source en signalant les navigateurs où la redirection ne fonctionne pas, ou en proposant d?autres idées de valeur pour error_prepend_string et error_append_string, d?autres traitement pour la page de traitement...
-------------------------------------------------
Annexe :.htaccess version production
-------------------------------------------------
Explication des autres choix Htaccess version production.
? error_reporting = 2147483647 : permet de notifier toute erreurs quel que soit la version de PHP, y compris celles à venir.
? display_startup_errors = On : Je ne sais pas comment provoquer cette erreur pour tester ! Malgré que fortement déconseillé en Prod, je mets On pour privilégier le fait d?être informé de l?erreur plutôt que la sécurité.
? log_errors_max_len=4096 : Test : La valeur minimum est 1 (0 ne fonctionne pas). Le réglage influence le rapport affiché autant que le Log J?ai mis à 4 fois la valeur par défaut pour encore une fois privilégier l?information sur la sécurité
? ignore_repeated_errors et ignore_repeated_source=Off : sinon un client qui insisterait en rafraichissant la page ne serait pas détecté
? report_memleaks= On : Valeur par défaut, il vaut mieux rapporter ce type d?erreur
? track_errors= On : Si pas utilisé dans script, Influence ? Ressources ? Je préfère mettre à On si jamais un script tiers utilise la variable globale.
? html_errors=Off : n?influence pas le log, ni les directives error_prepend_string et error_append_string. Seulement la mise en page du rapport d?erreur
? docref_root et docref_ext=Off : Ce n?est pas le but ici.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.