138 Chapitre 3. Programmation objet try { if (isSet($_GET[ ’postgresql ’])) $bd = new BDPostgreSQL (NOM, PASSE, BASE, SERVEUR) ; else if (isSet($_GET[ ’sqlite ’])) $bd = new BDSQLite (NOM, PASSE, BASE, SERVEUR) ; else $bd = new BDMySQL (NOM, PASSE, BASE, SERVEUR) ; $resultat = $bd−>execRe quete ( "SELECT ∗ FROM F i l m S i m p l e " ) ; while ($film = $bd−>objetSuivant ($resultat )) echo "<b>$film−>titre </b>, paru en $film−>annee , " . " réalisé par $film−>prenom_realisateur $film−> nom_realisateur<br/>" ; } catch (Exception $exc) { echo "<b>Erreur rencontrée:</b> " . $exc−>getMessage() . "\n"; } ?> </body> </html> Si on passe une variable postgresql en mode GET, c’est à PostgreSQL qu’on se connecte, sinon c’est à MySQL, ou à SqLite, etc. Dans une application importante, détaillée dans la seconde partie de ce livre, on peut instancier initialement un objet en choisissant le SGBD à utiliser, et le passer ensuite en paramètre aux fonctions ou objets qui en ont besoin. Ceux-ci n’ont alors plus à se soucier de savoir à quel système ils accèdent, tant qu’ils se conforment au comportement de la classe générique. REMARQUE – Écrire une application multi-plateformes demande cependant quelques pré- cautions supplémentaires. Il existe de nombreuses différences mineures entre les différents SGBD qui peuvent contrarier, et parfois compliquer, la production d’un code complètement compatible. La première précaution à prendre (nécessaire, mais par forcément suffisante ) est de respecter strictement la norme SQL du côté SGBD. Il faut ensuite étudier soigneusement les interfaces entre PHP et le SGBD pour détecter les points susceptibles de poser problème. Le fait que l’interface de PostgreSQL traduise tous les identificateurs en minuscules est par exemple une source d’incompatibilité à prendre en compte dès la conception, en n’utilisant que des identificateurs déjà en minuscules. Nous revenons en détail page 233 sur le problème de la portabilité multi-SGBD. 3.1.6 Résumé Ce premier tour d’horizon a permis de voir l’essentiel des principes de la programma- tion objet. Si c’est votre premier aperçu de cette technique, il est probable que vous trouviez tout cela compliqué et inutilement abstrait. À l’usage, la cohérence de cette approche apparaît, ainsi que ses avantages, notamment en terme sde simplification de la programmation et de la maintenance. Il n’est pas obligatoire de programmer 3.1 Tour d’horizon de la programmation objet 139 en objet pour réaliser des applications robustes, et on peut envisager de ne pas maîtriser l’ensemble de la panoplie des concepts et techniques. La programmation PHP s’oriente cependant de plus en plus vers l’utilisation et la réutilisation d’objets prêts à l’emploi. La compréhension de ce mode de production du logiciel semble donc s’imposer. Les exemples qui vont suivre permettent d’approfondir cette première présenta- tion et de présenter quelques nouveautés qui sont brièvement résumées ci-dessous pour compléter cette première section. Constantes. Il est possible en PHP 5 de définir des constantes locales à une classe. L’usage est principalement d’initialiser des valeurs par défaut utilisables par la classe et ses sous-classes. Propriétés et méthodes statiques. Les méthodes ou propriétés vues jusqu’à présent étaient toujours considérées dans le cadre d’un objet de la classe. Chaque objet dispose d’une valeur propre pour chaque propriété, et les méthodes appliquées à un objet s’appliquent à ces valeurs. Les propriétés et méthodes statiques sont au contraire rattachées à la classe, pas à chacune de ses instances. Il en existe donc une unique copie par classe, utilisable, par exemple, pour compter le nombre d’objets instanciés à un moment donné. Interfaces. Une interface, comme son nom l’indique, est la spécification d’une liste de fonctions avec leur nom et leur mode d’appel. Une classe abstraite propose le même type de spécification, implicitement destinée à s’appliquer aux instances de la classe. La notion d’interface est un peu plus générale dans la mesure où elle est définie indépendamment de toute classe, donc de toute instance. Une classe peut alors implanter une ou plusieurs interfaces. L’utilisation des interfaces permet de pallier en partie l’absence de concepts comme l’héritage multiple. Il s’agit cependant de techniques avancées qui dépassent le cadre de ce livre et ne seront donc pas détaillées. Identité d’un objet. Un objet, c’est une identité et une valeur. Deux objets sont dits identiques s’ils ont la même identité, et égaux s’ils ont la même valeur. L’égalité se teste avec l’opérateur classique ==, alors que l’identité se teste avec l’opérateur PHP5 === 1 . Important : quand on passe un objet en paramètre à une fonction, c’est son identité (ou sa référence, en terminologie PHP) qui est transmise, pas sa valeur. De même l’affectation $a = $b;,oùb est un objet, fait de a une référence vers b (voir page 61). Les objets constituent donc une exception au principe de passage des paramètres par valeur en usage dans tous les autres cas. Concrètement, cela signifie que toute modification effectuée dans la fonction appelée agit directement sur l’objet, pas sur sa copie. Cette règle ne vaut que depuis la version 5, puisque PHP 4 (et versions antérieures) appliquaientt la règle du passage par valeur. 1. Ceux qui confondraient déjà l’opérateur d’affectation = et l’opérateur de comparaison == apprécieront ! 140 Chapitre 3. Programmation objet Classes cibles L’opérateur :: permet dans certains cas d’indiquer explicitement la classe dans laquelle chercher une définition. La syntaxe est NomClasse::d´efinition,oùd´efinition est soit une constante de la classe NomClasse, soit une propriété ou une méthode statique. Deux mot-clés réservés peuvent remplacer NomClasse : parent et self qui désignent respectivement la classe parent et la classe courante. Quand une méthode est surchargée, ils peuvent indiquer quelle version de la méthode on souhaite appeler (voir par exemple page 128). Le chapitre 11 complète cette rapide présentation et donne l’ensemble de la syntaxe objet de PHP. En ce qui concerne la modélisation des applications objet, rappelons que tout ce qui précède est repris, en PHP, d’autre langages orientés-objet, notamment du C++ et, dans une moindre mesure de Java. Pour aller plus loin dans l’approfondissement de la programmation objet, vous pouvez recourir à un ouvrage généraliste consacré au C++, à Java, ou à la conception objet en géné- ral. 3.2 LA CLASSE TABLEAU La classe présentée dans cette section montre comment concevoir et réaliser un utilitaire de production de tableaux HTML qui évite d’avoir à multiplier sans cesse, au sein du code PHP, des balises <tr>, <td>, etc. Un tel utilitaire prend place dans une stratégie générale de séparation du code HTML et du code PHP sur laquelle nous reviendrons au chapitre 5. La première chose à faire quand on projette la création d’une nouvelle classe, c’est de bien identifier les caractéristiques des objets instances de cette classe, leur représentation, les contraintes portant sur cette représentation, et enfin les méthodes publiques qu’ils vont fournir. À terme, ce qui nous intéresse, c’est la manière dont on va pouvoir communiquer avec un objet. 3.2.1 Conception Le but est de produire des tableaux HTML. Il faut pour cela les construire dans l’objet, en attendant de pouvoir afficher par la suite le code HTML correspondant. Pour commencer, il faut se faire une idée précise de ce qui constitue un tableau et des options de présentation dont on veut disposer. On cherche le meilleur rapport possible entre la simplicité de l’interface des tableaux, et la puissance des fonction- nalités. On peut commencer par identifier les besoins les plus courants en analysant quelques cas représentatifs de ce que l’on veut obtenir, puis spécifier les données et traitements nécessaires à la satisfaction de ces besoins. Les tableaux sont très utilisés en présentation de données statistiques. Prenons le cas d’une base d’information sur la fréquentation des films (aou « box office » pour faire court), classée selon divers critères comme les villes et la semaine d’ex- ploitation, et voyons les différentes possibilités de représentation par tableau. La 3.2 La classe Tableau 141 première possibilité est simplement de mettre chaque donnée en colonne, comme ci-dessous. Tableau 3.2 — Tableau A. Film Semaine Ville Nb entrées Matrix 1 Paris 12000 Matrix 2 Paris 15000 Matrix 3 Paris 11000 Spiderman 1 Paris 8000 Spiderman 2 Paris 9000 Spiderman 3 Paris 9500 Matrix 1 Caen 200 Matrix 2 Caen 2100 Matrix 3 Caen 1900 Spiderman 1 Caen 1500 Spiderman 2 Caen 1600 Spiderman 3 Caen 1200 C’est la représentation qu’on obtient classiquement avec un SGBD relationnel comme MySQL. Elle est assez peu appropriée à la visualisation des propriétés du jeu de données (comme l’évolution du nombre d’entrées, ou les proportions entre les différents films). Voici une seconde possibilité qui montre, sur Paris, et par film, le nombre d’entrées au cours des différentes semaines. Tableau 3.3 — Tableau B. Box office Semaine 1 Semaine 2 Semaine 3 Matrix 12000 15000 11000 Spiderman 8000 9000 9500 On s’est ici limité à deux dimensions, mais des artifices permettent de présenter des tableaux de dimension supérieure à 2. Voici par exemple une variante du tableau précédent, montrant les mêmes données sur Paris et sur Caen, ce qui donne un tableau à trois dimensions. Tableau 3.4 — Tableau C. Box office Film Semaine 1 Semaine 2 Semaine 3 Paris Matrix 12000 15000 11000 Spiderman 8000 9000 9500 Caen Matrix 2000 2100 1900 Spiderman 1500 1600 1200 Bien entendu on pourrait présenter les entrées dans un ordre différent, comme dans l’exemple ci-dessous. 142 Chapitre 3. Programmation objet Tableau 3.5 — Tableau D. Box office Semaine 1 Semaine 2 Semaine 3 Paris Caen Paris Caen Paris Caen Matrix 12000 2000 15000 2100 11000 1900 Spiderman 8000 1500 9000 1600 9500 1200 Une possibilité encore : Tableau 3.6 — Tableau E. Paris Semaine 1 Semaine 2 Semaine 3 Matrix 12000 15000 11000 Spiderman 8000 9000 9500 Caen Semaine 1 Semaine 2 Semaine 3 Matrix 200 2100 1900 Spiderman 1500 1600 1200 Tous ces exemples donnent dans un premier temps un échantillon des possibilités de présentation en clarifiant les caractéristiques des données qui nous intéressent. Ces deux aspects, présentation et données, sont en partie indépendants puisqu’à partir du même box office, on a réussi à obtenir plusieurs tableaux très différents. L’étape suivante consiste à décrire dces tableaux de manière plus abstraite. Pour les données, nous pouvons distinguer les dimensions, qui servent au classement, et les mesures qui expriment la valeur constatée pour une combinaison donnée de dimensions 2 . Dans les exemples ci-dessus, les dimensions sont les films, les villes, les semaines, et la seule mesure est le nombre d’entrées. Autrement dit, le nombre d’entrées est fonction d’un film, d’une ville, et d’une semaine. Veut-on gérer plusieurs mesures, c’est-à-dire présenter plusieurs valeurs dans une même cellule du tableau ? On va répondre « non » pour simplifier. D’une manière générale on a donc une fonction M qui prend en paramètres des dimensions d 1 , d 2 , ,d p et renvoie une mesure m. On peut gérer cette information grâce à un tableau PHP multi-dimensionnel $M[d 1 ][d 2 ] [d p ]. À ce stade il faut se demander si cela correspond, de manière suffisamment générale pour couvrir largement les besoins, aux données que nous voudrons manipuler. Répondons « oui » et passons à la présentation du tableau. Un peu de réflexion suffit à se convaincre que si l’on souhaite couvrir les pos- sibilités A, B, C, D et E ci-dessus, l’utilisation de la classe deviendra assez difficile pour l’utilisateur (ainsi bien sûr que la réalisation du code, mais cela importe moins puisqu’en principe on ne fera l’effort une fois et on n’y reviendra plus). Le cas du 2. Cette modélisation reprend assez largement la notation, le vocabulaire et les principes en usage dans les entrepôts de données, supports privilégiés de ce type de tableaux statistiques. . cependant de techniques avancées qui dépassent le cadre de ce livre et ne seront donc pas détaillées. Identité d’un objet. Un objet, c’est une identité et une valeur. Deux objets sont dits identiques. obligatoire de programmer 3.1 Tour d’horizon de la programmation objet 139 en objet pour réaliser des applications robustes, et on peut envisager de ne pas maîtriser l’ensemble de la panoplie des concepts. classe, c’est de bien identifier les caractéristiques des objets instances de cette classe, leur représentation, les contraintes portant sur cette représentation, et enfin les méthodes publiques