Gérer les erreurs en PHP
Les erreurs en PHP sont gérer par le système error reporting qui affiche sur la page la gravité des messages : Warning, Notice, Fatal error. Dans l’exemple ci-dessous, on essaye d’instancier un objet PDO sans paramètre.
echo $mystere;
Affichage
Notice: Undefined variable: mystere in C:\wamp\www\essai.php on line 25
Le bout de code affichera une erreur de faible importance, de type informative.
Les niveaux d’erreur
PHP attribue pour chaque niveau d’erreur un numéro et une constante qui représente un type d’erreur.
- 1 – E_ERROR : erreur critique entraînant une interruption du script
- 2 – E_WARNING : message d’avertissement qui peut entraîner des comportements anormal par la suite (comme l’échec de l’ouverture d’un fichier) .. mais PHP peut continuer son exécution
- 4 – E_PARSE : erreur de syntaxe dans le fichier
- 8 – E_NOTICE : message de faible importance et l’exécution ne sera pas perturbée (comme lire une variable pas déclarée)
- 256 – E_USER_ERROR : Message d’erreur généré par l’utilisateur. Elle est générée par le programmeur en PHP par l’utilisation de la fonction trigger_error()
- 512 – E_USER_WARNING : Message d’erreur généré par l’utilisateur. Elle est générée par le programmeur en PHP par l’utilisation de la fonction trigger_error()
- 1024 – E_USER_NOTICE : Message d’erreur généré par l’utilisateur. Elle est générée par le programmeur en PHP par l’utilisation de la fonction trigger_error()
- 2048 – E_STRICT : erreur d’avertissement pour utilisation d’une ancienne syntaxe déconseillée
Désactiver un message d’erreur
Il est possible de désactiver la gestion des erreurs, pour une commande particulière, en la préfixant avec l’opérateur @.
echo @$mystere;
L’instruction ne déclenchera aucune erreur!
Gestionnaire d’erreurs personnalisé
Le principe consiste à appeler une fonction lorsqu’une erreur PHP se produit. Cette fonction peut accepter cinq paramètres :
- $errno – le niveau d’erreur (obligatoire)
- $errstr – le message (obligatoire)
- $errfile – le nom du fichier (optionnel)
- $errline – le numéro de ligne (optionnel)
- $errcontext – un tableau avec toutes les variables qui existaient lorsque l’erreur a été déclenchée (optionnel).
function ErrorPersonnalise($errno, $errstr, $errfile, $errline){
echo "Erreur numéro [$errno], ligne [$errline], du fichier $errfile : $errstr";
}
On associe cette fonction d’erreur avec la commande set_error_handler().
// appel de la fonction 'ErrorPersonnalise' si erreur
set_error_handler(ErrorPersonnalise);
On déclenche, pour tester le gestionnaire, une erreur en affichant par exemple une variable non déclarée.
echo $inconnu;
Affichage
Erreur numéro [8], ligne [106], du fichier /homepages/12/d364229332/htdocs/tutovisuel/gestion-erreurs-php.php : Undefined variable: inconnu
Déclencher ses propres erreurs
Vous pouvez créer vos propres erreurs et définir leurs niveaux de gravité avec la fonction trigger_error() qui prend comme arguments le message à afficher et le type d’erreur.
$prix=0;
if ($prix==0) {
trigger_error("Le prix ne peux pas être nul",E_USER_WARNING );
}
Affichage
Erreur numéro [512], ligne [122], du fichier /homepages/12/d364229332/htdocs/tutovisuel/gestion-erreurs-php.php : Le prix ne peux pas être nul
Les différents types d’erreur sont :
- E_USER_ERROR – Fatal erreur d’exécution généré par l’utilisateur. L’exécution du script est interrompue
- E_USER_WARNING – Avertissement d’exécution généré par l’utilisateur. L’exécution du script n’est pas interrompue
- E_USER_NOTICE – Par Defaut.Message de faible importance et l’exécution ne sera pas perturbée
Il est possible d’utiliser un gestionnaire personnalisé pour vos propres erreurs déclenchées.
function MyErrorPersonnalise($errno, $errstr){
echo "Erreur numéro [$errno] : $errstr";
}
set_error_handler(MyErrorPersonnalise,E_USER_WARNING);
$prix=0;
if ($prix==0) {
trigger_error("Le prix ne peux pas être nul",E_USER_WARNING );
}
Affichage
Erreur numéro [512] : Le prix ne peux pas être nul
Les assertions
Une assertion est une affirmation fonctionnelle logique, comme dire que 2 est supérieur à 1. Vous pouvez donc, en PHP, mettre une assertion qui vérifie un résultat logique avec la fonction assert().
Il faut encapsuler l’affirmation (qui retourne un booléen) dans une chaine de caractères qui sera interprétée comme pour la fonction eval(). Si l’affirmation n’est pas vraie, alors PHP renvoie une erreur.
assert('2>3');
Affichage
Erreur numéro [2], ligne [157], du fichier /homepages/12/d364229332/htdocs/tutovisuel/gestion-erreurs-php.php : assert(): Assertion "2>3" failed
Personnaliser la gestion d’erreur
Une assertion retourne une erreur standard, mais il est possible de traiter l’erreur avec un gestionnaire spécifique qui accepte trois paramètres :
- L’adresse du fichier : exemple $script
- Le numéro de ligne : exmple $ligne
- le message : exemple $message
function gestion_assert($script, $ligne, $message){
echo "Assertion fausse faite dans le fichier : <br> $script <br> à la ligne $ligne : <br>$message";
}
On fixe et on lit différentes options d’assertions avec les directives ASSERT_ACTIVE, ASSERT_WARNING et ASSERT_QUIET_EVAL de la fonction assert_options().
//Active l'évaluation de la fonction assert
assert_options(ASSERT_ACTIVE, 1);
//Génère une alerte PHP pour chaque assertion fausse
assert_options(ASSERT_WARNING, 0);
//Désactive le rapport d'erreur durant l'évaluation d'une assertion
assert_options(ASSERT_QUIET_EVAL, 1);
On enregistre ensuite le gestionnaire avec la directive ASSERT_CALLBACK de la fonction assert_options().
assert_options(ASSERT_CALLBACK,'gestion_assert');
Affichage
Assertion fausse faite dans le fichier :
/homepages/12/d364229332/htdocs/tutovisuel/gestion-erreurs-php.php
à la ligne 201 :
2>3
Les exceptions
Le PHP 5 propose une nouvelle gestion des erreurs plus simple et plus personnalisable. Il suffit d’imbriquer l’instruction pouvant provoquer une erreur dans un bloc try et de récupérer l’erreur dans le bloc catch.
try{
$pdo = new PDO('');
} catch(Exception $e){
print_r($e);
}
echo "<br>suite..";
Affichage
PDOException Object ( [message:protected] => invalid data source name [string:Exception:private] => [code:protected] => 0 [file:protected] => /homepages/12/d364229332/htdocs/tutovisuel/gestion-erreurs-php.php [line:protected] => 218 [trace:Exception:private] => Array ( [0] => Array ( [file] => /homepages/12/d364229332/htdocs/tutovisuel/gestion-erreurs-php.php [line] => 218 [function] => __construct [class] => PDO [type] => -> [args] => Array ( [0] => ) ) ) [previous:Exception:private] => [errorInfo] => )
suite..
Vous remarquez que l’affichage de l’erreur ne bloque plus le script (echo suite..) qui suit l’instuction qui provoque l’erreur.
L’objet Exception
La fonction catch() fait passer l’exception sous forme d’objet $e. Cet objet contient des informations à travers des attributs privés ou protégés, comme le message d’erreur (message:protected) et le code associé (code:protected). Voici le contenu de la classe Exception:
lass Exception
{
protected $message = 'Exception inconnue'; // message de l'exception
private $string; // __toString cache
protected $code = 0; // code de l'exception défini par l'utilisateur
protected $file; // nom du fichier source de l'exception
protected $line; // ligne de la source de l'exception
private $trace; // backtrace
private $previous; // exception précédente (depuis PHP 5.3)
public function __construct($message = null, $code = 0, Exception $previous = null);
final private function __clone(); // Inhibe le clonage des exceptions.
final public function getMessage(); // message de l'exception
final public function getCode(); // code de l'exception
final public function getFile(); // nom du fichier source
final public function getLine(); // ligne du fichier source
final public function getTrace(); // un tableau de backtrace()
final public function getPrevious(); // exception précédente (depuis PHP 5.3)
final public function getTraceAsString(); // chaîne formatée de trace
// Remplacable
public function __toString(); // chaîne formatée pour l'affichage
}
La récupération des attributs se fait à travers les accesseurs, c’est à dire des méthodes qui récupères les attributs privés (private) ou protégés (protected) de l’objet $e :
- getMessage()
- getCode()
- getFile()
- getLine()
- getTrace()
try{
$pdo = new PDO("");
} catch(Exception $e){
echo $e->getMessage();
}
echo "<br>suite..";
Affichage
invalid data source name
suite..
Lever manuellement une exception
Il est possible de provoquer une exception en créant l’objet avec l’instruction new Exception et de le lancer avec l’instruction throw. Cela permet de personnaliser ses exceptions en mode dynamique.
try{
if (!file_exists($cheminFichier)) {
throw new Exception("Aucun fichier trouvé");
}
}catch(Exception $e){
echo $e->getMessage();
}
echo "<br>suite..";
Affichage
Erreur numéro [8], ligne [301], du fichier /homepages/12/d364229332/htdocs/tutovisuel/gestion-erreurs-php.php : Undefined variable: cheminFichierAucun fichier trouvé
suite..
Dans cet exemple, si le fichier n’est pas trouvé, PHP lance une exception avec un message personnalisé.
Voici un autre exemple qui lance une exception si une classe n’existe pas.
try{
if (class_exists('MyClass')) {
$myclass = new MyClass();
}else{
throw new Exception('Classe inexistante');
}
} catch(Exception $e){
echo $e->getMessage();
}
echo "<br>suite..";
Affichage
Classe inexistante--
suite..
Important : les erreurs fatales (E-ERROR) générées par PHP ne peuvent pas être interceptées.
Finally
Le code à l’intérieur du bloc finally sera toujours exécuté après les blocs try et catch, indépendamment du fait qu’une exception ai été lancée, avant de continuer l’exécution normale.
try{
if (class_exists('MyClass')) {
$myclass = new MyClass();
}else{
throw new Exception('Classe inexistante');
}
} catch(Exception $e){
echo $e->getMessage();
} finally{
echo "<br>toujours exécuté";
}
echo "<br>suite..";
Affichage
Classe inexistante
toujours exécuté
suite..
Ce bloc est souvent utilisé pour les opérations de nettoyage : fermeture de fichier ou fermeture de connexion..
Créer ses propres exceptions
Comme les exceptions sont gérées sous forme de classes, il est possible d’étendre leurs possibilités en y ajoutant des méthodes et des propriétés pour gérer des cas spécifiques. L’exemple ci-dessus gère le cas d’un fichier inexistant :
class FichierInexistant extends Exception{
private $fichierInexistant;
public function __construc($message, $fichierInexistant){
$this->fichierInexistant = $fichierInexistant;
parent::__construct($message);
}
public function getFichierInexistant(){
return $this->fichierInexistant;
}
}
On y ajoute la propriété privée $fichierInexistant, on surcharge la méthode __construc() et on créer la méthode getFichierInexistant() qui retournera le nom du fichier manquant.
On lance maintenant une exception :
try{
$cheminFichier = 'inconnu.php';
if (!file_exists($cheminFichier)) {
$message = "Le fichier suivant est introuvable : ";
throw new FichierInexistant($message, $cheminFichier);
}
}catch(FichierInexistant $e){
echo $e->getMessage().$e->getFichierInexistant();
}
Affichage
Le fichier suivant est introuvable : inconnu.php