Politiques de gestion des erreurs en PHPDate de mise à jour : 29/10/06 (version 0.22)
Par
Guillaume Piolle (Page perso sur DVP)
Ce cours traite des erreurs PHP, des différents outils qu'offre le langage pour les gérer,
des bonnes pratiques de développement et le déploiement d'applications web en termes
d'erreurs PHP. Les exceptions ne sont pas traitées dans ce tutoriel, mais dans l'article
intitulé Exceptions et PHP5.
I. Introduction
II. Présentation des erreurs PHP
III. Les outils à notre disposition
III-A. Configuration du niveau d'erreur
III-B. Génération d'erreurs
III-C. Masquage des erreurs
III-D. Journalisation
III-E. Le remote debugging
III-F. Personnalisations diverses
III-G. Interception
IV. Les assertions
V. Les principes d'une politique efficace
IV-A. Phase de développement
IV-B. Phase de production
VI. Implémentation
V-A. Via le fichier de configuration php.ini
V-B. Via une classe PHP
VII. Remerciements
VIII. Références
I. Introduction
Comme tous les langages de programmation, PHP est susceptible de générer,
d'afficher et de traiter des erreurs. Le terme étant à dénotation intrinsèquement
négative, on a forcément tendance à vouloir les éviter à tout prix, à obtenir une
exécution sans aucun message d'erreur, quitte à les ignorer, ce qui revient à
entasser la poussière sous le tapis du salon lorsqu'on fait le ménage... En réalité
il vaudrait sans doute mieux considérer les mécanismes d'erreurs comme des aides à la
programmation. Certes c'est toujours désagréable de récolter une série de messages
d'erreurs lorsqu'on vient de finir de coder l'application qui révolutionnera
l'avenir de l'internet ! Mais les erreurs PHP permettent de corriger les défauts
de l'application, d'améliorer son style de programmation, et de gérer les impondérables
qui surviendront lorsque des utilisateurs réels expérimenteront l'application.
 Messages d'erreurs PHP standard
