Notez qu’on ne peut pas conserver l’identifiant du résultat d’une requête comme variable interne au même titre que $connexion car, pour un même objet instance de la classe, on peut envis
Trang 1fonction classique Pour des raisons exposées précédemment, les propriétés sont
privées Elles peuvent donc être utilisées dans les méthodes de la classe (préfixées
par $this->), mais restent inaccessibles pour une application manipulant un objet Toute interaction passe nécessairement par les méthodes publiques
Le constructeur est une méthode (optionnelle) spéciale, ayant soit le nom construct (avec deux caractères ’_’), soit le même nom que la classe Si un constructeur est défini, il est exécuté au moment ó un nouvel objet est créé, ce qui permet donc d’une part d’affecter une valeur initiale, si besoin est, aux propriétés de l’objet, d’autre part d’effectuer les tâches initiales de cet objet Ici, on se connecte au serveur MySQL à la base choisie Les instructions throw correspondent à des
« lancers » d’exception quand une erreur est rencontrée : nous y revenons plus loin Notez l’utilisation de @ préfixant les fonctions MySQL, pour éviter l’affichage incontrơlé de messages d’erreur si un problème survient (en effet, l’opérateur @ peut s’appliquer à n’importe quelle expression PHP pour annuler les messages d’erreur) Après exécution du constructeur, si aucune erreur n’est rencontrée, les propriétés
$connexion et $nomBase sont correctement initialisées et prêtes à être utilisées par les méthodes Pour construire un objet, on utilise l’opérateur new suivi d’un appel au constructeur (ou simplement du nom de la classe si on n’a pas défini de constructeur) Voici par exemple la création d’une connexion à MySQL
r e q u i r e _ o n c e ( " Connect php " ) ;
r e q u i r e _ o n c e ( "MySQL php " ) ;
$bd = new MySQL (NOM, PASSE , BASE , SERVEUR) ;
Les constantes NOM, PASSE, BASE et SERVEUR sont définies dans le fichier
Connect.php, ce qui permet de les modifier très facilement pour toute l’application La variable $bd est maintenant un objet sur lequel on va pouvoir appliquer toutes les méthodes de la classe MySQL
Les méthodes publiques correspondent aux fonctionnalités de base de MySQL Notez qu’on ne peut pas conserver l’identifiant du résultat d’une requête comme variable interne au même titre que $connexion car, pour un même objet instance
de la classe, on peut envisager d’exécuter simultanément plusieurs requêtes Il existe donc potentiellement plusieurs identifiants de résultats valides à un moment donné
L plus simple pour les gérer est de les échanger avec le script appelant pour désigner
la requête concernée
/ / On r é c u p è r e un i d e n t i f i a n t d e r é s u l t a t
$ r e s u l t a t = $bd−>execRequete ( "SELECT ∗ FROM FilmSimple " ) ;
/ / On s ’ e n s e r t p o u r d é s i g n e r l e r é s u l t a t qu ’ on v e u t p a r c o u r i r
w h i l e ( $ f i l m = $bd−>o b j e t S u i v a n t ( $ r e s u l t a t ) ) { }
La dernière méthode, destruct, est le destructeur que l’on trouve dans des
langages orientés-objets plus évolués comme C++ La notion de destructeur est introduite en PHP 5 Notons que la présence d’un destructeur n’est pas indispensable,
et souvent de peu d’utilité en PHP ó les ressources sont libérées automatiquement
en fin de script Ici, on ferme la connexion à MySQL
Trang 23.1.3 Les exceptions
Voyons maintenant le mécanisme de « lancer » d’exception Il répond au problème suivant : un programme (ou un script) un tant soit peu complexe peut être vu comme
un arbre composé d’appels successifs à des fonctions qui effectuent des tâches de plus
en plus spécialisées au fur et à mesure que l’on s’enfonce dans la hiérarchie On est souvent embarassé pour traiter les erreurs dans un tel programme car la manière dont l’erreur doit être gérée dépend du contexte – le programme appelant – parfois éloigné
de l’endroit ó l’erreur est survenue La situation classique est illustrée sur un cas simple dans la partie gauche de la figure 3.2 Le programme A appelle une fonction
B qui appelle elle-même une fonction C, ó l’erreur est rencontrée On peut alors considérer tout un ensemble de solutions parmi les deux extrêmes suivants :
1 on reporte l’erreur au moment ó on la rencontre, soit dans la fonction C pour notre exemple ;
2 on remonte l’erreur, de C vers A, par des passages de paramètres successifs vers
le programme appelant
La première solution, simple, a l’inconvénient de ne pas permettre l’adaptation
à un contexte particulier L’impossibilité de se connecter à une base de données par exemple peut être, selon le programme, soit une erreur fatale entraỵnant l’arrêt total, soit une erreur bénigne qui peut être compensée par d’autres actions (par exemple le recours à une base de secours) Effectuer la décision d’arrêt ou de poursuite au niveau
de la procédure de connexion n’est donc pas satisfaisant
message code
Exception
catch throw
Traitement classique Traitement avec exception
erreur!
Fonction B appel
appel
Gestion de l’erreur
erreur!
Fonction C
Fonction B appel
appel
retour retour Gestion de l’erreur
Objet C
Figure 3.2 — Gestion des exceptions.
La seconde solution est conceptuellement correcte puisqu’elle permet de décider
à quel niveau de la hiérarchie des appels on va traiter l’erreur rencontrée Elle est cependant, dans un cadre classique de programmation par fonctions, pénible à mettre
en œuvre à cause de la nécessité d’une part de gérer la « remontée » des erreurs avec des paramètres ou des valeurs de retour, et d’autre part de devoir détecter sans cesse, après un appel à une fonction, la présence d’une erreur
Trang 3Le mécanisme de « lancer » d’exception facilite considérablement cette remontée d’erreur Il est maintenant répandu dans de nombreux langages (comme C++, Java ainsi que d’autres non spécifiquement objet comme le PL/SQL d’Oracle) La partie droite de la figure 3.2 illustre le principe :
• quand une erreur est rencontrée, on « lance » (throw en anglais) une
excep-tion, placée dans un espace réservé du programme ;
• à chaque niveau de la hiérarchie des appels, on peut « attraper » (catch
en anglais) l’exception levée auparavant par une fonction ou une méthode appelée
Le fait de placer les exceptions dans un espace séparé évite d’avoir à les inclure dans les paramètres des fonctions ou méthodes De plus, une exception est un objet qui fournit plusieurs informations sur le contexte de l’erreur : un message,
un code d’erreur (optionnel), le fichier et le numéro de la ligne de l’instruction PHP qui a déclenché l’erreur Ces informations sont respectivement obtenues par les méthodes getMessage(), getCode(), getFile() et getLine() de la classe prédéfinie Exception
Voici un exemple de gestion d’exception dans la classe MySQL Au niveau du constructeur, on lance l’exception si la procédure de connexion a échoué :
f u n c t i o n _ _ c o n s t r u c t ( $ l o g i n , $m ot DePas s e , $ b a s e , $ s e r v e u r )
{
.
/ / C o n n e x i o n au s e r v e u r MySQL
i f ( ! $ t h i s−>connexion = @mysql_pconnect ( $ s e r v e u r , $log in ,
$ m o t D e P a s s e ) )
t h r o w new E x c e p t i o n ( " E r r e u r de c o n n e x i o n au s e r v e u r " ) ;
}
Quand l’instruction throw est déclenchée, l’exécution de la méthode est inter-rompue et l’exception est mise en attente Tout programme appelant la méthode (ou appelant une fonction appelant la méthode, et ainsi de suite) peut « attraper » cette exception et la traiter Il faut pour cela utiliser la construction suivante :
t r y {
/ / E s p a c e 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 l a n c é e s
}
c a t c h ( E x c e p t i o n $e )
{
/ / T r a i t e m e n t d e l ’ e x c e p t i o n l a n c é e
}
Le bloc try définit la partie du script qui va « attraper » toute exception lancée par un appel à une méthode effectuée dans le bloc Quand une exception est attrapée dans le bloc try, le flux d’exécution se redirige immédiatement vers le bloc catch qui récupère l’exception en la plaçant dans une variable (ici $e) et peut alors la traiter Voici comment nous avons géré les exceptions de la classe MySQL dans le script ApplClasseMySQL.php, page 119
Trang 4t r y {
$bd = new MySQL (NOM, PASSE , BASE , SERVEUR) ;
.
}
c a t c h ( E x c e p t i o n $ e x c )
{
echo " <b> E r r e u r r e n c o n t r é e : < / b> " $exc−>g e t M e s s a g e ( ) "\n " ;
}
Il est évidemment possible de décider au cas par cas de la gestion d’une exception
On peut se contenter de l’afficher, comme dans l’exemple ci-dessus, ou bien envoyer
un e-mail à l’administrateur et afficher un message neutre et poli à l’utilisateur si l’on
ne souhaite pas exhiber une faiblesse du site Le chapitre 5 reviendra en détail sur la politique de gestion des erreurs
3.1.4 Spécialisation : classes et sous-classes
Un concept essentiel en programmation objet est la spécialisation : il désigne la
possibilité de créer des sous-classes définissant des objets plus spécialisés que ceux de
la classe-mère Si on considère par exemple une classe Fichier avec des méthodes d’ouverture, de fermeture, d’affichage et de lecture/écriture dans le fichier, on peut ensuite spécialiser le concept de fichier avec des sous-classes FichierTexte,
qu’une sous-classe étend sa classe parente Chaque objet instance de la sous-classe est aussi une instance de la super-classe et peut être traité comme tel si c’est nécessaire.
Dans notre exemple, chaque instance de FichierTexte est aussi instance de Fichier Voici un squelette des définitions possibles de la classe Fichier et de deux de ses sous-classes :
c l a s s F i c h i e r {
/ / P r o p r i é t é s
p r i v a t e $nom ;
/ / C o n s t r u c t e u r
p u b l i c _ _ c o n s t r u c t ( $ n o m F i c h i e r ) { }
/ / Une m é t h o d e
p u b l i c c o p i e r ( $ d e s t i n a t i o n ) { }
}
/ / S o u s−c l a s s e d e s f i c h i e r s t e x t e
c l a s s F i c h i e r T e x t e e x t e n d s F i c h i e r
{
/ / P r o p r i é t é s
p r i v a t e $ c o n t e n u ;
/ / A j o u t d ’ u n e m é t h o d e
p u b l i c a f f i c h e r ( $nom_imprimante ) { }
}
Trang 5/ / S o u s −c l a s s e d e s f i c h i e r s r é p e r t o i r e
c l a s s R é p e r t o i r e e x t e n d s F i c h i e r
{
/ / P r o p r i é t é s
p r i v a t e $ l i s t e _ f i c h i e r s ;
/ / S u r c h a r g e d e l a m é t h o d e c o p i e r ( )
p u b l i c c o p i e r ( $ d e s t i n a t i o n ) { / ∗ D é f i n i t i o n p r o p r e aux
r é p e r t o i r e s ∗ / }
}
Cet exemple très partiel est essentiellement destiné à illustrer les principaux
concepts liés à la spécialisation : héritage des propriétés ou méthodes de la super-classe, ajout de propriétés ou de méthodes dans les sous-classes, surcharge de méthodes.
Voyons cela dans l’ordre
Héritage
La notion d’héritage découle directement de celle de spécialisation Dans la mesure
ó un objet instance d’une sous-classe est aussi une instance de la super-classe, la sous-classe doit disposer – ou « hériter » – de toutes les propriétés et méthodes de cette dernière Par exemple les fichiers textes étant des fichiers particuliers, toutes les descripions ou opérations valables pour les fichiers au sens générique du terme le sont également pour un fichier texte Un objet instance de FichierTexte dispose donc, sans qu’il soit besoin de rien préciser ou redéfinir, de la propriété nom et de la méthode copier()
L’héritage permet de considérer l’ensemble des instances d’une classe C, ou de n’importe laquelle de ses classes descendantes comme des objets uniformes dotés du même comportement, celui de la classe C Dans notre exemple, les fichiers texte
ou les répertoires (et aussi les fichiers images, les fichiers exécutables ou toute autre instance d’une sous-classe de Fichier) ont un nom et disposent de la méthode copier(), ce qui peut servir par exemple à effectuer une sauvegarde en appliquant systématiquement cette méthode sans se soucier du type précis de fichier manipulé
En d’autres termes, on « factorise » au niveau de la super-classe le comportement commun à toutes les instances de ses descendantes, facilitant ainsi les traitements qui n’ont pas besoin d’effectuer de distinction entre les différentes spécialisations
Ajout de nouvelles propriétés ou méthodes
Dans certaines circonstances, on souhaite au contraire considérer un objet comme une instance d’une classe spécialisée dotée de caractéristiques particulières La classe
FichierTexte illustre cet aspect : les objets instances de cette classe ont, en plus des propriétés et méthodes de la classe Fichier, des propriétés et méthodes propres :
• la propriété contenu permet de stocker sous forme de chaỵne de caractères le contenu du fichier ;
• la méthode afficher rend possible le rendu de ce contenu
Ces caractéristiques sont propres à ce type de fichier : on n’imagine pas de gérer le contenu d’un fichier exécutable ou de l’afficher L’ajout de propriétés ou de méthodes