Gestion des erreurs en PHP
Par Francis Besset le samedi 9 janvier 2010 - Développements | Lien permanent

Lorsque vous créez votre application, votre site, votre blog, etc, il est très important de faire remonter les erreurs afin que celles-ci puissent être corrigées par le ou les développeurs.
En temps normal lorsque vos utilisateurs utiliseront votre application, ils sont susceptibles de rencontrer des erreurs de codages ou d'évènements. Ca peut ne pas être bien grave, tout comme vous faire une mauvaise réputation si jamais celle-ci est récurrente.
De plus le visiteur sera le seul à la visualiser, et il aura donc le choix de vous la faire remonter tout comme d'aller voir ailleurs. Dans le dernier cas c'est crédibilité zéro !
Alors comment faire en sorte d'être tenu au courant en cas d'erreur sur votre application PHP ?
La réponse se situe au niveau de la fonction set_error_handler(). Elle vous permettra d'indiquer la fonction ou méthode qui doit être appelée en cas d'erreur. La fonction est disponible depuis la version 4.0.1.
L'utilisation de cette fonction ignore totalement l'effet de la fonction error_reporting().
Pour cela, vous devrez placer dans vos scripts la fonction set_error_handler().
Si vous souhaitez appeler une fonction, dans ce cas, vous devrez utiliser la syntaxe suivante :
set_error_handler('my_error_handler');
Pour l'appel d'une méthode, vous devrez procéder ainsi (possible uniquement depuis la version 4.3.0) :
set_error_handler(array('MyErrorHandler', 'trigger'));
Le premier élément dans le tableau est le nom de la classe et le second est le nom de la méthode qui doit être appelée.
Ce n'est pas tout. En effet, votre fonction ou votre méthode doit désormais recevoir au minimum deux paramètres.
Il s'agit du code de l'erreur, ainsi que du message d'erreur. Depuis la version 4.0.2, votre fonction ou votre méthode de gestion d'erreurs peut contenir trois autres arguments qui sont le fichier où a eu lieu l'erreur, la ligne dans le fichier et pour finir le contexte.
Le contexte est un tableau qui contient des données sur les variables d'environnement et la méthode d'appel du script qui vous permettra de débugger plus aisément.
Votre gestionnaire d'erreur aura la possibilité de renvoyer un booléen ou bien même de tuer l'exécution du script.
Si vous renvoyez false, alors l'erreur s'affichera sur la page et le script poursuivra son exécution.
Si vous renvoyez true, alors l'erreur ne s'affichera pas, et le script poursuivra son exécution.
Si vous utilisez die() ou exit(), alors l'exécution du script s'arrêtera instantanément. J'estime que ce sera la méthode à utiliser dans la majorité des cas.
Quelles sont les limites de set_error_handler() ?
Cette fonction n'est malheureusement pas capable de gérer toutes les erreurs ! Cela signifie que vous serez tout de même dans l'incapacité de gérer les erreurs ci-dessous :
- E_ERROR
- E_PARSE
- E_CORE_ERROR
- E_CORE_WARNING
- E_COMPILE_ERROR
- E_COMPILE_WARNING
- Et la plupart des E_STRICT
Vous pouvez consulter la liste des erreurs pouvant être provoquées par PHP.
Vous pouvez aussi consulter la liste des fonctions sur la gestion des erreurs en PHP.
Depuis PHP5, set_error_handler() accepte un second argument optionnel, qui permet de filtrer les erreurs à gérer. Ainsi vous pourrez indiquer la constante E_ALL ou E_STRICT. Si rien n'est spécifié, la fonction spécifiée sera appelée pour toutes les erreurs.
Pour finir en beauté, je vous propose un script PHP afin de tester la gestion d'erreurs. Le script est directement pompé de la documentation de PHP.
<?php
// Gestionnaire d'erreurs
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
switch ($errno) {
case E_USER_ERROR:
echo "<strong>Mon ERREUR</strong> [$errno] $errstr<br />\n";
echo " Erreur fatale sur la ligne $errline dans le fichier $errfile";
echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
echo "Arrêt...<br />\n";
exit(1);
break;
case E_USER_WARNING:
echo "<strong>Mon ALERTE</strong> [$errno] $errstr<br />\n";
break;
case E_USER_NOTICE:
echo "<strong>Mon AVERTISSEMENT</strong> [$errno] $errstr<br />\n";
break;
default:
echo "Type d'erreur inconnu : [$errno] $errstr<br />\n";
break;
}
/* Ne pas exécuter le gestionnaire interne de PHP */
return true;
}
// Fonction pour tester la gestion d'erreurs
function scale_by_log($vect, $scale)
{
if (!is_numeric($scale) || $scale <= 0) {
trigger_error("log(x) for x <= 0 is undefined, you used: scale = $scale", E_USER_ERROR);
}
if (!is_array($vect)) {
trigger_error("Type d'entrée incorrect, tableau de valeurs attendu", E_USER_WARNING);
return null;
}
$temp = array();
foreach($vect as $pos => $value) {
if (!is_numeric($value)) {
trigger_error("La valeur à la position $pos n'est pas un nombre, utilisation 0 (zéro)", E_USER_NOTICE);
$value = 0;
}
$temp[$pos] = log($scale) * $value;
}
return $temp;
}
// Configuration du gestionnaire d'erreurs
$old_error_handler = set_error_handler("myErrorHandler");
// Génération de quelques erreurs. Commençons par créer un tableau
echo "vector a\n";
$a = array(2, 3, "foo", 5.5, 43.3, 21.11);
print_r($a);
// Générons maintenant un second tableau
echo "----\nvector b - a notice (b = log(PI) * a)\n";
/* Valeur à la position $pos n'est pas un nombre, utilisation de 0 (zéro) */
$b = scale_by_log($a, M_PI);
print_r($b);
// Ceci est un problème, nous avons utilisé une chaîne au lieu d'un tableau
echo "----\nvector c - a warning\n";
/* Type d'entrée incorrect, tableau de valeurs attendu */
$c = scale_by_log("non un tablau", 2.3);
var_dump($c); // NULL
// Ceci est une erreur critique : le logarithme de zéro ou d'un nombre négatif est indéfini
echo "----\nvector d - fatal error\n";
/* log(x) pour x <= 0 est indéfini, vous utilisez : scale = $scale" */
$d = scale_by_log($a, -2.5);
var_dump($d); // Jamais atteint
?>
Maintenant vous pouvez laisser libre court à vos besoins en créant par exemple un fichier de log d'erreur, ou bien même un envoi d'email d'alerte en cas d'erreur.




Commentaires
A part la photo, cet article n'a rien d'original et n'apporte rien ;-)