Quels sont donc les enjeux d'une politique de gestion des erreurs ? Tout d'abord et
évidemment, il faudra utiliser intelligemment ces erreurs en phase de développement et
surtout de tests. Ensuite, il faudra prendre garde à ce que ces messages d'erreurs ne
viennent pas défigurer une charte graphique soignée lorsqu'on mettra l'application en
production : on prendra alors soin de masquer les erreurs aux visiteurs, tout en
gardant la possibilité d'en être averti (phase de maintenance de l'application).
II. Présentation des erreurs PHP
En programmation, une erreur est définie comme un comportement anormal de
l'application. En PHP on les distingue des exceptions, qui sont des
comportements exceptionnels, mais cependant normaux. Dans certains cas, vous
serez amenés à vous demander si c'est une erreur que vous devez définir,
ou une exception. Tout est une question de sémantique, mais aussi d'outils
associés. Le comportement de PHP n'est pas le même face à une erreur et face
à une exception (et les deux sont configurables). La gestion des exceptions
en PHP5 est décrite dans cet article.
Dans un langage de programmation compilé, comme le C, on distingue les erreurs
de compilation des erreurs d'exécution. Les erreurs de compilation sont celles
qui peuvent être anticipées par la machine dès l'écriture du code, et qui empêchent
la génération du langage machine. Ce sont les plus facile à corriger puisque le
compilateur (le préprocesseur, l'analyseur syntaxique, l'éditeur de liens...)
donne une liste de ces erreurs à chaque tentative de compilation. Les erreurs
d'exécution sont plus sournoises, ce sont ces "segmentation faults" qui n'apparaissent
que lorsque le programme (mal testé ?) est en production et que l'utilisateur
entre des valeurs bizarres dans la machine. PHP, lui, est un langage interprété,
donc cette distinction n'existe pas vraiment : toutes les erreurs apparaîtront
dans la phase d'interprétation du script. Néanmoins il reste certaines similitudes.
Par exemple dans un compilateur comme dans un interpréteur, il y a un analyseur
syntaxique qui va vérifier que votre programme est bien conforme à la grammaire
formelle du langage (c'est-à-dire que vous avez respecté la syntaxe, que vous
n'avez pas oublié un point-virgule dans un coin, ce genre de choses). Les erreurs
rencontrées par cette analyseur syntaxique sont les "parse errors" (erreurs d'analyse),
les erreurs que vous verrez sans doute apparaître en premier puisqu'elles empêchent
l'interprétation du reste du script.
En fait toutes les erreurs PHP sont réparties en catégories, soit par nature, soit par
gravité de l'erreur (gravité qui peut être subjective ou dépendante de l'application,
d'ailleurs). Voici un petit tableau récapitulatif :
Valeur décimale |
Valeur hexadécimale |
Valeur binaire |
Constante PHP |
Affichage Apache |
Description |
1 |
0001 |
00000000 00000001 |
E_ERROR |
Fatal error |
Le niveau d'erreur "standard". Par défaut, ces erreurs sont
affichées par l'interpréteur, et l'exécution du script est
stoppée. Elles sont donc destinées à désigner des erreurs
suffisamment graves pour interrompre l'affichage de la page.
C'est ce type d'erreur qui sera levée si vous appelez une
fonction qui n'existe pas, par exemple.
|
2 |
0002 |
00000000 00000010 |
E_WARNING |
Warning |
Les warnings, ou "alertes", sont affichées mais
n'arrêtent pas l'exécution, par analogie avec les langages
compilés, où ils ne stoppent pas la compilation. C'est
une erreur de moindre gravité, qui permet tout de même
au reste du script de s'exécuter (comme la division par
zéro dans l'exemple d'exécution affiché plus haut).
|
4 |
0004 |
00000000 00000100 |
E_PARSE |
Parse error |
La faute de syntaxe, l'erreur "énervante", celle que l'on
garde pour soi et dont on ne fait pas profiter les copains
ou les forums d'aide, parce qu'on a bien trop honte...
Cette erreur n'apparaît qu'à l'étape de codage, et elle
signifie que l'interpréteur n'a même pas été lancé sur
votre code, parce que l'analyseur syntaxique a détecté
un problème : votre code ne respecte pas la syntaxe PHP.
Vous avez oublié de fermer une parenthèse ou une accolade
par exemple, ou bien vous avez oublié un point-virgule.
|
8 |
0008 |
00000000 00001000 |
E_NOTICE |
Notice |
Les "notifications" sont à peine des erreurs, ce sont des
indications de l'interpréteur, qui peuvent le plus souvent
être ignorées (d'ailleurs par défaut elles ne sont même pas
affichées), mais qui pourtant peuvent avoir beaucoup d'intérêt
pour identifier les bogues. C'est le genre d'erreur qui apparaît
par exemple lorsque vous utilisez une variable ou une constante
non encore déclarée, ce que pourtant vous faites tout le temps,
j'en suis sûr !
|
16 |
0010 |
00000000 00010000 |
E_CORE_ERROR |
|
Ce type d'erreur est générée par le code de l'interpréteur
PHP, et ne concerne pas le développeur. Vous n'en entendrez
probablement jamais parler.
|
32 |
0020 |
00000000 00100000 |
E_CORE_WARNING |
|
Ce type d'erreur est générée par le code de l'interpréteur
PHP, et ne concerne pas le développeur. Vous n'en entendrez
probablement jamais parler.
|
64 |
0040 |
00000000 01000000 |
E_COMPILE_ERROR |
|
Ce type d'erreur est générée par le Zend Scripting
Engine, et ne concerne pas le développeur. Vous n'en entendrez
probablement jamais parler.
|
128 |
0080 |
00000000 10000000 |
E_COMPILE_WARNING |
|
Ce type d'erreur est générée par le Zend Scripting
Engine, et ne concerne pas le développeur. Vous n'en entendrez
probablement jamais parler.
|
256 |
0100 |
00000001 00000000 |
E_USER_ERROR |
|
C'est une erreur similaire à E_ERROR, mais générée
directement
par l'utilisateur via trigger_error (voir plus tard).
|
512 |
0200 |
00000010 00000000 |
E_USER_WARNING |
|
C'est un avertissement similaire à E_WARNING, mais
généré directement
par l'utilisateur via trigger_error (voir plus tard).
|
1024 |
0400 |
00000100 00000000 |
E_USER_NOTICE |
|
C'est une notification similaire à E_NOTICE, mais
générée directement
par l'utilisateur via trigger_error (voir plus tard).
|
2048 |
0800 |
00001000 00000000 |
E_STRICT |
|
Uniquement à partir de PHP 5(1). Ces erreurs sont des
notifications (donc pas vraiment graves) destinées à améliorer
votre code pour le rendre compatible avec certaines recommandations
officielles de PHP. Si vous ne les respectez pas, comme pour
les notifications, votre programme peut fonctionner quand même.
Mais si vous les respectez, il aura d'autant plus de chances
de s'exécuter sans erreur sur une autre machine ou une nouvelle
configuration !
|
4096 |
1000 |
00010000 00000000 |
E_RECOVERABLE_ERROR |
|
Uniquement à partir de PHP 5(2). C'est une erreur relativement
grave venant de la machine Zend. Ce n'est vraiment pas une
erreur courante, et pour être tout à fait honnête je ne sais rien
à son sujet. Vous ne devriez jamais la rencontrer, sauf à
aller fouiner dans l'interpréteur, auquel cas vous savez sans
doute mieux que moi ce que vous faites !
|
8191 |
1FFF |
00011111 11111111 |
E_ALL |
|
Dans les versions de PHP < 5(3), la valeur numérique est
en fait 2047, et 6143 en PHP 5, ce qui correspond dans les
deux cas à la somme de tous les codes d'erreur valides, à
l'exception de E_STRICT. C'est donc un code qui permet
d'embrasser toutes ces catégories. A partir de PHP 6.0, cette
valeur sera "enfin" de 8191, ce qui correspond vraiment à
la totalité des erreurs.
|
Le codage bit à bit de tous les codes d'erreurs, qui ne choquera
On remarquera en particulier que la valeur E_ALL ne couvre pas
les erreurs E_STRICT.
Niveaux d'erreur, informations associées (message, script, numéro de ligne)
Valeurs de retour à NULL ou FALSE, or, or die (à éviter)
III. Les outils à notre disposition
III-A. Configuration du niveau d'erreur
configuration du niveau d'erreur (php.ini et en ligne)
php.ini : error_reporting = ... un mot sur E_ALL et E_STRICT
III-B. Génération d'erreurs
Avec trigger_error
E_USER_NOTICE
E_USER_WARNING
E_USER_ERROR
III-C. Masquage des erreurs
Désactivation des erreurs avec @, à éviter
php.ini : display_errors = Off
III-D. Journalisation
php.ini : log_errors = On,
error_log = fichier
Attention à la journalisation vue comme une poubellisation
ignore_repeated_errors
error_log = syslog : journalisation système (sur un système dédié)
log manuel avec error_log($message)
envoi par mail avec error_log($message, 1, $email, $headers);
titre du message non modifiable car header Subject déjà existant
utile en cas d'intrusion car intouchable une fois qu'envoyé
III-E. Le remote debugging
remote_debugging dans le php.ini, error_log avec deuxième paramètre à 2
serveur dédié au débuggage
III-F. Personnalisations diverses
que fait track_errors dans le php.ini ?
Affichage personnalisé avec error_prepend_string et error_append_string
III-G. Interception
PHP ne s'occupe plus de rien. Ni journalisation, ni filtrage par error_reporting ou @,
ni arrêt du script après E_USER_ERROR -> appeler exit au besoin
callback = fonction de rappel
méthode : tableau à la place d'une chaîne de caractères
set_error_handler, restore_error_handler
ne concerne pas E_ERROR et E_PARSE, entre autres
IV. Les assertions
Digression sur les assertions
Aide à la sûreté de fonctionnement
A désactiver en production ?
V. Les principes d'une politique efficace
IV-A. Phase de développement
Niveau d'erreur au minimum, ne jamais masquer les erreurs,
Tout montrer pour faciliter le débogage.
Outil pour amener l'application à un état de bon fonctionnement
importance des jeux de tests
Importance des notice (exemple des indices de tableau associatif)
IV-B. Phase de production
Ne jamais afficher le détail des erreurs (raisons de sécurité),
enrober l'erreur au niveau interface, logger, avertir qqn
en cas de souci (niveau d'erreur significatif : moins de
ressources en production qu'en développement).
error reporting personnalisé utilisateurs/administrateurs ?
Les erreurs permettent de détecter les problèmes transitoires
et les tentatives d'attaques.
VI. Implémentation
Système permettant de switcher entre une configuration de développement
et une configuration de production.
V-A. Via le fichier de configuration php.ini
V-B. Via une classe PHP
VII. Remerciements
Je tiens à remercier
Yogui
pour sa très grande patience.
VIII. Références
PHP 5 avancé, pages de doc
http://fr.php.net/manual/fr/ref.errorfunc.php
(1) |
Je ne suis pas tout à fait sûr de cette valeur, c'est
peut-être PHP 5.2, la page de documentation d'où j'ai
tirée les informations de ce tableau n'était pas tout-à-fait
cohérente. Si quelqu'un veut bien installer une version 5.1,
faire les tests et me communiquer ses résultats, je lui
devrai évidemment une reconnaissance éternelle.
| (2) | ou 5.2, voir
note 1. | (3) | ou 5.2, voir
note 1. |
Copyright ©2006 Eusebius.
Aucune reproduction, même partielle, ne peut être faite
de ce site et de l'ensemble de son contenu : textes, documents, images, etc
sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E
de dommages et intérêts. Cette page est déposée à la SACD.
|