I. Présentation▲
Les exceptions sont pour beaucoup de personnes un système élaboré de gestion d'erreur. Ce n'est pas le cas.
Et même si dans la pratique, on peut, comme nous le verrons, établir des liens entre ces deux concepts, leurs buts sont totalement différents.
Une erreur est dans la majorité des cas assimilable à un bug, c'est à dire une réaction non désirée.
Une exception est un traitement qui sera appelé lorsqu'un cas particulier est détecté pendant le déroulement du programme.
Pour synthétiser, une erreur est le résultat un fonctionnement anormal alors qu'une exception est un fonctionnement normal, mais exceptionnel.
I-A. Mots-clés [throw] [try] [catch]▲
Comme tous les mots-clés de programmation, ces trois mots proviennent de l'anglais et signifient
- throw : lancer
- try : essayer
- catch : attraper
La signification de ces 3 mots-clé est très représentative du mécanisme utilisé et doit toujours être gardé à l'esprit. En effet, les exceptions fonctionnent de la même façon dans tous les langages. Dans un bloc défini (try), l'environnement d'exécution envoie un signal (throw) au gestionnaire d'exception qui diffusera l'information aux différents blocs de traitement (catch). Le bloc adéquat au signal émis attrappera alors le signal (catch) et exécutera un code adapté.
La mise en place d'une exception se présente comme ceci
try
{
throw new Exception ('
ceci
est
faux
'
);
echo '
Code
non
executé
'
;
}
catch(Exception $myException
)
{
echo $myException
-
>
getMessage();
}
- On entre dans le bloc try
- On lance une exception (on dit aussi "soulever une exception").
- On quitte le bloc try (sans exécuter le code restant du bloc try)
- Le catch attrape l'exception
- On execute le contenu du bloc catch
Le code précédent affichera ainsi :
Ceci est faux
Il s'agit ici du cas le plus simple car l'exception est au même niveau que le bloc try/catch et nous n'avons traité qu'un cas d'exception, en utilisant la classe native de PHP. Nous allons voir qu'il est possible de personnaliser ce mécanisme par l'écriture de classe d'Exception propre à un contexte, et comment utiliser au mieux ce mécanisme, en comprennant bien le rôle et la place du throw et des blocs try/catch
I-B. Profondeur de throw▲
Un bloc try peut ne pas contenir directement de throw. Les throw sont en effet répartis dans le code en fonction des besoins. On peut ainsi lancer une exception dans une fonction, et placer l'appel à cette fonction dans un bloc try.
function verif_text( $text
)
{
if (empty($text
))
{
throw new Exception ('
Le
texte
est
vide
'
);
}
else
{
return $text
;
}
}
try
{
verif_text( '
'
);
}
catch(Exception $myException
)
{
echo $myException
-
>
getMessage();
}
Cet exemple lancera bien l'exception et affichera le message 'Le texte est vide'.
Le principe est exactement le même dans les méthodes d'une classe.
On a vu au I-A que le code suivant un throw dans un bloc try n'était pas éxecuté. Il en est de même ici, même à l'intérieur de la fonction. Ainsi, ceci :
function myFct()
{
throw new Exception("
Voici
l
'
exception
"
);
echo "
Une
exception
vient
d
'
être
levée
"
;
}
try
{
myFct();
}
catch(Exception $e
)
{
echo $e
-
>
getMessage();
}
affichera uniquement
Voici l'exception
Il est donc inutile de mettre un die, exit ou return directement après un throw, la fonction est de toute manière interrompue.
L'intéret est de distinguer les instructions throw et try/catch. L'écriture d'une classe ou d'une fonction ne devrait contenir que des throw, et rarement de try/catch que l'on utilise plus lors des appels de ces classes/fonctions.
I-C. Intérêt des exceptions▲
- Pouvoir interrompre un bloc de code si on detecte la moindre exception.
- Pouvoir générer des exceptions pour les erreurs systèmes, mais aussi pour les erreurs utilisateurs ou tout autre évènement défini par le développeur.
- Personnaliser le traitement de l'exception dans le bloc catch et ainsi appliquer un correctif ou une alerte adapté.
On pourrait alors se dire que les exceptions ne sont qu'un système d'erreur évolué. Pas du tout ! Il faut bien distinguer les erreurs des exceptions. Une erreur est en général une réponse du système à problème rencontré. Les exceptions sont des alertes dont l'emplacement et le comportement sont définis par le développeur. Les exceptions permettent de gérer les erreurs, la réciproque n'a pas de sens.
Les exceptions répondent à un besoin, qui est de laisser la gestion des erreurs utilisateurs aux mécanismes adaptés pour ceci. Vous pensez que c'est ce que vous faites? Qui n'a jamais écrit une fonction de ce type?
<?php
function
testLogin( $login
)
{
if
( !
($res
=
mysql_query("
SELECT
1
FROM
membres
WHERE
login
=
'
"
.
mysql_real_escape_string($login
).
"
'
"
)) )
{
return
FALSE
;
}
else
{
$row
=
mysql_fetch_assoc($res
);
if
($row
[
'
login
'
]
=
=
$login
)
{
return
TRUE
;
}
else
{
return
FALSE
;
}
}
}
?>
Ceci est une horreur. Que peut-on conclure si la fonction retourne un false ? Absolument rien, peut-être y a-t-il eu une erreur, peut-être pas...
Par définition, une fonction doit toujours renvoyer une valeur attendue et jamais une erreur (et encore moins les deux en même temps). Imaginez votre voiture, vous mettez de l'essence en entrée, vous obtenez une vitesse en sortie. Lorsqu'un problème intervient, avec le système incorrect ci-dessus, vous obtienteriez que votre vitesse est nulle, la voiture ne fonctionne plus, et c'est tout. Or, le problème en question n'est qu'un feu stop cassé. Avec les exceptions, la voiture continue de rouler, vous lisez la vitesse sur le compteur, et un petit voyant s'est allumé sur le tableau de bord indiquant qu'un feu stop est cassé.
En renvoyant erreurs et valeurs, des collisions peuvent se produire car false == 0
Il faudra donc typer les comparaisons pour distinguer les erreurs des valeurs
Par exemple
if ( countMembre() === false ) { // c'est une erreur...
if ( countMembre() === 0) { // Il y a 0 membre...