Gestion des erreurs en PHP

Créer des erreurs volontairement

Nous allons préparer notre fichier PHP pour tester le bon fonctionnement de nos prochaines fonctions.

Nous allons donc volontairement créer 3 types d'erreurs :

  • Le type notice : ce sont plus des remarques que des erreurs PHP. Par défaut, elles ne sont pas affichées. Ce sont par exemple des erreurs de variables non déclarées.
  • Le type warning : c'est un problème que rencontre PHP. Par exemple, diviser un nombre par 0 est un avertissement.
  • Le type error : ce sont des erreurs fatales, le script est interrompu. Ces erreurs ne peuvent pas être toutes ignorées. Elles surviennent par exemple lors d'appel à des fonctions inexistantes, des problèmes d'allocation de mémoire, ...

Voilà notre code PHP intégrant trois erreurs :

1 echo $variable_non_definie; // Erreur type "notice"
2 
3 $division_par_0 = 80 / 0; // Erreur type "warning"
4 
5 fonction_inexistante(); // Erreur type "error"
6 
7 require('fichier-inexistant.php'); // Erreur type "error" fatale

Gestion des erreurs

seterrorhandler

Première étape, on fait appeler une fonction (que l'on nommera gestionDesErreurs) à chaque fois que PHP rencontre une erreur.

Pour cela, nous allons utiliser la fonction seterrorhandler :

1 set_error_handler('gestionDesErreurs');

Ce code doit bien entendu être placé au début du script (donc avant les erreurs).

Il nous faut maintenant créer notre fonction gestionDesErreurs qui sera appelée à chaque fois. Elle doit prendre en paramètres :

  • Le premier paramètre, qui est obligatoire, contient le niveau d'erreur.
  • Le second paramètre, qui est aussi obligatoire, contient le message d'erreur.
  • Le troisième paramètre, facultatif, contient le nom du fichier dans lequel l'erreur a été commise.
  • Le quatrième paramètre, facultatif aussi, contient le numéro de la ligne à laquelle l'erreur a été rencontrée.
  • Le cinquième paramètre, facultatif, contenant un tableau avec toutes les variables qui existaient lorsque l'erreur a été déclenchée. Ce n'est pas très utile et nous ne l'utiliserons pas ici.

Ce qui nous donne :

1 function gestionDesErreurs($type, $message, $fichier, $ligne)
2 {
3     echo '<p>Erreur de type ' . $type . ' : ' . $message . '<br/>
4     Dans "' . $fichier . '" ligne ' . $ligne . '.</p>';
5 }
6 
7 set_error_handler('gestionDesErreurs');

gestionDesErreurs

Vous l'avez peut être remarqué, $type est un nombre. En fait, c'est une constante.

Vous trouverez la liste de ces constantes ici : http://fr.php.net/manual/fr/errorfunc.constants.php.

 1 switch ($type)
 2 {
 3     case E_ERROR:
 4     case E_PARSE:
 5     case E_CORE_ERROR:
 6     case E_CORE_WARNING:
 7     case E_COMPILE_ERROR:
 8     case E_COMPILE_WARNING:
 9     case E_USER_ERROR:
10         $type_erreur = "Erreur fatale";
11         break;
12 
13     case E_WARNING:
14     case E_USER_WARNING:
15         $type_erreur = "Avertissement";
16         break;
17 
18     case E_NOTICE:
19     case E_USER_NOTICE:
20         $type_erreur = "Remarque";
21         break;
22 
23     case E_STRICT:
24         $type_erreur = "Syntaxe Obsolète";
25         break;
26 
27     default:
28         $type_erreur = "Erreur inconnue";
29         break;
30 }

Ce qui nous donne :

 1 function gestionDesErreurs($type, $message, $fichier, $ligne)
 2 {
 3     switch ($type)
 4     {
 5         case E_ERROR:
 6         case E_PARSE:
 7         case E_CORE_ERROR:
 8         case E_CORE_WARNING:
 9         case E_COMPILE_ERROR:
10         case E_COMPILE_WARNING:
11         case E_USER_ERROR:
12             $type_erreur = "Erreur fatale";
13             break;
14 
15         case E_WARNING:
16         case E_USER_WARNING:
17             $type_erreur = "Avertissement";
18             break;
19 
20         case E_NOTICE:
21         case E_USER_NOTICE:
22             $type_erreur = "Remarque";
23             break;
24 
25         case E_STRICT:
26             $type_erreur = "Syntaxe Obsolète";
27             break;
28 
29         default:
30             $type_erreur = "Erreur inconnue";
31             break;
32     }
33     echo '<p>' . $type_erreur . ' : ' . $message . '<br/>
34     Dans "' . $fichier . '" ligne ' . $ligne . '.</p>';
35 }

Ici, je ne fais qu'afficher l'erreur. Donc il y a peu de différence avec le code de départ. Les intérêts de faire une fonction pour gérer les erreurs peuvent être :

  • Envoyer les erreurs par mail à l'administrateur/webmaster
  • Sauvegarder ces erreurs dans une base de données
  • Les ignorer pour afficher le site en production comme si rien ne s'était passé
  • ...

error_reporting

Maintenant, il va falloir cacher les erreurs, car certaines s'affichent encore.

La première solution est de modifier la configuration de PHP temporairement :

1 ini_set("display_errors", false);

Cela masquera toutes les erreurs.

Cependant, sur certains hébergeurs, cette fonction n'est pas possible.

Je vous conseille alors d'utiliser :

1 error_reporting(0);

Cela définie le niveau d'erreur. Si c'est 0, aucune erreur ne sera traitée.

Vous pouvez changer le 0 en une constante (http://fr.php.net/manual/fr/errorfunc.constants.php), en fonction de vos besoins.

La fonction seterrorhandler ne prenant pas en compte error_reporting, les erreurs seront bien toujours gérées, même si error_reporting vaudra 0 ; elles ne seront juste plus affichées.

Gestion des exceptions

Nous avons vu pour gérer les erreurs PHP. Cependant, il peut aussi y avoir des erreurs types exceptions.

Nous allons rediriger ces exceptions vers notre fonction gestionDesErreurs.

Tout d'abord, même procéder que seterrorhandler, mais avec setexceptionhandler :

1 set_exception_handler("gestionDesExceptions");

Nous créons maintenant notre fonction gestionDesExceptions, qui va renvoyer vers la fonction gestionDesErreurs.

Nous allons utiliser le type EUSERERROR :

1 function gestionDesExceptions($exception)
2 {
3     gestionDesErreurs (E_USER_ERROR, $exception->getMessage(), $exception->getFile(), $exception->getLine());
4 }

Le require

Certaines erreurs ne seront encore pas signalées.

Les erreurs avec la fonction require par exemple, émettent une erreur avertissement, suivi d'une erreur fatale. Mais entre ces deux erreurs, la fonction require aura fait arrêter le chargement de la page et donc qu'une seule erreur ne sera signalée.

Nous allons alors utiliser la fonction registershutdownfunction qui sert à exécuter une fonction dès que le chargement de page est finie (finie normalement, ou stopper, comme la fait le require).

Nous allons lui faire appeler une nouvelle fonction gestionDesErreursFatales, qui récupérera la dernière erreur survenue et non traitée par la fonction seterrorhandler.

 1 function gestionDesErreursFatales()
 2 {
 3     if (is_array($e = error_get_last()))
 4     {
 5         $type = isset($e['type']) ? $e['type'] : 0;
 6         $message = isset($e['message']) ? $e['message'] : '';
 7         $fichier = isset($e['file']) ? $e['file'] : '';
 8         $ligne = isset($e['line']) ? $e['line'] : '';
 9 
10         if ($type > 0) gestionDesErreurs($type, $message, $fichier, $ligne);
11     }
12 }
13 
14 register_shutdown_function('gestionDesErreursFatales');

Code complet

 1 function gestionDesErreurs($type, $message, $fichier, $ligne)
 2 {
 3     switch ($type)
 4     {
 5         case E_ERROR:
 6         case E_PARSE:
 7         case E_CORE_ERROR:
 8         case E_CORE_WARNING:
 9         case E_COMPILE_ERROR:
10         case E_COMPILE_WARNING:
11         case E_USER_ERROR:
12             $type_erreur = "Erreur fatale";
13             break;
14 
15         case E_WARNING:
16         case E_USER_WARNING:
17             $type_erreur = "Avertissement";
18             break;
19 
20         case E_NOTICE:
21         case E_USER_NOTICE:
22             $type_erreur = "Remarque";
23             break;
24 
25         case E_STRICT:
26             $type_erreur = "Syntaxe Obsolète";
27             break;
28 
29         default:
30             $type_erreur = "Erreur inconnue";
31     }
32 
33     $erreur = date("d.m.Y H:i:s") . ' - <b>' . $type_erreur.'</b> : <b>' . $message . '</b> ligne ' . $ligne . ' (' . $fichier . ')';
34 
35     // Affichage de l'erreur
36     echo $erreur;
37 
38     // Enregistrement de l'erreur dans un fichier txt
39     /*
40     $log = fopen('Erreurs.txt', 'a');
41     fwrite($log, $erreur . "\n");
42     fclose($log);
43     */
44 
45     // Envoi par mail
46     // ...
47 }
48 
49 function gestionDesExceptions($exception)  
50 {
51     gestionDesErreurs (E_USER_ERROR, $exception->getMessage(), $exception->getFile(), $exception->getLine());  
52 }
53 
54 function gestionDesErreursFatales()
55 {
56     if (is_array($e = error_get_last()))
57     {
58         $type = isset($e['type']) ? $e['type'] : 0;
59         $message = isset($e['message']) ? $e['message'] : '';
60         $fichier = isset($e['file']) ? $e['file'] : '';
61         $ligne = isset($e['line']) ? $e['line'] : '';
62 
63         if ($type > 0) gestionDesErreurs($type, $message, $fichier, $ligne);
64     }
65 }
66 
67 error_reporting(0);
68 
69 set_error_handler('gestionDesErreurs');
70 set_exception_handler("gestionDesExceptions");
71 register_shutdown_function('gestionDesErreursFatales');

Ce code est, je le rappelle, à placer en début de la page.

Suppléments

trigger_error

La fonction trigger_error vous permet de déclencher des erreurs.

Cela peut vous êtes très pratique.

Cette fonction prend 2 paramètres :

  • Le premier paramètre est le message d'erreur, au format string.
  • Le second paramètre est le type d'erreur (EUSERERROR, EUSERWARNING, ...)

Un exemple :

1 if ($diviseur == 0)
2 {
3     trigger_error("Il est impossible de diviser par zéro !", E_USER_ERROR);
4 }

Renverra une erreur fatale (Il est impossible de diviser par zéro !) dans "mon_fichier.php" ligne XX.

La fonction user_error est un alias de cette fonction.

Compléments d'informations

Vous pouvez trouver d'autres informations sur la gestion des erreurs sur php.net.


PHP

Article publié le 30 Novembre 2011.

Commentaires