La classe Exception ne demande qu’à être étendue dans des sous-classes person-nalisant la gestion des exceptions et la description des erreurs rencontrées.. Si, quand le script se termin
Trang 1La classe Exception ne demande qu’à être étendue dans des sous-classes person-nalisant la gestion des exceptions et la description des erreurs rencontrées Voici à titre d’exemple une sous-classe SQLException destinée à gérer plus précisément les erreurs survenant au cours d’un accès à un SGBD
Exemple 5.6 exemples/SQLException.php:Extension de la classe Exception pour les exceptions SQL
<? php
/∗ ∗
∗ S o u s −c l a s s e de l a c l a s s e e x c e p t i o n , s p é c i a l i s é e p o u r
∗ l e s e r r e u r s s o u l e v é e s p a r un SGBD
∗ /
c l a s s SQLException e x t e n d s E x c e p t i o n
{
/ / P r o p r i é t é s
p r i v a t e $ s g b d ; / / nom du SGBD u t i l i s é
p r i v a t e $ c o d e _ e r r e u r ; / / c o d e d ’ e r r e u r du SGBD
/ / C o n s t r u c t e u r
f u n c t i o n SQLException ( $ m e s s a g e , $ s g b d , $ c o d e _ e r r e u r =0)
{
/ / A p p e l du c o n s t r u c t e u r d e l a c l a s s e p a r e n t e
p a r e n t : : _ _ c o n s t r u c t ( $ m e s s a g e ) ;
/ / A f f e c t a t i o n a u x p r o p r i é t é s d e l a s o u s −c l a s s e
$ t h i s−>sgbd = $sgbd ;
$ t h i s−>c o d e _ e r r e u r = $ c o d e _ e r r e u r ;
}
/ / M é t h o d e r e n v o y a n t l e SGBD q u i a l e v é l ’ e r r e u r
p u b l i c f u n c t i o n getSGBD ( )
{
r e t u r n $ t h i s−>sgbd ;
}
/ / M é t h o d e r e n v o y a n t l e c o d e d ’ e r r e u r du SGBD
p u b l i c f u n c t i o n g e t C o d e E r r e u r ( )
{
r e t u r n $ t h i s−>c o d e _ e r r e u r ;
}
}
? >
On peut alors lancer explicitement une exception instance de SQLException et intercepter spécifiquement ce type d’exception Rappelons encore une fois que toute
instance d’une sous-classe est aussi instance de toutes les classes parentes, et donc
qu’un objet de la classe SQLException est aussi un objet de la classe Exception, ce qui permet de le faire entrer sans problème dans le moule de gestion des exceptions PHP 5
Trang 2Le fragment de code ci-dessous montre comment exploiter cette gestion des exceptions personnalisées
/ / B l o c d ’ i n t e r c e p t i o n d e s e x c e p t i o n s
t r y
{
/ / C o n n e x i o n
$bd = m y s q l _ c o n n e c t ( ( SERVEUR , NOM, PASSE ) ;
i f ( ! $bd ) / / E r r e u r s u r v e n u e ? On l a n c e l ’ e x c e p t i o n
t h r o w new SQLException ( " E r r e u r de c o n n e x i o n " , "MySQL" ) ;
.
}
c a t c h ( SQ LExcept ion $e ) / / I n t e r c e p t i o n d ’ u n e e r r e u r SQL
{
t r i g g e r _ e r r o r ( " E r r e u r s u r v e n u e d a n s " $e−>getSGBD ( )
" : " $e−>g e t M e s s a g e ( ) , E_USER_ERROR) ;
}
c a t c h ( E x c e p t i o n ) / / I n t e r c e p t i o n d e n ’ i m p o r t e q u e l l e e r r e u r
{
t r i g g e r _ e r r o r ( " E r r e u r : " $e−>g e t M e s s a g e ( ) , E_USER_ERROR) ;
}
On a utilisé plusieurs blocs catch, en interceptant les erreurs les plus précises en premier PHP exécutera le premier bloc catch spécifiant une classe dont l’exception est instance
L’utilisation des exceptions implique leur surveillance et leur interception par une construction try et catch Si, quand le script se termine, PHP constate que certaines exceptions n’ont pas été interceptées, il transformera ces exceptions en erreurs standards, avec affichage ou placement dans le fichier des erreurs selon la politique choisie Le message produit est cependant assez peu sympathique Voici par exemple ce que l’on obtient si on oublie d’intercepter les exceptions soulevées par la classe d’accès aux bases de données BD
Fatal error: Uncaught exception ’Exception’ with
message ’Erreur de connexion au SGBD’
in BD.class.php:23
On peut remplacer ce comportement un peu brutal par un gestionnaire d’excep-tion personnalisé, comme le montrera la prochaine secd’excep-tion
L’introduction des exceptions depuis PHP 5 fait de ce dernier –au moins pour cet aspect – un langage aussi puissant et pratique que C++ ou Java, auxquels il emprunte d’ailleurs très exactement le principe et la syntaxe de cette gestion d’erreurs Les exceptions offrent un mécanisme natif pour décrire, créer et gérer des erreurs de toutes sortes, sans imposer une gestion « manuelle » basée sur des échanges de codes d’erreur au moment des appels de fonctions, suivi du test systématique de ces codes
La gestion des exceptions est d’une grande souplesse : on peut spécialiser les diffé-rents types d’exception, choisir à chaque instant celle qu’on veut traiter, « relancer »
Trang 3les autres par un throw, séparer clairement les parties relevant de la gestion des erreurs de celles relevant du code de l’application
Attention cependant : le lancer d’une exception interrompt le script jusqu’au catch le plus proche, ce qui n’est pas forcément souhaitable pour toutes les erreurs détectées Par exemple, quand on teste les données saisies dans un formulaire, on
préfère en général afficher d’un coup toutes les anomalies détectées pour permettre à
l’utilisateur de les corriger en une seule fois Ce n’est pas possible avec des exceptions
5.2.4 Gestionnaires d’erreurs et d’exceptions
PHP permet la mise en place de gestionnaires d’erreurs et d’exceptions personnalisés grâce aux fonction set_error_handler() et set_exception_handler() Toutes deux prennent en argument une fonction qui implante la gestion personnalisée Commençons par la gestion des erreurs La fonction gestionnaire doit prendre
en entrée 5 paramètres : le niveau d’erreur, le message, le nom du script, le numéro
de ligne et enfin le contexte (un tableau qui contiendra les variables existantes au moment ó la fonction est appelée)
Quand une erreur est déclenchée, par l’interpréteur PHP ou par le développeur via la fonction trigger_error(), PHP appelle la fonction gestionnaire d’erreurs en lui passant les valeurs appropriées pour les paramètres L’exemple ci-dessous montre une fonction de gestion d’erreur
Exemple 5.7 webscope/lib/GestionErreurs.php : Un gestionnaire d’erreurs PHP
<? php
/ / D é f i n i t i o n d ’ un g e s t i o n n a i r e d ’ e r r e u r s
/ / E l l e a f f i c h e l e m e s s a g e e n f r a n ç a i s
f u n c t i o n G e s t i o n E r r e u r s ( $ n i v e a u _ e r r e u r , $ m e s s a g e ,
$ s c r i p t , $ n o _ l i g n e , $ c o n t e x t e = a r r a y ( ) )
{
/ / R e g a r d o n s l e n i v e a u d e l ’ e r r e u r
s w i t c h ( $ n i v e a u _ e r r e u r ) {
/ / L e s e r r e u r s s u i v a n t e s n e d o i v e n t p a s ê t r e t r a n s m i s e s i c i !
c a s e E_ERROR :
c a s e E_PARSE :
c a s e E_CORE_ERROR :
c a s e E_CORE_WARNING :
c a s e E_COMPILE_ERROR :
c a s e E_COMPILE_WARNING :
echo " C e l a ne d o i t j a m a i s a r r i v e r ! ! " ;
e x i t ;
c a s e E_WARNING :
$ t y p e E r r e u r = " A v e r t i s s e m e n t PHP" ;
b r e a k ;
c a s e E_NOTICE :
$ t y p e E r r e u r = " Remarque PHP" ;
Trang 4b r e a k ;
c a s e E_STRICT :
$ t y p e E r r e u r = " S y n t a x e o b s o l è t e PHP 5 " ;
b r e a k ;
c a s e E_USER_ERROR :
$ t y p e E r r e u r = " A v e r t i s s e m e n t de l ’ a p p l i c a t i o n " ;
b r e a k ;
c a s e E_USER_WARNING :
$ t y p e E r r e u r = " A v e r t i s s e m e n t de l ’ a p p l i c a t i o n " ;
b r e a k ;
c a s e E_USER_NOTICE :
$ t y p e E r r e u r = " Remarque PHP" ;
b r e a k ;
d e f a u l t :
$ t y p e E r r e u r = " E r r e u r i n c o n n u e " ;
}
/ / M a i n t e n a n t on a f f i c h e e n r o u g e
echo " < f o n t c o l o r = ’ r e d ’ > <b> $ t y p e E r r e u r < / b> : " $ m e s s a g e
" < b r / > L i g n e $ n o _ l i g n e du s c r i p t $ s c r i p t < / f o n t >< b r / > " ;
/ / E r r e u r u t i l i s a t e u r ? On s t o p p e l e s c r i p t
i f ( $ n i v e a u _ e r r e u r == E_USER_ERROR ) e x i t ;
}
? >
On peut noter que les niveaux d’erreur E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING sont traités de
manière rapide : en principe PHP gèrera toujours ce type d’erreur lui-même, sans
faire appel au gestionnaire d’erreur ; on ne devrait donc pas les rencontrer ici Pour les autres niveaux d’erreur on met en place une gestion personnalisée, consistant ici simplement à afficher les informations en rouge On peut faire
exac-tement ce que l’on veut : écrire dans un fichier de log (journalisation), envoyer
un e-mail à l’administrateur, ou toute combinaison appropriée de ces solutions Une possibilité par exemple est d’une part d’afficher un message neutre et poli à l’utilisateur du site l’informant que l’application est provisoirement indisponible et que l’équipe d’ingénieurs s’active à tout réparer, d’autre part d’envoyer un e-mail à cette dernière pour la prévenir du problème
Le gestionnaire d’erreurs est mis en place grâce à l’appel suivant :
/ / G e s t i o n n a i r e p e r s o n n a l i s é d ’ e r r e u r s V o i r G e s t i o n E r r e u r s p h p
s e t _ e r r o r _ h a n d l e r ( " G e s t i o n E r r e u r s " ) ;
Trang 5Soulignons que ceci vient remplacer la gestion normale des erreurs PHP, et qu’il est donc de sa responsabilité d’agir en fonction du niveau détecté Notre gestionnaire interrompt donc le script avec une instruction exit quand une erreur de niveau E_USER_ERROR est rencontrée Si l’on souhaite dans un script abandonner, tempo-rairement ou définitivement, la gestion personnalisée des erreurs, on peut revenir
au gestionnaire par défaut avec la fonction restore_error_handler() Cela peut être utile par exemple quand on inclut des scripts PHP pas entièrement compatibles PHP 5 et pour lesquels l’interpréteur engendre des messages d’avertissement
Le gestionnaire d’exception est basé sur le même principe que le gestionnaire d’erreur : on définit une fonction personnalisée qui prend en entrée un objet instance
de la classe Exception (et donc de n’importe laquelle de ses sous-classes) Pour faire simple, on peut transformer l’exception en erreur en appelant le gestionnaire d’erreurs défini précédemment
Exemple 5.8 webscope/lib/GestionExceptions.php : Un gestionnaire d’exceptions PHP
<? php
/ / D é f i n i t i o n d ’ un g e s t i o n n a i r e d ’ e x c e p t i o n s On f a i t
/ / s i m p l e m e n t a p p e l au g e s t i o n n a i r e d ’ e r r e u r s
f u n c t i o n G e s t i o n E x c e p t i o n s ( $ e x c e p t i o n )
{
/ / On t r a n s f o r m e d o n c l ’ e x c e p t i o n e n e r r e u r
G e s t i o n E r r e u r s (E_USER_ERROR ,
$ e x c e p t i o n−>g e t M e s s a g e ( ) ,
$ e x c e p t i o n−> g e t F i l e ( ) ,
$ e x c e p t i o n−>g e t L i n e ( ) ) ;
}
? >
On peut alors mettre en œuvre le gestionnaire d’exceptions grâce à l’appel suivant :
set_exception_handler("GestionExceptions");
La fonction GestionExceptions() sera appelée pour toute exception lancée dans un script qui n’est pas interceptée par un bloc catch Une solution possible est donc de ne pas utiliser du tout les try et les catch et de se reposer entièrement sur
le gestionnaire d’exceptions C’est d’ailleurs la solution adoptée pour notre site Attention à ne pas entrer dans une boucle sans fin en utilisant un gestionnaire d’erreurs qui lance une exception, laquelle à son tour se transforme en erreur et ainsi
de suite
Une fois ces gestionnaires en place, il suffit de les modifier selon les besoins pour obtenir une politique de gestion des erreurs flexible et évolutive