You are on page 1of 1440

Copyright

2005

Micro Application 20-22, rue des Petits-Htels 75010 Paris

1re dition - Janvier 2005

Auteurs

Laurent GUDON, Damien HEUTE, Thomas HEUTE et Pierre-Emmanuel MULLER Toute reprsentation ou reproduction, intgrale ou partielle, faite sans le consentement de MICRO APPLICATION est illicite (article L122-4 du code de la proprit intellectuelle). Cette reprsentation ou reproduction illicite, par quelque procd que ce soit, constituerait une contrefaon sanctionne par les articles L335-2 et suivants du code de la proprit intellectuelle. Le code de la proprit intellectuelle nautorise aux termes de larticle L122-5 que les reproductions strictement destines lusage priv et non destines lutilisation collective dune part, et dautre part, que les analyses et courtes citations dans un but dexemple et dillustration.

Avertissement aux utilisateurs

Les informations contenues dans cet ouvrage sont donnes titre indicatif et nont aucun caractre exhaustif voire certain. A titre dexemple non limitatif, cet ouvrage peut vous proposer une ou plusieurs adresses de sites Web qui ne seront plus dactualit ou dont le contenu aura chang au moment o vous en prendrez connaissance. Aussi, ces informations ne sauraient engager la responsabilit de lEditeur. La socit MICRO APPLICATION ne pourra tre tenue responsable de toute omission, erreur ou lacune qui aurait pu se glisser dans ce produit ainsi que des consquences, quelles quelles soient, qui rsulteraient des informations et indications fournies ainsi que de leur utilisation. ISBN : 2-7429-3608-4 Tous les produits cits dans cet ouvrage sont protgs, et les marques dposes par leurs titulaires de droits respectifs. Cet ouvrage nest ni dit, ni produit par le(s) propritaire(s) de(s) programme(s) sur le(s)quel(s) il porte. Couverture ralise par Stefanos ATHANASSOPOULOS

MICRO APPLICATION 20-22, rue des Petits-Htels 75010 PARIS Tl. : 01 53 34 20 20 - Fax : 01 53 34 20 00 http://www.microapp.com

Support technique disponible sur www.microapp.com

Mister Onet, lhomme la rfrence, vous montre le chemin !


Rendez-vous sur le site Internet de Micro Application www.microapp.com. Dans le module de recherche, sur la page daccueil du site, retrouvez Mister Onet. Dans la zone de saisie, entrez la rfrence 4 chiffres quil vous indique sur le prsent livre. Vous accdez directement la fiche produit de ce livre.

4608

Avant-propos
La collection Bible Micro Application a t conue pour permettre aux utilisateurs avancs experts dapprofondir leurs connaissances dun thme prcis. Exhaustifs, ces ouvrages permettent dacqurir une connaissance intgrale du sujet tudi, la fois en thorie et en pratique.

Conventions typographiques
Afin de faciliter la comprhension des techniques dcrites, nous avons adopt les conventions typographiques suivantes :
j j j

gras : menu, commande, bote de dialogue, bouton, onglet. italique : zone de texte, liste droulante, case cocher, bouton radio.
Police bton : instruction, listing, texte saisir.

: indique un retour la ligne d aux contraintes de la mise en page. Au cours de votre lecture, vous rencontrerez les encadrs suivants :

Propose des trucs pratiques.

Met laccent sur un point important quil ne faut ngliger aucun prix.

Mentionne un fichier exemple ou un programme disponible sur le CD daccompagnement de louvrage.

Vous recommande une technique ou une marche suivre.

Vous indique le nom et lemplacement des fichiers tlcharger.

Renvoi un site o vous trouverez des infos complmentaires ou des outils tlcharger.

Il sagit dinformations supplmentaires relatives au sujet trait.

Fait rfrence un chapitre o vous trouverez des informations complmentaires.

Contenu en un clin dil


Chapitre 1 Chapitre 2 Chapitre 3 Chapitre 4 Chapitre 5 Chapitre 6 Chapitre 7 Chapitre 8 Chapitre 9 Chapitre 10 Chapitre 11 Chapitre 12 Chapitre 13 Chapitre 14 Chapitre 15 Chapitre 16 Chapitre 17 Chapitre 18 Chapitre 19 Chapitre 20 Chapitre 21 Chapitre 22 Chapitre 23 Introduction Prise en main Le langage PHP Les en-ttes HTTP Les techniques de programmation Les fonctions mathmatiques La manipulation des chanes de caractres La gestion des dates et des calendriers La gestion des chiers et des rpertoires Lutilisation des bases de donnes Les annuaires LDAP La messagerie : envoi et lecture de mails Les images et les animations Flash La cration de documents PDF Lutilisation de XML La gestion des protocoles HTTP, FTP, SOAP, etc. Les processus et les identiants Linteroprabilit avec COM Loptimisation des temps de rponse Lobfuscation : Distribuer ses scripts sans dvoiler son code Annexe A : des exemples dapplications Annexe B : les en-ttes HTTP et les variables externes Annexe C : les erreurs HTTP 25 49 111 251 295 325 353 433 485 633 901 959 1021 1137 1185 1263 1309 1325 1339 1379 1393 1419 1425

Sommaire
Chapitre 1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 quoi sert PHP ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Prsentation, rle et fonctionnement dun langage de script . . . . . . . . . . . 27

Les version 1 5 de PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29


Rasmus Lerdorf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Naissance et volution de PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 La cration de la communaut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

La communaut du libre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Historique . . . . . . . . . . . . La machine en marche . . . . . Cathdrale et bazar . . . . . . La scission : lOpen Source . . Le droit et les logiciels libres PHP et le libre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 36 37 37 38 39 40 41 41 42 44 44

PHP face ses concurrents (ASP, JSP, etc.) . . . . . . . . . . . . . . . . . . . . . . . . 40


PHP face aux autres langages de script web Comparatif PHP/Perl . . . . . . . . . . . . . . Comparatif PHP/ASP . . . . . . . . . . . . . . Comparatif PHP/JSP . . . . . . . . . . . . . . Perspectives . . . . . . . . . . . . . . . . . . . En bref . . . . . . . . . . . . . . . . . . . . . .

Pourquoi ont-ils choisi PHP ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45


Ils ont choisi PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 PHP lassaut du Net . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

Chapitre 2 Prise en main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51


Avec Apache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Avec IIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Avec iPlanet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

Le chier de conguration php.ini . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84


Options PHP de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Scurit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Gestion des erreurs et rcupration des messages derreur . . . . . . . . . . . . 87

Sommaire

Gestion des chiers . . . . . . Gestion des donnes . . . . . . Les magic quotes . . . . . . . . Sessions . . . . . . . . . . . . . Gnration du document . . . Gestion de laffichage . . . . . Extensions dynamiques . . . . Conguration des extensions Divers . . . . . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

90 91 91 92 94 95 96 96 97

Les diteurs et dbogueurs PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97


Lartillerie lourde . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Les spcialistes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Dreamweaver et GoLive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

Chapitre 3 Le langage PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 Intgrer le code PHP au HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113


Les balises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Mon premier script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

Les commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 Les constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 Les variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118


Dnition et syntaxe . . . Les variables dynamiques Les types . . . . . . . . . . Les variables externes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 119 120 130 140 141 142 142 143 144 145 145 147 147 148 152 153 156

Les oprateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140


Arithmtiques . . . . . . . . . . . . . Binaires . . . . . . . . . . . . . . . . . Chanes de caractres . . . . . . . . Affectation . . . . . . . . . . . . . . . Incrmentation et dcrmentation Comparaison . . . . . . . . . . . . . Logique . . . . . . . . . . . . . . . . . Contrles derreur . . . . . . . . . . Excution . . . . . . . . . . . . . . . . Priorits . . . . . . . . . . . . . . . . If, else, elseif . While, do while For, foreach . . Switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Les structures de contrle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

Sommaire

Break, continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

Les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158


La syntaxe . . . . . . . . . . . . . . . . . . La porte des variables . . . . . . . . . . Le passage des paramtres . . . . . . . . Les paramtres par dfaut . . . . . . . . Le passage de paramtres par rfrence Retourner une valeur . . . . . . . . . . . Manipuler des fonctions . . . . . . . . . La rcursivit des fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 160 163 163 166 167 168 173 175 175 176 177 178 209 210 210 211 211 213 214 219 220 221 223 227 233 234 235 238 241 246

Les tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174


Les valeurs dun tableau . . . . . . . . . . . . . Initialisation dun tableau . . . . . . . . . . . Les subtilits dinitialisation dun tableau . . Remplissage dun tableau . . . . . . . . . . . . Les fonctions de manipulation des tableaux

Les inclusions de chiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206


Inclusions multiples . . . . . . . . . . . . . . . . . . . . . . . . . . Les noms des chiers inclus . . . . . . . . . . . . . . . . . . . . . Les chiers insrs distants . . . . . . . . . . . . . . . . . . . . . Le passage de paramtres . . . . . . . . . . . . . . . . . . . . . . . Les chemins relatifs . . . . . . . . . . . . . . . . . . . . . . . . . . Cas derreur et code retour . . . . . . . . . . . . . . . . . . . . . . Un cas dutilisation pratique mais potentiellement dangereux Dnir une classe . . . . . . . . . . . . . . . Les constructeurs . . . . . . . . . . . . . . . Les attributs . . . . . . . . . . . . . . . . . . Les mthodes . . . . . . . . . . . . . . . . . Lhritage . . . . . . . . . . . . . . . . . . . . Les interfaces . . . . . . . . . . . . . . . . . Les classes abstraites . . . . . . . . . . . . Les exceptions . . . . . . . . . . . . . . . . . Les fonctions de manipulation des objets Programmation avance . . . . . . . . . . . Les tableaux en POO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Les classes, les objets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216

Chapitre 4 Les en-ttes HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 Principe gnral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Gestion personnalise de len-tte HTTP . . . . . . . . . . . . . . . . . . . . . . . . . 258
Redirection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260

Sommaire

Dclaration du type MIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 Gestion des caches (des navigateurs) . . . . . . . . . . . . . . . . . . . . . . . . . 261

Cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
Gnralits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 En PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264 Exemple utilisant des cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266

Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
Exemple utilisant des sessions . . . . . . . . . . . . Stockage personnalis des variables de sessions Clore une session . . . . . . . . . . . . . . . . . . . . Les autres fonctions . . . . . . . . . . . . . . . . . . Les fonctions historiques . . . . . . . . . . . . . . . Les fonctions de base . . . . . . . . . Compression des donnes . . . . . . Optimisation des temps de rponse . Gestion du cache interne . . . . . . . Les autres fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274 277 283 283 287 287 289 290 292 293

Mise en cache avant mission des donnes . . . . . . . . . . . . . . . . . . . . . . . 287

Chapitre 5 Les techniques de programmation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 Rgles de codage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297


Prsentation du code . . . . . . . . . . . . . . . . . . Programmation . . . . . . . . . . . . . . . . . . . . . . Noms de classes, fonctions, variables et constantes Commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 299 299 301

Sparation du code et de la mise en page . . . . . . . . . . . . . . . . . . . . . . . . . 307


Utilisation des objets et de linstruction include . . . . . . . . . . . . . . . . . . 307 Utilisation des modles (templates) . . . . . . . . . . . . . . . . . . . . . . . . . 309

Chapitre 6 Les fonctions mathmatiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 Les fonctions mathmatiques et les constantes . . . . . . . . . . . . . . . . . . . . . 327
Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 Fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328

Calculs de prcision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348


Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349

Chapitre 7 La manipulation des chanes de caractres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353

Sommaire

Gnralits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
Afficher du texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357 Manipuler les caractres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363

Fonctions de gestion des chanes de caractres . . . . . . . . . . . . . . . . . . . . . 363


Extraction et substitution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 Fonctions statistiques (longueur et nombre doccurrences) . . . . . . . . . . . 370 Fonctions de position . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375

Comparaison de chanes de caractres . . . . . . . . . . . . . . . . . . . . . . . . . . 376


Comparaison par ordre alphabtique . . . . . . . . . . . . . . . . . . . . . . . . 377 Comparaison orthographique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381 Comparaison phonique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383

Gestion des caractres spciaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385


Ajout du caractre dchappement . . . . Suppression du caractre dchappement Conversion des caractres en code HTML Conversion dun alphabet un autre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 386 388 394

Manipulation des balises HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395


Suppression des espaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 Modication de casse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399

Insertion de motifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 Fusion et dcoupe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402


Autres... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405 Somme de contrle et cryptage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407

Expressions rgulires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409


Perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409 Posix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421

Adapter le texte la langue du visiteur . . . . . . . . . . . . . . . . . . . . . . . . . . 431 Chapitre 8 La gestion des dates et des calendriers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433 Les fonctions de date et heure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435
Rcuprer une date au "format informatique" Effectuer des oprations sur les dates . . . . . Afficher des dates . . . . . . . . . . . . . . . . . . Les heures GMT . . . . . . . . . . . . . . . . . . . Les microsecondes . . . . . . . . . . . . . . . . . Autres fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435 436 437 442 442 443

Les dates et calendriers particuliers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444


Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444 Pques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444 Conversion dune date dun calendrier lautre . . . . . . . . . . . . . . . . . . 446

Sommaire

Les gestionnaires dvnements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449 Chapitre 9 La gestion des chiers et des rpertoires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485 Le systme de chiers POSIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487 Accder au systme de chiers du serveur . . . . . . . . . . . . . . . . . . . . . . . . 490
Lire et crire le contenu dun chier . . . . . . . . . . . . . . . . . . . Lister le contenu dun dossier . . . . . . . . . . . . . . . . . . . . . . . Manipulation de chiers et rpertoires . . . . . . . . . . . . . . . . . Upload de chiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Encore plus de fonctions daccs au systme de chiers du serveur Exemple dapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lecture sur un "pipe" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Installation . . . . . . . . . . . Les gestionnaires disponibles Les ltres . . . . . . . . . . . . . Contexte de ressource . . . . . Travailler avec les ux . . . . . Ajouter des gestionnaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490 518 526 532 538 564 574 575 593 593 597 601 607 609

Les streams ou les ux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593

Chapitre 10 Lutilisation des bases de donnes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633 Introduction aux bases de donnes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635 Introduction au langage SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636
Le typage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636 Les contraintes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636

Les relations entre tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636


Cls primaires et compteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639

Le langage SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639


Cration/suppression dune base de donnes Les types . . . . . . . . . . . . . . . . . . . . . . . Cration/suppression dune table . . . . . . . . Ajouter des donnes . . . . . . . . . . . . . . . . Mettre jour des donnes . . . . . . . . . . . . Supprimer des donnes . . . . . . . . . . . . . . Lire des donnes . . . . . . . . . . . . . . . . . . Rcuprer des informations sur une base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 640 640 643 645 646 647 648 651

Accder une base de donnes via PHP . . . . . . . . . . . . . . . . . . . . . . . . . 652

Sommaire

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 652 Couches dabstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 654 ODBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 654

Prsentation de lapplication dexemple . . . . . . . . . . . . . . . . . . . . . . . . . 654


Le modle de donnes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 657 Le contrleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661 Les vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677

Access (MS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 683


Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 683 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686

DB2 (IBM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687


Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 690

MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 690
Installation . . . . . . . . Utilisation . . . . . . . . . Exemples dapplications En savoir plus... . . . . . . Installation . . . . . . . . Utilisation . . . . . . . . . Exemples dapplications En savoir plus... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691 699 714 723 730 731 745 754 761 775 790 792 797 800 810 812 813 824 833 836 844 859 869

ODBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 730

Oracle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 761
Installation . . . . . . . . . . . . . . . . . . . . . . . . . Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . Mise prot des requtes prpares . . . . . . . . . . Utilisation des objets de grande taille (BLOB, CLOB) Gestion des erreurs . . . . . . . . . . . . . . . . . . . . Exemples dapplications . . . . . . . . . . . . . . . . . En savoir plus . . . . . . . . . . . . . . . . . . . . . . . . Installation . . . . . . . . Utilisation . . . . . . . . . Exemples dapplications En savoir plus... . . . . . . Installation . . . . . . . . Utilisation . . . . . . . . . Exemples dapplications En savoir plus... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

SQLite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 812

SQL Server (MS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 836

Les couches dabstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 871

Sommaire

Pear DB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 872

Chapitre 11 Les annuaires LDAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 901 Le schma LDAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905
Installation du serveur OpenLDAP . . . . . . . . . . . . . . . . . . . . . . . . . . 905 Installation du module LDAP pour PHP . . . . . . . . . . . . . . . . . . . . . . . 907

Linterrogation de LDAP avec PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 908


Connexion, authentication et dconnexion sur le serveur LDAP Oprations sur un annuaire LDAP . . . . . . . . . . . . . . . . . . . Recherche dans un annuaire LDAP . . . . . . . . . . . . . . . . . . . Gestion des erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . Opration sur le Distinguished Name (DN) . . . . . . . . . . . . . . Opration sur les options . . . . . . . . . . . . . . . . . . . . . . . . . Lauthentication sur lannuaire . . . . . . Lajout dune nouvelle entre . . . . . . . . Recherche dans lannuaire . . . . . . . . . . Modication dune entre . . . . . . . . . . . Ralisation dun arbre de navigation LDAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 908 910 918 933 934 936 939 944 947 949 952

Exemple dapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 938

Chapitre 12 La messagerie : envoi et lecture de mails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 959 E-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 961


Installation . . . . . . . . . . . . . . . . . . Envoyer un e-mail simple . . . . . . . . . . Type MIME . . . . . . . . . . . . . . . . . . . Envoyer un e-mail au format HTML . . . . Envoyer un e-mail avec chiers attachs . Envoyer un e-mail multi-part . . . . . . . Envoyer un e-mail HTML avec des images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 961 962 965 965 966 968 972

Accder son compte messagerie IMAP, POP3 ou NNTP . . . . . . . . . . . . . . . . 974


Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 975 Connexion et dconnexion un serveur . . . . . . . . . . . . . . . . . . . . . . . 976 Slection dune bote lettres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 979 Aperu du contenu de la bote lettres . . . . . . . . . . . . . . . . . . . . . . 983 Lecture des en-ttes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 986 Lecture des messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 995 Recherche et tri des messages . . . . . . . . . . . . . . . . . . . . . . . . . . 1000 Modication des drapeaux et suppression des messages . . . . . . . . . . . . 1002 Ajout et dplacement de messages . . . . . . . . . . . . . . . . . . . . . . . . 1004

Sommaire

Inscription/dsinscription un serveur de nouvelles Identiants ........................ Composition et dcomposition dadresses e-mail . . Gnration et envoi de mails . . . . . . . . . . . . . . . Coder / dcoder ..................... Grer les erreurs . . . . . . . . . . . . . . . . . . . . . . Administration des botes lettres

. . . . .

. . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

1005 1006 1006 1008 1009 1011

Application dexemple : le webmail . . . . . . . . . . . . . . . . . . . . . . . . . . . 1012


. . . . . . . . . . . . . . . . . . . . . . . 1017

Chapitre 13 Les images et les animations Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1021 Images (utilisation de la bibliothque GD) . . . . . . . . . . . . . . . . . . . . . . . 1023
Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . Dnition de limage de base . . . . . . . . . . . . . . . . Du texte dans les images . . . . . . . . . . . . . . . . . . . Dessiner des formes gomtriques . . . . . . . . . . . . Utiliser les couleurs . . . . . . . . . . . . . . . . . . . . . Copier des parties dimage . . . . . . . . . . . . . . . . . Taille dune image . . . . . . . . . . . . . . . . . . . . . . Un exemple : lhistogramme . . . . . . . . . . . . . . . . Rcuprer des informations sur un chier image . . . Rcuprer des informations EXIF sur un chier image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1023 1026 1041 1053 1065 1065 1072 1073 1078 1078

Les animations Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1082


Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1083 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1084

Chapitre 14 La cration de documents PDF . . . . . . . . . . . . . . . . . . . . . . Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . Crer la base dun document PDF . . . . . . . . . . . . . Prciser les attributs (mots-cls) du document . . . . . Prciser les paramtres de la page . . . . . . . . . . . . . Afficher du texte . . . . . . . . . . . . . . . . . . . . . . . . Dessiner des formes gomtriques . . . . . . . . . . . . Modier les paramtres du trac . . . . . . . . . . . . . . Inclure une image . . . . . . . . . . . . . . . . . . . . . . Ajouter des liens et des annotations . . . . . . . . . . . . Ajouter des chiers attachs et aperus (thumbnails) . Modier le systme de coordonnes . . . . . . . . . . . Lire, sauvegarder et restaurer les paramtres courants

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

1137 1139 1140 1144 1144 1146 1152 1157 1163 1166 1170 1171 1173

Sommaire

Crer un modle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1178 Chapitre 15 Lutilisation de XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1185 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1187


Prsentation du langage XML . . Le format XML . . . . . . . . . . . Exemple de document XML . . . Utilisation des documents XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1187 1187 1189 1191

Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1192 Les parseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1192


Le parseur SAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1192 Le parseur DOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1215 Le parseur SimpleXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1232

XSLT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1241
Prsentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1241 Les transformations de documents XML . . . . . . . . . . . . . . . . . . . . . . 1243

Gnration de messages XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1254


Les messages WDDX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1254

Chapitre 16 La gestion des protocoles HTTP, FTP, SOAP, etc. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1263 Fonctions rseau (de base) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1265 Rseau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1265
Adresses IP et DNS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1265 Protocoles et services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1269

Les sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1270 FTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1275


Installation . . . . . . . Les fonctions de base . Exemple dapplication Autres fonctions .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1275 1276 1281 1286

CURL (client URL Library) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1288


Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1289 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1290 Exemples dapplications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1295

SOAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1299
Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1303 Utiliser les classes PEAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1303 Interroger Google via PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1304

Sommaire

Chapitre 17 Les processus et les identiants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1309 Excution dun programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1311 POSIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1313 Chapitre 18 Linteroprabilit avec COM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1325 COM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1327
Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1327 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1327

Chapitre 19 Loptimisation des temps de rponse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1339 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1341 Environnement de test des solutions "bas niveau" (modules PHP) . . . . . . . . . 1342
Conguration matrielle Pages testes . . . . . . . . Instrument de mesure . . Prsentation des mesures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1342 1343 1345 1345

En labsence de solution doptimisation . . . . . . . . . . . . . . . . . . . . . . . . 1346


Mesures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1346

Avec Zend Optimizer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1349


Description . Installation . Mesures . . . Conclusion . Description . Installation . Mesures . . . Conclusion . Description . Installation . Mesures . . . Conclusion . Description . Installation . Mesures . . . Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1349 1350 1354 1357 1358 1358 1359 1362 1362 1363 1363 1366 1366 1367 1373 1376

Avec Alternative PHP Cache (APC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1358

Avec PHP Accelerator (PHPA) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1362

Avec Zend Accelerator (Zend Performance Suite) . . . . . . . . . . . . . . . . . . 1366

Sommaire

Conclusion sur les solutions "bas niveau" (modules PHP) . . . . . . . . . . . . . . 1376 Les solutions "haut niveau" (programmation PHP) . . . . . . . . . . . . . . . . . . 1377 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1378 Chapitre 20 Lobfuscation : Distribuer ses scripts sans dvoiler son code . . . . . . . . . . . . . . . . . . . . 1379 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1381 Avec Zend Encoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1381
Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1382 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1386 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1388

Avec ionCube PHP Encoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1388


Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1389 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1389

Avec PHP guardian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1389 Avec POBS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1390


Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1390 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1390 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1392

Autres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1392 Chapitre 21 Annexe A : des exemples dapplications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1393 Administration de bases de donnes . . . . . . . . . . . . . . . . . . . . . . . . . . . 1395
phpMyAdmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1395 Autres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1400

Cration de sites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1401


PHPNuke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1401 SPIP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1405 Autres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1407

Forums de discussion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1407


PHPbb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1407

Phorum : un moteur de forums . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1409


Autres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1411

Annuaires de liens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1412


Netref . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1412 Autres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1413

Solutions de travail collaboratif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1413


Moregroupware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1413 Autres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1416

Sommaire

Graphiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1416
JPGraph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1416

Chapitre 22 Annexe B : les en-ttes HTTP et les variables externes . . . . . . . . . . . . . . . . . . . . . . . . 1419 Chapitre 23 Annexe C : les erreurs HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1425 Chapitre 24 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1429

Laurent GUEDON Je ddie ce livre tous mes amis et plus particulirement...


j j j j

Philippe, Amiel (les comptences) et lquipe de Felix ainsi qu la socit Cyberbrain (mon couffin) ; Myriam, si adorable ; mes parents pour leur soutien ; la winwin team, Zou et Syl.

Damien HEUTE Parce quil y a des choses plus faciles crire qu dire, je ddie ce livre :
j j j j

mes parents que jaime et qui mont toujours apport un soutien indfectible ; mes frres et mon neveu qui peut-tre, un jour, sintressera la version 2015 de PHP ; mes collgues qui par leur bonne humeur leur et professionnalisme mont beaucoup appris durant ma premire exprience professionnelle ; mes amis que jai un peu dlaisss pour crire ce livre.

Thomas HEUTE Je ddie lnergie apporte dans ce livre :


j j j j

mes parents et frres que jai peu vus durant la dernire anne ; Mon filleul Adrien, star du chapitre sur GD, et qui a encore le temps avant dapprendre le PHP ; Mes amis de France et des tats-Unis, que jai quelque peu dlaisss (Id like to thank my US friends and to apologize about having been so busy. By the way, well keep in touch) ; Aux membres actifs de lESIAL Roller Dream Team 1999-2000.

Pierre-Emmanuel MULLER
Merci Amiel, Sylviane, Pierre, Rgis Priqueler (http://www.aizenko.com) et Steph Pineau (http://steph.pineau.free.fr/php/).

Prface
qui sadresse ce livre ?
Ce livre a t crit avec, en constante toile de fond, les attentes des lecteurs lgard de ce que doit tre la Bible dun langage de programmation ; savoir quelle doit pouvoir rpondre aux interrogations du novice comme celles de lutilisateur expriment. Une brve histoire du PHP, ainsi quune introduction la philosophie du logiciel libre, vous montreront quautant PHP aide au dveloppement de lInternet autant Internet contribue lvolution de PHP et offre quantit de ressources qui lui sont lies. Les dbutants ne seront pas laisss sur le bord du chemin ds les premires pages puisque les diffrentes possibilits dinstallation de PHP font lobjet dun chapitre complet et dtaill o les principaux diteurs du march sont galement passs en revue. De trs nombreux aspects de PHP sont couverts dans cet ouvrage et la majeure partie des fonctions prsentes sont illustres par des exemples mettant bien en avant leur utilisation et comportement. Voil pourquoi ce livre est plus quune simple documentation de base. Le PHP est replac dans une optique dapprentissage, ainsi que dans une ide dutilisation au quotidien. Le lecteur apprendra vite produire des formulaires, crer des images, manipuler des fichiers ainsi que des bases de donnes, ou encore envoyer des e-mails. Le novice sera pris par la main pour quaucune zone dombre ne puisse subsister. Mme si la prsentation de la programmation procdurale nest pas dlaisse, ce qui peut vous permettre de tirer partie de ce livre si vous restez attachs la version 4 de PHP, la programmation oriente objet est bien videmment prsente minutieusement afin de tirer pleinement partie de PHP5. Une fois acquis les premiers rudiments, lutilisateur devenu initi, trouvera dans ce livre de quoi aller plus avant dans sa matrise du PHP. Il pourra apprendre utiliser des bases de donnes professionnelles ainsi que les annuaires LDAP. Il pourra manipuler les documents XML, crer des animations flash ou des fichiers PDF, accder aux fonctionnalits rseau dont SOAP voire utiliser PHP en conjonction avec COM. Enfin, pour une utilisation vritablement professionnelle, il aura tout intrt consulter les comparatifs de solutions doptimisation et dobfuscation du code. Comme le dmontrent les tmoignages dutilisateurs qui ont fait le choix du langage PHP, bien quhistoriquement cr pour les besoins dune page "perso", PHP a dsormais sa place dans le monde de lentreprise.

Les auteurs
Les quatre auteurs de cette Bible disposent tous dune exprience diffrente de PHP. Venant dhorizons divers, ils ont tenu mettre en commun leurs approches pour balayer le maximum daspects relatifs au PHP.

21

Prface

Damien HEUTE
N en 1972, ingnieur E.N.S.P.S. (cole nationale suprieure de physique de Strasbourg), spcialit traitement dimages, Damien a travaill trois ans et demi en tant quingnieur tude et dveloppement pour un grand groupe europen daronautique et de dfense. Il y a mis en uvre les technos C, C++/CORBA, Java, et, dans une moindre mesure, des technologies relatives lInternet et aux bases de donnes professionnelles. Il a ensuite pass dix mois en tant quingnieur tude et dveloppement pour une start-up spcialise dans laide la navigation via Internet sur des supports "sans fil", o il a mis en uvre des technologies Java et JSP/Servlet. Maintenant dans un grand groupe franais acteur majeur de la tlphonie mobile, de la biomtrie et de la dfense, il conoit et dveloppe, dans le cadre de gros projets, des applications web bases sur le langage Java. Il pratique le PHP titre personnel, en particulier pour les sites http://www.ootoogo.com et
http://www.toutestfacile.com

Il aime le VTT et le cyclisme sur route, il fait un peu de photo et beaucoup dinformatique.

Thomas HEUTE
N en 1977, il a suivi ses tudes lESIAL (cole suprieure dinformatique et applications de Lorraine) et possde de nombreuses comptences dans le domaine informatique. Thomas connat bien les systmes Windows, Linux ou UNIX. Les langages dans lesquels il est le plus laise sont Java et PHP. Il matrise galement de nombreuses bases de donnes, ainsi que des outils de conception de logiciels (UML ou MERISE). Il a travaill trois ans au National Institute of Standards and Technology (USA), o il a effectu des recherches sur la scurit et les PDA aprs avoir travaill sur les systmes denregistrement dobjets par XML (ebXML). Il est galement lorigine du site http://www.toutestfacile.com, site vocation denseignement du PHP, du SQL et du XML. Il sinvestit dans le dveloppement Open Source avec "Nukes the JBoss Portal" en Java/J2ee. Il aime la batterie, la guitare et la photographie mais surtout linformatique.

Laurent GUEDON
N en mai 1975, ce qui, pour lui, est dj trs (trop) loin. Aprs une formation E.E.A (lectronique), Laurent, vouant une grande passion au dveloppement Internet, a rejoint en 1999 une SSII spcialise dans le dveloppement dapplications et de sites Internet. Laurent est dveloppeur PHP depuis PHP 2, ses premiers pas ayant t effectus sur lex-hbergeur AlternB. Dveloppeur indpendant depuis septembre 2002, il est charg denseignement la facult de Rennes. Il pratique (plutt mal) la guitare, fait du roller et se fait de petits trous dans la peau avec des piques en mtal (il appelle a le piercing). Mais, surtout, il ne se spare jamais de son Psion qui lui permet de dvelopper pendant ses dplacements.

22

Prface

Pierre-Emmanuel Muller
Journaliste spcialis dans linternet et les nouvelles technologies, il a un intrt marqu pour tout ce qui touche la protection de la vie prive ainsi quaux logiciels libres. Il a particip diverses traductions dapplications libres. Il est lauteur ou coauteur de plusieurs ouvrages de vulgarisation informatique (Scurisez votre PC, Montez votre serveur de A Z, Utiliser les logiciels libres, etc.).

23

Chapitre 1

Introduction
1.1 1.2 1.3 1.4 1.5 quoi sert PHP ? . . . . . . . . . . . . . . . . . Les version 1 5 de PHP . . . . . . . . . . . . La communaut du libre . . . . . . . . . . . . PHP face ses concurrents (ASP, JSP, etc.) Pourquoi ont-ils choisi PHP ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 29 35 40 45

quoi sert PHP ?

1.1.

quoi sert PHP ?


1. Introduction

Prsentation, rle et fonctionnement dun langage de script


Avant de prsenter le langage PHP, il est utile de situer brivement sa place sur linternet. Comment, en effet, bien comprendre lutilit dun langage de script si la notion de "serveur" est encore floue ? LInternet est un rseau de rseaux, constitu dordinateurs connects entre eux. Sa structure est maille, non pyramidale. Il y a bien des chelons, mais les chelons les plus levs sont, en fait, assez proches de la base, et sont, surtout, en trs grand nombre. Ces chelons sont interchangeables. Quand votre chelon suprieur est absent, en panne, ou disparu, vous pouvez utiliser un autre chelon de mme type. En bref, deux machines sont gnralement interchangeables. Il est ainsi trs difficile de "diriger" lInternet. Comme tout bon processus de communication, Internet dispose dun langage (en fait de plusieurs langages) qui dpend du service que vous dsirez utiliser (web, mail, ftp, etc.). Quel que soit le service en question, ce langage est commun toutes les machines informatiques, et est indiffrent aux plateformes. Les donnes provenant dInternet sont donc, moyennant parfois quelques retraitements, rutilisables par tout ordinateur. Ainsi, un site web est construit indpendamment de la plateforme sur laquelle il est conu. Ce sont les logiciels qui sadaptent aux machines. Il existe un navigateur web (Netscape) pour PC et une autre version pour Mac. Les donnes quils exploitent, en revanche, sont indpendantes des systmes dexploitation (Windows, MacOs, Linux, etc.). Les composantes les plus connues de lInternet sont le Web (World Wide Web) ou le courrier lectronique (e-mail). Concentrons-nous sur le Web, car cest de cela quil est question avec PHP. Admettons que vous dsirez consulter le site web du moteur de recherche Google. Vous donnez ladresse http://www.google.com votre navigateur, vous lancez la recherche, et, quelques secondes plus tard, la page daccueil du site saffiche sur votre cran. En fait, derrire cette action se cache toute une interaction client-serveur, primordiale intgrer pour bien saisir le fonctionnement de PHP. Votre navigateur, le client, interroge un serveur, en lui demandant la page daccueil dun site. Le serveur est une machine qui hberge le site web en question. Cette machine doit tre, en principe, connecte en permanence au rseau. Concrtement, ce sont les disques durs de cette machine qui stockent les pages HTML ou PHP qui seront demandes par les internautes. Pour que le serveur soit en mesure de vous rpondre, il faut que certains programmes et services soient prsents et fonctionnels en son sein. Dans le cas dun site web, il faut que le serveur dispose dun serveur web, cest--dire dun programme permettant linterprtation et la diffusion des pages demandes par les internautes. Votre navigateur demande la page, le serveur web reoit et comprend votre requte, il recherche la page en question et, si elle est disponible, vous la retourne. En fait, il ne vous retourne que le code source de la page, en gnral du HTML, mais ce peut tre une image ou une animation. La mise en forme, la construction et laffichage de la page incombent votre navigateur. PHP est un langage de script HTML, cest--dire quil fonctionne en relation avec le langage HTML (HyperText Markup Language). Il fonctionne du ct du serveur, et non pas du ct du client, et permet de gnrer des pages web " la vole". Concrtement, un script PHP est intgr au code source dune page HTML. Lorsque la page est appele, le script PHP est interprt, et le tout est livr au serveur web qui, au final, rpond au navigateur de linternaute. Le surfeur obtient une page HTML tout ce quil y a de plus classique, la diffrence que cette page

27

Chapitre 1

Introduction

nexistait pas en tant que telle sur le serveur web. On dit alors que la page a t cre " la vole", ou dynamiquement.

1. Introduction

Plus concrtement, prenons une page HTML toute simple dont voici le code source :
<html> <head> <title>Je teste le langage PHP</title> </head> <body> </body> </html>

Voici un script PHP sans prtention :


<?php echo ("PHP est un palindrome."); ?>

Pour intgrer ce script la page HTML, il suffit, ici, dinsrer le code entre les balises <body> et </body> de la page. Ce qui nous donne alors ceci :
<html> <head> <title>Je teste le langage PHP</title> </head> <body> <?php echo "PHP est un palindrome."; ?> </body> </html>

Cest aussi simple que a. Comme vous pouvez le constater, le script PHP est encadr par une balise de dbut et une de fin ( savoir <?php et ?>). Ce sont des informations qui, la lecture de la page, indiquent au serveur quil doit interprter ces informations comme de PHP, et non plus comme du HTML. Un script est dfini comme suit par le jargon Linux France : "Une suite dinstructions simples, peu structures, permettant dautomatiser certaines tches [...]". Dit ainsi, cest assez cinglant. En clair, un script PHP vous permet non seulement de gnrer du texte ou du code HTML, mais galement denvoyer un courriel, daccder une base de donnes, de lancer un programme sur le serveur, etc. Il est donc ainsi possible de compter le nombre de visiteurs sur votre page, de grer un livre dor ou bien mme de raliser des applications web part entire, comme des gestionnaires de contenus (PHPNuke, DaCode, SPIP, etc.) ou des outils de travail collaboratifs (PHPGroupware, par exemple). En fait, PHP possde les mmes fonctionnalits que les autres langages de script. Son gros atout rside dans son fonctionnement rsolument tourn vers le Web. En natif, ce sont plus de vingt bases de donnes qui sont supportes par PHP, sans que lutilisateur ait faire quoi que ce soit. Tous les grands protocoles de linternet fonctionnent, eux aussi, sans autre forme de procs avec PHP : SMTP, POP3, IMAP, FTP, SNMP, etc.

28

Les version 1 5 de PHP

1.2.

Les version 1 5 de PHP


1. Introduction

Rasmus Lerdorf
Chaque grand projet libre a un pre ou un leader charismatique. PHP ne droge pas la rgle. Qui plus est, lhistoire de PHP facilite les choses, ses premiers pas tant tout ce quil y a de plus simple narrer. Les premires esquisses de PHP sont le fait dun seul homme : Rasmus Lerdorf. Sur son site personnel, Rasmus Lerdorf reste assez discret. Les rares lments que lon peut glaner sur son parcours personnel se limitent des expriences professionnelles ou quelques hauts faits de programmation. On en apprend mme plus en suivant lhistoire de PHP, intimement lie celle de son crateur, tout au moins dans les premires annes. Rasmus Lerdorf est n en 1969 sur lle de Greenland. On comprend que le petit Rasmus ait prfr linformatique lagriculture, tant lle de Greenland est peu clmente : les terres arables, les forts et les pturages permanents reprsentent peine 1 % de la superficie totale de lle. Lle de Greenland est tout de mme dune superficie trois fois suprieure celle du Texas (2 170 000 km_) pour une population infrieure celle de lle de Guernesey qui ne fait que 78 km_ (56 300 personnes).
Figure 1.1 : Rasmus Lerdorf

Rasmus Lerdorf ne se dfinit pas comme un programmeur, mme si le fait quil soit capable de faire fonctionner PHP sur son magntoscope conduit le spectateur penser le contraire. Il na pas de diplme dinformaticien, mais une formation dingnieur. Il a travaill pour des socits comme Bell, IBM ou Linux Care. Selon une tude mene grands coups de scripts Perl par Per Abrahamsen, Rasmus Lerdorf est lun des Danois les plus clbres. Il arrive mme, dans le classement, avant le penseur Soren Kierkegaard. Signalons enfin que Rasmus Lerdorf, en bon dveloppeur du logiciel libre, nest pas dnu de sens de lhumour. Le petit dernier des Lerdorf a pour nom Carl Alexander Lerdorf. Sur le site de la famille Lerdorf, son nom se lit : Carl AlexandeR Lerdorf Rcursif, quand tu nous tiens !

Quelques sites (en anglais) Site officiel de la famille Lerdorf (avec les photos du petit Carl Alexander Lerdorf) :
http://www.lerdorf.com

Les Danois clbres :


http://www.dina.kvl.dk/~abraham/fame/fame.html

29

Chapitre 1

Introduction

Naissance et volution de PHP


1. Introduction

Naissance et premire version


La premire version de PHP nen tait pas une. Ce ne furent que quelques outils dvelopps par Rasmus Lerdorf pour les besoins de son site personnel. Dans le courant de lanne 1993, M. Lerdorf avait commenc dvelopper des scripts en langage C et en Perl. partir de l a pu tre constitue, en septembre 1993, une premire librairie. Lass de devoir rcrire encore et toujours les mmes portions de code, M. Lerdorf eut lide de sparer sa logique de programmation de celle du HTML, afin de pouvoir rutiliser plus facilement certaines portions de code. Pour quune premire version de PHP comme langage de script voie le jour, il ne manquait plus la librairie quun interprteur capable danalyser le code HTML, pour y reprer des balises particulires et appeler les fonctions qui y sont lies. Cela fut fait en novembre 1993, date laquelle M. Lerdorf situe la naissance de la toute premire version de PHP. La premire mouture du langage navait donc pas de trs grandes ambitions. PHP se limite alors un interprteur qui analyse une page HTML, en ressort des balises (inspires du SGML), et appelle les fonctions correspondantes ces balises. Tout cela dans quel but ? Afin de compter et denregistrer le nombre de visiteurs consultant un curriculum vitae sur son site personnel. Rasmus Lerdorf rsume ses motivations une lassitude face Perl, jug comme tant trop lent et dot dun analyseur trop restrictif. Cette premire version neut quun succs trs limit, et pour cause elle ne fut jamais publie. Il faut attendre fvrier 1994 pour quune premire version de PHP soit enfin diffuse.

Interviews de Rasmus Lerdorf Interview de Rasmus Lerdorf dans le Journal du Net :


http://developpeur.journaldunet.com/itws/it_phpnexen_rasdorf.shtml

Interview de Rasmus Lerdorf pour OReilly (en anglais) :


http://web.oreilly.com/news/lerdorf_0200.html

PHP 2 et louverture sur le monde


La premire utilisation plus large de PHP remonte au site http://www.io.org. Rasmus Lerdorf rutilisa son langage de script pour installer divers petits outils en ligne (un compteur de visiteurs, laffichage de la dernire personne connecte, etc.). Alors, le succs de PHP fut immdiat. Dautres utilisateurs du site voulurent utiliser PHP, et les scripts poussrent dans le HTML comme les champignons dans un sous-bois humide. tant donn que linterprteur voqu plus haut tait lui-mme un CGI, les administrateurs du site reprrent rapidement le changement. PHP se rvlait fort gourmand en ressources. Pour remdier cela et viter une mort certaine du langage, Rasmus Lerdorf se pencha alors sur le serveur web pour y inclure PHP comme module interne plutt que de le conserver en module externe (CGI), beaucoup plus lourd. Le serveur utilis tait HTTPD NCSA, de lUniversit de lIllinois. Une fois PHP ajout au serveur, M. Lerdorf convainquit tout de mme les administrateurs de passer sous Apache, serveur web beaucoup plus souple utiliser et programmer.

30

Les version 1 5 de PHP

Cest cette poque que M. Lerdorf obtint un emploi luniversit de Toronto. Sa mission tait de mettre en place un systme de connexion lInternet gr depuis une interface web. Le tout faisait intervenir une base de donnes des tudiants, des serveurs, des terminaux Cisco ainsi que quelques autres composants. En recherchant un outil utilisable dans la mise en place de cette architecture, Rasmus Lerdorf se rendit compte quil ny avait rien qui lui plaisait rellement. Il dcida donc de rcrire linterprteur de PHP et ses outils connexes, pour les rendre plus facilement multi-usages et gnralistes. PHP devait tre capable de dialoguer avec des bases de donnes ou dautres sources extrieures (comme, par exemple, des formulaires HTML). Ce sera nouveau, pour Rasmus Lerdorf, loccasion dutiliser PHP et de le faire progresser. Anciennement Personal Home Page, PHP sappelle alors PHP/FI (PHP/Form Interpreter, interprteur de formulaires), du fait des nouveaux outils ajouts par M. Lerdorf pour interfacer PHP avec des bases de donnes. La syntaxe de PHP/FI reste simple, encore un peu incohrente et assez proche du Perl. PHP/FI connat alors un trs large succs. De nombreux dveloppeurs utilisent PHP, et non pas seulement pour interroger des bases de donnes. PHP/FI sert dj crer des pages web au contenu dynamique, ce qui sera lune des applications les plus populaires du langage par la suite. Il prsente dj certaines des principales fonctionnalits de PHP. En 1997, ce sont dj plus de 50 000 sites qui utilisent PHP.

1. Introduction

PHP 3
Publie en juin 1998, aprs neuf mois de tests, la troisime version du dsormais officiellement nomm PHP (PHP : Hypertext Preprocessor, le premier P faisant rfrence PHP lui-mme. Rcursif quand tu nous tiens...) fait un grand bond en avant. La sortie de cette nouvelle version correspond galement une solide refonte du moteur de PHP. Deux dveloppeurs, Zeev Suraski et Andi Gutmans jugeaient que PHP/FI ntait pas assez performant pour leurs applications de commerce en ligne, et dcidrent donc de le rcrire. PHP 3 fut annonc comme le successeur officiel de PHP/FI. Lune des principales nouveauts de PHP 3 principale en tout cas au regard de son dveloppement fut une API (Application Programming Interface, interface de programmation dapplication) qui permit de nombreux dveloppeurs de participer au dveloppement du langage. De plus, PHP supportait dsormais la syntaxe objet, sa syntaxe propre devenant, elle, plus cohrente et solide. La version finale de PHP 3 fonctionnait sur de nombreuses plateformes, avec de nombreux serveurs web et bases de donnes. Les protocoles SNMP ou IMAP taient alors supports moyennant une compilation approprie. PHP pouvait tre utilis en mode CGI avec la plupart des serveurs HTTP, ou bien tre charg en module, comme par exemple avec Apache. De nombreuses fonctionnalits avaient t ajoutes PHP 3, mais, en plus, cette sortie concidait avec lattente de nombreux nouveaux webmestres qui avaient besoin dun outil simple pour ajouter une touche de dynamisme leurs sites web. La fin des annes 1990 fut, en effet, une priode faste pour le Web, port dans sa croissance par larrive de lInternet dans le grand public. PHP permettait alors de mettre en place trs facilement une solution de commerce en ligne, des albums photo, des systmes de gestion de contenus, etc. Sa facilit daccs et dusage, ainsi quune gamme doutils rsolument tourns vers le Web, faisaient de ce langage la solution idale pour de nombreux webmestres. la fin de lanne 1998, plus dun million de serveurs web devaient utiliser PHP 3. Le langage de script avait conquis plusieurs dizaines de milliers dutilisateurs.

31

Chapitre 1

Introduction

PHP 4
Fidle la toute jeune tradition, PHP 4 allait une nouvelle fois entraner une rcriture complte de son moteur. Ds lhiver 1998, Andi Gutmans et Zeev Suraski se penchrent sur le moteur interne du langage pour le reprendre de fond en comble. Leur objectif tait de rendre PHP encore plus performant (ce que lon comprend aisment), et de rendre le code encore plus modulaire. Il fallait galement permettre au PHP dtre plus laise avec des applications complexes. PHP 3 posait problme face ces applications complexes. Sa syntaxe permettait leur excution, mais le moteur du langage navait pas t conu pour les faire fonctionner efficacement. Lcriture dun nouveau moteur semblait alors ncessaire pour permettre au PHP de passer une nouvelle tape de sa croissance. Ce nouveau moteur devait porter le nom de ses deux crateurs : le Zend Engine, combinaison de ZEev et ANDi. Une premire version de PHP dot de ce nouveau moteur sortit dans le courant de lanne 1999. La publication officielle de la version finale fut annonce en mai 2000, six ans aprs le premier PHP. PHP 4 assurait une compatibilit ascendante par rapport PHP 3, et la migration de PHP 3 PHP 4 fut encore plus souple que celle de la version 2 la version 3. Outre un cur neuf, PHP disposait dune plthore de nouveaux membres. Dans sa quatrime version, PHP supporte quasiment tous les serveurs web du march, les bases de donnes les plus rpandues, plusieurs nouvelles structures de langage ou encore la bufferisation de sortie. On compte galement des amliorations en matire de scurit. Larchitecture de PHP 4 est encore plus ouverte et volutive que celle de PHP 3. On remarque notamment la cration dune interface ISAPI (Internet Server Application Programming Interface, outil de spcification des DLL pouvant tre utilis par les serveurs web de Microsoft). PHP 4 permet galement dinstancier et de manipuler des classes Java comme si elles taient de simples classes PHP. PHP peut aussi excuter des servlets. Autre amlioration majeure de PHP 4 : lintroduction des sessions en mode natif. Limpossibilit pour PHP 3 de grer les sessions constituait une grosse lacune pour un langage tout entier tourn vers le Web. Cette faiblesse ne jouait pas en faveur de PHP, tout particulirement face lASP qui, lui, savait dj grer les sessions. La lacune de PHP 3 pouvait certes tre comble via des solutions comme PHPLib, mais linclusion en mode natif dans PHP 4 rglait dfinitivement la question. PHP 4 marque galement lentre du langage dans le monde des socits commerciales. Les deux pres fondateurs de PHP 3, Zeev Suraski et Andi Gutmans, crrent la socit Zend pour distribuer et vendre des produits gravitant autour de PHP. Si le Zend Engine reste libre, bien que sous une licence assez critique jusque dans sa seconde version, certains produits commercialiss par Zend sont des logiciels propritaires. Signe vident dune maturit du langage, PHP devient alors le support dun commerce tourn vers les grands comptes de lInternet. Belle volution pour ce qui ntait, au dpart, quune petite collection de scripts Perl destins compter des visiteurs... La communaut PHP ne compte plus seulement des dveloppeurs ou des webmestres. Dsormais, de nombreux internautes participent la documentation de PHP, sa traduction ou son annotation. En France, par exemple, la socit Nexen hberge la documentation officielle de PHP en franais, dont elle a produit une version annote. Le projet Pear regroupe, lui aussi, de nombreux participants, qui ne sont pas directement impliqus dans le dveloppement de PHP. On compte aujourdhui plusieurs millions de sites web qui utilisent PHP. En se basant sur ce comptage des noms de domaines, on peut dire que cela reprsente 20 % de lInternet. Les dveloppeurs, eux, sont des centaines de milliers lutiliser. Le site Security Space tient jour une liste des modules Apache les plus utiliss. En juin 1998, PHP tait prsent sur 8 % des sites audits par Security Space. En mars 2002, presque 45 % des sites audits avaient install le

1. Introduction 32

Les version 1 5 de PHP

module PHP pour Apache. Perl, lui, tait, la mme date, prsent sur 20 % de ces sites (rappelons que Perl date de 1987 et PHP de 1994).

1. Introduction

Figure 1.2 : Le nombre de sites utilisant PHP crot de jour en jour

PHP 5
La tant attendue version 5 de PHP est sortie le 13 juillet 2004. Elle apporte de trs nombreuses nouveauts tout en conservant une large compatibilit avec PHP4. Si la grande nouveaut de la version 5 reste le nouveau modle orient objet, les dveloppeurs de PHP nont pas oubli lhritage des 4 prcdentes versions qui ont permis de trs nombreux dveloppeurs de faire leurs premiers pas dans le monde du script pour le web. La plupart des scripts crits pour PHP4 devraient fonctionner sans modifications avec PHP5. Il existe toutefois quelques diffrences dont la liste est disponible sur le site officiel du projet PHP.

Incompatibilits entre PHP4 et PHP5 Mme si vos scripts crits pour PHP4 ont de trs larges chances dtre compatibles avec PHP5, certaines incompatibilits ou modifications sont connues et listes. Le site officiel PHP en dnombre une dizaine. Vous les trouverez cette adresse :
http://www.php.net/manual/fr/migration5.incompatible.php

Lvolution de PHP
PHP, et avec lui toute la communaut de dveloppeurs, doit faire face des questions indites. Sa taille provoque des soucis dchelle, dj rencontrs par dautres projets (comme Linux, par exemple). Jusqu prsent, les rponses apportes par la communaut aux problmes apparus furent satisfaisantes, tout au moins assurrent-elles sa survie et sa croissance, sans nuire la qualit du langage. On peut citer, titre dexemple, la mise en place dune quipe dassurance qualit durant lt 2000 pour faire face aux nombreuses critiques suscites par la pitre qualit des premires versions de PHP 3. Le langage avait, en effet, t test sur trop peu de plates-formes diffrentes. Dsormais, une quipe complte de dveloppeurs a pour objectif principal de chasser le bug au sein du projet PHP.

33

Chapitre 1

Introduction

1. Introduction

Alors que PHP est un langage de script n du Web pour le Web, lon voit mme natre des projets impliquant PHP, qui nont plus rien voir avec les objectifs premiers du langage. PHPGtk est ainsi une solution permettant de dvelopper des applications en PHP partir dune interface graphique ct client. De mme, lentre en jeu de socits commerciales a amen des questionnements soulevs par des acteurs du monde du libre, comme la FSF (cf. problme de la licence du moteur Zend). Encore une fois, la communaut PHP a su faire preuve de beaucoup de pragmatisme dans ses rponses. Rsultat des pressions de la FSF, Zend a chang la licence de son moteur. PHP 4 reste, pour sa part, sous une licence Apache, juge plus souple pour les dveloppeurs. Et, quand on demande aux dveloppeurs de PHP comment ils prennent les critiques que lon peut leur adresser parce que PHP 4 nest pas GPL, ils vous rpondent avec des frites. Si Rasmus Lerdorf a pu tre, un moment, une figure de proue de PHP, et quil reste aujourdhui encore son reprsentant le plus mdiatique, on peut tout de mme remarquer que la communaut PHP ne bnficie pas dune structure centralisatrice qui ferait linterface entre le langage et les entreprises ou les institutions. Le logiciel libre a lOpen Source Initiative ou la FSF, un projet comme Kde dispose de toute une infrastructure qui assure sa promotion ou sa reprsentation, Linux a Linus Torvalds. Vu de lextrieur, le monde de PHP parat encore flou.

PHP La socit Zend, ditrice du Zend Engine (en anglais) :


http://www.zend.com

La socit Nexen :
http://www.nexen.net

Nombre de sites utilisant PHP (en anglais) :


http://www.php.net/usage.php

Modules Apache les plus utiliss (en anglais) :


http://www.securityspace.com/s_survey/data/man.200203/apachemods.html

Des projets attachs au PHP :


http://php3.de/manual/fr/html/history.php.related.html

Interview du crateur de PHPGtk (en anglais) :


http://beta.usephp.net/article.php3?id_article=3p

La cration de la communaut
Si PHP a pu crotre et prosprer jusqu devenir lun des langages de script les plus utiliss, cest en grande partie grce une communaut de dveloppeurs qui, ds la version 3, fut la cheville ouvrire de ses amliorations. PHP/FI, seconde version du langage, reste luvre dun seul homme, Rasmus Lerdorf, pre de PHP. partir de la version 3, Rasmus Lerdorf nest plus seul la tte de PHP. Zeev Suraski et Andi Gutmans prirent en main, par deux fois, la refonte complte du moteur de PHP. Cette ouverture de PHP est due une interface API mise en place trs tt, mais, surtout, la volont de son crateur de partager son travail avec dautres dveloppeurs. Rasmus Lerdorf le dit lui-mme : il a toujours appris en regardant le code dautres programmeurs. Ne pas faire profiter, en retour, la communaut de son travail ne lui a mme pas travers lesprit.

34

La communaut du libre

Comment cette communaut est-elle ne ? Dans une interview, Rasmus Lerdorf situe sa date de naissance au jour o, alors employ par luniversit de Toronto, il avait mis en ligne son code source disposition sur une page web. Cela dans loptique vidente que dautres puissent en profiter. Il navait alors aucune ide de qui utilisait PHP de par le monde, ni pour quelles applications. Un beau jour, il reut un courriel dun utilisateur japonais, qui lui faisait parvenir un patch. Le patch tait tout fait fonctionnel et pertinent. Il rsolvait un problme auquel Rasmus Lerdorf navait pas encore eu affaire, mais qui allait se poser inluctablement. PHP bnficiait dune aide extrieure, la communaut tait ne ; elle compte aujourdhui plus de 300 dveloppeurs.

1. Introduction

La communaut PHP Rasmus Lerdorf raconte la naissance de la communaut :


http://developpeur.journaldunet.com/itws/it_phpnexen_rasdorf.shtml

1.3.

La communaut du libre

Pourquoi prsenter le monde du logiciel libre dans un livre traitant de PHP ? Simplement parce que, sans cette communaut, PHP ne serait pas ce quil est aujourdhui. Si la marque du monde du libre nest pas particulirement visible sur le langage lui-mme, sa philosophie et son mode de dveloppement ont eu, et ont toujours, une influence notable sur le langage PHP et sa croissance. Il suffit de voir le rle prpondrant que joue le triptyque Apache-MySQL-PHP dans le monde du Web face des solutions comme IIS-ASP-Access. PHP est indissociable du monde du libre. Cette partie na pas pour objectif de faire lapologie du logiciel libre, ni mme de faire un comparatif entre code source ouvert ou code source ferm ; tout comme le souligne Linus Torvalds lui-mme, les deux existent et cest tant mieux. Il nous a pourtant sembl utile de prsenter le monde du libre, pour permettre celui qui dcouvre PHP, dune part de comprendre le contexte de sa croissance et de son volution, et dautre part de savoir vivre dans le monde de PHP. Celui qui ne sait pas que les dveloppeurs qui travaillent avec PHP distribuent largement leurs sources et discutent massivement en ligne de lvolution du langage et des questions techniques qui sy rattachent sera vite perdu et passera ct de lun des principaux atouts de PHP : sa communaut.

Historique
Le monde du logiciel libre plonge ses racines dans lhistoire des hackers (au sens premier du terme). Toute la culture du logiciel libre et son folklore doivent beaucoup aux pionniers de linformatique, ces "vrais programmeurs" : les hackers (selon la dfinition dEric S. Raymond). Pour une histoire complte et documente de cette culture, on se reportera Une brve histoire des hackers, par M. Eric S. Raymond. Disons simplement que les logiciels libres ne sont pas ns avec Linux. Leur histoire est bien plus riche et complexe. Cest dans lun des plus prestigieux laboratoires dinformatique du monde, celui dintelligence artificielle du MIT (Institut de technologie du Massachusetts) que sest cristallise lopposition entre logiciels libres et logiciels propritaires. Chef de file du laboratoire, et froce opposant la commercialisation des techniques mises au point dans ce laboratoire, Richard M. Stallman cra, en 1984, la Fondation du logiciel libre (Free Software Foundation, FSF). Hacker au sens

35

Chapitre 1

Introduction

propre du terme, il dveloppa alors des logiciels libres, dont le clbre diteur Emacs. M. Stallman entrepris alors de recrer un clone complet libre du systme dexploitation propritaire UNIX. Cest ainsi que naquit le projet GNU (GNU is not UNIX. Dcidment, acronyme rcursif quand tu nous tiens). La FSF avait pour objectif de soutenir et daccompagner des projets libres. Sa cration formalisait les thses et ides des dfenseurs du logiciel libre. Fortement imprgne de la culture de lchange et de la transmission libre des savoirs des milieux universitaire et scientifique, la FSF estime que "tout comme les ides, les logiciels ne sont pas tangibles et peuvent tre copis sans perte. Les transmettre est la base dun processus dvolution qui alimente le dveloppement des rflexions." (site de la FSF Europe, Quest-ce quun logiciel libre ?). Pour tre qualifi de libre, un logiciel doit, selon la FSF, rpondre quatre critres de libert. Tout dabord, un programme doit pouvoir tre excut pour nimporte quel usage. Ensuite, un utilisateur doit pouvoir tudier le fonctionnement du programme et ladapter ses besoins. Il doit galement tre possible de redistribuer des copies et, enfin, damliorer le programme en rendant publiques les modifications pour que lensemble de la communaut en bnficie. Pour assurer ces liberts aux logiciels libres, M. Stallman tablit la GPL : GNU General Public License.

1. Introduction

La machine en marche
Les logiciels de la FSF ne sont pas les seuls produits libres. De trs nombreux logiciels libres sont en rapport avec linternet. Sils ny sont pas directement lis, cest leur dveloppement qui en a profit. On peut citer Sendmail, dvelopp en 1981 par Eric Allman. Aujourdhui encore distribu gratuitement par la socit Sendmail Inc., Sendmail est lagent de transport de mails le plus utilis sur Internet. Il dtient plus de 75 % des parts de march. Autre figure historique et emblmatique du monde du libre : Perl. Perl signifie Pratical Extraction and Report Language (langage pratique dextraction et de rapport). Cest un langage de programmation trs largement utilis sur lInternet. Il sert principalement aux administrateurs de systmes et de rseaux. Il sert galement dans le dveloppement de CGI. On estime quune centaine de programmeurs participe au dveloppement de Perl. Les programmeurs utilisant Perl seraient 500 000 et les utilisateurs, eux, plusieurs millions. En se basant sur les ventes douvrages ddis chaque langage, les ditions OReilly estiment que Perl est aussi souvent utilis que Java. Apache est un projet libre denvergure ; peut-tre celui qui a dmontr le premier quun logiciel libre pouvait faire jeu gal avec les grandes entreprises de dveloppement de logiciels. Il dtient aujourdhui la plus importante part de march pour les serveurs web (source Netcraft), et cela face des acteurs aussi puissants que Microsoft ou Netscape. En juin 1998, le gant de linformatique IBM annonait soutenir officiellement le groupe Apache. Ce choix dApache par IBM fut une tape importante dans lhistoire des logiciels libres. Les impratifs commerciaux et conomiques qui prsident aux dcisions dIBM donnaient ce soutien Apache une valeur toute particulire. Un logiciel libre pouvait servir les intrts du monde commercial sans se galvauder ni perdre ses ambitions. Lhistoire de la FSF nest pas jonche seulement de russites. Lun des principaux checs de la FSF fut de mettre beaucoup trop de temps pour fournir un noyau son systme dexploitation (GNU). Cependant, lune de ses principales russites fut de fournir une trousse outils celui qui allait dvelopper le noyau libre le plus connu : Linus Torvalds. Cest en effet grce aux

36

La communaut du libre

logiciels de la FSF que le jeune tudiant de luniversit dHelsinki a pu dvelopper son propre UNIX libre, Linux. Linus Torvalds voulait dvelopper un UNIX pour son ordinateur personnel. Aprs avoir tabli les premiers lments de son systme dexploitation, il mit rapidement le code source la disposition des internautes du monde entier. Cest l que rside lune des particularits les plus importantes de Linux. Il est dvelopp et maintenu par des programmeurs du monde entier, grce lInternet. De grands acteurs de lindustrie informatique font dsormais confiance Linux (IBM, Sun, Dell, HP, etc.).

1. Introduction

Cathdrale et bazar
Ayant observ le dveloppement de Linux, Eric S. Raymond a voulu thoriser ce nouveau modle de dveloppement. Schmatiquement, il oppose deux modles : la cathdrale et le bazar. Le modle en cathdrale est un modle classique. Cest celui des entreprises et administrations classiques : centralis, trs hirarchis, il met beaucoup de temps ragir, et les dcisions sont soumises de multiples validations. Dans le modle bazar, tout est beaucoup plus horizontal, mouvant et flexible. Un modle ouvert et collaboratif comme le bazar permet une volution rapide et pertinente. Chacun est libre de soumettre un correctif ou une amlioration, ce qui vite de brider les initiatives.

La scission : lOpen Source


Richard Stallman na jamais fait lunanimit dans le monde du logiciel libre. Son dogmatisme et ses prises de position fermes taient vues par beaucoup comme des freins au dveloppement plus rapide du monde du libre, tout particulirement en direction des entreprises. Mme si la licence GPL ninterdit pas du tout la commercialisation dun logiciel libre, la FSF vhiculait une image hostile au monde du commerce. Daucuns pensaient que les ides dveloppes par la FSF nuiraient plus la croissance de la communaut du libre quelles ne la serviraient. De ce fait, des programmeurs et dautres acteurs du logiciel libre dcidrent de substituer le terme Open Source celui de Free Software, le terme "free" tant jug trop ambigu (en anglais, il dsigne aussi bien ce qui est gratuit que ce qui est libre). Afin de ne plus effrayer le monde de lentreprise, le mouvement Open Source vit donc le jour. On retrouvait sa tte certains des plus prestigieux acteurs du monde du libre comme, par exemple, Bruce Perens (ancien mainteneur du systme dexploitation Debian http://www.debian.org et fondateur du projet de standardisation Linux Standard Base) ou Eric S. Raymond. Lobjectif de ce nouveau mouvement tait clairement exprim : il sagissait de mieux vendre et promouvoir le logiciel libre. Il est important de bien comprendre que le courant de lOpen Source et celui des logiciels libres ne sont pas antinomiques, mais, quau contraire, ils sont complmentaires. Ils font la promotion du logiciel libre dans diffrentes directions. Toutefois, la FSF voit en lOpen Source un danger potentiel pour les logiciels libres. En effet, les points de divergence ne se situent pas seulement dans les termes, mais galement dans les licences, la dfinition du logiciel libre et lutilisation qui peut en tre faite. Pour quun programme soit dit open source, il faut quil respecte un certain nombre de critres dfinis comme suit par le mouvement Open Source. Tout dabord, le logiciel open source doit pouvoir tre librement donn ou vendu, sans que cela entrane lacquittement dune redevance ou de droits dauteur, et ce pour tous les utilisateurs de ce logiciel, sans distinctions. Le logiciel doit tre distribu avec son code source, qui peut tre modifi ou rutilis par lutilisateur condition que ce dernier respecte la licence du programme originel. Un logiciel peut tre open source mme si sa licence nautorise pas explicitement la rutilisation de son code source. ce

37

Chapitre 1

Introduction

moment l, la diffusion de patches (fichiers de modification) doit tre autorise. Une licence open source peut galement demander ce quune version modifie dun logiciel nait pas le mme nom que le logiciel "modle". Elle ne doit pas non plus tablir de discrimination lencontre de personnes ou de groupes de personnes, ni mme de distinctions relatives aux domaines dutilisation du logiciel (il peut tre commercial ou exploit dans des domaines qui sont sujets dbat, comme la recherche gntique par exemple). La licence ne doit pas tre limite un ensemble de logiciels. Chaque logiciel formant une "suite" doit bnficier de la licence open source. Cest la neuvime clause de la dfinition officielle de lOpen Source qui diffrencie principalement le mouvement Open Source de celui du logiciel libre. Elle dit : "La licence ne doit pas imposer de restrictions dautres logiciels distribus avec le programme. Par exemple, la licence ne doit pas exiger que tous les programmes distribus sur le mme support soient des logiciels open source." Malgr cela, lOpen Source reconnat la GPL comme tant compatible avec ses dfinitions : "La licence GPL est bien conforme cette clause. Les bibliothques sous licence GPL "contaminent" seulement les logiciels avec lesquels elles sont lies statiquement lors de la compilation, pas les logiciels avec lesquels elles sont distribues" (justification de la clause 9 dans la dfinition de lOpen Source). Mme si la porte reste ouverte, la FSF, elle, ne se reconnat pas dans lOpen Source. Elle continue daffirmer son attachement la porte philosophique du logiciel libre et considre lOpen Source comme "quelque chose de proche (mais pas didentique) au "logiciel libre"(cf. site de la FSF).

1. Introduction

Quelques liens La dfinition de lOpen Source :


http://www.idealx.org/fr/doc/fr-osd/fr-osd.html#toc1

La dfinition du logiciel libre :


http://www.fsfeurope.org/documents/freesoftware.fr.html

Licences compatibles avec la dfinition de lOpen Source :


http://www.idealx.org/fr/doc/fr-licences/fr-licences.html

Licences compatibles avec la dfinition de la FSF :


http://www.gnu.org/licenses/license-list.fr.html

Le droit et les logiciels libres


Signe de sa richesse et de sa complexit, le monde du logiciel libre regorge de licences sous lesquelles un dveloppeur peut placer son travail. On compte plus dune dizaine de licences dites "libres" ou apparentes. Pourquoi un tel foisonnement ? Parce que le logiciel libre ne date pas dhier et que les acteurs sont nombreux. Rien nempche une entreprise ou un particulier de crer sa propre licence se voulant libre. On peut citer les cas de Sun, Netscape, ou Apple, qui crrent leurs propres licences. Parmi toutes ces licences, on peut tout de mme noter que les plus rpandues sont : la GPL et la LGPL, la licence FreeBSD ou la MPL. PHP est un langage de programmation libre et ouvert. Il propose, par exemple, une API (Application Programming Interface, une interface de programmation dapplications) qui permet des dveloppeurs dajouter des fonctions au langage. Mais, encore une fois, rien nest simple. Les diffrentes versions de PHP nont pas t diffuses sous la mme licence. PHP 3 a t diffus sous licence GPL, tandis que PHP 4 nest pas

38

La communaut du libre

compatible avec la GPL. La licence actuelle (2.02) fait de PHP 4 un logiciel libre, mais il nest pas reconnu comme compatible avec la GPL. La FSF encourage lutilisation de PHP 3, diffus sous GPL. Les responsables de PHP expliquent leur choix en raison des aspects trop contraignants de la GPL. Les dveloppeurs ont dcid de publier PHP 4 sous une licence plus souple, pour permettre au PHP dtre le plus populaire possible. La licence de PHP 4 se rapproche de la licence dApache (PHP fait partie de la fondation Apache). Autre pomme de discorde : le Zend Engine, distribu avec PHP 4. Jusquen novembre 2001, le Zend Engine tait publi sous une licence QPL, non compatible avec la GPL. Depuis, Zend a chang la licence de son moteur pour une licence de type BSD, compatible, elle, avec la GPL. En tout tat de cause, avant de faire quoi que ce soit avec PHP, lisez attentivement sa licence et celle de tout produit connexe que vous utiliseriez, pour savoir sils sont compatibles avec ce que vous voulez en faire.

1. Introduction

Le texte (en anglais) des licences Licence PHP 4 :


http://www.php.net/license/2_02.txt

Licence Zend Engine :


http://www.zend.com/license/2_00.txt

PHP et le libre
Et la communaut PHP dans tout a ? Comme tout projet libre, PHP bnficie de nombreuses contributions apportes par des dveloppeurs bnvoles impliqus partout dans le monde. On estime plus de 300 membres la communaut des dveloppeurs PHP. Projet collaboratif, il tire avantage de tous les aspects positifs dun dveloppement libre. Les bugs dcouverts peuvent notamment tre corrigs rapidement. Cest grce son ouverture que PHP a pu crotre aussi vite. De par son API, il sest enrichi de nombreuses fonctionnalits comme, par exemple, le support des protocoles les plus utiliss sur linternet (comme POP3, IMAP, ou NNTP), un accs aux annuaires LDAP, ou bien encore un parseur XML. Langage n pour le Web, PHP dispose dune communaut en ligne trs active. Le pre de PHP, Rasmus Lerdorf, le dit lui-mme : PHP a t dvelopp par la communaut, et non pas par moi (interview Nexen pour le Journal du Net). Dune certaine manire, on peut comparer le dveloppement de PHP celui de Linux. Rasmus Lerdorf a eu le mme rle que Linus Torvalds. Il a initi le mouvement, a pos les premires bases, puis a permis des internautes dutiliser sa cration et den connatre le code source. Ces tapes pralables runies, la cration spontane dune communaut de dveloppeurs ntait plus trs loin. De nombreux sites proposent des centaines de scripts au tlchargement. Les dveloppeurs qui utilisent PHP nhsitent pas faire profiter le reste de la communaut de leurs crations. Que ce soit sur des sites "perso" ou des sites connus, un programmeur qui veut mettre en place un forum, un site de gestion de contenus, ou mme un freemail (de type Hotmail ou Caramail) ou un systme de knowledge managment trouvera, coup sr, des programmes en PHP qui rpondent dj ses attentes. Lun des premiers rflexes dun programmeur en PHP qui travaille sur un nouveau projet sera daller chercher en ligne ce qui a dj t fait dans son domaine, pour sen inspirer ou pour adapter une solution. Le projet PEAR (PHP Extension

39

Chapitre 1

Introduction

1. Introduction

and Add-on Repository, ou dpt dextension et dadd-on PHP pear signifie poire en anglais) reprsente bien lesprit open source et "opportuniste" de PHP. Largement inspir du systme CPAN (Comprehensive Perl Archive Network) pour le langage Perl, Pear est une base de donnes en ligne de programmes ou dextensions en PHP. Les dveloppeurs partagent ainsi leurs crations. PHP a su rcuprer lun des aspects les plus intressants du monde Perl. La communaut dispose, en plus, du soutien dentreprises qui participent au dveloppement de PHP, ou qui en sont de fervents supporters. La socit Zend propose de nombreuses solutions logicielles autour de PHP, en plus du Zend Engine, interprteur gnrique intgr PHP 4. On peut galement citer la socit franaise Nexen, spcialise dans les services Internet, qui, en plus de ses activits, soutient activement PHP (hbergement de miroirs, diffusion de documentation, etc.).

Quelques liens Pear (en anglais) :


http://pear.php.net/

CPAN (en anglais) :


http://www.cpan.org

Interview de Rasmus Lerdorf :


http://developpeur.journaldunet.com/itws/it_phpnexen_rasdorf.shtm

1.4.

PHP face ses concurrents (ASP, JSP, etc.)

PHP face aux autres langages de script web


"PHP nest pas un langage neuf ou rvolutionnaire. Il emprunte une grande partie de sa syntaxe des langages comme le C, Perl ou Java". Qui est lauteur de ce jugement dfinitif sur la prtendue rvolution ou sur le caractre novateur de PHP ? Bill Gates, Scott McNeally ou Larry Wall ? Aucun dentre eux ! Cest bien le pre de PHP lui-mme, Rasmus Lerdorf, dans une interview au journal en ligne Computerworld. Et ce nest pas tout. Quelle est la diffrence entre PHP et son grand rival propritaire, ASP, de Microsoft ? Il ny en a pas vraiment. "Au fond, ils font les mmes choses", nhsite pas ajouter Rasmus Lerdorf. Encore un peu, et lon va apprendre que M. Lerdorf code en VisualBasic et quil en est trs content... Non, la cure sarrte l. Mais Rasmus Lerdorf a raison. PHP nest pas une rvolution proprement parler et, sur le fond, PHP napporte rien de bien particulier par rapport ASP, Java ou Perl. Envoyer des mails, gnrer des pages la vole, tout cela, PHP le permet tout comme ASP, par exemple. Comparer PHP ses grands rivaux nest pas toujours chose aise, voire admissible. Ainsi, la comparaison avec Perl nest pas forcment fonde. Perl est un langage de script, alors que PHP est un langage de script fait pour lInternet. On ne compare alors quune portion de Perl la totalit de PHP. De mme, ASP sintgre de plus en plus dans la plateforme .Net de Microsoft, ce qui lui ouvre dautres horizons. PHP, lui, nest pas infod une plateforme. Idem pour Java. Java a t conu pour voluer dans une architecture dite "n-tiers", alors que PHP, lui, reste dans un environnement "2 tiers" (voir schma).

40

PHP face ses concurrents (ASP, JSP, etc.)

Se servir de Java pour dynamiser un site personnel, cela revient quelque chose prs se servir dun lance-flammes pour dsherber un parterre de rosiers ! Ceci tant dit, il est tout de mme possible de se pencher sur ces langages de script pour voir quels sont leurs avantages et leurs inconvnients sur les points quils ont en commun.

1. Introduction

Comparatif PHP/Perl
Perl est avant tout un langage de script systme, n pour remplacer sed et awk. Face lui : PHP, un langage de script n du Web pour le Web. Les points de comparaison, sils existent, ne doivent pas faire oublier que Perl na pas pour objectif premier la cration de sites web. De base, PHP inclut beaucoup plus de bibliothques que Perl. Pour Perl, il faut souvent aller chercher une librairie souhaite sur CPAN. En revanche, Perl, dispose, au final, de beaucoup plus de bibliothques que PHP. L, PHP fait les frais de son jeune ge face un langage dge dj vnrable. Sans parler des librairies, les solutions en Perl sont dj trs nombreuses. Toutefois, le dynamisme tout particulier de la communaut PHP est en passe de combler cette lacune. Langage orient web, PHP est plus facile maintenir et faire voluer que Perl. Retoucher ou adapter rapidement un site tout entier tourn vers Perl reste plus ardu que si le site dispose dune architecture en PHP. Perl a aussi su sadapter au Web. Alors quil crait un nouveau processus sur le serveur chaque nouvelle requte, Perl a, depuis, su normaliser ses rapports avec le serveur web. Le problme a en effet t rgl par lapparition de mod_perl ou FastCGI.

Comparatif PHP/ASP
ASP (Active Server Pages) est un langage de script dvelopp par Microsoft. PHP et ASP sont assez proches dans leur philosophie et dans leur mise en uvre. Dans les deux cas, le code du script est insr directement dans la page web. Jusqu PHP 3, ASP disposait dun trs net avantage sur PHP : PHP ne grait pas les sessions. Avec lintroduction de cette gestion en mode natif dans PHP 4, lavantage est perdu. Si PHP 3 doit imprativement tre utilis, pour des raisons de licence par exemple, il existe de toute faon des alternatives, comme PHPLib, qui permettent de grer les sessions malgr tout. Le gros inconvnient dASP par rapport PHP rside dans sa trs forte dpendance la plateforme Windows. ASP ne se dploie en effet que dans un environnement Microsoft. Il existe certes un portage sous UNIX, grce la solution mise en place par Sun avec Chilisoft ASP, mais cela reste en de de ce que peut offrir PHP. PHP na pas t dvelopp pour une plateforme en particulier, ce qui ouvre de bien plus vastes horizons en matire de portabilit des applications ainsi quen volutivit. PHP fonctionne sous Linux comme sous Windows NT, sans avoir recourir des programmes tiers. Un script en PHP pourra tre rutilis bien plus facilement quun script en ASP. Il a souvent t reproch PHP daccuser des temps de rponse assez longs. Ce point peut tre amlior grce des solutions logicielles de cache. Zend Accelerator ou PHP Accelerator rduisent ainsi nettement les temps de rponse de PHP. Autre grosse diffrence entre PHP et ASP : PHP sinterface en natif avec lensemble des systmes de gestion de bases de donnes standard du march, alors quASP doit passer par

41

Chapitre 1

Introduction

ODBC. Cette diffrence peut tre envisage de deux faons. Dun ct, une meilleure matrise de la base de donnes et peut-tre mme de meilleures performances jouent en faveur de PHP. Dun autre ct, les fonctions varient dune base de donnes lautre, ce qui ncessite dadapter le code pour chaque base de donnes, alors quen thorie, ASP ne demandera que quelques modifications. En fait, mme si rien nest propos en standard, il existe des solutions (prsentes dans ce livre) de couches dabstraction pour PHP, mais, surtout, limplmentation du langage SQL variant grandement dun serveur de bases de donnes lautre, ladaptation du code en fonction du serveur de bases de donnes est invitable (cest dailleurs pour cette raison que Rasmus Lerdorf nest pas favorable lintgration dune couche dabstraction dans PHP). Aujourdhui, ASP va trs largement vers .Net, la plateforme "n-tiers" de services web de Microsoft. Il se rapproche en cela de Java avec J2EE de Sun. De son ct, PHP deviendra de plus en plus un langage "srieux", incluant dclaration de variable, typage, etc. Face lASP, PHP peut galement jouer la carte du prix. Prenons le cas dune entreprise qui veut dvelopper une solution Microsoft. Windows 2000 Server lui cotera 934 euros, Internet Security and Acceleration Server, 8 000 euros, SQL Server 2000 Entreprise Edition, 2 300 euros, Microsoft Proxy Server, 900 euros et, enfin, la souscription au MSDN, 2 100 euros par dveloppeur. Ce qui fait un total de 14 234 euros. Face cela, une architecture similaire autour de PHP peut tre construite avec Linux, Apache et SSL, PostgreSQL et Squid, le tout pour zro euros (hormis le cot de bande-passante requis pour tlcharger les produits). Pour une jeune entreprise, une telle manne financire peut se rvler trs utile dans dautres domaines

1. Introduction

Comparatif PHP/JSP
Encore une fois, comparer PHP JSP est un exercice prilleux. Le principe de fonctionnement est un peu diffrent : PHP a t conu pour sintgrer au code HTML, tandis que JSP est une utilisation de Java permettant de faire grer des scripts intgrs au code HTML. En fait, une page JSP est systmatiquement convertie en servlet. Alors que lexcution dun script PHP est compose de lanalyse du document, de la compilation (en opcode) et de lexcution proprement dite, celle dun script JSP est compose de lanalyse du document, de la gnration de la servlet (qui consiste principalement convertir le code HTML en appels Java "affichant" ce mme code), de la compilation de la servlet et, enfin, de lexcution proprement dite. Il est possible dimaginer que cest la "lourdeur" de ce travail qui fait que les servlets sont systmatiquement mises en cache (ce qui cre parfois des surprises aux dveloppeurs dbutants), alors que lutilisation de caches nest quoptionnelle avec PHP (il est donc important de tenir compte de cette diffrence lors dun comparatif de performances). Alors quavec PHP, tout passe par lutilisation de scripts PHP, avec JSP, lutilisation des scripts (scriptlets) doit tre rduite au minimum. Ces scriptlets doivent autant que possible se contenter dappeler des mthodes de Beans. Cela prsente linconvnient de devoir systmatiquement travailler de front dans deux espaces diffrents : dun ct les pages web, de lautres les Beans. Chaque modification entranera une nouvelle compilation des Beans et, ventuellement, la gnration dune nouvelle archive dployer dans lespace du serveur. Avec PHP, une simple modification du script dans lespace du serveur suffit. En revanche, la compilation des Beans vous assure de ne pas rencontrer de stupides erreurs de syntaxe lors de lexcution du code (problme que lon rencontrera avec PHP). Mais ce nest toutefois pas a qui vous assurera davoir un code qui fonctionne (mme sil est vrai que cela y contribue grandement). En fait, JSP se conoit comme un lment parmi dautres dans une architecture J2EE. Pour des sites de grande envergure, lavantage est indiscutable : on peut plus facilement partager les tches et les comptences dune quipe sur llaboration dun code en Java. De

42

PHP face ses concurrents (ASP, JSP, etc.)

mme, larchitecture "n-tiers" de Java (permettant lappel dobjets mis disposition sur un serveur distant) offre un ventail de solutions plus large (et avec des solutions plus robustes) pour des sites forte audience et trafic dense. Mais pour aboutir ce rsultat, nombreuses sont les normes ou rgles de conceptions respecter ce qui ne facilite pas lapprentissage du langage. Il est noter toutefois que bon nombre de ces rgles peuvent trs bien tre appliques PHP (comme par exemple le modle MVC). Dans ce cas, il est juste de la responsabilit de lquipe de dveloppeurs de simposer ou nous ces choix de conception.

1. Introduction

Figure 1.3 : Architecture en "n-tiers" de Java face PHP

Via J2EE, Java rend lclatement dune plateforme applicative beaucoup plus facile et simple que dans le cas de PHP. Pour PHP, le script doit thoriquement tre excut sur la machine qui reoit la requte (traitement du script sur la machine qui hberge le serveur web). Aussi est-il plus ardu de mettre en place une structure clate, plus modulaire, et tenant de lourdes charges. Linterfaage avec les bases de donnes seffectue grce aux pilotes JDBC, ce qui permet de communiquer avec tout type de serveur de bases de donnes avec un langage commun, mais, comme nous lavons dit prcdemment, ce nest pas le cas par dfaut pour PHP (mme si des solutions existent). Toutefois, comme cela a galement t dit, le langage SQL varie sensiblement dun serveur de bases de donnes lautre, rendant ncessaire lutilisation de code ddi (ce qui rduit grandement lintrt dune telle interface). Pour une application spcifique, le choix de Java peut se rvler judicieux. Par exemple, on ne peut pas parler de vritable pool de connexion en PHP, alors que, pour Java, il est prsent dans le container de EJB-J2EE. Dans le mme esprit, il est possible de partager des Beans en commun avec tous les scripts excuts (ce que ne propose pas PHP). Il est noter que Java a t conu comme tant orient objet (comme Smalltalk ou ObjectiveC). PHP, lui, na pas t cr pour la programmation objet, mais il est tout de mme possible de programmer de la sorte, mme si toutes les proprits auxquelles nous pourrions nous attendre ne sont pas disponibles. Aujourdhui les choses sont en train de changer, et le moteur Zend 2 va plus loin dans le sens de la programmation objet. Heureusement, comme pour PHP, il existe des solutions open-source plus ou moins compltes comme par exemple Tomcat et JBoss.

43

Chapitre 1

Introduction

Perspectives
1. Introduction
PHP a pour lui une trs grande facilit dinstallation. Il est propos de base sur quasiment toutes les distributions Linux. De trs nombreux kits dinstallation existent, qui permettent de faire rapidement ses premiers pas. Ces kits offrent galement une solution de mise jour pratique et facile mettre en uvre. PHP fait partie de la fondation Apache, ce qui garantit un interfaage entre le langage de script et le serveur web, sinon parfait, du moins tenu jour. Comme nous lavons dj dit plusieurs reprises, PHP dispose dune trs large et dynamique communaut de dveloppeurs, et les tutoriels en PHP sont trs nombreux. Entirement traduite en franais, la documentation officielle est disponible gratuitement sous de nombreux formats. PHP a galement su sinspirer des points positifs de ses concurrents. Le CPAN de Perl avait ainsi donn naissance son quivalent PEAR (base de ressources centralises pour PHP). Il est trs largement reconnu que PHP est dune prise en main facile. Sa syntaxe simple permet dapprocher beaucoup plus vite de la solution. Pour une entreprise, PHP peut galement tre intressant par son faible cot de dploiement. Par rapport ASP, par exemple, qui sous-entend une plateforme Microsoft avec de nombreuses licences acheter, PHP aligne des quivalences libres, et bien souvent gratuites, tout aussi fonctionnelles. Petit point ngatif pour PHP, les comparatifs sont bien peu de choses face une culture dentreprise. Mme si PHP offre, dans certains cas, une solution tout fait satisfaisante et bien meilleur march, il sera souvent plus simple de lui prfrer une solution ASP ou JSP pour des raisons historiques propres lentreprise. Cest l que PHP peut avoir un caractre rvolutionnaire. Ladopter, cest faire confiance une technologie atypique par son histoire et sa porte. Cest l que le plus gros travail reste faire pour les dveloppeurs. Si, sur le papier, les dcideurs informatiques acceptent bien volontiers les avantages de PHP, basculer une plateforme vers PHP reste une dcision importante. La tendance semble pourtant sinverser du fait du passage de certains grands comptes vers PHP (liberation.fr par exemple) : on fait de plus en plus fait confiance au PHP. Cette confiance associe une recherche dconomie dans le monde de lInternet font que cest tout naturellement que PHP dpasse ASP en terme dquipement de sites web (avril 2002, sur les sites tudis par Netcraft).

Documentation officielPHP
http://www.php.net/docs.php

En bref
Pour des langages de script, il est possible de discerner quelques grands facteurs prendre en compte lors du choix de lun dentre eux : la facilit dapprentissage (accessibilit), la puissance au regard de la complexit, la portabilit et lenvironnement disponible (ressources en ligne, outils, etc.). Pour ASP, PHP, Java, Perl et PHP, la situation peut se rsumer comme suit :

44

Pourquoi ont-ils choisi PHP ?

Tableau 1.1 : Tableau comparatif des langages de script


PERL Accessibilit Puissance Portabilit Environnement + ++ ++ ++ ASP ++ ++ ++ JSP +++ +++ +++ PHP

1. Introduction

+++ ++ +++ +++

Au regard des critres que nous avons dfinis, PHP semble bien avoir le plus davantages. Il nimporte pas de savoir si, dans labsolu, PHP est plus puissant que Java, par exemple. Mais, en revanche, il sagit de savoir si, dans le cas de lutilisation dun langage de script pour rendre un site web dynamique, linvestissement en temps requis pour matriser Java est justifiable au regard de la facilit dusage de PHP. Le Jargon franais dfinit les objectifs dun langage de script comme suit : "Faire simple, rapide, utilitaire". Dans cette optique, PHP est clairement le plus adapt.

Le Jargon
http://www.linux-france.org/prj/jargonf

1.5.

Pourquoi ont-ils choisi PHP ?

Ils ont choisi PHP


De nombreuses applications ont dj t crites en PHP et les sites webs ("perso" comme professionnels) qui passent au PHP ne se comptent plus. Pourquoi un webmestre fait-il le choix de PHP ? Entre ambition de dveloppement et prfrence politique, les atouts de PHP sont varis. De plus, les performances alignes par PHP dans ses multiples applications grand public peuvent galement sduire. Nous avons recueilli les tmoignages de deux dveloppeurs qui ont fait le choix de PHP, pour les prsenter plus en dtail avant de passer une prsentation gnrale avec laide de lObservatoire franais de PHP.

Gros plan : Tuxfamily et DaCode


Tuxfamily, hbergeur indpendant
Lanc par Julien Ducros, Tuxfamily est un hbergeur de projets libres qui utilise PHP au sein de sa plateforme. Age de trois ans, la structure de Tuxfamily est dsormais solide : un systme LVS (Linux Virtual Server) orchestr par deux Load Balancer (N.D.A : rpartiteur de charge). Toute la plateforme est rplique et les donnes utilisateurs sont contenues sur un filer central de 360 Go en raid 5. Les responsables de Tuxfamily connaissent PHP depuis bien longtemps, lpoque mme o lon parlait encore de PHP/FI.

45

Chapitre 1

Introduction

1. Introduction

Pourquoi ont-ils choisi PHP ? Principalement pour sa rapidit de mise en uvre. Mais ce nest pas tout : "Le langage PHP a aussi t pour nous un choix politique", explique Pierre Machard. Il poursuit : "PHP est un logiciel libre de grande qualit. Sa flexibilit et sa polyvalence ont motiv ce choix. Par exemple, nous pouvons actuellement lutiliser indiffremment avec une base de donnes MySQL ou Postgres". Pour lui, mme sil noffre pas la puissance des CGI, PHP est beaucoup plus simple mettre en uvre et exploiter. Selon Pierre Machard, la syntaxe de PHP, proche du C, participe aussi de son succs. Enfin, il est, daprs lui, idal pour pauler Apache. PHP nest pas pour autant au-dessus de tout soupon. Comme toute technologie dite "dynamique", PHP expose les sites des attaques par cross site scripting (exploitation dune faille de scurit sur un serveur web en entrant des commandes directement dans ladresse dune page). Pour Tuxfamily, il est ncessaire de sassurer davoir la dernire version stable installe. Les alertes de scurit publies sont plutt le signe dune bonne sant de PHP. En tout cas, "une rustine est rapidement disponible sur lInternet", nous explique Pierre Machard, "ce qui nest pas le cas dASP, logiciel propritaire". Pour un site fort trafic comme Tuxfamily, PHP dispose dun moteur bien conu qui "naccapare pas outrance les ressources des machines, mme sil possde quelques carences", concde Pierre Machard. Seul petit bmol adress PHP par lquipe de Tuxfamily : la licence de la dernire version. Les version 3.x taient libres, alors que la licence applique partir de PHP 4.x est plus restrictive (voir notre partie sur les licences).

daCode, moteur de nouvelles


Crateur et webmestre du site dinformations sur Linux et les logiciels libres http://linuxfr.org, Fabien Penso a bien voulu nous expliquer pourquoi il avait choisi PHP pour dvelopper daCode, le moteur de son site. Il a rencontr PHP par hasard. Cherchant un langage de script simple pour faire des sites web, il a tout naturellement test PHP. Voulant rendre daCode utilisable par nimporte qui, il a choisi PHP pour dvelopper son logiciel, car cest le langage disponible sur les plateformes grand public comme Free ou Multimania. Cela allait dans le sens de sa dmarche. Lide tant galement davoir le plus de contributions possibles pour daCode, limportante communaut de dveloppeurs PHP a jou en faveur du langage libre. Il fut un temps question de Perl/ mod_perl mais cette solution posait trop de problmes de fuite de mmoire.

Leurs sites Tuxfamily, hbergement libre pour gens libres :


http://www.tuxfamily.org

Contact : Pierre Machard <pmachard@tuxfamily.org> Linuxfr, site dinformation sur Linux et les logiciels libres :
http://linuxfr.org

daCode, gestionnaire de contenus open source (GPL) :


http://www.dacode.org

Contact : Fabien Penso <penso@linuxfr.org>

46

Pourquoi ont-ils choisi PHP ?

PHP lassaut du Net


On ne dnombre plus les grands comptes qui se tournent vers PHP. Que ce soit par la petite porte, souffl un directeur informatique par un dveloppeur, ou dans un plus large panel doffres faites par une webagency, PHP nest plus un langage neuf ou exotique. Les dcideurs en informatique lui font de plus en plus confiance. Le second trimestre 2002 a vu natre deux structures parallles visant recenser toutes les utilisations professionnelles ou industrielles de PHP. LAssociation franaise des utilisateurs de PHP (AFUP), ne en avril 2002, et lObservatoire franais de PHP (OFPHP), n en juin 2002, prsentent des interviews, des tudes et des listes de sites utilisant PHP. Le surf sur ces sites montre quel point PHP a pntr les hautes sphres du web. Sur le site de lAFUP, on apprend que le quart des entreprises du CAC 40 utilisent PHP pour leur site web. Parmi elles, Cap Gemini, PSA Peugeot Citron, Schneider Electric SA, etc. On le voit, pour les grands comptes, le langage de script libre fait trs largement jeu gal avec ASP, JAVA ou ColdFusion. Du ct de lOFPHP, la liste des sites utilisant PHP de par le monde, prsente dans la section Rfrences, est impressionnante : http://sourceforge.net (30 millions de pages visionnes par mois), http://www.phpbuilder.com (9 millions de pages par mois) ou encore http://www.insight.com (plus de 2 milliards $US. de chiffre daffaire en 2000). Pour la France, citons simplement http://www .boursorama.com (14 378 807 visites en juillet 2001 avec une pointe 9 783 039 pages vues pour la seule journe du 17 septembre 2001, jour de la rouverture des marchs Wall Street). LOFPHP prsente galement des interviews dacteurs de linternet qui ont choisi de faire confiance au PHP.

1. Introduction

Lutilisation de PHP dans les entreprises AFUP : le quart des entreprises du CAC 40 utilisent PHP
http://www.afup.org/article.php3?id_article=105

OFPHP :
http://www.ofphp.com/index.php?page=references

ZDNet : les logiciels libres tiennent la charge


http://techupdate.zdnet.fr/story/0,,t381-s2111391,00.html

47

Chapitre 2

Prise en main
2.1 2.2 2.3 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Le chier de conguration php.ini . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 Les diteurs et dbogueurs PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

Installation

our crer un site en PHP, il ny a pas besoin de beaucoup de choses. Un diteur de texte et un serveur web suffisent.

Si vous utilisez les services dun hbergeur Internet, vous pouvez ventuellement vous contenter de dposer vos scripts dans lespace qui vous est rserv et voir le rsultat obtenu. Mais il est bien plus pratique dinstaller son propre serveur web sur sa machine, afin de tester ses scripts avant daller les dposer chez un hbergeur. Autrement dit, quels que soient les cas, vous serez amen installer un serveur web supportant PHP. Dailleurs, vu la simplicit de lopration, pourquoi sen priver ? Si vous tes votre propre hbergeur, le chapitre Configuration vous permettra de personnaliser les options autorises. Dans le cas contraire, il est conseill de consulter ce chapitre qui vous permettra (via un appel phpinfo()) de mieux connatre ce que permet votre hbergeur et ce quil interdit. Enfin, ce chapitre vous prsente quelques diteurs particulirement adapts PHP.

2. Prise en main

2.1.

Installation

PHP est disponible pour diffrents serveurs et systmes dexploitation. Dans ce chapitre, nous nous efforcerons de dcrire au mieux linstallation de PHP sur les serveurs Apache, IIS, iPlanet, etc.

Avec Apache
PHP pour Apache est notamment disponible sous les environnements Linux/UNIX, Windows et Mac OS X.

Apache 2 Apache 2 est considr par ses dveloppeurs comme la version officielle du serveur web. Malheureusement, Apache2 nest pas encore officiellement support par les dveloppeurs de PHP. Dans certains cas, la version 5 de PHP peut fonctionner avec Apache 2. Dans tous les cas, consultez la documentation officielle pour connatre lvolution de la compatibilit : www.php.net/manual/fr/install.apache2.php. Nous prsenterons donc essentiellement linstallation avec la premire version dapache tout en indiquant les diffrences mineures pour une installation avec Apache2.

Sous Linux/Unix
Nous pouvons considrer quil existe trois grandes mthodes dinstallation de PHP dans un environnement Linux/UNIX. Cela peut ainsi se faire :
j j j

En utilisant les scripts dinstallation fournis avec les distributions (Linux notamment) ; En utilisant des kits dinstallation disponibles sur Internet ; En faisant une installation "manuelle".

51

Chapitre 2

Prise en main

Utiliser les scripts dinstallation de votre distribution est le moyen le plus sr et le plus rapide pour dbuter avec PHP, mais passer par une installation "manuelle" vous permet de personnaliser au mieux votre serveur.

Installation via la distribution Linux (ou UNIX)


2. Prise en main
Lors de linstallation du systme dexploitation, de nombreuses distributions offrent leurs utilisateurs la possibilit dinstaller un serveur Apache avec PHP et, bien souvent, MySQL, voire galement dautres bibliothques. Il suffit alors gnralement de cocher une case ou deux. Certaines distributions proposent mme des versions dites "optimises". Nous ne pouvons malheureusement pas toutes les dtailler ici. Vous tes donc convi consulter la documentation fournie avec votre systme dexploitation. Il est galement possible dinstaller cet ensemble Apache/PHP (et ventuellement MySQL) a posteriori, grce aux systmes des "packages" (parfois appels paquetages) portant gnralement lextension .rpm.

Installation via un kit


Si votre distribution ne propose pas de quoi installer simplement PHP dans votre environnement, ou bien si elle ne propose pas de version rcente des serveurs Apache et de PHP, vous pouvez utiliser un kit dinstallation. Il existe, par exemple, Apache Toolbox, que vous trouverez ladresse http://www.apachetoolbox .com (mais malheureusement en anglais). ApacheToolbox est un projet qui permet en effet dinstaller et de mettre jour trs facilement Apache, PHP (version 3 ou 4, au choix), MySQL, ZendOptimizer, OpenLDAP, ainsi que prs de cinquante modules pour Apache. Bien que les auteurs ne laient jamais essay, sachez quil existe LinuxEasyInstaller, disponible ladresse http://www.phpmylinux.net/index.php3?rub=lei, qui installe Apache/PHP, MySQL et phpMyAdmin (scripts permettant ladministration des bases de donnes via un navigateur).

Installation manuelle
Linstallation manuelle est certainement la meilleure faon davoir exactement ce que lon veut : Apache et PHP avec la base de donnes de son choix (PostgreSQL ou Oracle, par exemple) et pas ncessairement MySQL, ainsi quavec les bibliothques que lon souhaite (au choix parmi celles prsentes tout au long de ce livre) et pas seulement avec celles supportes par les kits dinstallation (que ce soient ou non ceux des distributions). Cest galement le plus sr moyen davoir la toute dernire version (chacun des lments tant librement tlchargeable sur Internet). Bref, mme si ce nest pas la faon la plus simple dinstaller PHP, elle reste celle que nous prconisons. Les autres mthodes prsentes prcdemment sont toutefois fort pratiques pour dbuter en PHP.

Pr-requis
Il va de soi que, pour installer Apache manuellement, vous devez avoir une connaissance des bases de Linux (la notion de droit utilisateur) et des commandes lmentaires que sont cp, cd ou ls par exemple. Nous ne reviendrons pas sur lutilisation du systme Linux, et encore moins sur son installation. En revanche, vous trouverez dexcellentes documentations sur Internet ou

52

Installation

dans des livres. Ce message davertissement na pas pour objectif de vous dcourager ou de vous effrayer devant cet excellent systme dexploitation quest Linux. Nous vous invitons simplement prendre connaissance des bases avant de vous lancer plus avant dans linstallation dApache et de PHP.

Installation
La notice dinstallation suivante fonctionne avec la plupart des distributions Linux (RedHat, Mandrake, SuSE, etc.). Il peut nanmoins y avoir des diffrences darborescence, les diffrentes distributions nayant pas toujours la mme logique. Pour cela, reportez-vous au manuel de rfrence de votre systme dexploitation, qui doit vous fournir une description dtaille de sa structure. Il vous suffit alors de modifier les chemins donns dans les lignes de commande. Les grandes procdures, elles, restent inchanges. Linstallation se ralise en deux temps : 1. 2. Dans un premier temps, vous devez installer les bibliothques que vous souhaitez utiliser. Vous devez compiler PHP en tenant compte des bibliothques prcdemment installes, puis compiler Apache en intgrant PHP.

2. Prise en main

Suite de linstallation Une fois connect et authentifi sur un systme Linux, et pour que la suite de linstallation se droule correctement, vous devez passer en mode super utilisateur (root). Pour cela, dans un shell, tapez simplement la commande "su " suivie du mot de passe root quand le systme vous le demande.
Installation des bibliothques Si vous ne savez pas encore quelles bibliothques vous allez utiliser, vous pouvez vous contenter dune installation de base (sans bibliothque particulire). Les procdures dinstallation des bibliothques sont dcrites dans le chapitre traitant de la bibliothque, mais, gnralement, le principe est le suivant : il suffit de tlcharger la dernire version de la bibliothque sur Internet (ou dutiliser celle disponible sur le CD-ROM), de copier larchive (par exemple sous /usr/local/src), et de taper les commandes suivantes :
# # # # # tar zxvf librairie-version.tar.gz cd librairie-version ./configure make make install

Si vous rencontrez un problme, pensez consulter le fichier INSTALL (bien souvent en anglais) qui doit tre fourni avec larchive dinstallation. Vous y trouverez la documentation complte pour linstallation de la librairie, qui ncessite peut-tre des paramtres spciaux. Soyez galement attentif au message derreur qui pourrait tre donn par le compilateur. Il constitue gnralement un excellent moyen de savoir o se situe le problme (dpendances, version de compilateur trop ancienne, etc). Le fichier README (galement en anglais, moins

53

Chapitre 2

Prise en main

que vous trouviez un LISEZMOI) peut galement contenir des informations utiles comme, par exemple, des incompatibilits temporaires. Compilation de PHP et Apache Vous devez, dans un premier temps, tlcharger les dernires versions dApache et de PHP (ou utiliser celles fournies sur le CD-ROM).

2. Prise en main

Les sites officiels Apache :


http://www.apache.org

PHP :
http://www.php.net

Autant que possible, tlchargez les sources au format .tar.gz qui seront utilises dans la suite de notre explication. Cela vous permettra davoir des binaires optimiss pour votre systme. Allez dans le dossier contenant les archives que vous avez tlcharges. Vous pouvez dores et dj passer en mode administrateur (root), puisque cela est gnralement ncessaire pour lopration dinstallation. Dcompressez alors les deux archives (nous supposerons ici que les archives sont dcompresses dans le mme rpertoire).
# tar zxvf apache_1.3.31.tar.gz

Dans le cas dapache 2, la commande devient tar zxvf httpd2.0.50.tar.gz.


# tar zxvf php-5.0.1.tar.gz

Pour compiler PHP en tant que module APXS, vous devrez dabord compiler Apache en vous assurant quil autorise le chargement des modules dynamiques.
# # # # cd httpd_X ./configure --prefix=/usr/local/apache --enable-module=so make make install

Apache est dsormais install sous /usr/local/apache. Reste compiler le module APXS PHP.
# cd .. # cd php-5.0.1 # rm config.cache

La suppression du fichier config.cache est inutile lors de la premire compilation (ce fichier nexistant pas), mais, par la suite, elle est quasiment indispensable si vous souhaitez tre sr de recompiler PHP avec les nouvelles options prcises. Vous pouvez alors passer la configuration (prparation la compilation de PHP).
# ./configure --with-apxs=/usr/local/apache/bin/apxs <autres options>

54

Installation

Dans le cas dapache 2, la commande devient ./configure withapxs2=/usr/local/


apache/bin/apxs <autres options>

Il existe de nombreuses options de configuration consultables en tapant ./configure help. Pour chaque bibliothque prsente dans ce livre, loption de configuration est indique (vous devrez sans doute en cumuler plusieurs). Ainsi, par exemple, la compilation de PHP avec mysql et gd donnera :
# ./configure --with-apxs=/usr/local/apache/bin/apxs --with-mysql=/usr/local/ mysql --with-gd=/usr/local --with-jpeg-dir=/usr/local --with-png-dir=/usr/ local --with-zlib-dir=/usr/local

2. Prise en main

Il est noter quil nest pas obligatoire de prciser les chemins des bibliothques, PHP sassurant de retrouver la bibliothque concerne Mais il est toutefois conseill de le faire afin de sassurer quil ny ait pas de malentendu (en particulier sur la version installer). Vous pouvez ensuite passer la compilation :
# make

Compilation sous Solaris Sous Solaris, vous devrez vous assurer de compiler PHP avec les outils GNU. En dautres termes, vous devrez installer le "package" binutils (disponible sur le site http://www.sunfreeware.com) et vrifier que le make GNU est bien le premier trouv dans le PATH.

# make install

a y est, PHP est compil et install (un fichier libphp5.so a t ajout dans le rpertoire libexec dApache). Reste configurer PHP et Apache. Outre ce qui est dcrit dans le paragraphe suivant, vous devrez consulter le fichier /usr/local/apache/conf/httpd.conf et vrifier quil contient bien la ligne suivante (de prfrence juste aprs les lignes correspondant la mme directive). Au besoin, ajoutez la :
LoadModule php5_module libexec/libphp5.so

Compilation de PHP intgr Apache Il est galement possible de compiler PHP au sein dApache (sans utiliser de module). Pour cela, la procdure devient :
# # # # # # # # # cd apache_1.3.31 ./configure cd .. cd php-5.0.1 rm config.cache ./configure --with-apache=../apache_1.3.31 <autres options> make make install cd ../apache_1.3.31

55

Chapitre 2

Prise en main

# ./configure --prefix=/usr/local/apache --activate-module=src/modules/php5/libphp5.a # make # make install

Dans ce cas, vous ne devrez pas ajouter ou devrez commenter la ligne : 2. Prise en main
LoadModule php5_module libexec/libphp5.so

Reste copier le fichier de configuration par dfaut de PHP dans le rpertoire o il doit se trouver :
# cd ../php-5.0.1 # cp php.ini-dist /usr/local/lib/php.ini

Les principales options de php.ini seront dcrites dans le prochain chapitre.

Ensuite, ditez le fichier /usr/local/apache/conf/httpd.conf laide de Vi ou Emacs (selon votre appartenance), et ajoutez la ligne suivante afin que les fichiers portant les extensions indiques soient interprts par PHP :
AddType application/x-httpd-php .php .php5 .php4 .phtml AddType application/x-httpd-php-source .phps

Pour voir la vie en rose (ou bleu, ou jaune, ou rouge...) Si vous donnez une extension .phps vos scripts, alors ceux-ci ne seront pas interprts, mais le code source sera affich et coloris, ce qui peut parfois permettre de voir comment PHP lanalyse (et ainsi dtecter des parse error).
Il est aussi prfrable de modifier linstruction suivante :
DirectoryIndex index.html

en :
DirectoryIndex index.html index.php index.php5 index.php4

Cette instruction permet de forcer la page index que le navigateur doit afficher si lURL demande est incomplte. Avec la ligne prcdente, le serveur ira chercher dans le rpertoire prcis le fichier index.html et, sil ne le trouve pas, index.php, etc. Ainsi, appeler la page http://localhost/ renvoie la page se trouvant lURL http://localhost/index.html, si celle-ci existe. Pensez galement, si ce nest dj fait, dcommenter ou ajouter une ligne
ServerName <nom de votre machine>

Vous pouvez par exemple indiquer :


SeverName localhost

56

Installation

prsent, lancez le serveur Apache :


/usr/local/apache/bin/httpd start

Pour larrter, vous naurez qu taper la commande :


/usr/local/apache/bin/httpd stop

Si vous n Vous pouvez maintenant crer votre premire page web. ditez la page /usr/local/apache/ htdocs/index.php et insrez-y ces quelques lignes :
<?php phpinfo(); ?>

2. Prise en main

Vous navez plus qu appeler la page depuis votre navigateur en entrant ladresse http://localhost/index.php.
Figure 2.1 :

Voil votre page interprte en PHP

Sous Windows
Tout comme pour Linux, linstallation sous Windows pourra se faire de deux faons diffrentes : en cliquant ou en compilant. Il existe dsormais de nombreuses solutions "tout en un" qui vous permettent dinstaller Apache et PHP sur un systme Windows sans avoir faire de fastidieuses manipulations. De plus, ce type dinstallation ne ncessite quun minimum de temps et de connaissances techniques. Si ces programmes ont pour eux la simplicit et la rapidit, ils ont aussi les dfauts vidents de leurs avantages : installation non transparente et pas toujours personnalisable souhait. Il faut parfois galement aller ajouter "manuellement" des bibliothques.

57

Chapitre 2

Prise en main

Installer PHP5 pour Apache 2 Si vous souhaitez installer PHP5 et Apache2, vous devrez tlcharger larchive zippe de PHP5. Linstalleur automatique ne vous fournira pas tous les fichiers requis pour que PHP5 fonctionne avec Apache2. 2. Prise en main

Installation automatique
EasyPHP
EasyPHP est un programme bien pratique, qui permet dinstaller Apache, PHP, MySQL et PhpMyAdmin en quelques clics de souris. Il y a environ une nouvelle mouture chaque anne. Pour dbuter linstallation, lancez lexcutable EasyPHP1-7_setup.exe prsent sur le CD-ROM. Cela installera Apache 1.3.27, PHP 4.3.3, MySQL 4.0.15 et Phpmyadmin 2.5.3. Vous pouvez galement vous rendre sur le site dEasyPHP pour vrifier si une version plus rcente est disponible (www.easyphp.org). Si cest le cas, il est vivement conseill dutiliser le produit le plus rcent.
Figure 2.2 :

Dbut de linstallation dEasyPHP

Quoi quil en soit, linstallation nest en rien hors du commun, et se droule sans difficult particulire. Une fois lopration mene terme, le programme dinstallation vous propose de vous rendre sur la page daccueil dEasyPHP.
Figure 2.3 : Fin de linstallation dEasyPHP

58

Installation

Ne changez rien, puis cliquez sur Terminer (enfin... Finish si comme dans votre environnement vous avez un texte mi-anglais mi-franais) Et voil, cest fini. Un navigateur souvre alors pour vous prsenter la page daccueil dEasyPHP. Si le logiciel ne se lance pas automatiquement, dans le menu Dmarrer, cliquez sur Tous les programmes, puis sur EasyPHP 1.7 et, enfin, sur EasyPHP. Le programme va alors dmarrer.

2. Prise en main

Figure 2.4 : Page daccueil dEasyPHP

La page daccueil dEasyPHP prsente plusieurs choses fort utiles : une introduction EasyPHP en local et des liens vers le support en ligne. Vous pouvez galement accder cette page en cliquant droit sur le "E" qui a t ajout la barre des tches (dj certainement bien assez charge votre got).

Figure 2.5 : lment de la barre des tches

Ce E vous permettra daccder aux principales fonctions relatives ladministration dun serveur web. Dans le menu contextuel qui souvre alors, il suffit de choisir Web local, mais, pour le moment, cliquez plutt sur Administration. Cette option vous permet daccder une configuration centralise de certains des programmes que vous venez dinstaller.

59

Chapitre 2

Prise en main

2. Prise en main

Figure 2.6 : La page dadministration dEasyPHP

Il vous est alors possible (par exemple) de vrifier puis de changer le mot de passe daccs MySQL depuis le compte "root". Dans la section Environnement EasyPHP, cliquez sur le bouton Paramtres. La page se rafrachit pour vous donner les informations relatives aux paramtres de connexion par dfaut attribus votre serveur MySQL. Vous devez lire quelque chose comme ceci :
Paramtres par dfaut de la base de donnes : serveur : "localhost" username : "root" mot de passe : ""

Pour le serveur "localhost", lutilisateur "root" (celui qui a tous les droits) na pas de mot de passe ; il peut se connecter sans mme avoir sidentifier. Il peut donc tre important de corriger cela (si plusieurs personnes ont accs votre machine). Toujours sur la mme page, cliquez sur PhpMyAdmin dans la section Administrez vos bases de donnes. Vous devez voir safficher la page daccueil de PhpMyAdmin dans un nouveau navigateur. Pour plus dinformations, vous pouvez vous reporter la partie des annexes traitant de PhpMyAdmin.

60

Installation

2. Prise en main

Figure 2.7 : PhpMyAdmin

Dans la partie gauche de la page, vous devez trouver, sous la mention Accueil, un menu droulant des diffrentes bases de donnes prsentes sur le systme. La partie qui nous intresse se trouve sur la partie droite de la page. On peut voir deux colonnes : une premire qui propose des liens en rapport avec MySQL, et une seconde qui concerne PhpMyAdmin. Dans la colonne MySQL, cliquez sur le lien Utilisateurs et privilges. La nouvelle page qui saffiche prsente alors un tableau rcapitulatif des utilisateurs ayant un accs au serveur, un rsum de leurs privilges, ainsi que diverses options concernant les utilisateurs. Sur la ligne de lutilisateur "root", cliquez sur le lien Modifier. La page se recharge. Certains des champs ont t pr-remplis. Vrifiez que le champ "Utilisateur" contienne bien "root", puis donnez par deux fois le mot de passe que vous souhaitez voir utilis pour cet utilisateur. Cliquez enfin sur Excuter. Voil. Noubliez pas de noter le mot de passe de lutilisateur "root". Noubliez pas de lancer EasyPHP lorsque vous voulez utiliser Apache ou MySQL. Autre intrt dEasyPHP : il peut servir de base de dpart. Rien ne vous empche, sans avoir tout rinstaller, de mettre jour certains des programmes mis disposition par EasyPHP. Cela se fera, certes, au prix de quelques manipulations. PHP lui-mme pourra, par exemple, tre mis jour facilement grce PHPInstaller.

WAMP5 : pour installer PHP5, MySQL4 et Apache2 WAMP5 est un systme similaire EasyPHP qui permet dinstaller PHP5 et MySQL 4.0.18 automatiquement. Apache2, lui, est disponible sous forme dadd-on. Vous pouvez trouver WAMP5 cette adresse : www.wampserver.com. Attention toutefois : si vous avez dj install Apache2 ou PHP5, il faudra les dsinstaller sans quoi il risque dy avoir un conflit avec les versions installes par WAMP5.

PHPInstaller : mettre PHP jour facilement


PHPInstaller est un programme du groupe PHP (http://www.php.net), qui vous permet dinstaller PHP sur votre systme. Il est pratique plus dun titre. Si vous disposez dj dun serveur web sur votre machine, il lui est possible de configurer lui-mme ce serveur. Malheureusement, le programme de configuration automatique nexiste pas encore pour tous les serveurs web, et il faudra donc mettre la main la pte dans certains cas (Apache, tout particulirement). PHPInstaller est donc plutt a rserver pour une premire installation avec un serveur IIS ou dans

61

Chapitre 2

Prise en main

les autres cas, pour une mise jour. Ceci constitue un moyen simple et rapide de suivre au plus prs lvolution de PHP. Pour commencer, lancez lexcutable php-5.0.1-installer.exe prsent sur le CD-ROM.
Figure 2.8 : Page daccueil de PHPInstaller

2. Prise en main

Une fois passe la page daccueil et celle concernant la licence, PHPInstaller va vous proposer deux types dinstallation.
Figure 2.9 :

Choix du type dinstallation

Nous allons dcrire linstallation avance, linstallation standard ntant pas assez complte pour garantir un minimum de personnalisation. Une fois le processus dmarr, rpondez aux questions que vous pose lAssistant. Choisissez un rpertoire dinstallation, puis acceptez la sauvegarde des fichiers dj prsents sur le systme, comme vous le propose PHPInstaller.

62

Installation

Figure 2.10 : Rpertoire dinstallation

2. Prise en main

Les options qui arrivent maintenant sont propres au PHP. Vous devez donner un rpertoire temporaire qui servira pour les fichiers en attente de publication ("files upload") ainsi quun rpertoire de stockage pour les fichiers de sessions. Ensuite, lorsque la fonction mail() sera utilise, vous devrez spcifier ladresse qui sera utilise pour le champ "de" ("from").
Figure 2.11 : Configuration du mail

Vous pouvez ensuite choisir le niveau de rapport derreur. Votre choix sera guid par lutilisation que vous comptez faire du serveur sur lequel vous tes en train dinstaller PHP. Sil a pour vocation de devenir un serveur de test, vous choisirez laffichage maximal, cela afin de cerner au mieux les erreurs et dysfonctionnements. En revanche, si vous installez PHP sur une machine qui hbergera un site professionnel destin au grand public, choisissez le plus bas niveau daffichage. Les visiteurs ne sont pas concerns par ces questions de programmation, et il nest pas ncessaire de faciliter la tche dventuels pirates qui sauraient alors directement o aller fouiller... Ensuite, choisissez le serveur HTTP sur lequel vous tes en train dinstaller PHP : Microsoft PWS, IIS 3 ou 4, Apache ou Xitami.

63

Chapitre 2

Prise en main

Figure 2.12 :

Slection du serveur Web

2. Prise en main

Si le serveur que vous utilisez ne se situe pas dans cette liste, vous devrez alors passer par la case "configuration la main post-installation" (vous pouvez dailleurs utiliser les diffrentes mthodes prsentes dans ce livre). Enfin, choisissez les extensions qui devront tre interprtes comme tant de PHP. Cette dernire tape passe, PHPInstaller passe linstallation des composants de PHP sur votre machine. Si vous disposiez dj de PHP sur votre machine, le programme vous demandera si vous souhaitez ou non conserver votre ancien php.ini. Cela peut savrer trs intressant si vous aviez personnalis votre fichier php.ini.
Figure 2.13 : Voil, cest fini !

Et voil, cest fait.

Mise jour de PHP pour une installation dEasyPHP Dans le cas dune mise niveau de PHP pour un systme sur lequel avait t install EasyPHP, il faudra jongler un peu avec le fichier php.ini. EasyPHP installe PHP dans un rpertoire qui lui est propre. Si vous dsirez conserver la configuration dEasyPHP, ce qui est recommand, vous devrez diter le fichier php.ini situ la racine de votre dossier Windows pour lui donner les bons chemins pointant vers les diffrents composants de PHP (php.exe, dossier des extensions, etc.).

Installation personnalise
Vous pouvez choisir dinstaller les diffrents lments de la configuration un par un, grce des solutions plus ou moins automatises. Voici comment procder.

64

Installation

Installer Apache
Il existe des programmes qui vous permettent dinstaller facilement la dernire version dApache sur votre machine. Tlchargez lun de ces programmes, de prfrence depuis lun des miroirs du site Apache (http://mir2.ovh.net/ftp.apache.org/dist/httpd/binaries/win32/). Vous pouvez choisir entre un installateur automatique en .exe ou en .msi (Microsoft Installer). Si vous optez pour la version en .msi, assurez-vous que vous disposez bien de linstallateur Windows. Pour vrifier, dans le menu Dmarrer, puis dans Excuter, tapez la commande msiexec. Il vous faut au minimum la version 1.10.1029.1. Si vous ne disposez pas de la version approprie, tlchargez le programme depuis lune de ces adresses, en fonction de votre plateforme :
j j

2. Prise en main

Windows NT 4.0 : www.microsoft.com/downloads/release.asp?ReleaseID=17344 Windows 95 et 98 : www.microsoft.com/downloads/release.asp?ReleaseID=17343

Une fois que vous avez tlcharg le programme dinstallation dApache, lancez-le.
Figure 2.14 : Fentre daccueil

Acceptez la licence du programme, puis cliquez sur OK jusqu ce que vous arriviez sur la page qui vous pose quelques questions relatives la configuration du serveur.
Figure 2.15 :

Paramtrage minimal

65

Chapitre 2

Prise en main

Remplissez les champs Network Domain (nom du domaine pour lequel le serveur est install), Server Name (nom du serveur web qui va tre install), et donnez ladresse e-mail de ladministrateur. Choisissez ensuite si Apache doit tre install comme un service utilisable pour tous les utilisateurs, ou sil doit tre lanc manuellement par un utilisateur donn.
Figure 2.16 : Choix du type dinstallation

2. Prise en main

vous de faire votre choix selon les besoins du serveur que vous mettez en place. Donnez ensuite le chemin dinstallation pour que le processus puisse arriver terme.
Figure 2.17 : Fin de linstallation

Par la suite, vous pourrez rutiliser cet installateur pour rparer votre serveur web Apache si vous lavez mis mal avec de trop nombreux tests. Il vous suffit de relancer linstallateur pour quil vous propose soit de supprimer Apache, soit de le rparer.

Ruse de sioux Si vous installez Apache pour faire des tests sur votre machine personnelle, voici comment renseigner les champs de linstallateur Apache ltape Server Information.
j j

Network Domain : localdomain ; Server Name : localhost.localdomain ;

66

Installation

Administrators Email Address : votre adresse e-mail.

Si vous utilisez Windows XP avec le Service Pack 2, vous aurez certainement droit une alerte de scurit la fin de linstallation dApache.
Figure 2.18 : Alerte de Windows XP lors du dmarrage dApache

2. Prise en main

Cliquez sur le bouton Dbloquer pour permettre lexcution du serveur web. Une fois Apache install, il va se lancer automatiquement. Vous pourrez trouver une petite plume orne dune flche vers la droite dans la barre des tches Windows qui permet daccder la console de gestion de votre serveur Web. La console de gestion vous permet de connatre le statut du serveur, de larrter, de le relancer ou bien daccder la console de gestion des services Windows.
Figure 2.19 : Cliquez sur la petite flche verte sur fond blanc pour accder la console de gestion Apache

Figure 2.20 : La console de gestion du serveur Apache (ici ctait un test avec Apache2)

Vous pouvez lancer un navigateur et le faire pointer sur ladresse http://localhost pour vrifier si la page de test Apache saffiche bien. Une fois toutes ces tapes effectues, vous pouvez passer linstallation de PHP.

67

Chapitre 2

Prise en main

Installer PHP
Tlchargez larchive zippe disponible sur le site du groupe PHP (PHP Zip package dans la partie Windows Binairies de la section Download du site). Une fois que vous avez tlcharg le fichier compress, dcompactez-le sur votre disque dur dans un dossier spcialement cr cet effet. Sans vouloir vous influencer, c:\php serait une bonne ide (vitez tout particulirement les noms de dossiers avec des espaces). Dans ce dossier, reprez le fichier php.ini-dist, renommez-le en php.ini, et copiez-le dans votre rpertoire Windows (c:\Windows ou c:\WINNT). Une fois le fichier copi, ditez-le avec votre logiciel prfr. Recherchez cette ligne :
; extension_dir =

2. Prise en main

et renseignez le champ avec lemplacement o se trouvent les extensions PHP. Par exemple :
extension_dir = c:\PHP\ext\

si vous avez install PHP dans un dossier PHP la racine de votre disque dur. Noubliez pas, pour cette ligne et pour toutes les autres, de les dcommenter lorsque vous aurez rentr les paramtres ncessaires. Pour cela, il vous suffit de supprimer le ";" en dbut de ligne. Attention, ne dcommentez que la ligne contenant des paramtres ; laissez les lignes dexplication en commentaire. Recherchez ensuite la ligne
doc_root =

et renseignez le champ avec lemplacement de la racine de votre serveur web. Il sagit en fait de donner le chemin daccs du dossier c:\Program Files\Apache Group\Apache\htdocs\.
doc_root = "C:\Program Files\Apache Group\Apache\htdocs"

Une fois que vous en avez termin avec php.ini, copiez le fichier php5ts.dll qui se trouve la racine de votre rpertoire PHP dans le dossier System du rpertoire Windows (c:\windows\system pour Windows 9x/Me ou c:\winnt\system32 pour Windows NT/2000/XP).

Conguration
Vous allez devoir diter le fichier httpd.conf qui configure le serveur web Apache. Normalement, un lien a t prvu pour cela dans le groupe de programmes Apache cr aprs linstallation du serveur web (Configure Apache server puis Edit the Apache httpd.conf configuration file). Si vous ne trouvez pas ce lien, le fichier httpd.conf se trouve dans le dossier conf du rpertoire Apache. Avant de vous lancer dans la configuration, assurez-vous que votre serveur web Apache est bien arrt. Si vous lavez lanc depuis le lien prsent dans le menu Dmarrer, fermez simplement la console. Dans ce fichier, recherchez la ligne :
#LoadModule unique_id_module modules/mod_unique_id.so

Et ajoutez cette ligne juste aprs :


LoadModule php5_module c:/php/php5apache.dll

68

Installation

Attention, ne dcommentez pas la ligne dj prsente dans le fichier de configuration ; elle a juste t utilise pour permettre une localisation plus aise. Noubliez pas de donner votre propre chemin vers le fichier php5apache.dll. Si vous utilisez Apache 2 alors le nom du fichier devient php5apache2.dll. Recherchez ensuite la ligne:
#AddModule mod_setenvif.c

2. Prise en main

A sa suite, ajoutez cette ligne:


#AddModule mod_php4.c

Enfin, recherchez la ligne :


#AddType application/x-tar .tgz

la suite de laquelle vous ajoutez cette ligne :


AddType application/x-httpd-php .php .php5 .php4

Sauvegardez le fichier httpd.conf et relancez votre serveur web laide de la console Apache. Vous pouvez tester la bonne prise en compte de PHP en affichant un fichier test en PHP.

Racine Par dfaut, la racine de votre serveur web se trouve dans le dossier htdocs du rpertoire Apache. Cest donc l que vous devrez copier vos fichiers .php, .html, etc.

Complment dinstallation
Ca y est vous avez install PHP 5 pour Windows. Vous disposez de la majorit des bibliothques. Sachez toutefois, que le PHP Group propose galement un autre ensemble dextensions (pour la plupart peu utilises ou rendues obsoltes) dans un paquetage appel PECL. Celui-ci est disponible sur le site officiel ladresse http://www.php.net/downloads.php mais galement sur le CDROM fourni. Pour en profiter, il vous suffit de dzipper son contenu (ou seulement les dll qui vous intressent) dans le rpertoire contenant les extensions PHP dont le chemin est prcis dans le fichier php.ini sous le paramtre extension_dir. et de les activer en les supprimant les commentaires dans ce mme fichier.

Sous Mac OS X
Nous pouvons considrer quil existe deux grandes mthodes pour installer PHP dans un environnement Mac OS X. Cela peut ainsi se faire :
j j

Rien quen activant PHP au niveau du serveur prinstall (si vous disposez de la version serveur de Mac Os X) ; En faisant une installation "manuelle" (notamment si vous disposez de la version cliente de Mac Os X ou pour les mises jours).

69

Chapitre 2

Prise en main

Installation par un package


Des packages dinstallation prpars pour Mac sont disponibles pour Apache2 et PHP5. Comme pour PHP4, le site web Entropy.ch met disposition des internautes un package dinstallation de PHP5. Il est bien tenu jour et suit les remarques des utilisateurs. Vous pouvez le tlcharger cette adresse : http://www.entropy.ch/phpbb2/viewtopic.php?t=1446.

2. Prise en main

Linstallation dApache2 pourra se faire directement grce au package prpar par la Apache Software Foundation : http://www.apple.com/downloads/macosx/unix_open_source/apache.html. Vous naurez plus qu lancer une rapide compilation pour ensuite profiter dApache2.

Activation de PHP sur Mac Os X


Avec OS X, les Mac souvrent beaucoup plus facilement au web, que ce soit dans les versions serveur ou client. Mme si les Mac ont toujours fait des serveurs web trs scuriss, du fait, entre autres, de labsence de ligne de commande, la mise sur pied dun serveur web sur une machine de la firme de Cuppertino ntait pas, contrairement aux habitudes de la maison, un modle de simplicit. Le dernier systme dexploitation dApple, Mac OS X, repose sur Darwin, un noyau Unix libre. Avec larrive dune base Unix, les Mac gagnent en simplicit en matire de web. Alors que les utilisateurs de MacOs navaient leur disposition que quelques serveurs web quils devaient installer eux-mmes, Mac OS X dispose en natif dun serveur Apache qui nattend quun claquement de doigts pour tre oprationnel. De mme, PHP ne demande qu tre activ. On ne peut toutefois pas se limiter ses installations par dfaut. La volont lgitime davoir une installation plus personnalise (nouveaux modules, optimisation, etc.) passera par une installation ex nihilo dApache et de PHP, depuis des sources quil faudra compiler. Les mises jour dApache ou du langage PHP passeront par le suivi des annonces faites par Apple. Ainsi, nous verrons, dans un premier temps, lactivation des services et modules dj prsents linstallation et, dans un second temps, la compilation et linstallation des programmes depuis un code source.

Activer Apache
Serveur web le plus puissant ou le plus rpandu qui soit, peu importe : quand Apple fait quelque chose, il le fait de manire simple et accessible. Les amoureux de la ligne de commande vont en prendre pour leur grade Lancer Apache sur Mac OS X est encore plus simple que de terminer Adibou dcouvre les animaux en mode facile. Une fois Mac OS X lanc, allez dans le menu Pomme, puis dans Prfrences Systme, et slectionnez Partage. Dans la bote de dialogue qui souvre alors, vous trouverez de nombreuses options relatives la configuration de votre serveur web Apache. En effet, ce quApple appelle Partage web repose, en fait, sur le travail du serveur web (voir fig. 2.21). Sous le titre Partage web, cliquez simplement sur le bouton Dmarrer. Votre mot de passe vous sera alors demand ; rentrez-le, puis patientez quelques instants, le temps que le serveur se lance. Voil, le tour est jou. Si vous obtenez un message derreur, il se peut que vous ne soyez pas un utilisateur faisant partie du groupe "admin".

70

Installation

2. Prise en main

Figure 2.21 : La bote de dialogue Partage web sous Mac OS X

Le groupe "admin" Par dfaut, le premier utilisateur cr fait partie de ce groupe. Il faut faire partie de ce groupe pour accomplir certaines actions (lancer le partage web par exemple). Pour lancer ou arrter le serveur Apache, il faudra tre soit le premier utilisateur cr, soit un utilisateur qui aura t plac dans le groupe "admin".
Pour vrifier que tout fonctionne bien, vous pouvez lancer votre navigateur web prfr et vous rendre ladresse http://localhost/. Vous devriez y trouver une page daccueil par dfaut. Vous pouvez galement effectuer cette vrification avec votre nom dutilisateur, en vous rendant sur votre espace web personnel qui aura t cr automatiquement par le serveur. Si vous tes lutilisateur toto, votre espace personnel sera alors accessible ladresse http://localhost/toto/. Cela nest pas trs utile pour le moment, mais cela pourra se rvler intressant quand il sagira de faire des tests de scripts. Vous pourrez utiliser votre espace personnel plutt que le site web de premier niveau (un site en http://localhost/~toto plutt que http://localhost/). Les utilisateurs trouveront leur site dans leur rpertoire personnel, dans le dossier Sites. Pour publier des documents la racine du site, il faudra placer ces lments dans le dossier "/Library/Webserver/Documents/".

Activer PHP
Le serveur Apache install sur Mac OS X comporte dj le module PHP. Toutefois, celui-ci nest pas activ par dfaut. Il faut donc faire quelques acrobaties accompagnes dun redmarrage du serveur web pour que toutes les modifications soient prises en compte.

Faire fausse root En fouillant sur le web, ou en puisant dans ses connaissances dunixien, on peut tre tent dactiver le module PHP en passant par lutilisateur root. Or, ce compte nexiste pas sur Mac OS X. Il est bien sr possible de le crer. Toutefois, il est fortement recommand de ne pas crer ce compte. Dune part, on respecte ainsi la philosophie dApple vis--vis de son systme dexploitation et, dautre part, lon garantit une meilleure scurit au systme root ayant droit de vie et de mort sur le systme).

71

Chapitre 2

Prise en main

Pour mener bien certaines oprations, vous devrez utiliser la commande sudo (su pour "super-user" et do de "to do"). Cette commande vous permet davoir accs des actions normalement rserves lutilisateur root. Lorsque vous ferez appel cette commande pour la premire fois, le systme vous demandera votre mot de passe. Ensuite, vous pourrez lutiliser directement. Lactivation de PHP consiste principalement en une modification du fichier httpd.conf, fichier de configuration du serveur web Apache. Avant de faire des modifications sur ce fichier, il est fortement recommand den faire une copie, afin de garder une porte de sortie en cas de mauvaise manipulation. Rendre ce fichier de configuration inutilisable revient purement et simplement mettre en berne son site web, Apache ne pouvant alors plus dmarrer. Pour faire cette copie, lancez un terminal (depuis le Finder, dans le dossier Applications, puis le dossier Utilitaires, choisissez Terminal). Une fois le terminal lanc, saisissez cette ligne de commande :
sudo cp /etc/httpd/httpd.conf /etc/httpd/httpd.conf.copie

2. Prise en main

Le systme vous demande votre mot de passe ; donnez-le lui. Si jamais il vous arrivait malheur lors de ldition du fichier de configuration, vous nauriez alors qu craser le fichier de configuration par la sauvegarde que vous aviez faite. Pour cela, utilisez cette commande :
sudo cp /etc/httpd/httpd.conf.copie /etc/httpd/httpd.conf

Une fois cette opration effectue, nous pouvons travailler sans danger sur le fichier httpd.conf (ou tout au moins sans remords). Nous allons devoir rechercher les rfrences PHP dans ce fichier, pour nous assurer quelles sont bien prises en compte par le serveur lors de son dmarrage. Nous utiliserons lditeur de texte Pico pour travailler sur le fichier. Si cest la premire fois que vous utilisez cet diteur en mode texte, il peut tre utile den consulter laide. Cela vous vitera des heures derrance, coinc dans un fichier texte qui nen demandait pas tant. Puis, une fois Pico lanc, tapez [Ctrl}]+ [G] pour accder laide intgre. La plupart des commandes sobtiennent par le biais de la touche [Ctrl] suivie dune lettre. Vous pouvez dailleurs voir les fonctions les plus utiles en bas de la fentre de terminal. Une fois que vous avez compris les bases de lutilisation de Pico, vous pouvez lancer ldition du fichier http.conf :
sudo pico /etc/httpd/httpd.conf

Noubliez pas que vous devez donner votre mot de passe. Dans ce fichier, recherchons les rfrences PHP ([Ctrl}]+[}W], PHP, [Entre]). La premire rponse doit tre celle-ci :
#LoadModule php5_module libexec/httpd/libphp5.so

Le # devant la ligne signifie quelle est commente, et que le serveur ne prend pas en compte cette ligne de configuration lors de son dmarrage. Supprimez le # et refaites une recherche. Vous ne devriez pas avoir ressaisir "php", Pico gardant en mmoire la dernire occurrence de recherche. Votre nouvelle recherche doit vous amener cette ligne :
#AddModule mod_php4.c

De mme, supprimez le #. Dsormais, Apache chargera le module PHP lors de son chargement.

72

Installation

Continuons la recherche. Loccurrence suivante doit se trouver dans ce paragraphe :


# AddType allows you to tweak mime.types without actually editing it, or to # make certain files to be certain types. # # For example, the PHP 3.x module (not part of the Apache distribution - see # http://www.php.net) will typically use: # #AddType application/x-httpd-php3 .php3 #AddType application/x-httpd-php3-source .phps # # And for PHP 4.x, use: # #AddType application/x-httpd-php .php #AddType application/x-httpd-php-source .phps

2. Prise en main

Ce paragraphe stipule que les fichiers dlivrs par le serveur qui ont pour extension .php3, .php ou .phps doivent tre traits avec le module PHP. Supprimez aussi les # devant ces lignes, sinon le chargement du module PHP ne servirait pas grand-chose. Attention, ne dcommentez pas toutes les lignes, mais seulement les lignes dinstructions, comme ceci :
# # # # # # AddType allows you to tweak mime.types without actually editing it, or to make certain files to be certain types. For example, the PHP 3.x module (not part of the Apache distribution - see http://www.php.net) will typically use: AddType application/x-httpd-php3 .php3 AddType application/x-httpd-php3-source .phps # # And for PHP 4.x, use: # AddType application/x-httpd-php .php AddType application/x-httpd-php-source .phps

Recherchez maintenant loccurrence <IfModule mod_dir.c>. Vous devez arriver sur un paragraphe comme celui-ci :
<IfModule mod_dir.c> DirectoryIndex index.html </IfModule>

Ajoutez "index.php" la ligne du milieu, en laissant un espace aprs "index.html". Cela indique au serveur Apache quil doit, lorsquon lui donne une adresse du type http://toto.com/titi/, rechercher un fichier index.html dans le dossier /titi, mais galement un fichier index.php. Voil, toutes les modifications ncessaires ont t effectues. Vous pouvez sauvegarder le fichier et quitter Pico. Il vous faut maintenant redmarrer le serveur Apache, afin quil prenne en compte les modifications que vous avez effectues dans le fichier de configuration. Faites-le depuis linterface graphique (Partage web, en arrtant puis dmarrant le serveur), ou encore depuis votre terminal en tapant cette commande :
sudo apachectl restart

73

Chapitre 2

Prise en main

Pour vrifier que vos modifications ont bien t intgres, tapez cette commande dans votre shell :
tail /var/log/httpd/error_log

Cela aura pour effet dafficher les traces des messages derreur dApache. Au dbut du fichier, vous devez pouvoir trouver cette ligne :
[notice] Apache/1.3.23 (Darwin) PHP/4.1.2 configured -- resuming normal operations

2. Prise en main

Une fois que tout est intgr et fonctionnel, profitez de loccasion pour faire une copie de sauvegarde de votre fichier httpd.conf. Cela vous vitera, lors dune rinstallation, de devoir rpter toutes ces manipulations. Toujours dans votre shell, tapez cette commande :
sudo cp /etc/httpd/httpd.conf /etc/httpd/httpd.conf.copie

Une version serveur de pointe Sur la version serveur de Mac OS X, le serveur de bases de donnes MySQL fait galement partie de linstallation par dfaut. Dans la version client, il faut installer soi-mme le serveur.

Installation manuelle
Apple fournit des sources prtes tre compiles qui vous permettront de rester jour sans avoir rinstaller tout votre systme. Compiler une nouvelle version dApache ou du langage PHP peut tre obligatoire pour des raisons de scurit. Ayez en tte que vous devrez alors certainement revoir des options de configuration (tout particulirement pour httpd.conf) pour vos logiciels nouvellement installs. Faites galement le tour des modules que vous avez installs et des modules qui seront disponibles et compatibles aprs la mise jour. Certains portages peuvent prendre quelque temps. vitez donc de faire une mise jour trop rapide, qui vous priverait de modules dont vous avez besoin pour votre site.

Compiler Apache
Avant daller plus loin, assurez-vous que vous disposez bien des outils de dveloppement Apple sur votre machine. Si vous navez pas le CD qui contient ces logiciels, vous pouvez vous inscrire gratuitement au Developper Network dApple. Cet enregistrement vous donnera accs ces logiciels, que vous naurez plus qu tlcharger et installer. Nous vous recommandons dailleurs de faire des mises jour de ces logiciels. En effet, les versions les plus rcentes dApache ou de PHP pourraient ne pas se compiler avec des outils trop anciens. Une fois cette installation effectue, lancez un terminal (depuis le Finder, dans le dossier Applications, puis le dossier Utilitaires, choisissez Terminal). Saisissez alors les lignes de commande suivantes :
mkdir install_apache cd /install_apache

Vous crez et entrez dans un rpertoire qui vous servira pour cette compilation.
wget http://www.apache.org/dist/httpd/httpd_XX.tar.gz

Vous tlchargez la dernire version du serveur web Apache directement depuis le site dApple.

74

Installation

gnutar xzf httpd_XX.tar.gz

Vous dcompressez le fichier contenant les sources.


cd httpd_XX

Vous entrez dans le rpertoire qui contient les sources.


./configure --enable-module=most --enable-shared=max

2. Prise en main

Vous crez le fichier de configuration qui servira lors de la compilation.


make

Vous compilez les sources.


sudo make install

Vous installez les excutables sur votre systme. Noubliez pas que cest votre mot de passe quil faut donner au systme pour quil puisse excuter la commande sudo. Dans httpd_XX.tar.gz, les XX sont remplacer par le numro de la version dApache concerne. Noubliez pas darrter puis de relancer votre serveur Apache, comme nous lavons vu plus haut, afin que ce soit cette nouvelle version qui soit en service.

Compiler PHP
Dans un terminal, rentrez les commandes suivantes :
mkdir install_php cd install_php

Vous crez et entrez dans un rpertoire qui vous servira pour cette compilation.
wget http://www.php.net/distributions/php-XX.tar.gz

Vous tlchargez la dernire version du langage PHP directement sur le site de PHP.
gnutar -xzf php-XX.tar.gz

Vous dcompressez le fichier contenant les sources.


cd php-XX.tar.gz

Vous entrez dans le rpertoire qui contient les sources.


./configure --with-apxs=/usr/sbin/apxs --disable-pear

Sans PEAR cest mieux ? Si, comme nous, vous rencontrez des problmes lis la bibliothque PEAR, nhsitez pas utiliser loption --disable-pear. Vous pouvez toutefois essayer sans, histoire de voir si vous tes plus chanceux que nous

75

Chapitre 2

Prise en main

Vous crez le fichier de configuration qui servira lors de la compilation.


make

Vous compilez les sources.


sudo make install

2. Prise en main

Vous installez les excutables sur votre systme.


sudo cp php.ini-dist /usr/local/lib/php.ini

Vous copiez le fichier de configuration de PHP dans un rpertoire o Apache saura le trouver. Noubliez pas que cest votre mot de passe quil faut donner au systme pour quil puisse excuter la commande sudo. Dans php-XX.tar.gz, les XX sont remplacer par le numro de la version du langage PHP concerne. Assurez-vous enfin que votre fichier httpd.conf est bien configur pour permettre Apache dutiliser et dinterprter correctement PHP.

Quelques liens En franais Un tutoriel en franais trs complet et trs bien fait pour installer Apache2 et PHP5 :
www.phpmac.com/articles.php?view189

De nombreuses informations pour les dveloppeurs sous Mac Os X (page PHP) :


http://projectomega.online.fr/contents/fr/php/index.php

En anglais Installer Apache2 et PHP5 sous Mac OS X :


http://laughingmeme.org/archives/001787.html

PHP sur Mac Os X, chez Apple (conseils pour la compilation, modules compatibles, etc.) :
http://developer.apple.com/internet/Mac_OS_X/php.html

Apache et PHP sous Mac Os X par lun des crateurs de Darwin :


http://www.stepwise.com/Articles/Workbench/2001-10-11.01.html

Apache et PHP sous Mac Os X, par Marc Liyanage :


http://www.entropy.ch/software/macosx/php/

Avec IIS
Installer IIS
Linstallation du serveur web IIS est plutt simple. Insrez le CD-ROM dinstallation de Windows NT, 2000 ou XP Pro dans le lecteur de votre machine. Allez dans le menu Dmarrer puis dans Paramtres et Panneau de configuration. Lancez Ajout/Suppression de programmes. Cliquez sur longlet Ajouter/Supprimer des composants Windows, puis cochez la case Services

76

Installation

Internet (IIS), validez par OK. Vous pouvez tester la bonne installation dIIS en ouvrant un navigateur cette adresse : http://localhost/.

Installer PHP
Vous devrez donc utiliser larchive zippe disponible sur le site du groupe PHP (PHP Zip package dans la section Windows Binairies de la section Download du site), ou celle fournie sur le CD-ROM. Une fois que vous avez tlcharg le fichier compress, dcompactez-le sur votre disque dur, dans un dossier spcialement cr cet effet. Sans vouloir vous influencer, c:\php serait une bonne ide (vitez tout particulirement les noms de dossiers avec des espaces). Dans ce dossier, reprez le fichier php.ini-dist, renommez-le en php.ini , et copiez-le dans votre rpertoire Windows (c:\Windows ou c:\WINNT). Une fois le fichier copi, ditez-le avec votre logiciel prfr. Recherchez cette ligne :
; extension_dir=

2. Prise en main

et renseignez le champ avec lemplacement o se trouvent les extensions PHP. Par exemple :
extension_dir=c:\PHP\extensions\

si vous avez install PHP dans un dossier PHP la racine de votre disque dur. Noubliez pas, pour cette ligne et pour toutes les autres, de les dcommenter lorsque vous aurez rentr les paramtres ncessaires. Pour cela, il vous suffit de supprimer le ";" en dbut de ligne. Attention, ne dcommentez que la ligne contenant des paramtres ; laissez les lignes dexplication en commentaire. Recherchez maintenant la ligne :
;browscap=extra/browscap.ini

et donnez ladresse de votre fichier browscap.ini. Sous Windows 9x ou Me, vous le trouverez l : c:\windows\system\inetsrv\browscap.ini et, sous Windows NT, 2000 ou XP Server, il est situ au bout de ce chemin : c:\winnt\system32\inetsrv\browscap.ini. (Cette opration est plus que facultative). Si vous voulez installer dautres extensions, il vous suffit de disposer des DLL requises par celles-ci, et de dcommenter les lignes les concernant dans le fichier de configuration. Une procdure complte est prsente dans le fichier install.txt fourni avec larchive PHP. Cette procdure est galement dcrite pour chaque bibliothque prsente dans ce livre. Une fois que vous en avez fini avec le fichier php.ini, et quil est bien plac la racine de votre dossier Windows, passez la configuration du serveur lui-mme. Il vous faut travailler dans la console dadministration du serveur IIS. Pour cela, allez dans le Panneau de configuration, puis dans Outils dadministration. L, double-cliquez sur Gestionnaire des services Internet. Dans la fentre qui souvre, faites un clic droit sur le serveur web que vous voulez configurer, et choisissez Proprits. (Attention, droulez bien larborescence pour arriver au site web. Ne travaillez pas sur la machine locale.)

77

Chapitre 2

Prise en main

Figure 2.22 : Configuration de PHP pour IIS

2. Prise en main

Cliquez sur longlet Rpertoire de base, puis sur le bouton Configuration. Dans la nouvelle fentre, cliquez sur Ajouter. Dans la nouvelle fentre (Ajout/modification de mappage dextension de fichier), cliquez sur Parcourir, et donnez le chemin vers php4isapi.dll (normalement dans le dossier sapi de votre rpertoire PHP). Dans le champ extension, donnez .php. Vrifiez que la case Moteur de script est bien coche, puis cliquez sur OK pour revenir la console dadministration. Depuis cette mme console, arrtez et relancer votre serveur. Vous pouvez dsormais tester la bonne gestion de PHP. Vous devrez recommencer lopration pour toutes les extensions que le serveur doit interprter comme de PHP (.php3, .phtml, etc.).

Avec iPlanet
Sous Linux
Installer iPlanet
iPlanet sinstalle vite et bien. En plus dtre gratuit, il dispose dune interface web de configuration trs puissante, qui pourra aider les plus novices et qui, pour tous, facilite nombre de tches. Dans bien des situations, cela vite davoir passer par les fichiers de configuration. Nous prsentons ici une installation pour GNU/Linux sur une distribution RedHat. Pour une installation sur un autre systme de type UNIX, reportez-vous aux liens prsents en fin de partie. Pour installer iPlanet, moins que vous ne disposiez de votre propre copie, tlchargez-en une version sur le site de Sun (wwws.sun.com/software/download/download/5126.html). Le serveur est distribu sans contrepartie ; il vous suffit de laisser quelques informations Sun. Pendant que le tlchargement suit son cours, vous allez pouvoir faire quelques petites manipulations prparatoires. La version de iPlanet distribue par Sun pour Linux a t prpare pour une RedHat 6.0. Les autres distributions (hors Mandrake) auront certainement quelques difficults sadapter. Les versions postrieures la 6.0 posent dailleurs un problme assez gnant, puisquelles interrompent carrment le script dinstallation du serveur. En fait, iPlanet demande

78

Installation

la librairie ncurses dans sa quatrime version, alors quaujourdhui, cest la version 5.2 qui est fournie avec les systmes RedHat. Il est possible de tricher en faisant un lien symbolique de la version installe vers une prtendue version 4 ; version qui donnera alors entire satisfaction au script dinstallation. Pour cela, en tant logu en tant que root, rentrez la commande suivante :
ln -s /usr/lib/libncurses.so.5.2 /usr/lib/libncurses.so.4

Pour vrifier quelle est la version de ncurses installe sur votre systme, tapez la commande :

2. Prise en main

locate ncurses

Notez alors le chemin qui saffiche, et utilisez-le dans la commande donne plus haut. Cette manuvre ne met absolument pas en pril le systme dexploitation, pas plus quelle ne compromet le bon fonctionnement du serveur. La librairie concerne nest en effet utilise que lors de la cration de linterface dadministration. Lors de nos tests, cette procdure a parfaitement fonctionn, nentranant aucun dysfonctionnement du serveur, du systme Linux, ni de linterface graphique elle-mme. Une fois le lien cr et le tlchargement termin, vous pouvez passer linstallation du serveur. Avant de vous lancer dans la procdure dinstallation, assurez-vous que vous disposez bien de tous les outils logiciels ncessaires : compilateur, gestionnaire de fichiers compresss, etc. Les utilisateurs de Sun trouveront tout le ncessaire sur le site http://www.sunfreeware.com. Rendez-vous dans le dossier contenant larchive iPlanet et dcompactez-la. Entrez dans le dossier iws qui vient alors dtre cr. En tant quutilisateur root (commande su pour passer en root), lancez le script dinstallation (./setup). Renseignez ensuite tous les champs demands et rpondez aux questions qui restent assez classiques (dossier racine du site, cration dun utilisateur et dun groupe pour le serveur, etc.). Vous pouvez dailleurs choisir entre une configuration express ou une configuration avance. vous de voir ce qui convient le mieux linstallation que vous tes en train deffectuer. Si vous ne destinez pas le serveur une mise en exploitation, autant aller au plus vite. Retenez bien lidentifiant (login) et le mot de passe qui vous sont demands pour laccs linterface de gestion. Une fois iPlanet install, passons la compilation de PHP.

Compiler PHP
Tout dabord, tlchargez la dernire version de PHP sur le site officiel (http://www.php.net), ou bien utilisez celle fournie sur le CD-ROM. Passez en utilisateur root, et vrifiez que les paramtres suivants sont bien situs dans votre PATH (commande echo $PATH). Si elle ny sont pas, ajoutez-les :
:/usr/local/bin:/usr/sbin:/usr/bin:/usr/ccs/bin

Dcompactez larchive :
# tar xzvf php-XX.tar.gz

Rentrez dans le rpertoire cr lors du dcompactage, puis rentrez cette commande :


# ./configure --with-nsapi=/opt/netscape/suitespot/ --enable-libgcc

Le chemin suivant le paramtre withnsapi varie selon votre installation. vous de donner le bon chemin. Sous Linux, ce doit tre quelque chose comme : /usr/iplanet/servers/.

79

Chapitre 2

Prise en main

Si le serveur de base de donnes MySQL est install sur votre machine, vous pouvez galement donner ce paramtre comme option de configuration withmysql=/usr/lib/mysql. Une fois la configuration effectue, rentrez alors la commande :
# make

puis, finalement :

2. Prise en main

# make install

PHP est maintenant install sur votre systme. Vous pouvez passer la configuration du serveur web.

Conguration diPlanet
La configuration du serveur iPlanet se rsume ldition de quelques fichiers de configuration ponctue dun redmarrage dudit serveur. Rendez-vous dans le rpertoire contenant les fichiers de configuration de votre serveur (quelque chose comme /usr/iplanet/servers/ https-localhost.localdomain/config/). Faites attention, ne vous trompez pas entre le dossier https-loalhost.localdomain et le dossier https-admserv. Le premier est le bon ; cest celui qui contient les informations et documents relatifs votre serveur web public. Le second ne concerne que le serveur utilis par linterface web de configuration, Sun ayant offert linterface web son propre serveur (ce qui est plutt une bonne ide quand on sait ce que peut engendrer une mauvaise manipulation des fichiers de configuration). Nayez dailleurs pas peur lors de vos exercices de configuration : il existe dj sur votre machine un rpertoire de sauvegarde qui contient une copie des fichiers de configuration du serveur web. Situ au mme niveau que le dossier config, le dossier config-bk pourra vous sortir de lornire en cas de ppin. Il vous suffira de copier tout simplement son contenu dans le rpertoire config. Commencez dabord par diter le fichier mime.types pour y ajouter la ligne suivante :
type=magnus-internal/x-httpd-php exts=php,php3,php4,php5,phtml

Sauvegardez mime.types, puis passez magnus.conf. Ajoutez les lignes suivantes la fin de la section des inits, en dbut de fichier :
Init fn="load-modules" funcs="php5_init,php5_close,php5_execute,php5_auth_trans" shlib="/php5/nsapiPHP5.dll" Init fn="php5_init" errorString="Linitialisation du PHP a chou !" LateInit="yes"

Le chemin utilis pour shlib varie en fonction du systme dexploitation. Pour Linux, ce sera quelque chose comme /opt/netscape/suitespot/bin/libphp5.so ou /usr/iplanet/servers/bin/libphp5 .so. Donnez simplement le chemin qui pointe vers la librairie PHP 5, prcdemment installe lors de la compilation. Une fois magnus.conf complt, sauvegardez-le, puis ouvrez obj.conf. En suivant le modle et laspect gnral du fichier, ajoutez-y le bloc de texte suivant (un nouvel objet) :
</Object> <Object name="x-httpd-php"> ObjectType fn="force-type" type="magnus-internal/x-httpd-php" Service fn=php5_execute

80

Installation

</Object>

Ensuite, dans lobjet default, vous devrez ajouter la ligne suivante :


Service fn="php5_execute" type="magnus-internal/x-httpd-php"

et ce avant chaque ligne AddLog et aprs chaque ligne ObjectType. Voici un exemple, pris pour une configuration sous Linux :
<Object name=default> NameTrans fn="NSServletNameTrans" name="servlet" NameTrans fn="pfx2dir" from="/servlet" dir="/usr/iplanet/servers/docs/servlet" name="ServletByExt" NameTrans fn=pfx2dir from=/mc-icons dir="/usr/iplanet/servers/ns-icons" name="es-internal" NameTrans fn="pfx2dir" from="/manual" dir="/usr/iplanet/servers/manual/https" name="es-internal" NameTrans fn=document-root root="$docroot" PathCheck fn=unix-uri-clean PathCheck fn="check-acl" acl="default" PathCheck fn=find-pathinfo PathCheck fn=find-index index-names="index.html,home.html" ObjectType fn=type-by-extension Service fn="php5_execute" type="magnus-internal/x-httpd-php" ObjectType fn=force-type type=text/plain Service fn="php5_execute" type="magnus-internal/x-httpd-php" Service type="magnus-internal/jsp" fn="NSServletService" Service method=(GET|HEAD) type=magnus-internal/imagemap fn=imagemap Service method=(GET|HEAD) type=magnus-internal/directory fn=index-common Service method=(GET|HEAD|POST) type=*~magnus-internal/* fn=send-file Service fn="php4_execute" type="magnus-internal/x-htt AddLog fn=flex-log name="access" </Object>

2. Prise en main

Une fois le fichier obj.conf correctement renseign, sauvegardez-le et relancez le serveur web afin quil prenne en compte les dernires modifications (commande ./restart). Vous pouvez alors tester la bonne prise en compte de PHP avec une simple page place la racine de votre serveur web.

Sous Windows
Linstallation et la configuration du serveur web iPlanet sous Windows ne prsentent pas de difficult particulire. Bien que nombreuses, les tapes ncessaires ne sont en rien insurmontables.

Installation du serveur web iPlanet


Tout dabord, tlchargez directement la version Windows du serveur sur le site de Sun (wwws .sun.com/software/download/download/0104.html). Lancez le programme dinstallation. La procdure vous est propose en trois dclinaisons : express, typique ou personnalise. Si cest la premire fois que vous installez iPlanet sur votre machine, choisissez loption typique, qui est largement

81

Chapitre 2

Prise en main

2. Prise en main

suffisante, et qui vous permettra mme de modifier certains paramtres assez pratiques. Premier point important, vous allez devoir choisir un dossier pour linstallation du serveur web. Conservez le chemin propos par le programme dinstallation (vitez le dossier Program Files qui serait pineux utiliser dans des fichiers de configuration). Donnez ensuite un nom dutilisateur et un mot de passe, qui seront utiliss pour linterface dadministration web. Conservez prcieusement ces informations, sans quoi vous seriez un peu gn pour grer votre serveur. Le port dadministration (par dfaut 8888) ainsi que le port web (80) nont pas tre modifis, moins que vous nayez une ide bien spcifique. tape suivante, spcifiez et notez bien le dossier racine du site. Les dernires tapes de prparation de linstallation concernent lutilisation ventuelle dun annuaire LDAP ou de Java. Lorsque vous aurez rpondu toutes ces questions, linstallation proprement dite pourra dbuter. Une fois iPlanet correctement mis en place, vous pouvez tester son bon fonctionnement en rentrant ladresse http://localhost/ dans un navigateur web de votre choix.

Installer PHP
Tlchargez la dernire version de PHP pour Windows zippe sur le site officiel du groupe PHP (http://www.php.net), ou bien utilisez la version disponible sur le CD-ROM. Dcompactez cette archive dans un dossier c:\php, ou dans tout autre dossier simple, facile reprendre pour les ditions de fichiers de configuration venir. Copiez le fichier php4ts.dll ainsi dcompact dans votre dossier Windows (c:\WINNT). Toujours dans le dossier qui a servi pour le dcompactage, trouvez le fichier php.ini-dist, et renommez-le en php.ini. Le changement de nom effectu, ditez ce mme fichier, soit avec votre diteur de texte prfr, soit avec la ligne de commande suivante dans une fentre MSDos :
edit php.ini

Dans ce fichier, recherchez la ligne :


extension_dir = ./

et renseignez-la avec lemplacement sur votre systme du dossier contenant les extensions PHP. Si vous avez dcompact PHP dans un rpertoire c:\php, vous devez remplir la ligne ainsi :
extension_dir= c:\php\extensions\

Sauvegardez le fichier, puis copiez-le la racine de votre rpertoire WINNT :


copy php.ini c:\WINNT\

Il vous faut maintenant crer une association de fichiers pour PHP. Dans une fentre MSDos, rentrez les deux lignes de commande suivantes, en validant par la touche [Entre] chaque fin de ligne :
assoc .php=PHPScript ftype PHPScript=c:\php\php.exe %1 %*

noter que ladresse donne dans la seconde ligne est modifier selon vos propres paramtres. Vous pouvez passer maintenant la configuration du serveur web iPlanet pour quil prenne en compte PHP.

82

Installation

Congurer PHP
Tout dabord, stoppez votre serveur (depuis linterface web de configuration, dans la rubrique on/off). Commencez dabord par diter le fichier mime.types pour y ajouter la ligne suivante :
type=magnus-internal/x-httpd-php exts=php,php3,php4,phtml

2. Prise en main

Sauvegardez mime.types, puis passez obj.conf. Ajoutez les lignes suivantes la fin de la section des inits, en dbut de fichier :
Init fn="load-modules" funcs="php5_init,php5_close,php4_execute,php5_auth_trans" shlib="c:/php/sapi/php5nsapi.dll" Init fn="php5_init" errorString="Linitialisation du PHP a chou !" LateInit="yes"

Le chemin utilis pour shlib varie en fonction de votre installation. Avec lexemple cit plus haut, il faudrait donner ce chemin : c:/php/sapi/php4nsapi.dll. En suivant le modle et laspect gnral du fichier, ajoutez-y le bloc de texte suivant (un nouvel objet) :
</Object> <Object name="x-httpd-php"> ObjectType fn="force-type" type="magnus-internal/x-httpd-php" Service fn=php5_execute </Object>

Ensuite, dans lobjet default, vous devrez ajouter la ligne suivante :


Service fn="php5_execute" type="magnus-internal/x-httpd-php"

et ce avant chaque ligne AddLog et aprs chaque ligne ObjectType (pour un exemple de fichier de configuration, voir la partie Configuration sous Unix). Une fois ces fichiers dits et sauvegards, vous pouvez relancer le serveur web et tester votre nouvelle configuration.

Autres
Installation sous les autres systmes dexploitation Installation sous HP-UX :
www.php.net/manual/fr/install.hpux.php

Installation sous Solaris :


www.php.net/manual/fr/install.solaris.php

Installation sous Unix-OpenBSD :


www.php.net/manual/fr/install.openbsd.php

Tutoriel dinstallation pour PHP sous Windows NT :


http://benoit.noss.free.fr/php/install-php4.html

83

Chapitre 2

Prise en main

2.2.

Le chier de conguration php.ini

PHP se configure en deux fois. Dans un premier temps, lors de sa compilation, pour assurer le support de certaines bases de donnes, dun serveur web sous la forme dun module pour activer certaines fonctions, etc. ; et, dans un second temps, aprs son installation, par ldition et le renseignement du fichier php.ini.

2. Prise en main

Le fichier php.ini contrle bon nombre des comportements de PHP. Pour que PHP puisse lire et comprendre ce fichier, il doit imprativement avoir pour nom php.ini. Au dmarrage, PHP cherche ce fichier dans son rpertoire de travail, dans le chemin dsign par la variable denvironnement PHPRC puis, enfin, dans le chemin dfini lors de la compilation. Sous Windows, le chemin correspond au rpertoire Windows ; sous Linux, par dfaut, il sagit du rpertoire /usr/local/lib. Si PHP a t compil en module, le fichier php.ini ne sera lu quune seule fois, lors du lancement du serveur web. Si PHP fonctionne en CGI, php.ini sera lu chaque utilisation de PHP. Si vous utilisez des constantes dans vos valeurs et que ces constantes appartiennent une extension charge dynamiquement (extension PHP ou Zend), vous ne pouvez utiliser ces constantes quaprs la ligne de configuration qui charge cette extension. Les valeurs utilises dans le fichier php.ini-dist correspondent aux valeurs par dfaut de PHP. Cela veut dire que, si vous nutilisez pas de php.ini ou que vous effacez les lignes qui suivent, les valeurs et paramtres utiliss par PHP seront identiques ceux prsents dans php.ini-dist. Pour crer un fichier php.ini, utilisez le fichier php.ini-dist prsent dans votre rpertoire PHP. Ce fichier contient un squelette de configuration, quil vous appartiendra dadapter votre systme selon vos besoins. Notez quil existe galement un fichier php.ini-recommended, que vous trouverez, lui aussi, la racine de votre dossier PHP. Ce fichier est une recommandation de configuration pense pour vous par les dveloppeurs de PHP. Comme le prcise len-tte du fichier, cette configuration peut rendre PHP incompatible avec certaines applications. Elle rend galement le dveloppement plus difficile et plus rigoureux. Une bonne solution consiste se baser sur ce fichier, en passant en revue toutes les variables pour vrifier si elles conviennent votre environnement de travail. Vous ne modifierez ainsi que le strict ncessaire, tout en conservant une configuration plus sre et plus performante que celle offerte par dfaut par la simple mise en place du php.ini-dist. Dans cette partie, nous allons passer en revue toutes les options prsentes dans le fichier php.ini-dist ; fichier qui, une fois renseign, deviendra votre propre php.ini. La syntaxe du fichier php.ini est simple. Toute ligne commenant par un point-virgule ou toute chane de caractres contenue entre crochets ne sera pas interprte par PHP. Les directives utilisent une syntaxe simple :
directive = valeur

Attention, les noms des directives sont sensibles la casse : respectez donc scrupuleusement lutilisation des majuscules ou minuscules (EMMA est diffrent de Emma). La valeur peut consister en une chane de caractres, un nombre, une constante PHP (ex. : E_ALL ou M_PI), une des constantes INI (On, Off, True, False, Yes, No et None), une expression (ex. : E_ALL & ~E_NOTICE), ou, enfin, une chane de caractres entre guillemets ("emma").

84

Le fichier de configuration php.ini

Dans le fichier php.ini, les expressions sont limites aux oprateurs binaires et aux parenthses :
| & ~ ! binaire binaire binaire booleen OR AND NOT NOT

Les oprateurs boolens peuvent tre activs en utilisant les valeurs 1, On, True ou Yes. Pour les dsactiver, utilisez les valeurs 0, Off, False ou No. Une chane vide peut tre indique soit en ncrivant rien aprs le =, soit en utilisant le mot-cl none. Attention, dans lexpression toto = "none", la chane de caractres ne sera pas vide, mais contiendra le mot none ; une chane vide serait toto = none.

2. Prise en main

Options PHP de base


Balises
short_open_tag = On

permet dutiliser le tag court douverture de script PHP < ? (plutt que < ?php ou <script>).
asp_tags = Off

permet dutiliser les tags ASP <% %>.

Serveur
engine = On

autorise le moteur de langage de script PHP sous Apache.


zend.ze1_compatibility_mode = Off

active le module de compatibilit avec le Zend Engine 1 (utilis dans PHP4.x).


expose_php = On

permet dindiquer que PHP est install sur le serveur, et que, par consquent, on peut lutiliser. Cela ne constitue pas proprement parler un problme de scurit, mais cela signale tout de mme aux utilisateurs que PHP est install sur le serveur.
y2k_compliance = Off

Compatibilit an 2000. Il est dconseill dactiver cette option, car elle pourrait poser des problmes avec des navigateurs non compatibles an 2000.

85

Chapitre 2

Prise en main

Limites des ressources


max_execution_time = 30

Indiquez le temps maximum dexcution des scripts, en secondes (ici : 30 secondes).


memory_limit = 8M

2. Prise en main

Indiquez la quantit maximale de ressource mmoire utilisable par les scripts (ici : 8 Mb).

Scurit
Mode scuris
safe_mode = Off

Activation ou dsactivation du mode scuris.


safe_mode_gid = Off

louverture des fichiers, le mode scuris utilise, par dfaut, des vrifications comparatives des UID. Pour passer des comparaisons sur le GID, activez cette commande.
safe_mode_include_dir =

Si safe_mode est activ, les vrifications des UID/GID sont ignores lorsquun fichier contient des inclusions de fichiers provenant de ce rpertoire ou de ses sous-rpertoires. Le chemin concern doit tre prsent dans le include_path, ou alors cest le chemin complet qui doit tre donn pour linclusion.
safe_mode_exec_dir =

Si le mode scuris est activ, seuls les excutables qui se situent dans le rpertoire renseign ici seront autoriss lexcution via la famille des fonctions excutables (comme exec()).
open_basedir =

Indiquez le chemin du rpertoire sur lequel vous souhaitez limiter les oprations sur les fichiers. Ceci sera valable pour ce rpertoire et ses sous-rpertoires.
safe_mode_allowed_env_vars = PHP_

La configuration de certaines variables denvironnement peut prsenter des failles de scurit. Cette directive comprend une liste de prfixes spars par des virgules. En mode scuris, lutilisateur peut uniquement modifier les variables denvironnement dont le nom commence par les prfixes indiqus ici. Par dfaut, les utilisateurs ne pourront configurer que les variables denvironnement commenant par PHP_ (ex. : PHP_FOO=BAR). Si cette directive est vide, lutilisateur pourra modifier toutes les variables denvironnement !

86

Le fichier de configuration php.ini

Autres
safe_mode_protected_env_vars = LD_LIBRARY_PATH

Indiquez, en les sparant par une virgule, les variables denvironnement que lutilisateur final ne pourra pas modifier en utilisant putenv(). Ces variables seront protges, mme si la directive safe_mode_allowed_env_vars est configure pour que lon puisse les changer.

2. Prise en main

disable_functions =

Indiquez ici, spares par des virgules, les fonctions que vous souhaitez interdire pour des raisons de scurit. Lactivation ou non du mode scuris na aucune influence sur cette directive.
enable_dl = On

Activation ou non de la fonction dl() qui permet de charger des DLL la vole. Cette fonction ne marche pas correctement sur des serveurs multi-tches (multithread) comme, par exemple, IIS ou Zeus, et est automatiquement dsactive sur ces derniers.
cgi.force_redirect = 1
cgi.force_redirect est ncessaire pour apporter de la scurit si lon fait tourner PHP en

tant que CGI sous la plupart des serveurs web. Si vous laissez cette directive vide, PHP linterprtera comme active par dfaut. Il est tout fait dconseill de dsactiver cette directive (hormis sous IIS, pour lequel il vaut mieux lactiver).
cgi.redirect_status_env =

Si cgi.force_redirect est activ, et que vous ne vous trouvez pas sous un serveur Apache ou Netscape (iPlanet), vous devrez dterminer un nom de variable denvironnement que PHP interrogera afin de savoir sil peut ou non continuer lexcution. Ayez une ide prcise de ce que vous souhaitez faire avant de dterminer tout cela, la configuration de cette variable pouvant provoquer des problmes de scurit !
cgi.fix_pathinfo=0

Si cgi.fix_pathinfo est activ , PHP CGI corrigera son chemin pour se conformer aux spcifications. Si vous nactivez pas ce paramtre (en le laissant 0), PHP se comportera comme dans les versions antrieures. Il est conseill dutiliser SCRIPT FILENAME plutt que PATH TRANSLATION.
enable_dl = On

Gestion des erreurs et rcupration des messages derreur


error_reporting est un champ de bits. Vous pouvez dterminer quel type et quel niveau de rapport derreur vous souhaitez rcuprer.

E_ALL

87

Chapitre 2

Prise en main

Toutes les erreurs et avertissements.


E_ERROR

Erreurs fatales du programme.


E_WARNING

2. Prise en main

Avertissements du programme (qui ne sont pas des erreurs fatales).


E_PARSE

Erreurs danalyse lexicale la compilation.


E_NOTICE

Indications du programme. Ce sont des avertissements qui rsultent gnralement dun bug dans votre code, mais il se peut que ce soit intentionnel. Cest le cas, par exemple, si lon utilise une variable non initialise en considrant quelle sera automatiquement initialise par une chane vide.
E_STRICT

Permet PHP de vous indiquer des modifications dans votre code qui assureraient une meilleure inter-oprabilit et une meilleure compatibilit ascendante.
E_CORE_ERROR

Erreurs fatales survenant lors du dmarrage initial de PHP.


E_CORE_WARNING

Avertissements (qui ne sont pas des erreurs fatales) survenant lors du dmarrage initial de PHP.
E_COMPILE_ERROR

Erreur fatale la compilation.


E_COMPILE_WARNING

Avertissement derreur la compilation (qui ne sont pas des erreurs fatales).


E_USER_ERROR

Message derreur provoqu par lutilisateur.


E_USER_WARNING

Message davertissement provoqu par lutilisateur.


E_USER_NOTICE

Message dindication provoqu par lutilisateur. Exemples :


error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT

88

Le fichier de configuration php.ini

Montrer toutes les erreurs, sauf les messages dindication et les messages de qualit de code.
error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR

Ne montrer que les erreurs.


display_errors = On

Active laffichage des erreurs. Pour un site de production, il est conseill de dsactiver cette fonction et dutiliser, sa place, error logging. Si vous gardez display_errors active, vous risquez de rvler des informations de scurit aux utilisateurs finals comme, par exemple, des chemins daccs de votre serveur web, le schma de votre base de donnes, ou dautres informations encore.
display_startup_errors = Off

2. Prise en main

Mme si display_errors est activ, les erreurs qui se produisent lors du dmarrage de PHP ne sont pas affiches. Il est fortement conseill de ne pas activer cette fonction, sauf pour du dbogage.
log_errors = Off

Permet de stocker les erreurs dans un fichier de logs. Sil sagit dun site de production, il est fortement conseill dutiliser cette directive au lieu de error_display.
track_errors = Off

Archive le dernier message derreur ou davertissement dans $php_errormsg.


html_errors = Off

Interdit linclusion de tags HTML dans les messages derreur. Nutilisez pas cette fonction sur des serveurs de production.
error_prepend_string = "<font color=ff0000>"

Chane intgrer avant un message derreur.


error_append_string = "</font>"

Chane intgrer aprs un message derreur.


error_log = filename

Placer les traces derreur dans un fichier particulier. Remplacez filename par le nom du fichier que vous voulez utiliser.
error_log = syslog

Placer les traces derreur dans syslog (Event Log sur Windows NT, non valide sous Windows 95).
define_syslog_variables = Off

Cette directive active ou dsactive la dfinition de diverses variables syslog comme, par exemple, les variables $LOG_PID, $LOG_CRON, etc. Il est conseill de dsactiver cette directive

89

Chapitre 2

Prise en main

dans un souci de performance. Vous pourrez dfinir ces variables dans le programme en faisant appel la fonction define_syslog_variables().
warn_plus_overloading = Off

Prvenir si loprateur + est utilis dans les chanes.

2. Prise en main

Gestion des chiers


Include
include_path =

Indique quels rpertoires doivent tre explors lorsquun fichier est inclus. Sous UNIX, il devra tre donn de cette faon : include_path = ".:/php/includes" et, sous Windows, de la faon suivante : include_path = "c:\php\includes". Vous pouvez en spcifier plusieurs, en les sparant par un deux points (:) sous Linux, et par un point-vigule (;) sous Windows, comme ceci : include_path = "c:\php\includes;c:\php\emma \includes".

Ouverture distante de chiers


allow_url_fopen = On

Active ou dsactive lautorisation de traitement des URL (comme http:// ou ftp://) en tant que fichiers.
from="john@doe.com"

Dfinit le mot de passe anonyme du FTP. Ici, une adresse e-mail sera demande.

Publication de chiers
file_uploads = On

Autorise (ou non) lupload de fichiers HTTP.


upload_tmp_dir =

Indiquez, si besoin, le rpertoire temporaire o vous souhaitez archiver les fichiers HTTP publis (uploads). Si vous ne remplissez pas ce champ, ils seront placs dans le rpertoire temporaire par dfaut du systme.
upload_max_filesize = 2M

Taille maximale autorise des fichiers en upload.

90

Le fichier de configuration php.ini

Gestion des donnes


Depuis PHP 4.0.3, track_vars est toujours activ.
arg_separator.output = "&amp;"

Le sparateur des arguments utilis dans les URL gnres par PHP est, par dfaut, &.
arg_separator.input = ";&"

2. Prise en main

Liste des caractres que doit dtecter PHP pour sparer les arguments dans les URL (par dfaut les caractres & et ;). Chaque caractre est considr, dans cette directive, comme un sparateur.
variables_order = "EGPCS"

Cette directive dcrit lordre dans lequel PHP enregistre les variables passes par les mthodes GET, POST ou Cookie, les variables denvironnement et les variables incluses (respectivement G, P, C, E et S). Cet enregistrement prend en compte les valeurs de gauche droite, les nouvelles valeurs prenant le pas sur les plus anciennes.
register_globals = Off

Cette directive vous permet de choisir si vous enregistrez les variables EGPCS comme des variables globales ou pas. Par mesure de scurit, il est prfrable de laisser ce paramtre Off.
register_long_arrays = On

Cette directive vous permet de continuer utiliser la mthode HTTP_GET_VAR . Si vous nutilisez pas cette mthode (en prfrant la mthode $_GET["Varaible"]), il est prfrable de ne pas activer la directive pour optimiser les performances.
register_argc_argv = On

Cette directive dfinit si PHP dclare les variables argv et argc (qui pourraient contenir les informations GET). Si vous nutilisez pas ces variables, vous pouvez dsactiver cette directive pour amliorer les performances.
post_max_size = 8M

Taille maximale des donnes POST que PHP acceptera.

Les magic quotes


Les magic quotes sont des directives qui vous permettent dchapper les caractres qui pourraient provoquer des erreurs dans votre code. Par exemple, une apostrophe, un slash, etc. dans une variable issue dun formulaire qui pourraient tre interprts comme une fin de chane ou autre caractre interprt par PHP :
<form action="recupere.php"> <input type="hidden" name="exemple" value="Laventure cest laventure !"> <input type="submit"> </form>

91

Chapitre 2

Prise en main

Puis, laide de ce script :


<?php echo $_GET["exemple"]; ?>

2. Prise en main

vous rcuprez les donnes contenues dans recupere.php. Si les magic quotes sont actives, vous obtenez ceci : L\aventure c\est l\aventure ! Sans les magic quotes, nous avons ceci :
<?php echo $_GET["exemple"]; ?>

Laventure cest laventure !


magic_quotes_gpc = On

Active les magic quotes pour les donnes entrantes GET, POST et Cookie.
magic_quotes_runtime = Off

Dsactive les magic quotes pour les donnes gnres par le programme (ex. : donnes SQL, donnes provenant des fonctions exec(), etc.).
magic_quotes_sybase = Off

Si cette directive est active, des apostrophes seront utilises en lieu et place des "backslashes" pour les magic quotes (style Sybase, cest--dire au lieu de \).

Sessions
session.save_handler = files

Il sert redfinir la manire dont seront gres les sessions. Par dfaut, les sessions sont enregistres dans des fichiers. Cest grce ces fichiers que PHP retrouvera les donnes dune session. Si vous souhaitez une gestion personnalise des sessions indiquez alors "user" (voir chapitre sur les sessions).
session.save_path = /tmp

Rpertoire par dfaut o stocker les sessions. Il vaut mieux viter que ce rpertoire soit lisible par tous, auquel cas la scurit du site pourrait tre compromise. Quelquun pourrait usurper lidentificateur dun autre. Par dfaut, il vaut /tmp. Il faut donc imprativement modifier ce paramtre pour pouvoir faire fonctionner les cookies sous Windows.
session.use_cookies = 1

Permet dindiquer si le gestionnaire de sessions doit utiliser un cookie chez le client pour mmoriser lidentifiant de session. Par dfaut lutilisation de cookies est active (valeur 1).

92

Le fichier de configuration php.ini

session.name = PHPSESSID

Nom de lidentifiant de la session. Il ne contient que des caractres alphanumriques.


session.auto_start = 0

Indique si une session doit automatiquement tre lance lors de la premire requte. Cette option est dsactive par dfaut (valeur 0).

2. Prise en main

session.cookie_lifetime = 0

Permet de dfinir la dure de vie du cookie de session (en secondes). La valeur 0 (par dfaut) signifie que le cookie doit tre effac la fermeture du navigateur.
session.cookie_path = /

Permet de dfinir le chemin utiliser par les cookies. Par dfaut, il est mis /.
session.cookie_domain =

Permet de dfinir le domaine sur lequel est restreint le cookie.


session.serialize_handler = php

Permet de dfinir le gestionnaire de la srialisation/dsrialisation. Les formats PHP et WDDX sont supports, WDDX ntant disponible que si PHP a t compil avec WDDX.
session.gc_probability = 1

Permet de dfinir la probabilit dexcution de gc (garbage collector) chaque requte. gc est le dispositif permettant de supprimer les sessions qui ne sont plus valides. Gnralement, les sessions sont enregistres sous forme de fichiers, et gc se charge de supprimer les fichiers prims. Par dfaut, gc est requis chaque appel (la valeur vaut 1).
session.gc_maxlifetime = 1440

Aprs ce laps de temps (en secondes), une donne sera considre comme prime et pouvant tre supprime par gc.
session.referer_check =

Permet de ne valider une session que si lutilisateur provient dun site en particulier (typiquement le vtre). Il suffit de renseigner tout ou partie du nom de domaine. Si cette chane de caractres est contenue dans le HTTP_REFERER fourni par le navigateur, ou si cette valeur retourne est vide, alors la session est valide. Par dfaut, cette chane de caractres est vide.
session.entropy_file =

Permet de dfinir le chemin vers un fichier externe qui sera utilis pour gnrer (de faon pseudo-alatoire) un identifiant de session. Dans le monde UNIX, il est possible de dfinir /dev/random ou encore /dev/urandom.
session.entropy_length = 0

Permet de dterminer le nombre doctets lus dans le fichier dclar par session .entropy_file. Par dfaut, celui-ci tant dsactiv, il vaut 0.

93

Chapitre 2

Prise en main

session.cache_limiter = nocache

Permet de dfinir len-tte de contrle du cache qui doit tre envoy avec chaque script gnr partir de variables de sessions. Il peut tre dfini comme none, nocache, private, private_no_exprire ou public.
session.cache_expire = 180

2. Prise en main

Permet de dfinir len-tte dfinissant la dure de validit (en minutes) dune page gnre partir de variables de sessions. Cette option na aucune influence si le contrle du cache a t mis nocache.
session.use_trans_sid = 1

Permet dindiquer si lidentifiant de session doit tre transmis de manire transparente de page en page (URL rewriting). (Pour les versions PHP<=4.1.1, cette option est utilisable uniquement si PHP a t compil avec loption --enable-trans-sid). Par dfaut, cette option est active.
session.hash_function = 0

Dfinit le format de hash. 0 pour MD5 (128 bits) ou 1 pour SHA-1 (160 bits)..
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"

Permet de dfinir quelles URL seront rcrites afin de transmettre lidentifiant de session, si loption session.use_trans_sid est active. Par dfaut, ce sont les tags a=href, area=href, frame=src, input=src, form=fakeentry.

Gnration du document
Cache et compression
output_buffering = Off

La mise en tampon (ou mmoire cache) vous permet de nenvoyer le document gnr quune fois le script termin. Cela permet notamment denvoyer des en-ttes (instructions de manipulation des sessions et des cookies y compris), mme aprs avoir commenc gnrer la page. Mais, en contrepartie, cela ralentit la couche de sortie de PHP. Si vous voulez limiter le tampon une certaine taille, vous pouvez spcifier une taille en octets la place du On (ex. : output_buffering=4096).
output_handler =

Cette option permet dappliquer une fonction (typiquement de compression) sur le document gnr avant de lenvoyer au client. Par exemple, si vous configurez output_handler vers ob_gzhanler, la sortie sera compresse pour les navigateurs qui supportent Gzip. Si vous entrez un nom de fonction pour output_handler, cela activera automatiquement la mise en cache des sorties.
zlib.output_compression = Off

94

Le fichier de configuration php.ini

Cette directive permet la compression des sorties laide de la bibliothque Zlib. Les valeurs que vous pouvez indiquer pour cette commande peuvent tre On, Off ou une taille spcifique de tampon utiliser pour la compression (la taille par dfaut est 4 Kb). Attention : output_handler doit tre vide si cette directive est active.
implicit_flush = Off

Implicit flush demande PHP de vider les tampons de sortie ds quun lment du document est gnr. Ceci est quivalent lappel de la fonction flush() aprs chaque commande echo() ou print() et aprs chaque bloc HTML. Si vous activez cette fonction, vous rduirez vos performances. Cette option est conseille dans des objectifs de dbogage.

2. Prise en main

lments par dfaut


auto_prepend_file =

Pour ajouter automatiquement un fichier avant un document PHP.


auto_append_file =

Pour ajouter automatiquement un fichier aprs un document PHP.


default_mimetype = "text/html" default_charset = "iso-8859-1"

Spcifie le type du document et lencodage. Sachant que depuis PHP 4.0b4, PHP envoie par dfaut un en-tte prcisant lencodage. Si vous ne voulez pas le prciser, vous devrez, ici, mettre une chane vide. Par dfaut, sil nest pas prcis ici, le type du document est text/html.

Gestion de laffichage
Nombres dcimaux
precision = 12

Indiquez le nombre de dcimales aprs la virgule que vous souhaitez afficher.

Source
Couleurs pour la coloration syntaxique de votre code. Indiquez les codes couleurs qui vous conviennent :
highlight.string = #CC0000

pour une chane de caractres ;


highlight.comment = #FF9900

pour un commentaire ;
highlight.keyword = #006600

95

Chapitre 2

Prise en main

pour un mot-cl ;
highlight.bg = #FFFFFF

pour le fond ;
highlight.default = #0000CC

2. Prise en main

par dfaut ;
highlight.html = #000000

pour le html.

Extensions dynamiques
extension_dir = ./

Indiquez le chemin du rpertoire dans lequel se trouvent les extensions (modules) chargeables. Si vous souhaitez quune extension soit charge automatiquement, utilisez la syntaxe suivante :
extension=modulename.extension

Par exemple, pour Windows :


extension=php_gd.dll

ou, sous UNIX :


extension=php_gd.so

Notez que vous ne devez indiquer que le nom du module, et non pas les informations concernant le chemin du rpertoire (ce dernier doit obligatoirement tre celui spcifi par extension_dir).

Conguration des extensions


BcMath
bcmath.scale = 0

Prcision avec laquelle BcMath doit travailler (nombre de chiffres aprs la virgule souhaits).

Bases de donnes
sql.safe_mode = Off

Active ou non le mode scuris pour les bases de donnes. Il existe de nombreux autres paramtres pour les bases de donnes. Ceux-ci seront voqus dans les chapitres correspondants.

96

Les diteurs et dbogueurs PHP

Sockets
sockets.use_system_read = On

Utilise la fonction systme read() au lieu de la fonction programme php_read().

Divers
Browscap
browscap = extra/browscap.ini

2. Prise en main

Chemin vers le fichier browscap.ini contenant les informations qui permettent de dduire les caractristiques des navigateurs daprs leur HTTP_USER_AGENT.

2.3.

Les diteurs et dbogueurs PHP

Dans le monde de la programmation, les diteurs de texte font office de religions. On en utilise un comme on choisit une glise. Comme les religions, les diteurs connaissent leurs guerres. Lune des plus clbres oppose les partisans de Vi aux zlateurs dEmacs. Tout a t dit : "Emacs rend beau", "Vi fait repousser les cheveux", etc. En cherchant bien, on peut mme trouver sur le Web un mmo sur les diffrents diteurs de texte, rdig pour une universit canadienne, commenant par cette citation : "Papa, pourquoi nous cachons-nous de la police ? - Ils utilisent Emacs, fils, et nous utilisons Vi." Les adeptes dun diteur en particulier ressentent, gnralement, le besoin de prouver que le leur est le meilleur, le plus beau, le plus complet. Cela entrane immanquablement de folles discussions fort peu constructives, mais folkloriques, voire divertissantes. Mais le dbutant en qute de conseils ne sy retrouve pas pour autant. On peut tout de mme regrouper les diteurs en diffrentes grandes familles, pour ensuite comparer leurs avantages et inconvnients respectifs. Il nest pas opportun de comparer Emacs Dreamweaver MX. En revanche, mettre face face PHPEdit et Komodo prsente un intrt. Sur le CD-ROM, vous trouverez un tableau comparatif des diffrents diteurs ainsi que quelques fiches descriptives. Les gots et attentes de chacun interviennent beaucoup dans le choix dun diteur. Le contexte de dveloppement de PHP joue galement. Si cest pour un projet isol, le programmeur pourra choisir librement ; si, en revanche, il doit travailler en troite collaboration avec un graphiste, un logiciel comme Dreamweaver MX sera plus appropri. Pour mettre sur pied une architecture complexe imbriquant de multiples pages en PHP, une solution comme Zend Studio ou Maguma rendra de bien meilleurs services. Les outils les plus puissants ne doivent pas faire oublier quun site peut tre dvelopp avec un simple bloc-note (bien moins gourmand en mmoire et CPU). Ce nest pas lditeur qui fait le dveloppeur. Les assistants les plus pousss et conviviaux ne remplaceront pas une bonne connaissance du langage.

97

Chapitre 2

Prise en main

Nous avons class les diteurs en diffrentes catgories. Nous savons que ces catgories seront coup sr critiques par les partisans de lun ou lautre des logiciels prsents, mais cest un mal ncessaire
j

2. Prise en main

Lartillerie lourde, ce sont ces diteurs qui intgrent PHP toute une solution de dveloppement web. Rsolument tourns vers PHP, il leur faut une plateforme assez muscle pour fonctionner, et ils nont pas t penss pour le dveloppeur solitaire, coinc entre pizza et CVS. Ils permettent souvent un travail collaboratif pouss, qui place lditeur au centre dune architecture incluant un serveur web et un serveur de bases de donnes. Leur prix souvent lev les met hors de la porte des programmeurs isols. Les spcialistes, ce sont des diteurs PHP purement PHP. Ils ont t dvelopps pour ce langage de script en particulier. tant donn quils sont assez nombreux, nous ne prsentons ici que ceux que nous avons jugs pertinents en fonction de critres jugs primordiaux par plusieurs dveloppeurs. Nous traitons enfin, dans une partie spare, Dreamweaver et GoLive, deux logiciels de cration de sites web qui grent dsormais PHP, mais qui restent tout de mme en de de ce quoffrent les diteurs spcialiss.

Nos plus vifs remerciements vont Stphane Pineau, auteur dun comparatif dditeurs PHP, qui nous a permis de reproduire ici en grande partie son travail (par ailleurs disponible ladresse http://steph.pineau.free.fr/php/index.php?LNK=EDIT/). Nous vous conseillons dailleurs daller consulter cette page rgulirement pour vous tenir jour des dernires mises jour dditeurs. Vous pourrez galement y effecuter des recherches multicritres pour choisir lditeur qui vous convient le plus.

Lartillerie lourde
Zend Studio

Figure 2.23 : Zend Studio

98

Les diteurs et dbogueurs PHP

Tableau 2.1 : Zend Studio


Zend Studio diteur Langues Plateformes Langages supports Prix URL version 3.5.1 Zend Technologies Ltd. Anglais, allemand, franais, hollandais, espagnol, italien, coren. Windows, Linux, MacOSX. PHP, HTML. 249 $US.
www.zend.com

2. Prise en main

Principales fonctionnalits et commentaire Lditeur offre toutes les fonctions de base ncessaires : compltion du code PHP et HTML, compltion galement pour les variables, liste des fonctions disponibles dans un fichier, visualisation des fichiers en includes, coloration syntaxique, dition du mme fichier depuis diffrentes fentres, dition de fichiers depuis un serveur FTP, etc. Le dbogage est possible en local, et galement en direct sur des serveurs distants. Cela permet ainsi de contrler lexcution de PHP sur les serveurs de production. Le dbogueur intgr est particulirement performant. La suite Zend inclut galement un centre dadministration pour configurer et administrer les serveurs, ainsi quune application daide complte et fonctionnelle. On remarque aussi la prsence du Zend Optimizer, logiciel optimisant le code PHP et permettant lexcution de code camoufl (obfusqu). Il supporte la version 5 de PHP. Au rang des dernires nouveauts, on trouve les templates de code, personnalisation des schmas de coloration, dbogage actif ou passif, transmission scurise des fichiers (publication par SFTP et FTP sur SSH). Certainement lune des solutions les plus abouties et les plus compltes pour la cration dapplications en PHP.

Maguma Studio

Figure 2.24 : Maguma Studio

99

Chapitre 2

Prise en main

Tableau 2.2 : Maguma Studio


Maguma Studio diteur Langue OS Langage support Prix URL version 1.3.2 Maguma. Anglais. Windows. PHP. 69 5 pour lditeur. Existe une version gratuite limite.
www.maguma.com

2. Prise en main

Principales fonctionnalits et commentaire La plateforme Maguma intgre, en plus dun diteur puissant, toute une architecture de travail en commun, allant du client au serveur en passant par une interface dadministration gnrale. Lditeur offre la numrotation des lignes, la coloration syntaxique, une dition multi-fichiers, une aide PHP intgre, une aide MySQL intgre, une aide HTML intgre, un gestionnaire de fichiers, un gestionnaire FTP, un visualiseur HTML interne, une visualisation/excution depuis lditeur, un dbogueur interne ou externe, un explorateur de code PHP, linsertion assiste de code HTML, linsertion assiste de code CSS, linsertion assiste de code PHP, lauto-compltion PHP, la gestion des abrviations (code template), le commentaire des fonctions/classes, la recherche des paires []{}() et le RegExp en mode recherche.

NuSphere PHPEd

Figure 2.25 : NuSphere PHPEd

100

Les diteurs et dbogueurs PHP

Tableau 2.3 : NuSphere PHPEd


NuSphere PHPEd diteur Langue Plateformes Langages supports Prix URL version 3.3 NuSphere. Anglais. Windows, Linux, Solaris PHP, HTML. 299 $US.
www.nusphere.com/products/phpadv.htm

2. Prise en main

Principales fonctionnalits et commentaire Ajout de code depuis des modles, dbogueur de code, interfaage avec des serveurs de bases de donnes (support en natif de PostgreSQL), gestion de projets, connexion en FTP, FTPS, WebDAV/HTTPS, gestion du travail en quipe, dbogage de sessions, optimisation du code, etc. PhpED offre une compltion automatique du code qui supporte la programmation oriente objet. Le "PHP Profiler" intgr vous aide dans votre dveloppement et permet de constater sa progression et loptimisation de son code. Des fonctionnalits originales pour une solution vraiment complte.

Les spcialistes
Tous les diteurs prsents ici ont un dbogueur intgr, lexception de Jext qui compense ce manque par une kyrielle de fonctionnalits et dadd-on.

Komodo

Figure 2.26 : Komodo

101

Chapitre 2

Prise en main

Tableau 2.4 : Komodo


Komodo diteur Langue Plateformes Langages supports Prix version 3 ActiveState. Anglais. Windows et Linux. C, C++, Diff, Eiffel, HTML, Java, Javascript, Latex, Lisp, PHP, Pascal, Perl, Python, tcl, vb, XML, XLT, etc. La version 1.1 est gratuite dans le cadre dune utilisation en milieu enseignant, ou vise ducative. La version 1.2 est tlchargeable en valuation pour 21 jours, puis payante. De 29,5 $US 296 $US selon les types de licences.
www.activestate.com/Products/Komodo/

2. Prise en main

URL

Principales fonctionnalits et commentaire Numrotation des lignes, coloration syntaxique, multi-fichiers, aide PHP intgre, aide MySQL intgre, aide HTML intgre, gestionnaire de projets, gestionnaire de fichiers, gestionnaire de favoris, gestionnaire FTP, liste de "reste faire" (todo), rechargement automatique des derniers fichiers, visualiseur HTML interne, visualisation/excution depuis lditeur, dbogueur interne ou externe, macros, explorateur de code PHP, explorateur de code HTML, insertion assiste de code HTML, insertion assiste de code CSS, insertion assiste de code JavaScript, insertion assiste de code PHP, insertion code template, auto-compltion PHP, gestion des abrviations (code template), commentaire des fonctions/classes, recherche des paires []{}(), indentation / dsindentation de blocs, commentaire de blocs, partage de la fentre ddition, RegExp en mode recherche, archivage des fichiers/projets, slecteur de couleurs. Dvelopp autour du navigateur Mozilla auquel il sintgre et de lditeur Scintilla. Un petit module permet de tester ses expressions rgulires avec visualisation du rsultat en temps rel. Possibilit de cacher le code des classes, fonctions et blocs (outlining). "Debug" pour Perl, Python, PHP et XSLT. Affichage des paramtres requis lors de lutilisation dune fonction. Rechargement des derniers fichiers, gestionnaire FTP. La version comporte son lot damliorations et dajouts de fonctionnalits (dont le support de PHP5). La liste des nouveauts est consultable cette adresse : http://aspn.activestate.com/ASPN/docs/Komodo/3.0/relnotes.html#New_Features.

102

Les diteurs et dbogueurs PHP

PhpCoder

2. Prise en main

Figure 2.27 : PhpCoder

Tableau 2.5 : PhpCoder


PhpCoder diteur Langue Plateforme Langage support Prix URL version R2 Prerealese 3 phpIDE.de. Anglais. Windows. PHP. Gratuit.
www.phpide.de

Principales fonctionnalits et commentaire Numrotation des lignes, coloration syntaxique, multi-fichiers, aide PHP intgre, aide MySQL intgre, gestionnaire de projets, visualiseur HTML interne, visualisation/excution depuis lditeur, dbogueur interne ou externe, insertion assiste de code HTML, lauto-compltion PHP. Un clone de PHPEd quasi conforme, mais qui ncessite encore quelques amliorations.

103

Chapitre 2

Prise en main

PHPEdit

2. Prise en main

Figure 2.28 : PHPEdit

Tableau 2.6 : PHPEdit


PHPEdit diteurs Langue Plateforme Langage support Prix URL Version 1.0.3.68 Waterproof SARL Anglais, franais, allemand, espagnol. Windows et Linux. PHP. Gratuit pour une utilisation personnelle, version professionnelle 75 5 HT (Open Source).
www.phpedit.com

Principales fonctionnalits et commentaire Rest longtemps la version 0.6, PHPEdit a tenu ses promesses et combl ses lacunes de jeunesse. Il est disponible en franais avec une documentation complte et de trs nombreuses fonctionnalits. Les dernires versions ont apport un gnrateur daide, des raccourcis personnalisables, plus de 100 commandes scriptables, le mappage de clavier personnel, un gestionnaire de todo. Lditeur offre galement : numrotation des lignes, coloration syntaxique, multi-fichiers, aide PHP intgre, aide MySQL intgre, aide HTML intgre, gestionnaire de fichiers, visualisation/excution depuis lditeur,

104

Les diteurs et dbogueurs PHP

PHPEdit

Version 1.0.3.68

dbogueur interne ou externe, explorateur de code PHP, insertion assiste de code PHP, gestion des abrviations (code template), commentaire des fonctions/classes, indentation/dsindentation de blocs, commentaire de blocs, RegExp en mode recherche Lexplorateur de code est excellent ; il spare bien les fonctions et classes de chaque fichier, et hirarchise correctement les mthodes des classes. Apprciable galement : la fonction dautocomment des classes et fonctions. Le systme dinsertion assiste de code PHP, similaire celui du VBA, est agrable (plus que celui de PHPEd), et laffichage des paramtres requis dune fonction native par simple placement du curseur entre parenthses est vraiment pratique. On apprcie galement la possibilit dimprimer avec les numros de lignes et la mise en valeur des mots-cls. Un petit gestionnaire de copier/coller fonctionnant en drag and drop est intressant. Sil tait possible de lintgrer en tant que panneau latral plutt que de le laisser en fentre libre, ce serait encore plus pratique. Dommage quaucun choix de langue ne soit propos, dautant quil sagit dune production franaise. Labsence de toute documentation est vraiment pnible, car nombre de petits gadgets assez droutants de prime abord mriteraient une aide un peu plus substantielle.

2. Prise en main

SciTE

Figure 2.29 : SciTE

105

Chapitre 2

Prise en main

Tableau 2.7 : SciTe


SciTE diteur Langues Plateformes Langages supports Prix URL version 1.61 Neil Hodgson. Anglais, Franais, Allemand. Windows et Linux. C, C++, C#, Eiffel, Java, Js, Latex, Lisp, Pascal, Perl, Php, Python, Sql, Vbscript, XML, etc. Gratuit (Open Source).
www.scintilla.org

2. Prise en main

Principales fonctionnalits et commentaire Numrotation des lignes, coloration syntaxique, multi-fichiers, gestionnaire de projets, rechargement automatique des derniers fichiers, visualisation/excution depuis lditeur, dbogueur interne ou externe, macros, insertion assiste de code PHP, auto-compltion PHP, gestion des abrviations (code template), recherche des paires []{}(), commentaire de blocs, RegExp en mode recherche. Lditeur offre galement la recherche dans des fichiers non ouverts. Peut se placer en mode rduit dans la barre des tches. Il ne pse que 500 Ko avec sa DLL. On peut zoomer et dzoomer du code en cours ddition. Permet de masquer laffichage (outlining) logique des blocs dun texte (HTML) ou dun script. On peut donc masquer le corps des fonctions (dun bloc If/end, par exemple) dun simple clic (ou par [Ctrl]+[*]). On peut ainsi obtenir le squelette dun script en naffichant plus que le nom des classes, les fonctions et les commentaires. Il est galement possible deffectuer une inversion rapide des lignes (ligne courante avant la suivante). Lditeur se configure via des fichiers, ce qui est un peu lourd. La configuration par dfaut est plutt restreinte ; nombre de possibilits ne sont pas visibles de prime abord. Les fichiers pour le franais ne sont pas inclus dans larchive, mais on peut les rcuprer sur : www.scintilla.org/locale.fr.properties. Le chargement en mmoire est quasi instantan sur un PIII 533 MHz, ce qui est loin dtre le cas de bien des diteurs. On ne trouve pas de macros ni de gestion de projets en natif, mais ce manque est compens par un add-on FilerX. Il nexiste pas dexplorateur de code. Trop de fonctions intressantes sont dsactives par dfaut. Lisez bien la documentation pour connatre toutes les possibilits de paramtrage. Cest vraiment lditeur ne pas manquer pour sa lgret et sa puissance, dautant que les sources fournies (projet Scintilla) permettent de greffer ses propres fonctions. Cest dailleurs lditeur qui est intgr dans Komodo. Voici quelques "trucs" pour activer des fonctions intressantes. Pour activer loutlining, il faut dcommenter la ligne fold.html=1 dans le fichier html.properties, et la ligne fold=1 dans le fichier sciteglobal.properties. Dans ce dernier, vous pouvez galement mettre la valeur 0 la ligne fold.symbol. Pour afficher les numros de lignes, il faut dcommenter la ligne line.number dans le fichier sciteglobal.properties, et lui mettre une valeur de 30. Pour pouvoir ouvrir plusieurs fichiers, il faut dcommenter la ligne buffers dans le fichier sciteglobal.properties, et lui mettre la valeur de 10 par exemple.

106

Les diteurs et dbogueurs PHP

Jext

2. Prise en main

Figure 2.30 : Jext

Tableau 2.8 : Jext


Jext diteur. Langues. Plateformes Langages supports Prix URL version 5 Romain Guy. Franais, anglais. Java (multi-plateforme). Ncessite JRE 1.301 ou JDK 1.2. PHP, ASM, ASP, C, C#, C++, Eiffel, HTML, XML, Java, Perl, Python, Sql, Shell scripts, etc. Gratuit (OpenSource).
www.jext.org

Principales fonctionnalits et commentaire Numrotation des lignes, coloration syntaxique, multi-fichiers, gestionnaire de projets (add-on), gestionnaire de fichiers, gestionnaire de favoris, gestionnaire FTP (add-on), rechargement automatique des derniers fichiers, explorateur de code PHP, insertion assiste de code HTML, insertion assiste de code PHP, auto-compltion PHP, gestion des abrviations (code template), recherche des paires []{}(), indentation/dsindentation de blocs, commentaire de blocs, RegExp en mode recherche.

107

Chapitre 2

Prise en main

Jext

version 5

Avec ses add-on, cet diteur est particulirement intressant. Il offre ainsi un systme de bureau, cest--dire une liste de fichiers ouverts faisant partie, par exemple, dun mme programme. Il est possible de crer plusieurs bureaux, et donc de disposer dun gestionnaire de projets basique mais efficace. Un add-on "Wapppaaa" permet douvrir en une opration lensemble des fichiers contenus dans un rpertoire et ses sous-rpertoires. Ladd-on Xinsert permet de grer ses code template de manire hirarchique, et cela pour chaque langage voulu. Il autorise linclusion automatique du texte slectionn dans le template choisi. Ladd-on FindAll permet, en double-cliquant sur un mot, et en appuyant sur [Ctrl] + [F3], dobtenir toutes ses occurences dans une liste slectionnable ; cest trs utile pour trouver les occurrences dune variable ou dune fonction. Les recherches sont, de plus, mmorises. Ladd-on ProjectMaster remplacera utilement le gestionnaire de projets CodeMaster fourni par dfaut, car il sintgre directement dans le panneau latral. Bien que plutt ax Java, il peut tre utilis en PHP. Jext dispose dun langage de script intgr, Dawn. On apprciera galement le systme One Clic : il suffit de slectionner une commande de ce menu, par exemple Ajouter un commentaire simple, puis de cliquer sur chaque ligne que lon veut commenter, et cest tout. La commande slectionne sapplique chaque ligne clique tant que loption One Click nest pas arrte. Ladd-on Code2Html transforme le fichier en cours (ou la slection) en fichier HTML, tout en conservant la coloration syntaxique. Idal pour publier le code source dun langage quelconque de manire attrayante. De nombreux autres add-on sont disponibles : console systme, skins, impression avec numros de lignes, tri de lignes... En bref : cest un excellent diteur. Il nest pas inutile de lire la documentation (en franais ou en anglais) pour tirer parti de toutes ses possibilits.

2. Prise en main

Le choix des auteurs titre purement indicatif, les auteurs de cette Bible utilisent, par ordre de pagaille : Vi, Emacs, Nedit, Wordpad, le bloc-notes ou encore UltraEdit pour programmer en PHP. Vous le voyez, aucun diteur spcialis... Comme quoi, ce nest (dcidment !) vraiment pas lditeur qui fait le dveloppeur.

Dreamweaver et GoLive
Au dpart, ce sont des outils de cration de sites web destins aux graphistes et webmestres Aujourdhui, et tout particulirement dans les dernires versions, les deux diteurs supportent particulirement bien PHP. On peut, par exemple, facilement crer des pages contenant des objets en PHP en puisant dans des bibliothques prtes lemploi. Les deux diteurs ont intgr le travail avec des bases de donnes (GoLive est vendu avec Apache, PHP, JSP et MySQL). Sans aller jusquau serveur de dbogage de Zend, installer directement sur les machines de production, Dreamweaver et GoLive ont dpass le simple stade du "wysiwyg" (what you see is what you get ou, vous voyez ce que vous avez). Les deux logiciels disposent dune composante de travail collaboratif. Il est mme possible de travailler avec Webdav, ou mme davoir une gestion centralise du code source. Lintrt des logiciels de cration de sites web dans le cadre dun dveloppement en PHP reste limit. Si une page contient uniquement un dveloppement original en PHP, il sera inutile daller lditer dans Dreamweaver. De mme, quel intrt peut-il y avoir dvelopper toute une application en PHP dans un logiciel comme GoLive, largement plus performant dans le Webdesign ?

108

Les diteurs et dbogueurs PHP

Dans une optique PHP, Dreamweaver et GoLive restent de trs bons outils dintgration finale et dhabillage des dveloppements en PHP. Un meilleur support de PHP reste un point positif. Cela signifie, par exemple, quun graphiste aura plus de souplesse pour travailler une page contenant du code PHP.

Quelques site dditeurs Document traitant des diteurs, rdig pour luniversit McGill au Canada :
www.cs.mcgill.ca/~navindra/editors/

2. Prise en main

Vi :
http://vim.sourceforge.net/

Emacs :
www.gnu.org/software/emacs/emacs.html

UltraEdit :
www.ultraedit.com/

Pages personnelles de Stphane Pineau Dictionnaire francophone des acronymes informatiques :


www.teaser.fr/~spineau/acrodict/index.htm

Script PHP 3 gratuits (forum, gestionnaires BDD, etc.) :


http://steph.pineau.free.fr/php/index.php3

109

Chapitre 3

Le langage PHP
3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 Intgrer le code PHP au HTML Les commentaires . . . . . . . . Les constantes . . . . . . . . . . Les variables . . . . . . . . . . . Les oprateurs . . . . . . . . . . Les structures de contrle . . . Les fonctions . . . . . . . . . . . Les tableaux . . . . . . . . . . . . Les inclusions de chiers . . . Les classes, les objets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 116 117 118 140 148 158 174 206 216

Intgrer le code PHP au HTML

3.1.

Intgrer le code PHP au HTML

Comme cela a dj t dit dans lintroduction, le langage PHP est un langage de script qui sinsre dans des pages HTML, et les parties crites en langage PHP sont dclares au moyen de balises reconnues par le serveur. Le code PHP scrit donc avec un diteur de texte et lutilisation des diteurs "wysiwyg" (what you see is what you get) sarrte lorsque lcriture du langage PHP commence.

Vous pouvez vous reporter la section "Les diteurs" pour choisir le vtre. 3. Le langage PHP

Le principe de fonctionnement de PHP est assez simple : le serveur va effectuer un travail dinterprtation avant de retourner le rsultat (gnralement une page HTML) au client (classiquement un navigateur Internet). Lavantage par rapport lHTML est alors considrable, puisquil est ainsi possible de concevoir des sites dits dynamiques. Cest--dire que, dune fois sur lautre, une page peut changer de contenu sans quaucune intervention humaine ne soit ncessaire. Prenons le cas dun forum : il est souhaitable que, ds quune personne soumet une question, celle-ci soit disponible sur le site. Cest un cas typique dutilisation dun site Internet dynamique. Le langage PHP permettra alors de crer une page HTML partir de ce message (et des autres messages disponibles dans la base de donnes). Il faut toujours garder lesprit que cest un langage de script qui est excut ct du serveur ; il ne dpend donc ni du navigateur ni du systme dexploitation du visiteur. Lavantage est indniable puisque ce langage permet, partir dinformations de nature diffrente, (base de donnes, heure actuelle, configuration du client, etc.) denvoyer des pages dont on peut tre sr quelles seront comprhensibles par le navigateur du client ( condition de programmer proprement).

Les balises
Les parties correspondant au code PHP sont dclares au moyen de balises. Il existe plusieurs types de balises en fonction de vos prfrences, habitudes, et de la configuration de PHP sur le serveur ou tournera vos scripts. Il existe quatre diffrents types de balises regroups dans le tableau ci-aprs :

Tableau 3.1 : Les diffrentes balises


Balise <?php ?> <script language="php"> </script> Remarque Ce type de balise est le plus courant. Il est accept par dfaut par linterprteur. Ce type de balise est galement accept par dfaut par linterprteur.

113

Chapitre 3

Le langage PHP

Balise <? ?> <% %>

Remarque Ces balises courtes sont appeles short tags. Elles ne sont pas acceptes par dfaut, cela fait partie de la configuration de PHP. Ces balises sont l pour obtenir les mmes balises que pour lASP. Elles ne sont pas acceptes par dfaut, cela fait partie de la configuration de PHP.

3. Le langage PHP

Vous pouvez vous reporter au chapitre "Prise en main" afin de voir comment configurer PHP pour utiliser les balises qui vous serviront.
Pour ceux qui veulent en crire le moins possible, il existe aussi deux autres types de balises qui ont pour effet de simplifier la syntaxe lorsque vous souhaitez simplement afficher du texte avec la commande echo. Ainsi <? echo "toto" ?> peut tre avantageusement remplac par <?= "toto" ?> et <% echo "toto" %> par <%= "toto" %>.

Ne vous loignez pas des balises... standard Si vous crivez vos premiers scripts, utilisez le premier type de balises (<?php ?>). En effet, celui-ci est compris de lensemble des serveurs, car il ne dpend pas de leur configuration. Le troisime est le type pour fainants, mais peut se retourner contre vous car, si vous ne pouvez pas accder la configuration du serveur aprs en avoir chang, il vous faudra modifier toutes les balises ! De mme, il ne faut pas oublier que, si vous voulez distribuer votre script, il vous faut un script qui fonctionne sur nimporte quel serveur muni de PHP.

Mon premier script


Le premier script PHP est un grand classique ; il ne fait quafficher une phrase.
<html> <head> <title>Mon premier script</title> </head> <body> <?php echo "Mon premier script qui naffiche que du texte en attendant mieux..."; ?> </body> </html>

114

Intgrer le code PHP au HTML

Ici, lintrieur dun script HTML classique, on a insr des balises PHP dans lesquelles on a plac une seule instruction, echo, qui affiche simplement la chane de caractres qui suit. Le sparateur dinstructions est classiquement le point-virgule ; il peut tre omis aprs la dernire instruction dun bloc PHP (ici, en loccurrence, il aurait pu tre omis). Ce fichier, qui sera stock sur le serveur, va tre interprt puis envoy au client (le navigateur Internet du visiteur) quand celui-ci y fera appel.

3. Le langage PHP

Figure 3.1 : Ce que verra le visiteur

Comme nous pouvons le constater en rclamant le code source du document reu, le rsultat de linterprtation ne laisse plus apparatre de code PHP.

Figure 3.2 : Le code source reu par le client

Les balises PHP peuvent tre places nimporte o dans le script ; le script suivant donnera le mme rsultat :
<html> <head> <title>Mon premier script</title> </head> <body> <?php echo "Mon premier script" ?> qui naffiche <?php echo "que du texte en attendant mieux..."; ?> </body> </html>

Dans le cas prsent, lutilit nest pas flagrante, mais nous verrons des cas dapplications lorsque nous tudierons les boucles de contrle.

115

Chapitre 3

Le langage PHP

3. Le langage PHP

Client-serveur Il faut bien comprendre la logique client/serveur : dun ct le serveur est charg dinterprter le code PHP et denvoyer au client (le navigateur Internet du visiteur) le rsultat de linterprtation. De lautre, le client se contente dafficher la page correspondant au code source envoy. Il nest donc pas question de demander PHP dagir sur le client. Vous ne trouverez, par exemple, aucune fonction permettant de suivre le dplacement de la souris, et toute modification du contenu de la page passe ncessairement par une nouvelle interrogation du serveur (i.e. affichage dune nouvelle page ou, ventuellement, raffichage de la page avec de nouveaux paramtres). En contrepartie, le client na pas interprter PHP, ce qui implique que la machine na pas besoin doutils spcifiques, ni de beaucoup de ressources : cest le serveur qui fait tout le travail !

3.2.

Les commentaires

Pour commenter ses scripts et permettre ainsi de les rendre plus clairs, il existe trois faons de faire :

Tableau 3.2 : Les diffrentes faons dinsrer des commentaires


Notation # commentaire // commentaire /* commentaire */ Remarque Le texte entre le signe # et la fin de la ligne sera en commentaire. Cette faon de noter est celle des scripts shell. Le texte entre // et la fin de la ligne sera en commentaire. Tout le texte entre /* et */ sera en commentaire.

Listing 3.1 : Exemple de script avec commentaires


<?php echo "Ligne suivi dun commentaire"; # commentaire faon shell echo "Ligne suivi dun commentaire";// commentaire faon C /* commentaire sur plusieurs lignes */ echo "Ligne entre 2 blocs de commentaires"; /* commentaire * sur * plusieurs

116

Les constantes

* lignes * plus lisibles */ /* cette partie est commente // ce type de commentaire bien quinutile ici est valable # celui ci aussi peut tre imbriqu */ ?>

Un petit commentaire ? Les commentaires sont importants pour sy retrouver ; ils le sont plus encore quand vous relisez un script qui date de plusieurs mois. Mais cela na rien de nouveau et est valable pour nimporte quel langage Privilgiez lutilisation des // et /* */ et vitez #.

3. Le langage PHP

Ne pas imbriquer les commentaires /* */ Vous ne pouvez pas placer */ lintrieur dun commentaire entre /* et */. Par exemple, le script suivant provoquera une erreur :
<?php /* je mets des remarques parce que je le veux bien /* jaime tellement les remarques que je les imbrique */ */ ?>

Au moment de linterprtation, les commentaires sont supprims ; ils ne sont donc pas envoys au client, et, ainsi, ne ralentissent en rien lenvoi de la page. Encore une bonne raison pour user et abuser des commentaires

3.3.

Les constantes

PHP permet de dfinir des constantes, autrement dit des chanes de caractres reprsentant une valeur fige (chane de caractres, nombre ou boolen). Les constantes se dclarent par linstruction define(). Ainsi,
define("LANGAGE", "PHP"); define("VERSION", 4);

cre deux constantes, LANGAGE et VERSION, qui peuvent tre utilises trs naturellement ;
echo LANGAGE." ".VERSION;

117

Chapitre 3

Le langage PHP

retournera ainsi PHP 4 Outre les constantes que vous pourrez dfinir, PHP propose ses propres constantes dont :
j j j
PHP_VERSION qui contient le numro de version de PHP (ex. : "4.3.2"). PHP_OS qui contient le nom du systme dexploitation sous lequel PHP tourne ("Linux", "WINNT", "WIN32", "HP-UX", "AIX", etc.). __FILE__ qui contient le chemin complet du script actuellement lu (sil sagit dun script inclus, cest donc bien le chemin complet du script qui est retourn et non celui du script appel). __LINE__ qui contient le numro de la ligne actuellement excute.

3. Le langage PHP

Existent aussi les constantes TRUE (vrai) et FALSE (faux) et les constantes de niveau derreur que nous prsenterons plus loin.

Les constantes sont accessibles depuis nimporte quel endroit du code, y compris lintrieur des fonctions. Voir ce sujet la section concernant "les fonctions" et la porte des variables.

3.4.

Les variables

Dnition et syntaxe
Les variables sont destines stocker les donnes qui seront utilises et pourront tre modifies lors de lexcution du programme. Le langage PHP, tout comme le langage Perl, utilise une forme particulire de syntaxe pour dfinir une variable. Les variables sont reprsentes avec un caractre $ prfixant lidentification de cette variable. Par exemple, pour dclarer une nouvelle variable de nom "maVariable", il suffit de lappeler $maVariable lintrieur du code source. Contrairement au langage comme le C, PHP nexige pas la dclaration pralable des identificateurs avant leur utilisation. Les variables sont donc dites non types, cest--dire quune variable peut prendre une valeur de chane de caractres et, ensuite, tre utilise pour contenir un entier. Le type est dfini laffectation de cette variable. Cest en partie cette grande souplesse dutilisation qui fait de PHP un langage simple et rapide daccs. Dans lexemple ci-dessous, vous pouvez constater la simplicit dutilisation des variables :
<?php $maVariable = "0"; // $maVariable est une chane de caractres $maVariable = $maVariable + 1; echo $maVariable; // Renvoie "1" et est maintenant un entier

118

Les variables

$maVariable = 1; // $maVariable est present un entier $maVariable = $maVariable / 2; // $maVariable est maintenant du type double $maVariable = 1 + "2 Vive le PHP !"; echo $maVariable; // $maVariable est du type entier et renvoie 3 ?>

Le nom de la variable peut tre dfini par tous les caractres alphanumriques ainsi que par le caractre _ , mais il ne peut pas commencer par un chiffre.
$maVariable, $_maVariable, $maVariable1 sont des variables correctes. En revanche, $1maVariable provoquera une erreur de syntaxe.

3. Le langage PHP

Faites chauffer la colle (attention la casse) Les variables dfinies dans un programme PHP sont sensibles la casse. Faites donc attention, dans vos programmes, ne pas initialiser $maVariable et appeler $MAVARIABLE lutilisation. Ces deux variables sont distinctes.

Les variables dynamiques


Les variables dynamiques (aussi appeles variables "variables") sont des variables dont le nom dpend dautres variables. Les noms de ces variables sont donc construits dynamiquement pendant lexcution du code PHP. Lexemple ci-dessous est bien plus parlant quun long discours :
<?php $var = "Je dveloppe en PHP."; $dyn = "var"; echo $$dyn; // Affiche "Je dveloppe en PHP."; ?>

Ainsi, en crivant simplement $$dyn on rcupre la valeur de la variable dont le nom est contenu dans $dyn, cest--dire $var. Le recours aux variables dynamiques nest gnralement pas ncessaire, car elles peuvent, bien souvent, tre avantageusement remplaces par lutilisation de tableaux, mais qui sait... il est possible que cela vous dpanne un jour ! Il est souvent prfrable, et parfois indispensable, de mettre le nom des variables entre accolades. Cela vous permettra, par exemple, de crer un nom de variable avec une partie variable et une partie fixe, comme cest le cas dans lexemple suivant :
<?php $prefixe= "PHP"; $suffixe= " cest sympa";

119

Chapitre 3

Le langage PHP

$dyn echo $dyn echo ?>

= "pre"; ${$dyn}fixe; = "suff"; ${$dyn}fixe;

// Affichera PHP // Affichera cest sympa

Le rsultat aurait t videmment tout autre si nous avions utilis $dynfixe. Le problme est identique lorsquil sagit de slectionner un lment dun tableau ; $$dyn[0] est ambigu, contrairement ${$dyn[0]} et ${$dyn}[0].

3. Le langage PHP

Les types
Comme nous avons pu le constater, les variables PHP nont pas un type prdfini. Pourtant, un dveloppeur peut tre amen manipuler les types pour le besoin dune application et les problmes de conversion peuvent non pas causer des erreurs, mais retourner des rsultats surprenants et gnants. Pour viter cela, le langage PHP possde un jeu de fonctions qui lui permet de fixer et de rcuprer le type dune variable donne. On peut classer les diffrents types possibles en trois catgories : les types scalaires, les types composs et les types spciaux.

Tableau 3.3 : Dfinitions des quatre types scalaires


Type int (ou integer) Description Le type int est utilis pour contenir des entiers (nombres sans virgule). Les valeurs peuvent aller de 2147483648 2147483647. Le type double sert dfinir des nombres dcimaux, cest--dire comportant une virgule flottante. Le type string dfinit une chane de caractres. Le type boolen dfinit une variable prenant des valeurs de type binaire : TRUE (Vrai) ou FALSE (Faux). Exemple $maVariable = 2; $maVariable = 4; $maVariable = 2002; $maVariable = 1.0; $maVariable = 0.1 $maVariable = 3.1415972; $maVariable = "Vive le php !"; $maVariable = "1"; $maVariable = TRUE; $maVariable = FALSE;

double (ou real ou float)

string

boolean (ou bool)

Notation dans les diffrentes bases Le type entier peut prendre des valeurs exprimes en dcimales (en base 10), hexadcimales (en base 16) et octales (en base 8). Pour indiquer le changement de base, le programmeur placera un 0 devant laffectation.
<?php $dec = 16; // Affectation classique en base 10

120

Les variables

$hex = 0x10; $oct = 020; ?>

// Le 0x indique laffectation en hexadcimal // Le simple 0 devant indique laffectation en Octal

$dec, $hex et $oct possdent la mme valeur mais exprime dans une base diffrente. Il est noter quil nest pas possible dexprimer un nombre directement dans sa forme binaire.

Tableau 3.4 : Les deux types composs


Type array Description Dsigne un type tableau (ensemble de valeurs). Voir la sectionTableaux. Dsigne un type objet (variable possdant ses propres proprits, attributs et mthodes). Voir la section Classes. Exemple $monTableau = array (2, "Super, du PHP !", "cl"=>"valeur"); $monTableau[2] = "Top"; class MaClasse { } $monObjet = new MaClasse()

3. Le langage PHP

object

Tableau 3.5 : Les deux types spciaux supports


Type resource NULL Description Reprsente une rfrence (ex. : identifiant de connexion une base de donnes ou toute autre source). La variable de type NULL reprsente une variable ne possdant pas de valeur.

Rencontre avec le 9e type Dans les descriptions des fonctions, nous utiliserons galement, en lieu et place de certains types, dautres termes qui ne correspondent pas vritablement des types. Ainsi :
j j j j
mixed dsignera les paramtres (ou valeurs retour) pouvant tre de diffrents types. function dsignera des noms de fonctions (en fait, des types string mais avec une signification particulire). numeric dsignera des paramtres (ou valeurs retour) de type int ou double. void dsignera les fonctions sans paramtre ou sans valeur retour.

121

Chapitre 3

Le langage PHP

Bien que le type des variables soit dfini leur initialisation, il est quand mme possible de forcer une variable dans un type donn. Pour cela, nous utilisons la fonction setType().

setType()
Affecte un type une variable. Syntaxe $variable boolean setType(mixed $variable, string $type) Variable dont on veut fixer le type. Chane de caractres prcisant le type que lon veut affecter la variable. Ce peut tre au choix : integer pour un type entier. double pour un type rel. string pour une chane de caractres. array pour un tableau. TRUE en cas de succs ou FALSE (ex. : nom de type invalide).

3. Le langage PHP

$type

retour

Pour rcuprer le type vous utiliserez la fonction gettype().

getType()
Retourne le type de la variable. Syntaxe $variable retour string getType(mixed $variable) Variable dont on veut dterminer le type. Les diffrentes valeurs retournes possibles sont : integer pour un type entier. double pour un type rel. string pour une chane de caractres. array pour un tableau. object pour un objet. resource pour une ressource (un pointeur sur ...). user function pour une fonction cre par lutilisateur. unknown type pour un type indtermin.

Le code ci-dessous est un bon exemple de cette utilisation :


<?php setType($toto, "integer"); // La variable est du type entier echo getType ($toto); // Renvoie "integer"

122

Les variables

$i = 2+2; echo getType ($i); // Renvoie "integer" $i = "Jaime le chiffre ".$i; // Concatenation dune chane avec un entier echo getType ($i); // Renvoie "string" ?>

Le transtypage
Pour remdier aux problmes que vous pouvez rencontrer dans vos manipulations de conversion, le dveloppeur a la possibilit dutiliser le transtypage (ou type casting). Sous ce terme un peu barbare, se cache la possibilit de crer une nouvelle variable contenant la valeur dune autre avec un type diffrent mais compatible. Ainsi, le transtypage permet un programmeur de modifier le type de ses variables pendant lexcution de son programme, que ce soit pour faire un test dgalit ou des oprations entre deux variables de type diffrent. Le transtypage sutilise, comme pour le langage C, en crivant le type entre parenthses devant le nom de la variable, comme indiqu dans lexemple ci-dessous :
<?php $monEntier = 10; // $monEntier est un "integer" $maChaine = (string)$monEntier; // $maChaine est une chaine de caractres ?>

3. Le langage PHP

Les diffrentes conversions possibles sont donc :


j j j j j j
(array) pour convertir en type tableau. (boolean) ou (bool) pour convertir en type boolen. (double), (float) ou (real) pour convertir en type rel (dcimal). (int) ou (integer) pour convertir en type entier. (object) pour convertir en type objet. (string) pour convertir en type chane de caractres.

Dans lexemple suivant, nous montrons comment, depuis la conversion en tableau ou en objet, un programmeur peut rcuprer les donnes :
<?php $maVariable = "Super, encore du PHP !"; $tableau = (array)$maVariable; echo $tableau[0]; // renvoie "Super, encore du PHP !" $objet = (object)$maVariable; echo $objet->scalar;

123

Chapitre 3

Le langage PHP

// renvoie "Super, encore du PHP !" ?>

Notez que la conversion dune variable de type scalaire (int, double ou string) dans le type objet crera un attribut nomm scalar et contenant la valeur de la variable.

Les rfrences
PHP permet de crer une rfrence une variable existante. De la mme manire quavec le langage C, vous pouvez accder directement une zone mmoire contenant une variable. La rfrence une variable permet de crer une nouvelle variable qui utilise la mme zone mmoire que la variable dorigine. Pour cela, vous devez lindiquer laide du caractre & devant le nom de la variable, comme le montre lexemple suivant :
<?php $var1 = "Bonjour"; $var2 = &$var1; // $var1 et $var2 sont deux mmes noms pour une mme variable $var2 = "Au revoir"; echo $var1; // Affiche Au revoir ?>

3. Le langage PHP

Tester une variable


Dans vos manipulations des donnes, vous pouvez tre amen tester lexistence ou le type des variables que vous utilisez. Pour cela, on utilise un jeu de fonctions trs utile.

isSet()
Dtermine si une variable existe (a t initialise). Syntaxe $variable retour boolean isSet(mixed $variable) Variable que lon veut tester. TRUE si la variable existe bien et FALSE sinon.

unset()
Dtruit les variables.

124

Les variables

Syntaxe $variable1, ...


<?php echo isSet($toto); $toto = ""; echo isSet($toto); unset ($toto); echo isSet($toto); ?>

void unset(mixed $variable1 [, mixed $variable2 [, ...]]) Les variables dtruire.


// Renvoie FALSE (ce qui naffiche rien) // Renvoie TRUE (ce qui affiche 1)

// Renvoie FALSE (ce qui naffiche rien)

De la mme manire, la fonction empty() dtermine si une variable possde une valeur non nulle ou non.

3. Le langage PHP

empty()
Dtermine si une variable possde une valeur non nulle ou non. Syntaxe $variable retour boolean empty(mixed $variable) Variable que lon veut tester. TRUE si la variable nexiste pas, est une chane vide () ou vaut 0, NULL, FALSE sinon.

<?php echo <html><body>; // affectation des variables $var1 = 0; $var2 = 1; $var3 =""; $var4 ="Bonjour !"; // empty($var1) renvoie TRUE if (empty($var1)) echo $var1 est "vide"<br>; else echo $var1 = .$var1.<br>; // empty($var2) renvoie FALSE if (empty($var2)) echo $var2 est "vide"<br>; else echo $var2 = .$var2.<br>; // empty($var3) renvoie TRUE if (empty($var3)) echo $var3 est "vide"<br>; else echo $var3 = .$var3.<br>; // empty($var4) renvoie FALSE if (empty($var4)) echo $var4 est "vide"<br>; else echo $var4 = .$var4.<br>; echo </body></html>; ?>

125

Chapitre 3

Le langage PHP

Figure 3.3 : Le rsultat dans un navigateur

Pour dtruire une variable, utilisez la fonction unset().

3. Le langage PHP

is_bool(), is_int(), is_double(), is_numeric(), is_scalar(), is_object(), is_resource(), is_NULL().

Afin de tester le type des variables, PHP possde une srie de fonctions trs commodes : is_string(), is_array(),

Toutes ces fonctions sutilisent de la mme manire. Elles renvoient TRUE si le type de la variable passe en paramtre est exactement le type recherch, et FALSE dans le cas contraire.

is_bool()
Dtermine si une variable est de type boolen. Syntaxe $variable retour boolean is_bool(mixed $variable) Variable dont on veut dterminer si elle est de type boolen. TRUE si la variable est de type boolen, FALSE sinon.

<?php $var = 1; echo is_bool($var); // Ne renvoie rien, le rsultat du test est faux $var = TRUE; echo is_bool($var); // Renvoie 1, le rsultat du test est vrai ?>

is_int()
Dtermine si une variable est de type entier. Syntaxe $variable retour boolean is_int(mixed $variable) Variable dont on veut dterminer si elle est de type entier. TRUE si la variable est de type entier, FALSE sinon.

126

Les variables

is_int() est en fait un alias de is_long() dont is_integer() est un autre alias.

<?php $var = "15"; echo is_int($var); // Ne renvoie rien, le rsultat du test est faux $var = 15; echo is_int($var); // Renvoie 1, le rsultat du test est vrai ?>

3. Le langage PHP

is_double()
Dtermine si une variable est de type rel (dcimal). Syntaxe $variable retour boolean is_double(mixed $variable) Variable dont on veut dterminer si elle est de type rel. TRUE si la variable est de type rel, FALSE sinon.

is_float() et is_real() sont des alias de la fonction is_double().

<?php $var = 15; echo is_double($var); // Ne renvoie rien, le rsultat du test est faux $var = 15.0; echo is_double($var); // Renvoie 1, le rsultat du test est vrai ?>

is_numeric()
Dtermine si une variable est un nombre ou une chane de caractres reprsentant un nombre. Syntaxe $variable retour boolean is_numeric(mixed $variable) Variable dont on veut dterminer si elle est de type nombre ou chane de caractres reprsentant un nombre. TRUE si la variable est de type nombre ou chane de caractres reprsentant un nombre, FALSE sinon.

<?php $var1 = "quinze"; echo is_numeric($var1);

127

Chapitre 3

Le langage PHP

// Ne renvoie rien, le rsultat du test est faux $var2 = 15; echo is_numeric($var2); // Renvoie 1, le rsultat du test est vrai $var3 = "15"; echo is_numeric($var3); // Renvoie 1, le rsultat du test est vrai $var4 = 15.0; echo is_numeric($var4); // Renvoie 1, le rsultat du test est vrai ?>

3. Le langage PHP

is_string()
Dtermine si une variable est de type chane de caractres. Syntaxe $variable retour boolean is_string( mixed $variable) Variable dont on veut dterminer si elle est de type chane de caractres. TRUE si la variable est de type chane de caractres, FALSE sinon.

<?php $var = "15"; echo is_string($var); // Renvoie 1, le rsultat du test est vrai $var = 15; echo is_string($var); // Ne renvoie rien, le rsultat du test est faux ?>

is_array()
Dtermine si une variable est de type tableau. Syntaxe $variable retour boolean is_array(mixed $variable) Variable dont on veut dterminer si elle est de type tableau. TRUE si la variable est de type tableau, FALSE sinon.

<?php $var1 = 15; echo is_array($var1); // Ne renvoie rien, le rsultat du test est faux

128

Les variables

$var2 = array(15); echo is_array($var2); // Renvoie 1, le rsultat du test est vrai ?>

is_object()
Dtermine si une variable est de type objet.

3. Le langage PHP

Syntaxe $variable retour


<?php class Bible { var $x; }

boolean is_object(mixed $variable) Variable dont on veut dterminer si elle est de type objet. TRUE si la variable est de type objet, FALSE sinon.

$var = new Bible(); $var->x = "Je suis un attribut"; echo is_object($var); // Renvoie 1, le rsultat du test est vrai echo is_object($var->x); // Ne renvoie rien, le rsultat du test est faux ?>

is_scalar()
Dtermine si une variable est de type scalaire. Syntaxe $variable retour
<?php $var1[0] = 3.14; $var2 = 3.14; $var3 = "pi"; echo is_scalar($var1); // Ne renvoie rien, le rsultat du test est faux

boolean is_scalar(mixed $variable) Variable dont on veut dterminer si elle est de type scalaire. TRUE si la variable est de type scalaire, FALSE sinon.

129

Chapitre 3

Le langage PHP

echo is_scalar($var1[0]); // Renvoie 1, le rsultat du test est vrai echo is_scalar ($var2); // Renvoie 1, le rsultat du test est vrai echo is_scalar ($var3); // Renvoie 1, le rsultat du test est vrai ?>

3. Le langage PHP

is_resource()
Dtermine si une variable est de type resource. Syntaxe $variable retour boolean is_resource(mixed $variable) Variable dont on veut dterminer si elle est de type resource. TRUE si la variable est de type resource, FALSE sinon.

is_NULL()
Indique si une variable est NULL. Syntaxe : $variable retour boolean is_NULL(mixed $variable) Variable dont on veut dterminer si elle est NULL. TRUE si la variable est NULL, FALSE sinon.

<?php $var = 0; echo is_NULL($var); // Ne renvoie rien, le rsultat du test est faux unset($var); echo is_NULL($var); // Renvoie 1, le rsultat du test est vrai ?>

Les variables externes


Nous pouvons diffrencier deux types de variables externes :
j j

Les variables denvironnement (du serveur) ; Les variables passes en paramtre lors de lappel de la page (soit via un formulaire soit via lURL).

130

Les variables

Les variables denvironnement


Les variables denvironnement sont des variables gnres automatiquement par PHP partir des donnes rcupres sur le serveur ou de len-tte des requtes du client.

Voir le chapitre "Les en-ttes" pour plus de dtails sur les en-ttes.

Ces variables constituent en fait deux tableaux de porte globale (accessibles depuis nimporte quel endroit du script) :

3. Le langage PHP

j j

$_ENV contient les "vritables" variables denvironnement du serveur, cest--dire toutes les variables dont a pu hriter le compte sous lequel tourne le serveur web (ex. : PATH). $_SERVER contient, quant lui, les variables "internes" du serveur (nom et version du serveur, adresse IP, etc.) ainsi que celles rcupres du client (adresse IP du client, type du navigateur, etc.).

Vous pouvez simplement visualiser toutes les variables denvironnement sur la page gnre par la fonction phpinfo(). Une autre possibilit pour rcuprer la liste des variables est dutiliser la fonction get_defined_vars(); elle permet de rcuprer dans un tableau la liste de toutes les variables dfinies. Le tableau retourn contient alors toutes les variables denvironnement, mais aussi toutes les variables dfinies par lutilisateur.

get_dened_vars()
Liste toutes les variables dfinies. Syntaxe retour array get_defined_vars(void) Toutes les variables dans un tableau associatif o les noms des cls sont les noms des variables et les valeurs celles des variables.

Lexemple ci-dessous permet de gnrer un tableau HTML contenant la liste des variables et leurs valeurs au moment de lexcution du code :
<html> <body> <?php $a1 = "premire variable"; $a2 = "seconde variable"; echo "<table border=1>"; $a = get_defined_vars(); while (list($key, $val) = each($a)) { echo "<tr>";

131

Chapitre 3

Le langage PHP

echo "<td>\$".$key."</td><td>".$val."</td>"; echo "</tr>"; } echo "</table>"; ?> </body> </html> Figure 3.4 : Ce code retourne un tableau contenant noms des variables et valeurs

3. Le langage PHP

Le tableau $_ENV ne prsente gnralement pas un grand intrt hormis dans quelques cas particuliers. Vous pouvez aussi rcuprer les valeurs laide de la fonction getEnv().

getEnv()
Retourne la valeur dune variable denvironnement. Syntaxe $variable Environnement retour string getEnv(string $variableEnvironnement ) Variable denvironnement dont on veut dterminer la valeur. La valeur de la variable denvironnement ou FALSE si il y a une erreur

132

Les variables

Il est trs simple de modifier les variables denvironnement en utilisant la fonction putEnv(). Les valeurs ainsi fixes par le dveloppeur ne durent que le temps de lexcution du script et, ds la fin de celui-ci, lenvironnement par dfaut est restaur. Mais, comme la modification de certaines valeurs peut entraner des problmes de scurit, ladministrateur du systme a la possibilit dempcher certaines modifications. Cest dailleurs, par dfaut, le cas de la variable LD_LIBRARY_PATH (dun systme UNIX/Linux) qui, si elle venait tre modifie, pourrait ventuellement permettre aux pirates de masquer la prsence dune bibliothque (peut-tre utilise par le serveur web) au profit dune autre plus malicieuse. Ainsi, la directive safe_mode_protected_env_vars du fichier de configuration php.ini contient une liste de variables denvironnement que le dveloppeur ne peut modifier. De la mme faon, si safe_mode (mode protg) est activ (ce qui nest pas le cas par dfaut), seules les variables commenant par les prfixes prciss dans safe_mode_allowed_env_vars pourront tre modifies.

3. Le langage PHP

Pour plus dinformations sur le fichier php.ini, reportez-vous au chapitre "Prise en main".

putEnv()
Fixe une nouvelle valeur la variable denvironnement. Syntaxe void putEnv(string $chaineAffectation) $chaineAffectation Chane de caractres de la forme "<nom de variable>=<valeur>"
<?php $ip = getEnv("REMOTE_ADDR"); // retourne ladresse IP de lutilisateur putEnv("NOUV_IP=127.0.0.1"); // Dfinit une nouvelle variable denvironnement echo getEnv("REMOTE_ADDR"); // Affiche 127.0.0.1 ?>

Le tableau $_SERVER, quant lui, va nous permettre de raliser de nombreuses oprations.

Variantes dun serveur lautre Les variables $_SERVER prsentes sont celles disponibles sous Apache. La plupart sont galement disponibles sur les serveurs IIS et iPlanet, mais vous observerez tout de mme des diffrences.

133

Chapitre 3

Le langage PHP

Dterminer ladresse IP du client


Llment $_SERVER["REMOTE_ADDR"] retourne ladresse IP du client, ce qui est particulirement utile pour ne pas compter lutilisateur plusieurs fois dans le nombre des visiteurs dun site.

3. Le langage PHP

IP mouvante La grande majorit des internautes nest pas connecte en permanence linternet (mme les utilisateurs de lADSL sont gnralement contraints de se reconnecter au moins une fois par jour). Par consquent, ladresse IP (attribue par le fournisseur daccs) varie dun jour sur lautre. Il serait donc faux de supposer que deux visites deux jours dintervalle avec la mme adresse IP corresponde au mme visiteur. Alors que si lintervalle de temps entre les deux visites est bien plus court, lhypothse est fort valable.

Dterminer do vient le client


Il est gnralement possible de savoir quel lien a suivi le visiteur pour arriver sur le script en cours dexcution. Pour cela, il suffit de lire le contenu de $_SERVER["HTTP_REFERER"] ; ceci retourne alors une URL.

Dterminer le type de navigateur du client


Llment $_SERVER["HTTP_USER_AGENT"] permet de rcuprer la chane didentification fournie par le navigateur du client. Cela est particulirement utile si vous avez crire des scripts gnrant du code Javascript un peu pointu, car, comme vous le savez peut-tre, le Javascript dpend fortement du navigateur. Il en est de mme de certaines balises HTML. La valeur ainsi rcupre ncessite toutefois une petite analyse avant de dterminer avec prcision la nature du navigateur, comme le dmontre lchantillon de valeurs possibles suivant :
j

pour Internet Explorer :


Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC)

Konqueror :
Mozilla/5.0 (compatibles; Konqueror/2.2.1; Linux)

Netscape :
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1 Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.8) Gecko/20020204

Opera :
Mozilla/4.7 [tr] (X11; I; Linux 2.2.16 i686)

134

Les variables

Mozilla/4.0 (compatible; MSIE 5.0; Linux) Opera 6.0 [en]

Et tout cela se dcline pour ainsi dire linfini. Dautant que certains visiteurs ne sont pas des utilisateurs derrire leur navigateur, mais des aspirateurs de sites (soit pour les moteurs de recherche, soit pour un particulier). Mme si cela nest pas systmatique, la plupart prcisent leur propre identifiant et dautres offrent mme la possibilit lutilisateur de dfinir sa propre chane didentification. Voici, donc, un nouvel chantillon de valeur rencontre :
j

Les aspirateurs de sites et autres "spiders" de moteurs de recherche :


Googlebot/2.1 (+http://www.googlebot.com/bot.html) Mozilla/3.0 (Slurp/si; slurp@inktomi.com; http://www.inktomi.com/slurp.html) WebCopier v3.0

3. Le langage PHP

<html> <body> Vous avez ladresse IP : <?php echo $_SERVER["REMOTE_ADDR"]; ?> <br /> Vous avez un navigateur qui porte la signature : <?php echo $_SERVER["HTTP_USER_AGENT"]; ?> <br /> </body> </html>

Dterminer la langue du visiteur


Bien que cette fonctionnalit ne soit pas forcment bien connue, les navigateurs offrent la possibilit de dterminer ses langues prfres. Il est alors possible, lorsque lon gre un site multi-langue, de sadapter automatiquement en proposant la langue qui rpondra au mieux aux attentes du visiteur. Ce paramtre est accessible depuis le serveur via la variable $_SERVER["HTTP _ACCEPT_LANGUAGE"] qui aura une valeur du genre :
fr, en;q=0.5

Il sagit donc dune chane contenant les codes ISO des langues, spars par des virgules et par ordre de prfrence. La liste se termine par un point-virgule (et lon trouve ensuite un coefficient).

Dterminer le nom du serveur web


Il est possible de dterminer le nom du serveur en consultant le contenu de $_SERVER["SERVER_NAME"], ce qui peut vous permettre de crer un script unique ayant un comportement diffrent selon la machine sur lequel il tourne.

Dterminer la racine du serveur web


Si vous avez manipuler des noms de fichier, le chemin relatif la racine du site web ne sera peut-tre pas toujours suffisant. Si vous avez besoin du chemin complet depuis la racine du disque dur, vous pourrez faire appel $_SERVER["DOCUMENT_ROOT"] pour rcuprer le chemin depuis la racine du disque dur vers la racine du serveur web.

135

Chapitre 3

Le langage PHP

iPlanet, IIS et PWS Cette variable nest pas disponible sur les serveurs iPlanet, IIS et PWS.

Dterminer le nom du script en cours dexcution


La variable $_SERVER["PHP_SELF"] contient le chemin absolu (commence par un /) par rapport la racine du site web et le nom du script en cours dexcution. Cela est particulirement intressant lorsquil sagit dcrire des scripts qui doivent sappeler eux-mmes (ce qui est souvent le cas des scripts gnrant des formulaires) et que lon ne souhaite pas indiquer "en dur" le nom du script (pour ne pas avoir de soucis dans le cas o celui-ci serait renomm). Cela peut galement servir pour dterminer le chemin. La variable $_SERVER["SCRIPT_FILENAME"], quant elle, donne le chemin absolu par rapport la racine du disque dur.

3. Le langage PHP

Excution ! Le script en cours dexcution nest pas ncessairement le script dans lequel est crite linstruction en cours dexcution. Si un script A inclut un script B au niveau du script B, $_SERVER["PHP_SELF"] et $_SERVER["SCRIPT_FILENAME"] retourneront le chemin du script A. Pour connatre le chemin du script B, il faudra faire appel la constante __FILE__ qui donnera le chemin absolu par rapport la racine du disque dur.

iPlanet, IIS et PWS La valeur $_SERVER["SCRIPT_FILENAME"] nest pas disponible sous iPlanet, IIS et PWS ; la place, vous pouvez utiliser $_SERVER["PATH_TRANSLATED"].

Autres...
Mme si nous avons vu ici les principales variables denvironnement, il en existe de nombreuses autres.

Vous pouvez vous reporter aux annexes de ce livre pour une liste plus complte des variables denvironnement. Souvenez-vous... Avant PHP 4.1.0,

les tableaux $_SERVER, $HTTP_SERVER_VARS, $HTTP_ENV_VARS, etc.

$_ENV

sappelaient

136

Les variables

Les variables passes en paramtre du script (ou via des formulaires)


Comme vous le savez peut-tre dj (en tout cas, vous allez bientt le savoir) il est possible de passer des paramtres un script. Il existe diffrentes faons de passer ces paramtres, mais la plus simple - ou du moins la plus parlante - consiste ajouter les paramtres et leurs valeurs la suite de lURL aprs un point dinterrogation ? chaque couple <nom du parametre>=<valeur> tant spar dun autre par le caractre "et commercial" &. On parle alors de passage de paramtres par la mthode GET. Ce qui donne une URL du genre :
http://mondomaine.com/monscript.php?nom=Franois&prenom=DUPOND

3. Le langage PHP

Dans ce cas, les diffrents paramtres du script seront disponibles dans un tableau appel $_GET. Ainsi, si vous appelez le script suivant de la manire indique prcdemment,

Listing 3.2 : get_echo.php


<?php echo "Nom =".$_GET["nom"]."<br />"; echo "Prnom =". $_GET["prenom"]."<br />"; ?>

vous obtiendrez le rsultat suivant :


Nom = Franois Prnom = DUPOND

Je pense que vous commencez entrevoir des possibilits dapplications. Mais vous serez plus enthousiasm encore aprs avoir vu comment utiliser des formulaires de saisie.

Rappel sur les formulaires


Sans faire un descriptif complet des balises HTML, voici un rapide aperu des balises gnralement utilises pour crer un formulaire. Pour commencer, la dfinition dun formulaire se fait entre des balises <form> et </form>. La balise <form> possde, entre autres, deux attributs importants :
j j

Un attribut action prcisant quel page doit tre charge lorsque le formulaire sera valid. Un attribut method prcisant quel mode denvoi des donnes doit tre utilis. Ce dernier peut prendre lune des deux valeurs suivantes get (que nous venons de voir) ou post (que nous nallons pas tarder voir).

La plupart des lments dun formulaire se construisent avec la balise <input />. La balise <input> possde, entre autres, trois attributs importants :
j

Un attribut type prcisant le type de champ de saisie (voir ci-aprs).

137

Chapitre 3

Le langage PHP

j j

Un attribut name prcisant le nom du paramtre associ ce champ. Un attribut default ou checked (selon les cas) prcisant la valeur par dfaut.

Lattribut type peut prendre les valeurs :


j j j
text pour prciser un champ de saisie texte. radio pour prciser un lment dune liste de slection dans laquelle une seule des options peut-tre slectionne. checkbox pour prciser une case cocher.

3. Le langage PHP

Enfin, vous disposez galement des balises <select> (associe <option>) et <textarea>.

Application
Voici donc un petit exemple dapplication :

Listing 3.3 : form_get.html


<html> <body> <form action="get_echo.php" method="get"> Veuillez indiquer vos Noms et Prnoms<br /> Prnom: <input type="text" name="prenom" /><br /> Nom: <input type="text" name="nom" /><br /> <input type="submit" /> </form> </body> </html>

Comme vous pouvez le constater dans la barre dadresse de votre navigateur, le simple fait de valider ce formulaire appelle le script prcis dans le champ action (ici, le script get_echo.php prsent prcdemment) en ajoutant lURL la liste des paramtres et de leurs valeurs, comme cela peut se faire avec une mthode GET rdige manuellement.

Slection multiple Si vous souhaitez utiliser un lment de formulaire pouvant retourner une slection multiple (typiquement une balise <select> en mode "multiselect" ou encore une srie de cases cocher portant toutes le mme nom), vous devez alors lui affecter un nom de tableau (i.e. un nom suivi de []). La valeur rcupre dans $_GET ne sera alors pas de type string mais de type array.
Le fait dutiliser la mthode GET peut entraner des problmes dordres divers. Le problme le plus vident est li la longueur de lURL. Plus il y a de paramtres passer et plus lURL sera longue, ce qui pourrait mettre en dfaut votre serveur. Un autre problme, plus subtil (mais non des moindres) concerne la scurit. En effet, si vous utilisez une mthode GET pour passer des mots de passe (pour une section membre par exemple), ceux-ci apparatront dans lURL de la page. Outre le fait que le mot de passe devienne visible dans la barre dadresse du navigateur

138

Les variables

et dans lhistorique, le problme saggrave quand, depuis cette page, vous proposez un lien vers un autre site (site dune tierce personne). En effet, si ce site tablit des statistiques sur ses consultations, peut-tre trace-t-il linformation $_SERVER["HTTP_REFERER"] qui note do vient le visiteur. Dans ce cas, ladministrateur de ce site pourra lire lURL complte, indiquant ladresse de votre site et un mot de passe gnralement accompagn dun nom dutilisateur ! Bref, il aura en main tous les outils ncessaires pour accder des informations qui ne lui sont pas destines Pour pallier ces diffrents problmes, vous avez la possibilit dutiliser la mthode POST. Dans ce cas, les paramtres ne sont pas ajouts lURL, mais passs "discrtement" dans len-tte de la requte HTTP envoye au serveur. Dans ce cas, les deux fichiers prsents prcdemment deviennent :

3. Le langage PHP

Listing 3.4 : form_post.html


<html> <body> <form action="get_echo.php" method="post"> Veuillez indiquer vos Noms et Prnoms<br /> Prnom: <input type="text" name="prenom" /><br /> Nom: <input type="text" name="nom" /><br /> <input type="submit" /> </form> </body> </html>

Listing 3.5 : post_echo.php


<?php echo "Nom =".$_POST["nom"]."<br />"; echo "Prnom =". $_POST["prenom"]."<br />"; ?>

Vous noterez donc que le travail du dveloppeur est identique, puisquil suffit de remplacer get par post. Ainsi, le tableau contenant les donnes sappelle $_POST. En dehors de lutilisation de formulaires, la mthode GET reste la seule solution facilement implmentable pour passer des paramtres un script.

Souvenez-vous... Avant PHP 4.1.0, les tableaux $_GET, $_POST sappelaient $HTTP_GET_VARS, $HTTP_POST_VAR. Avant PHP 4.2.0, le fichier de configuration php.ini fixait par dfaut loption register_global on, ce qui avait pour effet de crer systmatiquement une variable globale portant le nom des paramtres GET, POST, etc. Ainsi, par exemple, $_GET["nom"] tait galement accessible par $nom., ce qui engendrait des problmes de scurit. Cela est particulirement vrai avec les fichiers destins tre inclus et qui sappuient sur des variables globales dclares dans le script appelant.

139

Chapitre 3

Le langage PHP

Car, dans ce cas, une variable $maVariable peut tre "pirate" en appelant le script inclus avec le paramtre ?maVariable=autreValeur.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur le fichier php.ini.
Il existe galement dautres variables denvironnement, mais nous leur consacrerons un chapitre spcifique.

3. Le langage PHP

Il sagit des tableaux $_COOKIE et $_SESSION tudis dans le chapitre En-ttes et du tableau $_FILES tudi dans le chapitre Fichiers.

3.5.

Les oprateurs

Arithmtiques
Les oprateurs mathmatiques sont classiques ; les voici regroups dans un tableau. Ils agissent aussi bien sur des entiers que sur des rels.

Tableau 3.6 : Les oprateurs arithmtiques


Oprateur $a + $b $a $b $a * $b $a / $b $a % $b Description Somme de $a et $b. Diffrence de $a et $b. Produit de $a par $b. Quotient de $a par $b. Reste de la division de $a par $b.

Loprateur / renvoie un entier si les deux valeurs de la division sont des entiers ou des chanes de caractres reprsentant des entiers. Si une des deux valeurs est un rel, alors le rsultat sera un rel.

Reste de la division Loprateur % est particulirement utile ; il peut permettre de savoir si un nombre est divisible par un autre. Par exemple, si vous souhaitez savoir si $a est un chiffre pair, il suffit de tester le rsultat de $a%2 sil vaut 0 alors $a est un chiffre pair (divisible par 2).
<?php for ($i=1; $i<= 5; $i++) { echo "$i:"; if ($i%2 == 0) echo "impair "; else echo "pair ";

140

Les oprateurs

} ?>

Le rsultat :
1:impair 2:pair 3:impair 4:pair 5:impair

Binaires
Vous pouvez traiter les donnes binaires laide de ces fonctions primaires :

Tableau 3.7 : Les oprateurs binaires

3. Le langage PHP

Exemple $a & $b $a | $b $a ^ $b ~$a $a<<$b $a>>$b

Nom Et Ou Ou exclusif Non Dcalage gauche Dcalage droite

Description Active les bits prsents dans $a et $b/. Active les bits prsents dans $a ou $b. Active les bits prsents dans $a ou $b mais pas dans les deux. Oppose les bits. Dcale $a gauche de $b rangs (revient multiplier $b fois par 2). Dcale $a droite de $b rangs (revient diviser $b fois par 2).

Considrons $a=10 soit 1010 en binaire, que lon notera 1010b et $b=13 soit 1101b
<?php $a=10; $b=13; echo "$a & $b = ".($a&$b); echo "$a | $b = ".($a|$b); echo "$a ^ $b = ".($a ^ $b); echo "~$a = ".(~$a); echo "$a<<2 = ".($a<<2); echo "$a>>2 = ".($a>>2); ?>

Voici le rsultat obtenu :

Figure 3.5 : Rsultat

141

Chapitre 3

Le langage PHP

Vrifions :
j j j j j j

1010b AND 1101b fait 1000b soit 8 1010b OR 1101b fait 1111b soit 15 1010b XOR 1101b fait 0111b soit 7 NOT 1010b fait 10101b soit en complment a 1 1011b donc -11 1010b<<2 fait 101000 soit 40 1010b>>2 fait 10 soit 2

Les rsultats concordent bien avec nos calculs.

3. Le langage PHP

Lcriture binaire Si vous ntes pas familier de la notation et des calculs binaires, cela peut vous paratre obscur. Bien que cela ne soit pas indispensable pour lapprentissage de PHP, si vous voulez en apprendre davantage sur la notation binaire, vous pouvez vous connecter, par exemple, aux sites Internet suivants :
http://www.histoire-informatique.org/technologie/binaire.html http://www.web2.cnam.fr/evariste/evariste/10_cours/binaire/binaire.htm http://www.lille.iufm.fr/labo/pagesProjets/leparc/base2/thema.htm

Chanes de caractres
Loprateur permettant la concatnation (fusion) de deux chanes de caractres et le point .. Voici un exemple de script affichant le rsultat de la concatnation de deux chanes :
<?php $a="PHP ?"; $b=" Facile !"; echo $a.$b; ?>

Affectation
Le signe = est le symbole utilis pour affecter une valeur une variable ; la valeur la droite de ce signe est affecte la variable de gauche. Il est possible de les mettre en squence, comme dans le script qui suit :
<?php $a = ( $b = 3 ) +5; ?>

Aprs cette instruction, $a vaut 8 et $b vaut 3.

142

Les oprateurs

Il existe des raccourcis particulirement utiles : au lieu dcrire $a = $a+10, vous pouvez crire $a += 10. De mme, $a = $a10 peut scrire $a = 10. /= et *= sont aussi des oprateurs daffectation. Pour les chanes de caractres, il existe le mme type doprateur, savoir : .=, crire $a .=
"toto"; est quivalent $a = $a."toto";

Incrmentation et dcrmentation
Tableau 3.8 : Oprateurs dincrmentation et de dcrmentation
Syntaxe ++$a $a++ $a $a Nom Pr-incrmentation Post-incrmentation Pr-dcrmentation Post-dcrmentation Description Incrmente $a de un puis retourne $a. Retourne $a puis incrmente $a de un. Dcrmente $a de un puis retourne $a. Retourne $a puis dcrmente $a de un.

3. Le langage PHP

<?php echo $a = echo echo echo echo echo $a = echo echo echo echo echo $a = echo echo echo echo echo $a = echo echo echo echo ?>

"Post-incrementation<br>"; 5; $a++; // affiche 5 "<br>";// place une nouvelle ligne dans le script resultat $a; // affiche 6 "<br>"; "Pre-incrementation<br>"; 5; ++$a; // affiche 6 "<br>"; $a; // affiche 6 "<br>"; "Post-decrementation<br>"; 5; $a--; // affiche 5 "<br>"; $a; // affiche 4 "<br>"; "Pre-decrementation<br>"; 5; --$a; // affiche 4 "<br>"; $a; // affiche 4 "<br>";

143

Chapitre 3

Le langage PHP

Comparaison
Tableau 3.9 : Les oprateurs de comparaison
Syntaxe $a == $b $a === $b $a != $b Nom gal Identique Diffrent Diffrent Non identique Infrieur Suprieur Infrieur ou gal Suprieur ou gal Description Renvoie TRUE si $a est gal $b. Renvoie TRUE si $a est gal $b et que $a et $b sont du mme type. Renvoie TRUE si $a est diffrent de $b. Renvoie TRUE si $a est diffrent de $b. Renvoie TRUE si $a est diffrent de $b ou de type diffrent. Renvoie TRUE si $a est infrieur $b. Renvoie TRUE si $a est suprieur $b. Renvoie TRUE si $a est infrieur ou gal $b. Renvoi TRUE si $a est suprieur ou gal $b.

3. Le langage PHP

$a <> $b $a !== $b $a < $b $a > $b $a <= $b $a >= $b

Tous ces comparateurs vous permettront de tester les variables pour agir en fonction du rsultat obtenu.

Typage Depuis PHP4, le typage est devenu plus fort, mme si lon peut encore comparer directement des chanes de caractres avec un entier ou un rel par exemple. Mais si FALSE == 0 (ce qui peut porter confusion lorsquune fonction peut retourner 0 dans un cas nominal et FALSE en cas derreur) et bien FALSE !== 0 (puisque FALSE est un boolen et 0 un entier).
Bien entendu, il est possible de combiner les oprateurs binaires et les oprateurs de comparaison. Lexpression correspondant aux phrases "la variable a est diffrente de 3 et la variable b vaut toto ou alors la variable c est un boolen valant FALSE" scrit de diffrentes faons. En voici quelques-unes :
(($a != 3 && $b == "toto) || ($c==FALSE)) // faire un test dgalit avec TRUE nest pas trs fut (($a != 3 && $b == "toto) || (!$c==TRUE)) // la faon la plus standard de faire, reste (($a != 3 && $b == "toto) || (!$c))

144

Les oprateurs

Logique
Les oprateurs de logique vont servir faire des tests complexes, par exemple pour savoir si $a vaut 3 ET $b est faux. Dans le tableau suivant sont regroups tous les oprateurs logiques supports par PHP :

Tableau 3.10 : Les oprateurs logiques


Syntaxe $a and $b $a && $b $a or $b $a || $b $a xor $b ! $a Description VRAI si $a et $b sont vrais. VRAI si $a et $b sont vrais. VRAI si $a ou $b est vrai. VRAI si $a ou $b est vrai. VRAI si $a ou $b est vrai, mais pas les deux. VRAI si $a est faux.

3. Le langage PHP

Utiliser loprateur OR comme expression conditionnelle PHP ninterprte pas la partie droite de lexpression OR si la partie gauche est vraie. On peut ainsi sen servir astucieusement pour excuter une instruction si une expression est incorrecte.
<?php $a=4; ($a==3) OR die("\$a ne vaut pas 3"); ?>

Ce script stoppe si $a ne vaut pas 3 et affiche un message. Cela est particulirement utile lors de lappel des fonctions (par exemple de connexion une base de donnes) qui retournent FALSE en cas derreur.
<?php connexion() OR die("Impossible de se connecter"); ?>

Contrles derreur
PHP intgre quatre grands niveaux de message derreur ou dalerte. chacun correspond une constante :
j j
E_NOTICE : simple remarque (comme lorsque lon essaye daccder un index inexistant dun tableau). E_PARSE : en cas derreur danalyse la compilation (comme une erreur de syntaxe).

145

Chapitre 3

Le langage PHP

j j

E_WARNING : une alerte ne ncessitant pas larrt du script. E_ERROR : une erreur "grave" ncessitant larrt du script.

Une constante supplmentaire fait la somme de tous ces types derreur et dalerte, il sagit de E_ALL. ceux-l viennent sajouter les niveaux E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, E_USER_ERROR, E_USER_WARNING et E_USER_NOTICE dune utilisation moins courante. Lorsquune erreur est rencontre et quelle dpasse le seuil dalerte, ou plus exactement lorsque son niveau de svrit fait partie de la liste des niveaux signaler, un message est envoy au client (i.e. est affich sur la page reue par le navigateur). Les niveaux derreur signaler sont dfinis dans le fichier de configuration php.ini, mais peuvent tre modifis au niveau du script par un simple appel la fonction error_reporting().

3. Le langage PHP

error_reporting()
Fixe les niveaux derreur devant tre signals. Syntaxe $niveaux retour int error_reporting([int $niveaux]) Combinaison par OU logique ou OU exclusif des diffrentes constantes indiques prcdemment. Anciennes valeurs des niveaux derreur.

Il est toutefois possible de saffranchir des messages derreur pour une instruction donne sans avoir recours cette fonction. Pour cela, il existe un oprateur de contrle derreur, cest le caractre @ ; il peut tre mis devant nimporte quelle fonction susceptible de gnrer une erreur. Cela peut tre particulirement utile pour gnrer vos propres messages derreur. Le script suivant fixe les niveaux dalerte "tous sauf les simples remarques" (ce qui est la configuration par dfaut de PHP), puis tente daccder un fichier qui nexiste pas.
<?php error_reporting(E_ALL ^ E_NOTICE); $fichier = @file (fichier_inexistant.toto) or die ("Impossible douvrir le fichier."); ?>

La fonction file renvoie un boolen indiquant si lopration sest bien droule. Si le fichier nexiste pas, alors la fonction renvoie un message. Ici, nous avons mis @ devant le nom de la fonction ; nous naurons donc pas cet affichage, mais le texte "Impossible douvrir le fichier". Notez que cela peut aussi sappliquer des expressions, et donc un tableau, pour viter un message si llment recherch nexiste pas (ex. : @tableau["index_inexistant"];). Ceci

146

Les oprateurs

dit, le message prvu en pareil cas est de niveau NOTICE, et PHP nest, par dfaut, pas configur pour afficher ce type de message.

Connexion une base de donnes Lorsque vous vous connectez une base de donnes, il se peut que celle-ci soit momentanment indisponible. Donc, au lieu dobtenir le message derreur standard, il vaut mieux faire prcder la fonction de connexion de @ et tester le code retour pour afficher votre propre message si la connexion a chou.

3. Le langage PHP

Excution
Il existe un oprateur dexcution, cest . Ce qui se trouve entre ces apostrophes inverses sera interprt par PHP comme une commande shell. Voici un exemple de script qui liste le contenu dun rpertoire, le stocke dans une variable, et laffiche :

Listing 3.6 : version Unix/Linux


<?php $liste=ls al; echo "<pre>$liste</pre>"; ?>

Listing 3.7 : version Windows


<?php $liste=dir; echo "<pre>$liste</pre>"; ?>

Configuration du serveur Ceci ne fonctionne pas si loption safe_mode du fichier de configuration php.ini a t active (on) ou si la fonction shell_exec() est dsactive.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur le fichier php.ini.

Priorits
Les priorits sur les calculs sont les mmes que celles que vous connaissez dj.
8 + 2 * 3 fera bien 8 + 6 = 14 (et pas 10 * 3 = 30).

147

Chapitre 3

Le langage PHP

Dans le tableau suivant, vous trouverez les oprateurs par ordre de priorit ; les premiers lments sont prioritaires sur les derniers.

Tableau 3.11 : Associativit et priorit des oprateurs par ordre dcroissant de priorit
Oprateur New [ ! ~ ++ (int) (double) (string) (array) (object) @ Associativit Aucune Droite Droite Gauche Gauche Gauche Aucune Aucune Gauche Gauche Gauche Gauche Gauche Gauche Gauche Gauche

3. Le langage PHP

* / % + . << >> < <= > >= == != === !== & ^ | && || ? : = += = *= /= .= %= &= |= ^= ~= <<= >>= ,

3.6.

Les structures de contrle

Extrmement utiles, les structures de contrle vous permettront de faire des boucles et des tests dans vos scripts PHP.

If, else, elseif


La boucle de contrle if est sans aucun doute la plus importante dans tous les langages de programmation ; cela vaut aussi en PHP. La syntaxe est classique :
if (expression) instruction;

ou, sil y a plusieurs instructions (et cela reste conseill mme sil ny a quune seule instruction) :

148

Les structures de contrle

if (expression) { instruction1; instruction2; instruction3; }


expression est une expression boolenne ; si elle est vrifie (TRUE), la ou les expressions qui suivent sont values :

<?php $a=3; if ($a>1) echo "a est suprieur un"; ?>

3. Le langage PHP

Expressions Les expressions peuvent bien entendu utiliser tous les oprateurs de comparaison et de logique. Il faut toutefois sassurer que les parenthses sont correctement places.
Maintenant, il est trs probable que vous ayez envie dexcuter certaines instructions si lexpression retourne TRUE (Vrai), et dautres si elle retourne FALSE (Faux). Dans ce cas, il faut utiliser lexpression suivante :
if (expression) { instruction1; instruction2; instruction3; } else { instruction4; instruction5; }

Voici un exemple :
<?php $a=3; if ($a>1) echo "a est suprieur un"; else echo "a est infrieur ou gal un"; ?>

Pour obtenir une valeur ou une autre selon le rsultat dun test, il est possible dutiliser les instructions ? et : selon le schma suivant :
(expression) ? (valeur1) : (valeur2)

Ce qui donne par exemple :


<?php $a=3; echo "a est ".(($a>1)?"suprieur":"infrieur ou gal")." un"; .>

149

Chapitre 3

Le langage PHP

Accolades Encore une fois, dans le cas dune seule instruction, les accolades peuvent tre omises, mais cela est dconseill (comme lindiquent les rgles de codage).
Il se peut que vous souhaitiez faire plusieurs tests conscutifs ; pour cela vous pouvez utiliser les instructions if..elseif..else
if (expression) { instruction1; instruction2; instruction3; } elseif { instruction4; instruction5; } else { instruction6; instruction7; }

3. Le langage PHP

Reprenons lexemple prcdent et amliorons-le :


<?php $a=3; if ($a>1) echo "a est suprieur un"; elseif ($a<1) echo "a est infrieur un"; else echo "a vaut 1"; ?>

Jouer lalternance Comme cela a dj t voqu, les portions de script PHP peuvent tre places comme bon vous semble dans le script (vous pouvez ainsi alterner les portions de PHP et de HTML). Ainsi, le script suivant est valide :
<?php $a=3; if ($a>1) { ?> a est suprieur un <?php } elseif ($a<1) { ?> a est infrieur un <?php else { ?> a vaut 1 <?php

150

Les structures de contrle

} ?>

Il existe encore une autre faon (mme si nous la dconseillons) de noter. Au lieu dutiliser les accolades, la notation suivante est galement valide. Dans ce cas, la fin du bloc est indique par endif.
if (expression): instruction1; instruction2; instruction3; elseif: instruction4; instruction5; else: instruction6; instruction7; endif;

3. Le langage PHP

Exemple (premire tape)


partir de cette boucle de contrle, il est dj possible de faire des scripts intressants. Ralisons ensemble un script de Quizz.

Listing 3.8 : quizz01.php


<html> <head> <title>Quizz</title> </head> <body> <?php if (isset($_POST["reponse"])) { $reponse=$ _POST["reponse"]; } else { $reponse=""; } ?> <p>Quel est le site officiel de PHP ?</p> <form type="post" action="<?php echo $_SERVER["PHP_SELF"];?>"> <input type="text" name="reponse" value="<?php echo $reponse ?>" /> <input type="submit" value="OK" /> </form> <?php if ($reponse!="") { if (strtolower($reponse) == "www.phpfacile.com") echo "Ce nest pas la bonne rponse"; elseif (strtolower($reponse) == "www.php.net") echo "Bingo !"; else echo "Et non, ce nest pas ".$reponse; } ?>

151

Chapitre 3

Le langage PHP

</body> </html>

Ici, la seule structure utilise est if elseif else. Le fichier HTML de dpart est un simple formulaire qui senvoie lui-mme la rponse saisie. Voici ce que signifie ce script : Si la variable $reponse est dfinie, alors on compare la valeur de la variable rponse transforme en minuscules avec la chane "www.phpfacile.com".. Si ces chanes sont identiques alors "Ce nest pas la bonne rponse" est affich, sinon on compare "www.php.net" .. Si ces chanes sont identiques "Bingo" est affich, sinon la phrase "Eh non, ce nest pas " suivie de la rponse entre est affiche.

3. Le langage PHP

Figure 3.6 : Quizz v0

While, do while
Pour rpter une srie dinstructions, linstruction while ou "tant que" en franais vous sera utile. Voici la syntaxe :
while (expression) instruction;

Cela signifie que tant que lexpression sera VRAIE, linstruction sera excute. Il faut donc sassurer que lexpression passe obligatoirement FAUX un moment donn, sinon le script bouclera linfini et ne se terminera que lorsque le temps maximal dexcution dun script sera atteint. Bien sr, lutilisation des accolades est galement possible (et conseille) ici.
while (expression) { instruction1; instruction2; }

La notation avec les : est galement valide (quoique dconseille). Dans ce cas, le bloc est termin par endwhile.
while (expression): instruction1; instruction2; endwhile;

152

Les structures de contrle

Voici un exemple concret de script qui affiche les entiers de 1 10.

Listing 3.9 : Exemple


<?php $i = 1; while ($i <= 10) { echo print $i++; } ?>

Dure de vie dun script Vous pouvez rgler le temps dexcution dun script dans le fichier de configuration de PHP : il suffit de donner une valeur en secondes max_execution_time au niveau du fichier de configuration php.ini ou via la fonction set_time_limit(). Ainsi, sil savre que votre boucle ne se termine pas, le script ne tournera pas indfiniment.

3. Le langage PHP

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur le fichier php.ini.
Une variante de la boucle while est la boucle dowhile. La diffrence rside dans ce que le test est fait aprs les instructions. Ainsi, la srie dinstructions est obligatoirement effectue au moins une fois avant dtre teste. Voici la syntaxe :
do { instruction1; instruction2; } while (expression);

For, foreach
Les boucles for sont trs utilises ; elles fonctionnent, comme dans dautres langages, de la faon suivante :
for (expression1; expression2; expression3) instruction
expression1 est excute avant toute itration. Elle sert donc gnralement initialiser les

variables de la boucle.
expression2 est excute chaque itration. Si elle est VRAIE, une nouvelle excution des

instructions a lieu, sinon le programme sort de la boucle.


expression3 est une instruction excute chaque itration. Elle sert gnralement incrmenter une variable.

Voici un exemple de script qui affiche les chiffres de 0 9 :


for ($i=0;$i<10;$i++) echo $i;

153

Chapitre 3

Le langage PHP

Il faut lire cette commande comme suit : aprs avoir initialis $i 0, et tant que $i est infrieur 10, afficher $i, puis lincrmenter. Linstruction break permet de sortir de la boucle. Dans ce cas, le restant des instructions nest pas excut.
for ($i=0;;$i++) { echo $i; if ($i==9) break; }

Ces lignes de code auront le mme effet que le script prcdent.

3. Le langage PHP

Il est aussi possible de se servir de la syntaxe utilisant les deux-points (:). Dans ce cas, le bloc se termine par endfor.
for (expression1;expression2;expression3): instruction1; instruction2; endfor;

Linstruction foreach. offre une autre manire de raliser une boucle, et elle est particulirement pense pour les tableaux. Voici deux syntaxes possibles :
foreach($tableau as $valeur) instruction; foreach($tableau as $cle => $valeur) instruction;

Dans la boucle, la valeur de lentre du tableau est rcuprable par $valeur ; la cl associe est rcuprable par $cle, condition dutiliser la seconde syntaxe dans cet exemple.

Pointeur de tableau Lorsque la boucle foreach est invoque, elle met le pointeur du tableau en premire position. Il est donc inutile dappliquer la fonction reset() dessus.

Exemple (deuxime tape)


Cette fois, le script propos permet de rpondre plusieurs questions sur une mme page. Il utilise une boucle foreach et une boucle for ainsi que des tests if.

Listing 3.10 : quizz02.php


<html> <head> <title>Quizz</title> </head> <body> <?php $questions = array("Quel est le site officiel de PHP ?", "Quel est le nom de la commande qui

154

Les structures de contrle

affiche une chane de caractre ?", "Quel est le nom de la commande qui met une chane de caractre en minuscule ?"); $reponses=array("www.php.net","echo","strtolower"); // initialisation des variables foreach($questions as $index => $question) { if (isset($_POST["reponse$index"])) { ${"reponse$index"} = $_POST["reponse$index"]; } else { ${"reponse$index"} = ""; } } ?> <form type="post" action="<?php echo $_SERVER["PHP_SELF"];?>"> <?php foreach($questions as $index => $question) { echo $question; echo "<input type=\"text\" name=\"reponse$index\" value=\"${"reponse$index"}\"><br>"; } ?> <input type="submit" value="OK"> </form> <?php if ($reponse0 != "") { $parfait = TRUE; for ($i=0; $i<sizeof($questions); $i++) { if (strtolower(${"reponse$i"}) == $reponses[$i]) { echo "<br />La rponse ".($i+1)." est correcte"; } else { echo "<br />La rponse ".($i+1)." est fausse"; $parfait = FALSE; } } if ($parfait) echo "<br />Bravo !"; else echo "<br />Perdu ..."; } ?> </body> </html>

3. Le langage PHP

Voici une capture dcran de ce script en cours dexcution.

155

Chapitre 3

Le langage PHP

Figure 3.7 :

Quizz v1

3. Le langage PHP

Switch
Utiliser switch revient utiliser des tests if conscutifs sur la mme variable. Voici un exemple dutilisation de switch.
switch ($chanteur) { case "Cantat": echo "Ce chanteur est celui de Noir Desir"; break; case "Harper": echo "Ce chanteur est celui de Ben Harper and the innocent criminals"; break; case "Torrini": echo "Cette chanteuse est Emiliana Torrini"; break; default: echo "Ce chanteur mest inconnu"; }

Ce script est quivalent :


if ($chanteur=="Cantat") echo "Ce chanteur est celui de Noir Desir"; elseif ($chanteur=="Harper") echo "Ce chanteur est celui de Ben Harper and the innocent criminals"; elseif ($chanteur=="Torrini") echo "Cette chanteuse est Emiliana Torrini"; else "Ce chanteur mest inconnu";
default est la condition qui sera VRAIE si aucune des autres ne lest.

Linstruction break est indispensable ici, sinon toutes les instructions qui suivent sont interprtes jusquau prochain break ou la fin du bloc switch. Cela peut tre utile dans certains cas.
switch ($i) { case 0:

156

Les structures de contrle

case 1: case 2: echo "i est positif mais infrieur 3 "; break; case 3: echo "i vaut 3"; }

Comparaison Contrairement dautres langages de programmation, la variable comparer peut tre aussi bien un nombre quune chane de caractres. 3. Le langage PHP

Break, continue
Deux instructions permettent de contrler les sorties de boucle (for, while). break est une instruction qui fait sortir de la boucle, alors que continue passe litration suivante sans excuter les instructions daprs.
<html> <head><title>Continue, Break</title></head> <body> <p> <?php for ($i=0;$i<10;$i++) { echo $i; // va afficher 0,2,4,6,8 $i++; echo $i; // va afficher 1.3.5.7.9 } echo "<br>"; for ($i = 0; $i < 10;$i++) { echo $i; $i++; if ($i>4) break; echo $i; } echo "<br>"; for ($i=0;$i<10;$i++) { echo $i; $i++; if ($i>4) continue; echo $i; } ?> </p> </body> </html>

Voici le rsultat obtenu :

157

Chapitre 3

Le langage PHP

Figure 3.8 : Rsultat

3. Le langage PHP

Pour bien comprendre, regardons la premire boucle. Elle affiche tous les chiffres de 0 9, mais affiche deux chiffres chaque itration. La deuxime boucle, semblable la premire, utilise linstruction break. la premire itration les chiffres 0 et 1 sont affichs. la seconde les chiffres 2 et 3 sont affichs. Puis 4 est affich. Enfin, aprs lincrmentation $i vaut 5 (et la condition est vrifie) et le programme sort dfinitivement de la boucle. La troisime boucle utilise linstruction continue. la premire itration les chiffres 0 et 1 sont affichs. la seconde les chiffres 2 et 3 sont affichs. Puis 4 est affich.Enfin, aprs lincrmentation $i vaut 5 (la condition est vrifie) et la seconde instruction echo nest pas excute (donc 5 nest pas affich). Mais une nouvelle itration est ralise faisant apparatre le chiffre 6, mais pas 7, puis 8, mais pas 9.

3.7.

Les fonctions

PHP possde, comme de nombreux langages, la possibilit de regrouper des portions de code sous la forme de fonctions (ou procdures). Si la dfinition de fonctions na aucun impact sur le fonctionnement dun programme, et donc sil est possible de construire son dveloppement comme une suite dinstructions mises bout bout, elle procure en revanche visibilit et rduction de la taille du code source. La maintenance nen est alors que plus simple et plus rapide. Les fonctions permettant de structurer le code, il est fortement conseill de les utiliser et de constituer des fichiers indpendants qui regrouperont les fonctions de mme type. Ces bibliothques pourront facilement tre rutilises dans dautres dveloppements et rduire ainsi le temps de mise au point (et donc le cot de production). Trois avantages dcoulent donc de lcriture du code sous forme de fonctions :
j

Le temps de dveloppement est considrablement rduit. En effet, vous navez pas retaper des squences de code identiques en divers endroits du programme. De la mme faon, les bugs ne sont pas dupliqus, do un gain de temps considrable lors de la phase de mise au point. Meilleure lisibilit du code source. Le simple fait de regrouper le code en fonctions et les fonctions dans des fichiers spars permet aux dveloppeurs de sy retrouver trs facilement. De plus, donner vos fonctions des noms significatifs est complmentaire avec lajout des commentaires, et facilite ncessairement la lisibilit et la comprhension du programme. Ceci est dautant plus important pour la prennit dun code. Ainsi, la

158

Les fonctions

maintenance et les modifications du programme sont facilites, mme pour un dveloppeur reprenant son propre code quelques temps aprs lavoir crit.
j

Le travail en quipe est amlior. Un dveloppement peut ainsi tre dcoup en plusieurs sous-parties, chaque dveloppeur ayant alors la tche de mettre au point une ou plusieurs fonctions.

Si lemploi de fonctions est un avantage certain, une tape de conception pralable reste ncessaire afin de bien dfinir les fonctions qui devront tre dveloppes et de bien cibler leurs rles respectifs. Plus important encore, ltape prliminaire permet de fixer les rgles dentre/ sortie de chacune des fonctions, ceci afin que chaque dveloppeur connaisse lavance les paramtres quil doit envoyer la fonction et ce quelle doit retourner une fois le traitement effectu. Si les fonctions sont connues ds le dbut, alors chacun pourra commencer les utiliser dans son code avant mme la mise en production desdites fonctions.

3. Le langage PHP

La syntaxe
La fonction est un sous-programme isol du reste du code et utilisable par un simple appel depuis nimporte quelle partie du programme. La syntaxe pour dclarer une fonction simple est la suivante :
<?php function premiereFonction() { echo "Jaime PHP !"; } ?>

Ce code naffiche rien tant que lon ne fait pas appel elle comme ceci :
<?php function premiereFonction() { echo "Jaime PHP !"; } premiereFonction(); // Affiche "Jaime PHP !" ?>

Le cas prcdent est un bon exemple de dclaration de fonction et dutilisation de celle-ci lintrieur du programme principal. On voit lintrt quapporte la dfinition de la fonction dans le cas o la tche de celle-ci est rptitive et devrait engendrer beaucoup de code source.

Le choix du nom dune fonction Afin de faciliter la lecture de votre code, nhsitez pas donner vos fonctions un nom vocateur. Tout comme pour les variables, la lecture de votre programme est facilite si ces lments portent des noms explicites. Si les fonctions du programme sappellent fonction1(), fonction2() et fonction3(), la maintenance nen sera que plus difficile. Ne donnez pas vos fonctions un nom trop nigmatique ou qui peut avoir plusieurs sens. vitez les noms de fonctions trop courts pour quils ne 159

Chapitre 3

Le langage PHP

soient pas utiliss plusieurs fois dans votre programme. Par exemple, pour une fonction devant compter un nombre de personnes prsentes sur une page web, ne lappelez pas simplement compteur(), mais plutt compteurPersonneEnLigne().

La porte des variables


3. Le langage PHP
Comme nous lavons dit, une fonction nest rien dautre quun bout de code isol du programme principal. Cest donc sans surprise que vous apprendrez quil est possible de dfinir des variables au sein des ses fonctions. Par contre, ce quil faut retenir cest que les variables ainsi dfinies ne sont pas accessibles du reste du programme (elles ont une porte locale), comme le dmontre lexemple suivant :
<?php function bicentenaire() { $annee = "2002"; echo "$annee ctait le bicentenaire de la naissance de Victor Hugo !"; } bicentenaire(); // Affiche "2002 ctait le bicentenaire de la naissance de Victor Hugo !" echo $anne; // naffiche rien, la variable nest pas dfinie. ?>

linverse, une variable dfinie en dehors de la fonction (dans le programme principal) nest pas accessible depuis la fonction.
<?php $annee = "2002"; $prenom = "Victor"; $nom = "Hugo"; function bicentenaire() { echo "$annee ctait le bicentenaire de la naissance de $prenom $nom !"; } bicentenaire(); /* affiche "ctait le bicentenaire de la naissance de !" Les variables $annee, $nom et $prenom ne sont pas dfinies au niveau de la fonction */ ?>

Pour utiliser des variables globales dans la fonction, il faut utiliser le mot-cl "global" lintrieur de cette fonction, comme le montre lexemple suivant :
<?php $annee = "2002";

160

Les fonctions

$prenom = "Victor"; $nom = "Hugo"; function bicentenaire() { global $annee, $prenom, $nom; echo "$annee ctait le bicentenaire de la naissance de $prenom $nom !"; $annee = "2003"; } bicentenaire("bicentenaire"); // affiche "2002 ctait le bicentenaire de la naissance de Victor Hugo!"

3. Le langage PHP

echo $annee; // affiche 2003 ?>

Comme vous le constatez, les modifications apportes ces variables globales au sein de la fonction se rpercutent en dehors de la fonction. Il existe une autre faon de faire pour utiliser les variables globales depuis une fonction. Cette mthode consiste utiliser directement le tableau prdfini $GLOBALS. Lexemple prcdent donnerait alors :
<?php $annee = "2002"; $prenom = "Victor"; $nom = "Hugo"; function bicentenaire() { echo $GLOBALS["annee"]." ctait le bicentenaire de la naissance de ". $GLOBALS["prenom"]." ".$GLOBALS["$nom"]." !"; $GLOBALS["annee"] = "2003"; } bicentenaire("bicentenaire"); // affiche "2002 ctait le bicentenaire de la naissance de Victor Hugo!" echo $annee; // affiche 2003 ?>

Variables denvironnement Les variables externes $_SERVER, $_ENV, $_GET, $_POST, $_SESSION, $_COOKIE, $_FILES, etc. sont, quant elles, accessibles depuis nimporte o. Il nest donc pas ncessaire, dans leur cas, de prciser global pour les utiliser dans une fonction.

161

Chapitre 3

Le langage PHP

La porte dune variable dpend donc de lendroit o elle est initialise. La porte dune variable ne sera pas la mme si elle est dfinie dans une fonction ou au dbut de votre programme. On peut considrer trois niveaux de dfinition.

Tableau 3.12 : Les diffrents niveaux de dfinition des variables


Niveau Local Description Les variables sont propres chaque fonction. Ds la fin de lexcution de cette fonction, la variable est dtruite et lespace mmoire qui contenait la valeur est libre. Les variables globales sont dfinies pour la totalit du temps dexcution du code de la page. Les variables statiques sont propres chaque fonction, mais elles ne sont pas dtruites la fin de lexcution de cette fonction. Si la fonction est rappele plusieurs fois, la valeur de la variable est conserve et modifie chaque fois.

3. Le langage PHP

Global Static

Il nous reste donc aborder le cas des variables statiques. Ces variables sont initialises au premier appel de la fonction et ne sont pas rinitialises les fois suivantes. Pour crer une variable statique, il faut utiliser le mot-cl static suivi du nom de la variable. Exemple dutilisation :
<? function maFonction (){ static $variable = "Emma "; $variable . =" Cest toi?"; echo $variable."<br>"; } maFonction(); maFonction(); maFonction(); ?>

Cela affichera en effet :


Emma Cest toi? Emma Cest toi? Cest toi? Emma Cest toi? Cest toi? Cest toi?

Initialisation dune variable statique Il nest pas possible dinitialiser une variable statique avec le rsultat dune fonction. On peut toutefois contourner ce problme en affectant cette variable une valeur quelle est suppose ne jamais atteindre, et appeler la fonction si jamais la variable prend cette valeur.

162

Les fonctions

<?php function maFonction() { static $date = -1; if ($date == -1) $date = time(); } ?>

Le passage des paramtres


Vous serez souvent amen rclamer des paramtres pour vos fonctions. Pour cela, il suffit de complter la ligne de dclaration de la fonction par une liste de noms de variables. Les variables ainsi dfinies ne sont accessibles qu lintrieur de la fonction ; ce sont donc des variables de visibilit locale.
<?php function bicentenaire($quoi) { echo "2002 ctait le $quoi de Victor Hugo !"; } bicentenaire("bicentenaire de la naissance "); // Affiche "2002 ctait le bicentenaire de la naissance de Victor Hugo !" echo $quoi; // naffiche rien, la variable nest pas dfinie. ?>

3. Le langage PHP

Les paramtres par dfaut


Vous pouvez donner votre fonction des paramtres par dfaut. Ainsi, si vous ne rentrez aucune valeur lors de lappel de cette fonction dans votre code, une valeur par dfaut est utilise afin dexcuter la fonction. Pour placer une valeur par dfaut, vous devez simplement spcifier cette valeur laide du signe "=" lors de la dclaration de la fonction. Comme ceci :
<?php function exemple($parDefaut="bonjour") { return $parDefaut; } ?>

Cette fonction peut donc recevoir ou non une valeur comme paramtre. Si ce nest pas le cas, alors celle-ci prend, par dfaut, la valeur "bonjour". Il y a donc deux faons dappeler cette fonction dans le programme principal.
<?php function exemple($pardefaut="bonjour") { return $pardefaut; }

163

Chapitre 3

Le langage PHP

// soit en plaant une valeur en paramtre echo exemple("bye bye"); // affiche "bye bye" // soit en laissant vide echo exemple(); // affiche "bonjour" ?>

Le fait que les fonctions ncessitent a priori un nombre fixe darguments vous posera peut-tre un jour un problme. Mais il y a deux faons dy faire face:
j j

En utilisant un tableau, si votre fonction naccepte quun seul argument mais que celui-ci est de type tableau, vous pouvez y mettre autant darguments que vous voulez. En utilisant les fonctions mises disposition par PHP (ce qui en fait sapparente utiliser un tableau cr par PHP).

3. Le langage PHP

Ainsi, alors que func_num_args() renvoie le nombre dlments passs en paramtre dune fonction, func_get_arg() et func_get_args() permettent de rcuprer un argument ou un tableau darguments.

func_num_args()
Retourne le nombre darguments passs une fonction. Syntaxe retour int func_num_args(void) Retourne un nombre correspondant aux nombres dlments passs comme arguments de la fonction.

<?php function elementsVariables() { return func_num_args(); } echo elementsVariables(); // Affiche 0; echo elementsVariables(1, 2, 3); // Affiche 3; echo elementsVariables("toto", 5, TRUE); // Affiche 3; ?>

func_get_arg()
Retourne la valeur dun des lments passs en argument de la fonction. Syntaxe $numArg retour mixed func_get_arg(int $numArg) Position de llment consulter. La valeur de largument.

164

Les fonctions

func_get_args()
Retourne un tableau contenant tous les lments passs en argument la fonction. Syntaxe retour array func_get_args(void) Tableau index contenant la liste des arguments de la fonction.

Voici un exemple de lutilisation qui peut tre faite des trois fonctions prcdemment dcrites :
<?php function elementsVariables() { // Compte le nombre dlments $nombreElements = func_num_args(); // Rcupre tous les lments dans un tableau $tableauElements = func_get_args(); for ($i=0; $i<$nombreElements; $i++) { // Affiche tous les arguments de la fonction echo "lment $i : ".$tableauElements[$i]."<br />"; } // Rcupre llment dsign par le deuxime argument echo "largument n".func_get_arg(1). " = ".func_get_arg(func_get_arg(1))."<br />"; } elementsVariables(10, 0, 3); echo "<br />"; elementsVariables("toto", 3, TRUE, "PHP"); ?>

3. Le langage PHP

Lexcution de ce programme renvoie donc ici :


lment 0 : 10 lment 1 : 0 lment 2 : 3 largument n0 = 10 lment 0 : toto lment 1 : 3 lment 2 : 1 lment 3 : PHP largument n3 = PHP

165

Chapitre 3

Le langage PHP

Le passage de paramtres par rfrence


Lorsque lon passe une variable en paramtre une fonction, la variable transmise na quune porte locale, et la variable manipule au sein de la fonction nest en fait quune copie de la variable transmise par le programme appelant. Ainsi, lexcution de la fonction nentrane aucune modification sur la variable transmise. Lorsque lon souhaite que la fonction modifie la valeur de la variable passe en paramtre, celle-ci doit tre passe non pas par valeur mais par rfrence. Lorsquune variable est passe en rfrence, la nouvelle variable locale ainsi cre pointe sur la mme zone mmoire, mais avec un autre nom que le paramtre. Ainsi, on a un alias de la variable qui se cre dans la fonction, et toutes les modifications qui lui seront apportes seront rpercutes sur loriginal.

3. Le langage PHP

Ce nest toutefois pas lappelant qui dcide si la variable doit tre passe par valeur ou par rfrence, mais la fonction. Ainsi, pour utiliser une rfrence, il suffit simplement de signaler le paramtre de la fonction avec un "&" devant le nom de la variable.
<? $phrase = "Ceci est temporaire"; function citation(&$reference, $nom, $prenom) { $reference = $nom." ".$prenom. " a crit : Les crivains ont mis la langue en libert." } citation($phrase, "Victor", "Hugo"); echo $phrase; // affiche "Victor Hugo a crit : Les crivains ont mis la langue en libert." ?>

Dans lexemple prcdent, nous pouvons constater que les modifications apportes la variable locale $reference se rpercutent sur la variable globale $phrase.

Utilisation des paramtres de type objet Comme nous le verrons dans le chapitre sur la programmation oriente objet, contrairement au comportement dautres langages de programmation, dans les versions de PHP infrieure la version 5 (incluant le moteur Zend2), les objets ne sont pas automatiquement passs par rfrence. Pour ne pas travailler sur une copie de lobjet il est donc, l aussi, ncessaire dutiliser le "et commercial" &.

PHP 5 Avec PHP 5, il est dsormais possible de spcifier une valeur par dfaut l o lon attend un argument pass par rfrence.
function maFonction(&$param = "valeurParDefaut")

Alors que, vous laurez devin, ce ntait pas possible auparavant.

166

Les fonctions

Retourner une valeur


Vous serez sans doute amen vouloir rcuprer le contenu dune variable la suite du traitement dune fonction. Pour effectuer le renvoi dune variable et ainsi terminer lexcution de la fonction, le langage PHP utilise le mot-cl return. Lorsque cette instruction est rencontre, la fonction value la valeur de la variable qui suit et la renvoie dans le programme principal. Exemple dutilisation :
return $valRetour; return 0; return "Laurent";

3. Le langage PHP

Ce qui donne dans le cas dune utilisation :


<?php function fonctionRetour() { return "guitare"; } echo fonctionRetour(); // affiche "guitare" ?>

Sil est possible de placer plusieurs instructions return lintrieur dune fonction, le premier return excut met un terme lexcution de la fonction.
<?php function associationNom($varATester) { if ($varATester=="Laurent") { return "GUEDON"; } elseif ($varATester =="Damien" || $varATester == "Thomas") { return "HEUTE"; } elseif ($varATester =="Pierre-Emmanuel") { return "MULLER"; } else { return "Qui ???"; } } ?>

Linstruction return ne permet de renvoyer quune seule valeur. Si vous souhaitez retourner plusieurs valeurs, deux possibilits soffrent vous :
j j

Retourner un tableau de valeurs ou un objet avec plusieurs attributs. Utiliser plusieurs paramtres passs par rfrence (qui serviront donc plus de valeur retour que de valeur dentre) ; ventuellement, la fonction pourra galement retourner une valeur via return.

Il nest pas vraiment possible de dire a priori quelle est la bonne mthode. Cest un peu au cas par cas. La premire oblige ensuite analyser le contenu dun tableau (et lutilisation dun objet

167

Chapitre 3

Le langage PHP

ne se justifie pas toujours). La seconde mthode nest pas totalement satisfaisante, puisque lon mlange paramtres dentre et paramtres de sortie ; a contrario, elle permet de rserver la valeur retour pour un boolen indiquant si lopration sest bien passe ou non. Voici un exemple utilisant un tableau montrant comment sortir de ce problme, que vous rencontrerez sans doute dans votre carrire de dveloppeur.
<?php function discotheque($choix) { switch ($choix) { case 1 : $artiste = "Placebo"; $titre = "Where is my mind"; break; case 2 : $artiste = "Emiliana Torrini"; $titre = "To be free"; defaut : $artiste = "Radiohead"; $titre = "Creep"; } return array($artiste, $titre); } $disque = discotheque(3); echo "Artiste ".$disque[0] ."\n"; echo "Titre ".$disque[1] ."\n"; ?>

3. Le langage PHP

Ici, la fonction retourne un tableau de valeurs. Il est donc ensuite possible de traiter le tableau et de sortir les diffrentes donnes, comme si la fonction nous avait renvoy plusieurs variables. Le rsultat du petit programme ci-dessus nous donne donc :
Artiste Radiohead Titre Creep

Manipuler des fonctions


Une srie de commandes permet de crer la vole, de tester lexistence des fonctions et de les manipuler. Lune delle permet de crer des fonctions dites anonymes.

create_function()
Permet de crer une fonction anonyme partir de paramtres.

168

Les fonctions

Syntaxe $arguments $code retour

string create_function(string $arguments ,string $code ) Liste des paramtres de la fonction spars par une virgule. Le code de la fonction. Nom attribu la fonction (en sassurant de son unicit).

<?php $fonction = create_function($a,$b,return $a + $b;); echo "Nom de la nouvelle fonction : $fonction<br />"; echo "10 + 5 = ".$fonction(10, 5); // "Nom de la nouvelle fonction : lambda_1" // "10 + 5 = 15" ?>

3. Le langage PHP

retourne
Nom de la nouvelle fonction: lambda_1 10 + 5 = 15

Notez que vous pouvez utiliser des guillemets ( la place des apostrophes) dans la dfinition des arguments et du code de la fonction, condition de ne pas oublier dchapper le caractre $ prcdant les noms de variables comme ceci :
$fonction = create_function("\$a,\$b","return \$a + \$b;");

Il est galement possible de vrifier si une fonction existe ou non. Ceci permet notamment de vrifier si lenvironnement (version de PHP, options de configuration) dans lequel tourne le script permet la ralisation de lopration prvue. Ceci peut galement permettre de crer une fonction mulant une fonction existant dans les dernires versions de PHP, uniquement si celle-ci nest pas disponible dans la version utilise (afin que le script puisse fonctionner sur danciennes versions).

function_exists()
Permet de vrifier si une fonction existe bien. Syntaxe $nomFonction retour boolean function_exists(function $nomFonction) Nom de la fonction vrifier. Retourne TRUE si la fonction a t trouve, FALSE sinon.

<?php if (function_exists("uneFonctionDontJAiBesoin")) { echo "Chouette je peux utiliser la fonction<br />"; uneFonctionDontJAiBesoin(); } else { echo "La fonction nexiste pas tant pis pour vous<br />"; }

169

Chapitre 3

Le langage PHP

if (function_exists("function_exists")) { echo "Par contre la fonction function_exists() existe<br />"; } else { echo "Curieux<br />"; }

retournera
La fonction nexiste pas tant pis pour vous Par contre la fonction function_exists() existe

3. Le langage PHP

On peut aussi simplement lister toutes les fonctions dfinies laide de la fonction get_defined_functions().

get_dened_functions()
Liste toutes les fonctions dfinies. Syntaxe retour array get_defined_functions(void) Tableau associatif contenant les cls. "internal" ayant pour valeur un tableau index contenant les noms des fonctions PHP "natives". "user" ayant pour valeur un tableau index contenant les noms des fonctions dfinies par lutilisateur.
<?php function fonction1($a, $b) { return ($a + $b); } function fonction2($a) { return $a; } function fonction3($a, $b) { return ($a + $b); } function fonction4($a, $b, $c) { return ($a + $b + $c); } function fonction5($a, $b, $c, $d) {

170

Les fonctions

return ($a + $b + $c + $d); } $tableauFonction = get_defined_functions(); print_r($tableauFonction); ?>

Cela affiche toutes les fonctions sous la forme dun tableau de tableaux.
Array ( [internal] => Array ( [0] => zend_version [1] => func_num_args [2] => func_get_arg ...... [1161] => apache_note [1162] => apache_lookup_uri [1163] => apache_child_terminate ) [user] => Array ( [0] => fonction1 [1] => fonction2 [2] => fonction3 [3] => fonction4 [4] => fonction5 ) )

3. Le langage PHP

Listons simplement les fonctions utilisateurs.


<?php while(list ($key, $val)=each($tableauFonction["user"])) { echo "$key => $val<br />"; } ?>

Le rsultat cette fois est simplement :


0 1 2 3 4 => => => => => fonction1 fonction2 fonction3 fonction4 fonction5

Les fonctions utilisateurs peuvent aussi tre appeles laide des commandes call_user_func_array() ou call_user_func(). Ces commandes sont trs utiles lorsquun programme doit faire appel diffrentes fonctions dynamiquement.

171

Chapitre 3

Le langage PHP

call_user_func()
Appelle une fonction utilisateur en lui transmettant des paramtres. Syntaxe $nomFonction $parametre retour mixed call_user_func(string $nomFonction [, mixed $parametre [, mixed ...]]) Nom de la fonction appeler. Liste des paramtres ( transmettre dans le mme ordre que sa dclaration). Renvoie le code retour de la fonction appele.

3. Le langage PHP

call_user_func_array()
Appelle une fonction utilisateur en lui transmettant des paramtres rassembls sous la forme dun tableau. Syntaxe $nomFonction $parametre retour mixed call_user_func_array(string $nomFonction [, array $parametre]) Nom de la fonction appeler. Liste des paramtres ( transmettre sous la forme dun tableau). Renvoie le code retour de la fonction appele.

<?php function nombreCaractere($phrase) { return strlen ($phrase); } echo "phrase 1 = ".call_user_func(nombreCaractere, Ich bin ein Berliner! - JF Kennedy(1963))." caractres<br />"; echo "phrase 2 = ".call_user_func(nombreCaractere, 13 janvier 1898, Zola publia Jaccuse)." caractres<br />"; ?>

Le rsultat de ce programme affiche ici :


phrase 1 = 40 caractres phrase 2 = 38 caractres <?php function function function function fonction1($a, fonction2($a, fonction3($a, fonction4($a, $b) $b) $b) $b) { { { { return return return return $a+$b; $a-$b; $a*$b; $a/$b; } } } }

$tableau = array(10,5);

172

Les fonctions

for ($i=1;$i<=4;$i++) { echo "$i => ".call_user_func_array(fonction.$i, $tableau)."<br />"; } ?> 1 2 3 4 => => => => 15 5 50 2

La rcursivit des fonctions


Une fonction est dite rcursive si elle sappelle elle-mme. Cette utilisation particulire des fonctions est rare (ce qui, entre nous, nest pas forcment un dfaut, car elle est trs gourmande en mmoire.). Et pourtant, si elle nest pas indispensable, elle peut-tre trs pratique lorsquil faut traiter certains problmes comme le parcours dune arborescence. Un exemple de fonction rcursive est celui de la fonction donnant le factoriel dun nombre.
<?php function factorielle($nombre) { if ($nombre==0) { return "1"."<br />"; }else{ return $nombre*factorielle($nombre-1)."<br />"; } } echo factorielle (3); // 3! = 1x2x3 = 6 echo factorielle (3); // 3! = 1x2x3 = 6 ?>

3. Le langage PHP

Juste un exemple... de ce quil ne faut pas faire Si cette mthode est la plus simple pour montrer ce quest une fonction factorielle, cest aussi la plus mauvaise mthode pour implmenter factoriel. De plus, les fonctions rcursives sont trs dlicates manipuler. Il est trs important de vrifier que votre fonction se termine bien un moment donn pour viter des problmes de boucles infinies.
Un des exemples de fonctions rcursives les plus rpandus est la rsolution du problme de la tour de Hano. La tour de Hano se prsente comme un casse-tte. Plusieurs disques sont empils sur une tige, du plus large au plus petit. Deux autres tiges se trouvent ct et le but est de dplacer les disques pour les superposer sur la tige centrale dans le mme ordre, cest--dire du plus grand au plus petit.

173

Chapitre 3

Le langage PHP

Figure 3.9 : La tour de Hano

3. Le langage PHP

<html> <body> <?php function deplaceDisque($disque, $tige1, $tige2) { echo "Dplacer le disque ".$disque." sur la tige ".$tige2."<br />"; } function hanoi($disque, $tige1, $tige2) { if ($disque == 1) // si le disque dplacer est le premier { // on ne fait quun dplacement deplaceDisque (1, $tige1, $tige2); }else{ // sinon il faut dplacer $disque-1 // sur la tige diffrente de $tige1 et $tige2 hanoi($disque-1, $tige1, 3-$tige1-$tige2); deplaceDisque ($disque, $tige1, $tige2); // et on redplace les ($disque-1) disques sur le disque dplac hanoi($disque-1, 3-$tige1-$tige2, $tige2); } } hanoi(4, 0, 1); ?> </body> </html> // 4 disques utiliss

3.8.
j

Les tableaux
Les tableaux indexs o chaque lment du tableau porte un numro (ce qui correspond la reprsentation habituelle dun tableau dans les autres langages de programmation). Par dfaut, la numrotation commence avec lindice 0. Les tableaux associatifs o chaque lment du tableau est associ une cl reprsente par une chane de caractres (ce qui correspond peu de choses prs une table de hash dans les autres langages de programmation).

En PHP, il est possible de distinguer trois types de tableaux.

174

Les tableaux

Les tableaux mixtes o chaque lment du tableau est associ aussi bien un indice qu une cl.

Cette distinction entre les tableaux est surtout "conceptuelle". En effet, leur mode de fonctionnement est totalement identique.

Index et ordre dans le tableau Les index doivent tre perus simplement comme des cls de type entier. La valeur dun index ne prjuge pas de la position dun lment dans le tableau. Un lment peut avoir un index gal 0 et se trouver en fin de tableau. Un tableau est juste un ensemble (ordonn) de couple (cl, valeur).

3. Le langage PHP

Les valeurs dun tableau


Les valeurs contenues dans un tableau peuvent tre de tout type connu. Ainsi, un tableau peut stocker des entiers, des rels, des chanes de caractres, des tableaux, des objets, etc. De plus, les types des valeurs contenues dans un tableau peuvent varier dun indice (ou dune cl) lautre. Le second lment dun tableau pourra contenir une chane de caractres, mme si le premier lment contient un objet.

Initialisation dun tableau


La syntaxe de base de linitialisation dun tableau est la suivante :
$monTableau = array();

Mais, part pour forcer le type dune variable au type tableau, il est bien rare que nous utilisions cette forme pure. Linitialisation du tableau se fait gnralement en mme temps que son remplissage. Ainsi, dans le cas "classique" dun tableau index, on pourra par exemple prciser les valeurs associes aux trois premiers index par :
$monTableau = array(23, "PHP", 12.4);

Ce qui donnera alors :


$monTableau[0] = 23; $monTableau[1] = "PHP"; $monTableau[2] = "12.4";

Dans le cas dun tableau associatif, il faudra prciser la cl et la valeur selon le schma suivant :
$tableauAge = array("Pierre" => 22, "Thierry" => 29, "Jean" => 34);

175

Chapitre 3

Le langage PHP

Pour obtenir :
$tableauAge["Pierre"] = 22; $tableauAge["Thierry"] = 29; $tableauAge["Jean"] = 34;

Et pour un tableau mixte il est possible de prciser :


$monTableau = array("Thierry", 29, "Prnom" => "Thierry", "Age" => 29);

Ce qui donnerait :

3. Le langage PHP

$monTableau[0] = "Thierry"; $monTableau[1] = 29; $monTableau["Prnom"] = "Thierry"; $monTableau["Age"] = 29;

Cas dutilisation des tableaux mixtes Les tableaux mixtes sont utiliss en particulier pour la lecture des enregistrements dune base de donnes. Ainsi, lutilisateur peut faire appel la valeur dun champ soit partir de son index soit partir du nom du champ.

Les subtilits dinitialisation dun tableau


Mme dans le cas dun tableau index, il est possible de prciser pour quel indice vous tes en train de dfinir la valeur ( la manire des tableaux associatifs).
$monTableau = array(1 => "Valeur1", 3 => "Valeur3");

donnera les valeurs suivantes :


$monTableau[1] = "Valeur1"; $monTableau[3] = "Valeur3";
$monTableau[0] et $monTableau[2], quant eux, nauront pas de valeur affecte.

Ordre daffectation Il nest pas ncessaire de prciser les valeurs dans lordre des indices. Ainsi
$monTableau = array(3 => "Valeur3", 1 => "Valeur1");

est tout fait valide.


L encore, il est possible, lors de linitialisation dun tableau, de mlanger cette notation avec celle dun tableau associatif, et mme avec la notation "traditionnelle" dun tableau index. Dans ce dernier cas, les valeurs pour lesquelles on ne prcise pas les index auront ncessairement pour index le dernier index affect + 1 (ou par dfaut 0).
$monTableau = array("Valeur0", 2 => "Valeur2", "Valeur3");

176

Les tableaux

donnera :
$monTableau[0] = "Valeur0"; $monTableau[2] = "Valeur2"; $monTableau[3] = "Valeur3";

Commencer un tableau lindice 1 Cette proprit est bien pratique pour commencer un tableau avec lindice 1.
$monTableau(1 => "Valeur1", "Valeur2", "Valeur3");

3. Le langage PHP

Dans le cas dun tableau index ou associatif, si, dans la chane dinitialisation, plusieurs valeurs sont affectes un mme indice ou une mme cl, la valeur conserve sera toujours la dernire rencontre. Ainsi,
$monTableau = array("Valeur qui va se faire craser", 0 => "Oups... jcrase");

donnera :
$monTableau[0] = "Oups... jcrase";

Remplissage dun tableau


Dune manire tout fait classique, le remplissage (o laffectation des valeurs) dun tableau se fait par un appel du type :
$monTableau[0] = "Valeur";

ou
$monTableau["cle"] = "Valeur";

Mais une des particularits du langage PHP est que la taille des tableaux nest pas fixe. Elle peut donc tre augmente au fil des besoins. Ainsi, pour un tableau index qui a t initialis avec trois lments, il est possible daffecter une valeur llment dindice 10, comme le montre lexemple suivant :
<?php $monTableau = array("valeur1, "valeur2", "valeur3"); $monTableau[10] = "valeur10", ?>

De mme, pour un tableau associatif, il est toujours possible dajouter un lment avec une nouvelle cl. Cela est particulirement utile pour composer une liste dlments. De plus, pour simplifier la tche, le langage PHP nous permet de ne pas prciser dindice ou de cl lors dune affectation, ceci afin dutiliser pour indice le dernier indice affect + 1.

177

Chapitre 3

Le langage PHP

$monTableau[] = "Valeur dindice 0"; $monTableau[] = "Valeur dindice 1";

sera alors quivalent :


$monTableau[0] = "Valeur dindice 0"; $monTableau[1] = "Valeur dindice 1";

Les fonctions de manipulation des tableaux


3. Le langage PHP
Il existe de nombreuses fonctions lies au traitement des tableaux. Certaines sont destines au parcours du tableau, dautres la fusion de tableaux, dautres encore au tri des valeurs ou des cls, etc. Vous dcouvrirez galement dans le chapitre ddi la programmation oriente objet "Les classes, les objets" quil existe galement des objets permettant la manipulation de tableaux.

Fonctions de base

is_array()
Indique si une variable est de type tableau. Syntaxe $variable retour boolean is_array(mixed $variable) Variable tester. TRUE si la variable est de type tableau, FALSE sinon.

count()
Retourne le nombre dlments contenus dans un tableau. Syntaxe $tableau retour int count(array $tableau) Le tableau dont on veut compter le nombre dlments. Le nombre dlments du tableau. Si toutefois le paramtre fourni ne correspond pas un tableau mais une variable existante, alors la valeur retourne est 1. Sil sagit dune variable qui nexiste pas, la fonction retourne 0.

Sil sagit dun tableau index avec des valeurs pour chaque index partir de 0, alors on pourra afficher son contenu grce au code suivant :
<?php $monTableau = array ("PHP", "Cest", "vraiment", "sympa"); for ($i=0; $i<count($monTableau); $i++) echo $monTableau[$i]."<br />"; ?>

178

Les tableaux

La fonction print_r() La fonction print_r() est galement une instruction fort pratique pour visualiser le contenu dun tableau (principalement titre de dbogage).

sizeof()
Est lquivalent de count() (mme syntaxe, mme comportement).

3. Le langage PHP

array_values()
Retourne un tableau index contenant les valeurs des lments dun tableau donn (ce qui peut permettre de rindexer un tableau ou de convertir un tableau associatif en tableau index). Syntaxe $tableau retour array array_values(array $tableau) Tableau de rfrence. Tableau index des valeurs trouves dans $tableau.

Voir aussi array_keys(), qui peut tre utilis pour faire des recherches dans un tableau.

array_unique()
Retourne un tableau dans lequel aucune valeur napparat plusieurs fois (associes diffrentes cls). Syntaxe $tableau retour array array_unique(array $tableau) Tableau de rfrence. Tableau dans lequel chaque valeur napparat quune seule fois. Cest toujours la dernire cl associe une valeur donne qui est conserve.

array_ip()
Intervertit les rles des cls (ou index) et des valeurs dun tableau. Cette fonction nest applicable que si les valeurs peuvent devenir des cls ou, autrement dit, si les valeurs sont des chanes de caractres ou des entiers.

179

Chapitre 3

Le langage PHP

Si le tableau possde plusieurs valeurs identiques, seule la dernire paire (cl, valeur) sera considre. Syntaxe $tableau retour array array_flip(array $tableau) Tableau pour lequel cls et valeurs doivent tre permutes. Tableau pour lequel les cls et les valeurs ont t permutes, ou FALSE en cas dchec.

3. Le langage PHP

array_rand()
Retourne un index (ou une cl) ou un tableau dindex (ou de cls) distincts pris pseudo-alatoirement dans un tableau. Syntaxe $tableau $nbCles retour mixed array_rand(array $tableau, [int $nbCles]) Tableau sur lequel seffectue la recherche. Nombre de cls ou index retourner (par dfaut le nombre de cls est fix 1). Un index (ou une cl) ou un tableau dindex (ou de cls) distincts pris pseudo-alatoirement dans le tableau.

Pseudo-alatoire Comme pour toutes les fonctions pseudo-alatoires, il est fortement conseill de faire au pralable un appel la fonction srand() pour "taper" un peu nimporte o dans la pile des nombres pseudo-alatoires.

Vous pouvez vous reporter au chapitre "Les fonctions mathmatiques" pour plus de dtails sur les nombres pseudo-alatoires et la fonction srand().

Fonctions de recherche dans les tableaux

array_keys()
Retourne un tableau index contenant les cls et index utiliss dans un tableau donn ou, ventuellement, les cls et index associs une valeur donne. Syntaxe $tableau array array_keys(array $tableau [, mixed $valeur]) Tableau de rfrence.

180

Les tableaux

$valeur

Argument optionnel prcisant quelle valeur doivent tre associs les cls et index retourns. Par dfaut, ce sont tous les index et cls du tableau qui sont retourns. Tableau des cls et index trouvs ou un tableau vide si la valeur nest pas trouve.

retour

Listing 3.11 : array_array_keys.php


<?php $sportifs = array("Z. Zidane" => "Foot", "C. Moreau" => "Cyclisme", "T. Henry" => "Foot", "M. Indurain" => "Cyclisme", "J. Durand" => "Cyclisme", "T. Marie" => "Cyclisme"); $cyclistes = array_keys($sportifs, "Cyclisme"); echo "Voici une liste de cyclistes <br />"; for ($i=0; $i<count($cyclistes); $i++) { echo $cyclistes[$i]."<br />"; } ?>

3. Le langage PHP

retournera bien les noms associs au cyclisme. Voici une liste de cyclistes C. Moreau M. Indurain J. Durand T. Marie

array_search()
Retourne la premire cl (ou index) du tableau, associe une valeur donne. Syntaxe $valeur $tableau $strict mixed array_search(mixed $valeur, array $tableau [,boolean $strict]) Valeur recherche. Tableau sur lequel se porte la recherche. Argument optionnel positionner TRUE si lon veut que la comparaison tienne galement compte du type de la valeur cherche. FALSE, par dfaut. Cl (ou index) trouve, FALSE sinon.

retour

181

Chapitre 3

Le langage PHP

array_key_exists()
Indique si un tableau contient ou non une cl donne. Syntaxe $cle $tableau retour boolean array_key_exists(mixed $cle, array $tableau) Cl recherche. Tableau sur lequel se porte la recherche. TRUE si lindex existe, FALSE sinon.

3. Le langage PHP

in_array()
Indique si un tableau contient ou non une valeur donne. Syntaxe $valeur $tableau $strict boolean in_array(mixed $valeur, array $tableau [, boolean $strict]) Valeur recherche. Tableau sur lequel se porte la recherche. Argument optionnel positionner TRUE si lon veut que la comparaison tienne galement compte du type de la valeur cherche. FALSE, par dfaut. TRUE si la valeur a t trouve dans $tableau. FALSE sinon.

retour

Fonctions de manipulation de portions de tableau

range()
Retourne un tableau compos des entiers compris entre une valeur de dbut et une valeur de fin. Syntaxe $debut $fin retour array range(int $debut, int $fin) Premier entier du tableau. Dernier entier du tableau (doit ncessairement tre suprieur ou gal $debut). Tableau compos des entiers compris entre la valeur de dbut (incluse) et la valeur de fin (inclus) ou bien un tableau vide en cas dchec.

182

Les tableaux

array_ll()
Retourne un tableau index construit partir de la rptition dune valeur. Syntaxe $indexDebut $nombre $valeur retour array array_fill(int $indexDebut, int $nombre, mixed $valeur) Premier index du tableau. Nombre dlments dans le tableau. Valeur donner chaque lment du tableau. Tableau index de $indexDebut $indexDebut+$nombre1 ne contenant que la valeur $valeur.

3. Le langage PHP

array_pad()
Retourne un tableau complt ( droite ou gauche) avec une valeur donne pour atteindre un nombre total dlments spcifis. Syntaxe $tableau $taille array array_pad(array $tableau, int $taille, mixed $valeur) Tableau de rfrence. Taille (en valeur absolue) souhaite pour le tableau rsultat. Si vous souhaitez complter le tableau gauche, indiquez alors la valeur en ngatif. Valeur utiliser pour complter le tableau. Retourne le tableau spcifi, complt par la valeur pour atteindre la taille demande. Si celle-ci (en valeur absolue) est infrieure la taille initiale du tableau, ce dernier nest tout simplement pas complt, mais sa taille nen est pas pour autant rduite.

$valeur retour

array_slice()
Retourne un tableau extrait dun autre tableau. Syntaxe $tableau $debut array array_slice(array $tableau, int $debut [, int $longueur]) Tableau de rfrence. Numro dordre du premier lment du tableau extraire. Au premier lment du tableau correspond le numro 0. Ce numro dordre est indpendant de lindex (en particulier aprs un appel la fonction array_reverse() avec comme second argument la valeur TRUE, llment dindex 0 peut se retrouver en fin de tableau). Si $debut est ngatif, alors le compte se fait en partant de la fin du tableau.

183

Chapitre 3

Le langage PHP

$longueur

Argument optionnel prcisant le nombre dlments extraire. Par dfaut, ce sont tous les lments suivants du tableau qui sont extraits. Si $longueur est ngatif, ce sont tous les lments jusqu llment qui se trouve abs($longueur) de la fin qui sont extraits. Tableau des lments extraits. Les cls sont conserves mais pas les index.

retour

Listing 3.12 : array_array_slice.php


<?php $tableau = array("cle" => "element0", 2 => "element1", 1 => "element2");

3. Le langage PHP

print_r(array_slice($tableau, 0, 2)); ?>

retourne par exemple : Array ( [cle] => element0 [0] => element1 )

array_splice()
Supprime les lments dun tableau ; ventuellement, insre des lments dans le tableau et retourne le tableau des lments supprims. Syntaxe $tableau $debut array array_splice(array $tableau, int $debut [, int $longueur [, array $remplacement]]) Tableau modifier. Numro dordre du premier lment du tableau supprimer. Au premier lment du tableau correspond le numro 0. Ce numro dordre est indpendant de lindex (en particulier aprs un appel la fonction array_reverse() avec comme second argument la valeur TRUE, llment dindex 0 peut se retrouver en fin de tableau). Si $debut est ngatif, alors le compte se fait en partant de la fin du tableau. Argument optionnel prcisant le nombre dlments supprimer. Par dfaut, ce sont tous les lments suivants du tableau qui sont supprims. Si $longueur est ngatif, ce sont tous les lments jusqu llment qui se trouve abs($longueur) de la fin qui sont supprims. Tableau optionnel contenant les valeurs insrer dans le tableau partir de llment point par $dbut. Si le nombre dlments insrs est suprieur au nombre dlments supprims, alors le reste du tableau est dcal. Dans ce cas, les cls sont conserves mais pas les index. Par dfaut, les lments sont simplement supprims. Tableau des lments supprims.

$longueur

$remplacement

retour

184

Les tableaux

array_chunk()
Retourne un tableau index ayant pour valeurs les morceaux dun tableau dcoup en morceaux. Syntaxe $tableau $taille $mode array array_chunk(array $tableau, int $taille [, boolean $mode]) Tableau dcouper en morceaux. Taille des morceaux (nombre dlments). Prcise si les cls du tableau doivent tre conserves :

3. Le langage PHP

TRUE, les cls sont conserves. FALSE (valeur par dfaut), chaque morceau de tableau est rindex en commenant par 0. retour Tableau index contenant des tableaux issus de la dcoupe en morceaux du tableau dentre.

Fonctions de manipulation des cls dun tableau

array_change_key_case()
Retourne un tableau avec la casse des cls modifie. Syntaxe $tableau $casse array array_change_key_case(array $tableau [, int $casse]) Tableau de rfrence. Au choix, lune des deux constantes suivantes : CASE_LOWER (valeur par dfaut), pour mettre toutes les cls en minuscules. CASE_UPPER, pour mettre toutes les cls en majuscules. retour Tableau avec tous les index en majuscules ou minuscules.

Fonctions de conversion tableau <-> variable

list()
Construit une liste de variables partir des donnes dun tableau. Ce nest pas une vritable fonction, puisquelle sutilise de la faon suivante :

185

Chapitre 3

Le langage PHP

list($variable1, $variable2, ...) = $tableau

Syntaxe $variable1 $variable2 ...

void list(mixed $variable1 [,mixed $variable2, ...]) Variable laquelle doit tre affecte la premire valeur du tableau. Variable laquelle doit tre affecte la seconde valeur du tableau. etc.

extract()
3. Le langage PHP
Construit une liste de variables partir des donnes dun tableau, les noms des variables tant bass sur les cls du tableau. Syntaxe $tableau $modeExtraction int extract(array $tableau [, int $modeExtraction [, string $prefixe]]) Tableau (associatif) dont on veut se servir pour crer des variables. Argument optionnel indiquant quelle stratgie adopter, principalement si la variable que lon souhaite crer existe dj. Cet argument peut prendre une valeur parmi : EXTR_OVERWRITE (valeur par dfaut) remplace la valeur de la variable par la valeur trouve dans le tableau si la cl correspond une variable existante. EXTR_SKIP ignore llment rencontr si la cl correspond une variable existante. EXTR_PREFIX_SAME fait prcder le nom de la variable par $prefixe si la cl correspond une variable existante. EXTR_PREFIX_ALL fait systmatiquement prcder le nom de la variable par $prefixe. EXTR_PREFIX_INVALID fait prcder le nom de la variable par $prefixe si la cl ne permet pas de crer un nom de variable valide (par exemple si la cl est en fait un index). $prefixe Argument optionnel prciser si $modeExtraction prend lune des valeurs suivantes : EXTR_PREFIX_SAME, EXTR_PREFIX_ALL, EXTR_PREFIX_INVALID. Nombre de variables gnres.

retour

compact()
Retourne un tableau associatif cr partir des noms de variables (qui seront les cls du tableau) et de leurs valeurs.

186

Les tableaux

Syntaxe $variable1, ...

array compact(string $variable1 [, string $variable2, ...]) Noms des variables ajouter au tableau. Ces arguments peuvent, en fait, galement tre des tableaux contenant des chanes de caractres prcisant des noms de variables (ou des tableaux). Chaque argument sous forme de tableau est trait de faon rcursive. Tableau associatif contenant lensemble des paires (cl, valeur) correspondant aux noms de variables donns.

retour

Fonctions de parcours de tableau


Les tableaux tant en fait des listes de couples (cl, valeur) ou (index, valeur), ils peuvent tre parcourus non pas uniquement en sappuyant sur les cls ou les index, mais galement grce un pointeur se dplaant dans la liste.

3. Le langage PHP

current()
Retourne la valeur actuellement pointe par le pointeur interne du tableau (sans avancer le pointeur). Syntaxe $tableau retour mixed current(array $tableau) Tableau parcourir. Valeur actuellement pointe par le pointeur interne de $tableau. FALSE si le pointeur est en dehors du tableau.

pos()
quivalent de current().

key()
Retourne la cl (ou index) de llment actuellement point par le pointeur interne du tableau (sans avancer le pointeur). Syntaxe $tableau retour mixed key(array $tableau) Tableau parcourir. Cl (ou index) de llment actuellement point par le pointeur interne de $tableau. FALSE si le pointeur est en dehors du tableau.

187

Chapitre 3

Le langage PHP

reset()
Remet le pointeur interne au dbut du tableau et retourne le premier lment. Syntaxe $tableau retour mixed reset(array $tableau) Tableau parcourir. Premier lment du tableau. FALSE si le tableau est vide.

3. Le langage PHP

next()
Avance le pointeur interne du tableau et retourne le nouvel lment point. Syntaxe $tableau retour mixed next(array $tableau) Tableau parcourir. lment suivant du tableau. FALSE si lon a dpass la fin du tableau.

Listing 3.13 : array_next.php


<?php // Exemple de parcours dun tableau // avec le pointeur interne et la fonction // next(); $tableau = array( "Dbut", "", "Milieu", 0, "Fin"); // Ici, lappel reset() nest pas ncessaire // puisque aprs initialisation le pointeur // de tableau est au debut. $valeur = reset($tableau); // Tant que valeur est diffrente de FALSE // ATTENTION: // 1 - Bien prendre soin de mettre les 2 signes = // afin de comparer galement les types // car 0 == FALSE (mme valeur) // alors que 0 !== FALSE (mme valeur mais pas mme type) // 2 - Ce type de parcours nest valable // que si le tableau ne possde aucun // lment valant FALSE while ($valeur !== FALSE) { echo "$valeur<br />"; $valeur = next($tableau); } ?>

188

Les tableaux

aura pour effet dafficher : Dbut


Milieu 0 Fin

prev()
Recule le pointeur interne du tableau et retourne le nouvel lment point. Syntaxe $tableau retour mixed prev(array $tableau) Tableau parcourir. lment prcdent du tableau. FALSE si le dbut du tableau a t dplac.

3. Le langage PHP

end()
Place le pointeur interne la fin du tableau et retourne le dernier lment. Syntaxe $tableau retour mixed end(array $tableau) Tableau parcourir. Dernier lment du tableau. FALSE si le tableau est vide.

each()
Retourne un tableau contenant la cl et la valeur de llment actuellement point par le pointeur interne du tableau, puis avance le pointeur. Syntaxe $tableau retour array each(array $tableau) Tableau parcourir. Tableau compos de quatre lments. llment dindex 0 et llment de cl "key" est associe la cl (ou lindex) de llment point. llment dindex 1 et llment de cl "value" est associe la valeur de llment point. FALSE si la fin du tableau est dpasse.

each() et list() un duo trs apprci en concurrence avec foreach Le tableau issu de lappel each() est souvent associ list() afin de manipuler de simples chanes plutt que des tableaux selon le shma list($cle, $valeur) = each ($tableau);. Ainsi, les tableaux sont souvent parcourus de la faon suivante : 189

Chapitre 3

Le langage PHP

reset($tableau); while (list($cle, $valeur) = each($tableau)) { echo "A la cl $cle est associ la valeur $valeur<br />"; }

Une autre solution consiste utiliser foreach. Mais il est galement possible de le faire de la faon suivante :
foreach($tableau as $cle => $valeur) echo "A la cl $cle est associe la valeur $valeur<br />";

3. Le langage PHP

Fonctions de gestion de piles


Il est possible dutiliser les tableaux PHP comme des piles, cest--dire comme des listes dans lesquelles sempilent les lments et auxquelles on peut accder en prenant le premier ou le dernier lment.

array_push()
Ajoute un ou plusieurs lments la fin du tableau (au-dessus de la pile). Syntaxe $tableau $valeur1, ... retour int array_push(array $tableau, mixed $valeur1, [mixed $valeur2, ...]) Tableau auquel vous souhaitez ajouter des lments. Valeurs (ou donnes) que vous souhaitez ajouter au tableau. Retourne le nombre dlments du tableau aprs ajout.

quivalent de array_push() la valeur retour prs, array_push($tableau, $valeur1) quivaut


$tableau[] = $valeur1;

array_pop()
Retourne et supprime le dernier lment du tableau (celui du dessus de la pile). Syntaxe $tableau retour mixed array_pop(array $tableau) Tableau que lon veut "dpiler". Le dernier lment du tableau ou NULL si le tableau est vide (ou si largument nest pas un tableau).

190

Les tableaux

array_unshift()
Ajoute un ou plusieurs lments au dbut du tableau (au bas de la pile). Syntaxe $tableau $valeur1, ... retour int array_unshift(array $tableau, mixed $valeur1, [mixed $valeur2, ...]) Tableau auquel vous souhaitez ajouter des lments. Valeurs (ou donnes) que vous souhaitez ajouter au tableau. La premire valeur donne correspondra la premire valeur du tableau rsultat. Retourne le nombre dlments du tableau aprs ajout.

3. Le langage PHP

array_shift()
Retourne et supprime le premier lment du tableau (celui du bas de la pile). Syntaxe $tableau retour mixed array_shift(array $tableau) Tableau que lon veut "dpiler" par le bas. Le premier lment du tableau ou NULL si le tableau est vide (ou si largument nest pas un tableau).

Fonctions de tri
Tri inverse

array_reverse()
Retourne un tableau avec les valeurs dans lordre inverse de celui spcifi. Syntaxe $tableau $avecCle array array_reverse(array $tableau, [boolean $avecCle]) Tableau de rfrence. Argument optionnel positionner TRUE si lassociation cl->valeur doit tre conserve (pour un tableau index, les valeurs conserveront galement leur index). Par dfaut $avecCle = FALSE ; le tableau rsultat est alors obligatoirement un tableau index entre 0 et la taille du tableau -1. Retourne le tableau spcifi avec les valeurs classes dans lordre inverse.

retour

191

Chapitre 3

Le langage PHP

Tri selon lordre croissant des valeurs

sort()
Trie les lments dun tableau dans lordre croissant des valeurs. Les cls (ou index) ne sont pas conserves ; le tableau devient obligatoirement un tableau index entre 0 et la taille du tableau-1. Syntaxe void sort(array $tableau) Tableau trier.

3. Le langage PHP

$tableau

Listing 3.14 : array_sort.php


<?php $tableauVille = array("Circuit" => "Le Mans", "Braderie" => "Lille", "Horloge" => "Rouen", "Place Stanislas" => "Nancy"); sort($tableauVille); for ($i=0; $i<count($tableauVille); $i++) { echo $i." - ".$tableauVille[$i]."<br />"; } ?>

affichera
0 1 2 3 Le Mans Lille Nancy Rouen

asort()
Trie les lments dun tableau dans lordre croissant des valeurs, tout en conservant lassociation cl => valeur. Syntaxe $tableau void asort(array $tableau) Tableau trier.

natsort()
Trie les lments dun tableau dans lordre croissant, dit "naturel", des valeurs. Ce tri ne se contente pas de comparer les chanes de caractres, caractre par caractre, mais distingue les parties numriques des parties alphabtiques. Ainsi, dans lordre "naturel", "mot2" apparat

192

Les tableaux

avant "mot10". Les cls ou index ne sont pas conservs ; le tableau devient obligatoirement un tableau index entre 0 et la taille du tableau-1. Syntaxe $tableau void natsort(array $tableau) Tableau trier.

natcasesort()
Trie les lments dun tableau dans lordre croissant, dit "naturel", des valeurs sans tenir compte de la casse. Ce tri ne se contente pas de comparer les chanes de caractres, caractre par caractre, mais distingue les parties numriques des parties alphabtiques. Ainsi, dans lordre "naturel", "mot2" apparat avant "mot10". Les cls ou index ne sont pas conservs ; le tableau devient obligatoirement un tableau index entre 0 et la taille du tableau -1. Syntaxe $tableau void natcasesort(array $tableau) Tableau trier.

3. Le langage PHP

natsort(), natcasesort() et ordre dcroissant Les fonctions natsort() et natcasesort() ne proposent pas dquivalent pour un tri dcroissant. Pour un tel tri, vous devrez faire appel natsort() ou natcasesort() puis $tableau = array_reverse($tableau);.

Tri selon lordre dcroissant des valeurs

rsort()
Trie les tableaux dans lordre dcroissant des valeurs. Les cls (ou index) ne sont pas conserves ; le tableau devient obligatoirement un tableau index entre 0 et la taille du tableau-1. Syntaxe $tableau void rsort(array $tableau) Tableau trier.

Voir lexemple associ la fonction sort().

arsort()
Trie les lments dun tableau dans lordre dcroissant des valeurs, tout en conservant lassociation cl => valeur.

193

Chapitre 3

Le langage PHP

Syntaxe $tableau

void arsort(array $tableau) Tableau trier.

Tri personnalis des valeurs

usort()
3. Le langage PHP
Trie les lments dun tableau dans lordre croissant des valeurs, en dterminant lordre des valeurs partir dune fonction dfinie par lutilisateur. Les cls (ou index) ne sont pas conserves ; le tableau devient obligatoirement un tableau index entre 0 et la taille du tableau-1. Syntaxe $tableau boolean usort(array $tableau, fonction $fonctionComparaison) Tableau trier.

$fonctionComparaison Nom de la fonction utiliser pour comparer les valeurs. Cette fonction doit accepter deux arguments et retourner : 0 en cas dgalit, 1 en cas de supriorit du premier argument sur le deuxime et 1 sinon. boolean TRUE.

Listing 3.15 : array_usort.php


<?php function maFonction($valeur1, $valeur2) { // La fonction suivante retourne // un pourcentage de similarit entre // les 2 chanes de caractres. // On pourra ainsi dire[ ]laquelle des 2 chanes // des 2 valeurs se rapproche le plus // de "Etretat" $s1 = similar_text($valeur1, "Etretat"); $s2 = similar_text($valeur2, "Etretat"); if ($s1 == $s2) return 0; return ($s1 > $s2) ? -1 : 1; } $tableauMot = array("Etat", "Etretat", "Etretot", "Arrete"); // Tri du plus proche du mot "Etretat" // au plus loign. usort($tableauMot, "maFonction"); print_r($tableauMot); ?>

retourne bien les lments du tableau du plus proche du mot "Etretat" au plus loign. Array ( [0] => Etretat [1] => Etretot [2] => Etat [3] => Arrete )

194

Les tableaux

Cas dutilisation Ce type de fonction est particulirement utile dans le cas dune mthode de comparaison un peu complexe (comme lorsque, dans lexemple, il sagit de calculer la similarit entre chanes de caractres), et surtout lorsque les lments du tableau sont des objets et que les comparaisons sappliquent sur les attributs de lobjet.

uasort()
3. Le langage PHP
Trie les lments dun tableau dans lordre croissant des valeurs, en dterminant lordre des valeurs partir dune fonction dfinie par lutilisateur. Les cls (ou index) ne sont pas conserves ; le tableau devient obligatoirement un tableau index entre 0 et la taille du tableau-1. Syntaxe $tableau boolean uasort(array $tableau, fonction $fonctionComparaison) Tableau trier.

$fonctionComparaison Nom de la fonction utiliser pour comparer les valeurs. Cette fonction doit accepter deux arguments et retourner : 0 en cas dgalit, 1 en cas de supriorit du premier argument sur le deuxime et 1 sinon. retour TRUE.

Tri selon lordre croissant des cls

ksort()
Trie les lments dun tableau dans lordre croissant des cls, tout en conservant lassociation cl => valeur. Syntaxe $tableau retour boolean ksort(array $tableau) Tableau trier. TRUE.

Tri selon lordre dcroissant des cls

krsort()
Trie les tableaux dans lordre dcroissant des cls, tout en conservant lassociation cl => valeur.

195

Chapitre 3

Le langage PHP

Syntaxe $tableau retour

boolean krsort(array $tableau) Tableau trier. TRUE.

Tri personnalis des cls

uksort()
3. Le langage PHP
Trie les lments dun tableau dans lordre croissant des cls, en dterminant lordre des cls partir dune fonction dfinie par lutilisateur. Syntaxe $tableau boolean uksort(array $tableau, fonction $fonctionComparaison) Tableau trier.

$fonctionComparaison Nom de la fonction utiliser pour comparer les cls. Cette fonction doit accepter deux arguments et retourner : 0 en cas dgalit, 1 en cas de supriorit du premier argument sur le deuxime et 1 sinon. retour TRUE.

Voir lexemple associ la fonction usort().

Tri sur des tableaux lis

array_multisort()
Trie les lments des tableaux selon lordre du premier tableau indiqu. Syntaxe $tableau1 $mode1 boolean array_multisort(array $tableau1 [,int $mode1] [, int $mode2] , array $tableau2 [, array $tableau3]) Tableau trier prendre comme rfrence pour le tri. Sens de tri. SORT_ASC pour un tri croissant. SORT_DESC pour un tri dcroissant. $mode2 Option de tri: SORT_REGULAR pour une comparaison "traditionnelle" des valeurs. SORT_NUMERIC pour une comparaison numrique des valeurs. SORT_STRING pour une comparaison alphabtique des valeurs. $tableau2, ... Tableaux sur lesquels les permutations effectues sur $tableau1 doivent tre rpercutes.

196

Les tableaux

Listing 3.16 : array_array_multisort.php


<?php // Exemple de 2 tableaux lis // Nom et Notes doivent toujours correspondre ... $eleves = array("Pierre", "Jean", "Henri", "Odille"); $notes = array(12, 15, 13, 10); // ... et pourtant on voudrait trier // selon les prnoms des lves. array_multisort($eleves, $notes);

3. Le langage PHP

echo "<b>Elves</b>:"; print_r($eleves); echo "<br />"; echo "<b>Notes</b>:"; print_r($notes); echo "<br />"; // ... ou encore selon lordre dcroissant // des notes. array_multisort($notes, SORT_DESC, $eleves); echo "<br />"; echo "<b>Elves</b>:"; print_r($eleves); echo "<br />"; echo "<b>Notes</b>:"; print_r($notes); ?>

affichera
Elves:Array ( [0] => Henri [1] => Jean [2] => Odille [3] => Pierre ) Notes:Array ( [0] => 13 [1] => 15 [2] => 10 [3] => 12 ) Elves:Array ( [0] => Jean [1] => Henri [2] => Pierre [3] => Odille ) Notes:Array ( [0] => 15 [1] => 13 [2] => 12 [3] => 10 )

197

Chapitre 3

Le langage PHP

Tri alatoire

shuffle()
Trie les lments dun tableau dans lordre.... alatoire. Autrement dit, mlange les lments dun tableau. Les cls (ou index) ne sont pas conserves ; le tableau devient obligatoirement un tableau index entre 0 et la taille du tableau -1. Syntaxe $tableau boolean shuffle(array $tableau) Tableau mlanger. TRUE.

3. Le langage PHP

retour

Fonctions de statistiques
Il existe quatre fonctions que lon peut assimiler des fonctions de statistiques.

array_sum()
Retourne la somme des valeurs des lments dun tableau (fort pratique pour calculer les moyennes). Syntaxe $tableau retour mixed array_sum(array $tableau) Tableau sur lequel doit seffectuer lopration. La somme des valeurs des lments du tableau, de type entier ou rel, selon le contenu du tableau.

array_count_values()
Retourne un tableau prcisant le nombre doccurrences dune valeur dans un tableau donn. Syntaxe $tableau retour array array_count_values(array $tableau) Tableau sur lequel doit seffectuer lopration. Tableau associatif ayant comme cls les valeurs du tableau sur lequel a t effectue lopration et comme valeur le nombre doccurrences de la cl.

Listing 3.17 : array_array_count_values


<?php $tableauNote = array ("Pierre" => 10, "Marcel" => 12, "Franck" => 10, "Jean" => 10, "Marie" => 15, "Cecile" => 12);

198

Les tableaux

$stats = array_count_values($tableauNote); echo "A ce devoir ...<br />\n"; while (list($note, $nb) = each($stats)) { echo "$nb lves ont eu $note<br />"; } ?>

donnera le rsultat
A 3 2 1 ce devoir ... lves ont eu 10 lves ont eu 12 lves ont eu 15

3. Le langage PHP

(nous vous laissons le soin damliorer ce script pour traiter le cas o $nb = 1).

Voir aussi les fonctions min() et max() dveloppes dans le chapitre "Les fonctions mathmatiques".

Fonctions mettant en uvre plusieurs tableaux


Comparaison de tableaux

array_diff()
Retourne un tableau prsentant les valeurs contenues dans un tableau, mais absentes dautres tableaux. Syntaxe $tableau1 $tableau2, ... retour array array_diff(array $tableau1, array $tableau2, [array $tableau3, ...]) Tableau dont on veut comparer le contenu avec ceux des autres tableaux. Tableaux dans lesquels on recherche lventuelle prsence des valeurs du tableau 1. Tableau prsentant toutes les valeurs contenues dans $tableau1 et qui nont t trouves dans aucun des autres tableaux prciss. Les cls sont conserves (identiques celle de $tableau1).

array_intersect()
Retourne un tableau prsentant les valeurs contenues dans un tableau et dans un ensemble dautres tableaux.

199

Chapitre 3

Le langage PHP

Syntaxe $tableau1 $tableau2, ... retour

array array_intersect(array $tableau1, array $tableau2, [array $tableau3, ...]) Tableau dont on veut comparer le contenu avec ceux des autres tableaux. Tableaux dans lesquels on recherche lventuelle prsence des valeurs du tableau 1. Tableau prsentant toutes les valeurs contenues dans $tableau1 et qui ont t trouves dans tous les autres tableaux prciss. Les cls sont conserves (identiques celle de $tableau1). Sil ny a pas de valeurs communes alors cest un tableau vide qui est retourn.

3. Le langage PHP

array_intersect_assoc()
Retourne un tableau prsentant les valeurs et les cls associes celle-ci, contenues dans un tableau et dans un ensemble dautres tableaux. Syntaxe : $tableau1 $tableau2, ... retour array array_intersect_assoc(array $tableau1, array $tableau2, [array $tableau3, ...]) Tableau dont on veut comparer le contenu avec ceux des autres tableaux. Tableaux dans lesquels on recherche lventuelle prsence des valeurs du tableau 1. Tableau prsentant toutes les valeurs et les clefs contenues dans $tableau1 et qui ont t trouves dans tous les autres tableaux prciss. Les cls sont conserves (identiques celle de $tableau1).

<?php $tableau1 = array(0=>"Belgique", 1=>"France", 2=>"Italie", 3=>"Suisse"); $tableau2 = array(1=>"France", 3=>"Italie", 2=>"Irlande"); $tableauFinal = array_intersect_assoc($tableau1, $tableau2); print_r($tableauFinal); ?> Array ( 1 => France )

Fusion de tableaux

array_merge()
Retourne un tableau issu de la fusion dun ensemble de tableaux.

200

Les tableaux

Syntaxe $tableau1, ... retour

array array_merge(array $tableau1, array $tableau2, [array $tableau3, ...]) Les tableaux fusionner. Tableau prsentant toutes les valeurs contenues dans les diffrents tableaux. Au fil du parcours des tableaux fusionner, les valeurs ont t ajoutes la fin du tableau rsultat. Les valeurs lies des cls peuvent tre crases si la cl est rencontre plusieurs fois.

array_merge_recursive()
Retourne un tableau issu de la fusion dun ensemble de tableaux. Dans ce cas, si une cl donne est rencontre plusieurs fois, la valeur dans le tableau rsultat ne sera pas la dernire valeur rencontre, mais la fusion (dans un tableau) des valeurs rencontres. Syntaxe $tableau1, ... retour array array_merge_recursive(array $tableau1, array $tableau2, [array $tableau3, ...]) Les tableaux fusionner. Tableau prsentant toutes les valeurs contenues dans les diffrents tableaux. Au fil du parcours des tableaux fusionner, les valeurs ont t ajoutes la fin du tableau rsultat. Les valeurs lies des cls rencontres plusieurs fois sont regroupes dans un tableau.

3. Le langage PHP

Listing 3.18 : array_array_merge_recursive.php


<?php $agenda1 = array("Lundi" => "Mdecin", "Mardi" => "Coiffeur"); $agenda2 = array("Mardi" => "Runion", "Vendredi" => "VTT"); $agenda = array_merge_recursive($agenda1, $agenda2); print_r($agenda); ?>

Voil comment fusionner intelligemment deux agendas...


Array ( [Lundi] => Mdecin [Mardi] => Array ( [0] => Coiffeur [1] => Runion ) [Vendredi] => VTT )

Fonctions de traitement personnalis des tableaux

array_lter()
Retourne un tableau filtr partir dune fonction crite par lutilisateur.

201

Chapitre 3

Le langage PHP

Syntaxe $tableau $fonctionFiltre

array array_filter(array $tableau [, function $fonctionFiltre]) Tableau filtrer. Fonction appeler pour dterminer si llment doit tre conserv ou non dans le tableau rsultat. Cette fonction doit prendre en compte un argument, et retourner TRUE si llment doit tre conserv, FALSE sinon. Ce paramtre est (curieusement) optionnel. Si aucune fonction de filtrage nest fournie, alors le tableau est restitu tel quel. Retourne le tableau dentre sans les lments qui ont t indiqus, par la fonction $fonctionFiltre, comme tant filtrer. Les cls et index du tableau sont conservs.

retour

3. Le langage PHP

Listing 3.19 : array_array_filter.php


<?php // Exemple de filtre qui ne conserve que les // prnoms commenant par M function monFiltre($prenom) { return ($prenom[0] == "M"); } $prenoms = array("Stphane", "Marie", "Thierry", "Abi", "Christophe", "Manu", "Anne"); print_r(array_filter($prenoms , "monFiltre")); ?>

ne conserve bien que les prnoms commenant par M.


Array ( [1] => Marie [5] => Manu )

array_map()
Retourne un tableau issu du rsultat de lapplication dune fonction crite par lutilisateur, et prenant en compte les donnes dun ou de plusieurs tableaux. Syntaxe $fonction array array_map(function $fonction, array $tableau1 [, array $tableau2, ...]) Fonction appeler pour chaque lment des tableaux $tableau1, $tableau2, etc. Cette fonction doit prendre en compte autant darguments que de tableaux fournis. Tableaux contenant les valeurs sur lesquelles doit sappliquer la fonction. Si certains tableaux sont moins longs que le plus grand des tableaux, des valeurs nulles compltent ces tableaux. Ces tableaux sont traits dans lordre de leurs lments (et non de leur index).

$tableau1, ...

202

Les tableaux

retour

Tableau index de la taille du plus grand des tableaux passs en paramtre et ayant pour valeurs le rsultat de la fonction applique aux lments des tableaux passs en paramtre.

Listing 3.20 : array_array_map.php


<?php // // // // Exemple de 2 tableaux servant stocker des coordonnes Cest pas aussi beau que la programmation objet mais des fois a dpanne

$tabX = array (1, 5, 2, 4); $tabY = array (10, 2, 3, 2);

3. Le langage PHP

// Exemple dune fonction permettant // le calcul de la distance entre un point // et le centre (0, 0) function distance($x, $y) { return sqrt($x*$x + $y*$y); } // Et, hop, dun simple appel // array_map jai mes distances // pour tous les points. print_r(array_map("distance", $tabX, $tabY)); ?>

retournera le tableau des distances suivant :


Array ( [0] => 10.049875621121 [1] => 5.3851648071345 [2] => 3.605551275464 [3] => 4.4721359549996 )

array_reduce()
Retourne le rsultat dune opration dfinie par lutilisateur, applique itrativement sur lensemble des valeurs dun tableau. Syntaxe $tableau $fonction mixed array_reduce(array $tableau, function $fonction [,int $valeurInitiale]) Tableau contenant les valeurs sur lesquelles doivent seffectuer lopration. Fonction appeler itrativement sur chaque lment du tableau. Cette fonction doit prendre en compte deux arguments, le premier tant le rsultat du calcul trouv jusque-l, le second tant la valeur prendre en compte pour la poursuite du calcul. La fonction doit retourner le nouveau rsultat obtenu.

203

Chapitre 3

Le langage PHP

$valeurInitiale retour

Argument optionnel, prcisant la valeur initiale utilise pour le calcul. Par dfaut $valeurInitiale = 0. Le rsultat du calcul voire la valeur initiale si le tableau est vide.

Listing 3.21 : array_array_reduce.php


<?php // // // // // // // // // // Calcul de P(x0) o P polynme P(x) = x^4 + 2x^3 + x^2 + 4x + 6 = (((x + 2)*x + 1)*x +4)*x + 6 Soit le calcul itratif Resultat = 1 Resultat = Resultat*x0 + 2 Resultat = Resultat*x0 + 1 Resultat = Resultat*x0 + 4 Resultat = Resultat*x0 + 6

3. Le langage PHP

// Ainsi avec le tableau des coefficients $tabCoef = array(2, 1, 4, 6); // et la chtite fonction function polynome($resultat, $coef) { $x0=5; // Calcul pour x0=5; return $resultat*$x0 + $coef; } // Jai mon rsultat echo "P(5)=".array_reduce($tabCoef, "polynome", 1); ?>

Si vous souhaitez vraiment le savoir, cela retourne :


P(5)=926

array_walk()
Appelle une fonction utilisateur sur chaque lment dun tableau. Syntaxe $tableau $fonction boolean array_walk(array $tableau, function $fonction [, mixed $argument]) Tableau contenant les valeurs sur lesquelles doivent seffectuer les oprations. Fonction appeler pour chaque lment du tableau. Cette fonction doit prendre en compte deux arguments (ou trois si $argument est spcifi), le premier argument tant la valeur de llment actuellement considr,

204

Les tableaux

le second tant la cl (ou index) de llment actuellement considr. Le troisime argument prendra la valeur de $argument). Attention ! il nest pas possible dans ce cas dappeler une fonction PHP, vous devez ncessairement crer votre propre fonction. $argument retour Argument optionnel, pass en troisime paramtre de la fonction utilisateur. TRUE si lopration sest bien passe, FALSE sinon.

Passage par valeur Noubliez pas que, par dfaut, les paramtres passs aux fonctions le sont par valeur. Si vous souhaitez utiliser array_walk() pour modifier les valeurs du tableau, noubliez pas dutiliser une interface similaire mafonction(&$valeur, $cl).

3. Le langage PHP

Listing 3.22 : array_array_walk.php


<?php $menu = array ("Accueil", "Forum", "A propos"); // Fonction pour afficher le contenu // du menu avec lindex et un sparateur function affiche($valeur, $key, $separateur) { echo ($key+1)." $separateur ".$valeur."<br />"; } // Fonction pour modifier les tiquettes // du menu function patch(&$valeur, $key) { $valeur="[".$valeur."]"; } // Affiche le menu array_walk($menu, "affiche", "-"); // Patche le menu array_walk($menu, "patch"); // ce qui donne le rsultat print_r($menu); ?>

retournera
1 - Accueil 2 - Forum 3 - A propos Array ( [0] => [Accueil] [1] => [Forum] [2] => [A propos] )

205

Chapitre 3

Le langage PHP

3.9.

Les inclusions de chiers

Le langage PHP permet dinsrer, dans un script, du code qui provient dun (ou de plusieurs) autres fichiers. Pour cela, PHP propose quatre fonctions (ou plutt, instructions) :
j j
require(); include();

et leurs variantes, depuis PHP 4.0.1,

3. Le langage PHP

j j

require_once(); include_once().

Ces instructions sont gnralement utilises pour intgrer des scripts dans lesquels des objets ou des fonctions rutilisables ont t dfinis (dans ce cas, les fichiers inclus font office de bibliothques de fonctions), ou bien pour intgrer des portions de code contenant les paramtres du script (dans ce cas, les fichiers inclus font office de fichiers de configuration).

Listing 3.23 : include_01.php


<?php // Inclut les paramtres include("include_01a.php"); // Inclut les fonctions include("include_01b.php"); monEcho($maChaine); ?>

Listing 3.24 : include_01a.php


<?php // Exemple de fichier de configuration // vraiment minimaliste $maChaine = "Bonjour tout le monde"; ?>

Listing 3.25 : include_01b.php


<?php // Exemple de bibliothque de fonctions // encore une fois bien minimaliste function monEcho($chaine)

206

Les inclusions de fichiers

{ echo $chaine; } ?>

sera alors quivalent (commentaires exclus) :

Listing 3.26 : include_01equiv.php


<?php $maChaine = "Bonjour tout le monde"; function monEcho($chaine) { echo $chaine; } monEcho($maChaine); ?>

3. Le langage PHP

Fonction ou instruction ? require() et include() ne sont pas de vritables fonctions, et lon peut aussi bien crire :
j j
include("nom de fichier"); include "nom de fichier";

Ces instructions peuvent tre utilises de faon conditionnelle ou bien encore dans des boucles, comme le montrent les exemples suivants :

Listing 3.27 : include_02.php


Je suis le script principal<br /> je vais tenter dinsrer les scripts<br /> aprs avoir test leur existence<br /> <?php if (file_exists("include_02a.php")) { include("include_02a.php"); } if (file_exists("fichierinconnu.php")) { include("fichierinconnu.php"); } ?>

207

Chapitre 3

Le langage PHP

Listing 3.28 : include_02a.php


* Je suis un simple script inclure nomm include_02a.php

affichera :
Je suis le script principal je vais tenter dinsrer les scripts aprs avoir test leur existence * Je suis un simple script inclure nomm include_02a.php

3. Le langage PHP

Le tout sans gnrer derreur, puisque le script principal ne tentera jamais dinclure le fichier inexistant.

Accolades ncessaires Notez la prsence des accolades qui dfinissent le bloc contenant uniquement linstruction include. Ces accolades sont ncessaires, il ne faut donc pas les omettre.

Listing 3.29 : include_03.php


Je suis le script principal<br /> je vais tenter dinsrer un script en boucle<br /> <?php for ($i=0; $i<3; $i++) { include("include_03a.php"); } ?>

Listing 3.30 : include_03a.php


* Je suis un simple script inclure nomm include_03a.php<br />

affichera, quant lui :


Je suis le script principal je vais tenter dinsrer un script en boucle aprs avoir test leur existence * Je suis un simple script inclure nomm include_03a.php * Je suis un simple script inclure nomm include_03a.php * Je suis un simple script inclure nomm include_03a.php

volution de linstruction require() Mme si cela ntait pas vrai auparavant pour linstruction require(), depuis la version 4.0.2, les fonctions require() et include() se comportent sensiblement de la mme faon (la commande require() stant rallie au comportement de la commande include()).

208

Les inclusions de fichiers

Comme cela se devine dans les exemples prcdents, les scripts insrs commencent sur la base dun texte brut (ou code HTML) ; il faudra donc rouvrir les balises PHP pour les portions de code PHP. De ce fait, les scripts insrs sont similaires aux scripts principaux.

Inclusions multiples
Il peut arriver que, sans vritablement le vouloir, un script soit inclus plusieurs fois. Cela arrive notamment lorsquun script A inclut un script B et un script C, alors que le script B lui-mme inclut le script C (cest gnralement ce qui arrive si les rgles de codage ne sont pas suffisamment claires sur ce point). Si le script inclus de multiples fois contient des dclarations de fonctions (ou dobjets) alors, invitablement, vous vous retrouverez avec un message derreur indiquant que la fonction (ou lobjet) a dj t dfinie. Afin de vous affranchir de ce problme, vous pouvez faire appel linstruction include_once() ou require_once() afin de ninclure le script quau premier appel. Ainsi, si lon reprend lexemple prcdent avec include_once(), cela donnera :

3. Le langage PHP

Listing 3.31 : include_04.php


Je suis le script principal<br /> je vais tenter dinsrer un script en boucle<br /> <?php for ($i=0; $i<3; $i++) { include_once("include_03a.php"); } ?>

et affichera seulement :
Je suis le script principal je vais tenter dinsrer un script en boucle aprs avoir test leur existence * Je suis un simple script inclure nomm include_03a.php

Notez, cette occasion, quil est tout moment possible de connatre la liste des fichiers inclus grce la fonction get_included_files() (ou son alias get_required_files()).

get_included_les()
Retourne la liste des fichiers inclus. Syntaxe retour array get_included_files(void) Tableau index contenant la liste des noms complets (chemins absolus) des fichiers inclus par include(), require(), include_once() ou require_once(). Les noms des fichiers inclus plusieurs fois napparaissent quune fois.

209

Chapitre 3

Le langage PHP

Les noms des chiers inclus


Les noms des fichiers inclus peuvent porter nimporte quelle extension. Mais, dans la pratique, il faut tre prudent et bien choisir son extension. Nous vous conseillons une extension "_inc.php".

Extension des fichiers inclus et risques de piratage Si vous ne donnez pas lextension .php, les fichiers inclus, sils sont accds directement, ne seront pas interprts et livreront tous leurs secrets. En effet, si, par exemple, votre script principal inclut un fichier nomm config.in" et quun pirate connat lexistence de ce fichier, il pourra lappeler directement depuis son navigateur et lire simplement son contenu, comme pour tout bon fichier texte (et il y trouvera certainement des choses intressantes du genre $motdepasse = secret;). Sil sagit dun fichier contenant des fonctions ou des classes, le pirate pourra rcuprer votre code source (et votre savoir-faire). Et pourtant, le moyen de se protger est trs simple : si vous ajoutez simplement lextension .php vos scripts inclus, le code PHP, avant dtre envoy au navigateur du pirate, sera interprt, et le pirate ne pourra lire que le rsultat de linterprtation (gnralement un simple page blanche, puisque par exemple $motdepasse = secret; naffichera rien).

3. Le langage PHP

Les chiers insrs distants


Les fichiers insrer sont gnralement sur le mme serveur que le script principal, mais il est galement possible dinsrer un fichier situ sur un autre serveur. Pour cela, il suffit de prciser lURL complte du fichier, par exemple http://www.php.net/chemin/ condition toutefois que la directive de compilation fichier.html, disableurlfopenwrapper nait pas t utilise. Il est noter que, dans ce cas, si vous appelez un script PHP, seul le rsultat de linterprtation du script par le serveur distant sera inclus dans le script principal (et non le code source du script inclus).

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur la compilation de PHP. Ouf ! Nous sommes protgs La remarque prcdente est importante. Elle implique que, tant que vous utilisez lextension .php et que votre serveur interprte les fichiers .php, un pirate ne peut pas esprer lire vos fichiers de configuration par un simple include("http: //www.serveurquejaimeraispirater.com/fichierconfig.php");.

210

Les inclusions de fichiers

Le passage de paramtres
Les fichiers tant tout btement intgrs dans le script principal, les variables globales qui auront t dfinies avant les commandes include() ou require() seront accessibles par les scripts intgrs. Et, rciproquement, les variables globales dfinies (ou modifies) dans les fichiers inclus (interprts localement) seront accessibles par les fichiers inclus suivants ainsi que par le script principal. Ainsi, si le script inclus ncessite un certain nombre de paramtres, il nest pas ncessaire (et cela ne fonctionnera pas) de faire :
<?php include("fichier_inc.php?parametre1=valeur1&parametre2=valeur2") ?>

3. Le langage PHP

mais plutt :
<?php $parametre1 = valeur1; $parametre2 = valeur2; include("fichier_inc.php"); ?>

Le seul cas o, dans un include(), on peut tre amen passer des paramtres, cest celui o le fichier inclus est un script PHP distant qui ncessite des paramtres. Cest un cas bien particulier, puisqualors le script inclus sera interprt par le serveur distant avant dtre inclus (et non inclus tel quel dans le script principal).
<?php include("http://www.php.net/script.php?param1=valeur1"); ?>

Les chemins relatifs


Les chemins prciss dans ces commandes, sils ne sont pas absolus, sont toujours relatifs au script en cours dexcution. Cela peut, premire vue, paratre banal, mais, cest en fait lourd de consquences. Si votre script principal.php du projet projet est stock dans un rpertoire projet et quil inclut un script inclus1_inc.php de la bibliothque biblio stock dans un rpertoire biblio, vous serez tent de mettre la commande include("../biblio/inclus1_inc.php"). vrai dire, jusque-l, tout va bien. Mais si votre script inclus1_inc.php a besoin dun autre fichier inclus2_inc.php (disons) de la mme bibliothque, ce dernier aura probablement utilis la commande include("inclus2_inc.php"). Et cest l le problme. Si vous dcidez dexcuter le script inclus1_inc.php, cela fonctionnera parfaitement. Mais, pour le script principal.php le chemin prcis dans la commande include de inclus1_inc.php sera relatif au script en cours (relatif au rpertoire projet). Autrement dit, on va chercher inclus2_inc .php sous projet et non sous ../biblio, ce qui, de toute vidence, ne fonctionnera pas.

211

Chapitre 3

Le langage PHP

Cela voudrait dire que, pour corriger le problme, nous devrions remplacer le chemin prcis dans inclus1_inc.php par un chemin relatif projet. En dautre termes, remplacer include("inclus2_inc.php") par include("../biblio/inclus2_inc.php"). Toutefois, cela est insatisfaisant plus dun titre. 1. 2. 3. la lecture de la bibliothque biblio cette rfrence ../biblio est plutt incongrue. Cette solution ne serait pas satisfaisante pour un projet situ dans un autre niveau darborescence. Lappel direct inclus1_inc.php fonctionne toujours, mais uniquement parce que nous avons pris un cas de figure plutt simple (projet et biblio sont au mme niveau darborescence).

Pour pallier ce problme, nous avons deux solutions possibles :

3. Le langage PHP

j j

Modifier le paramtre include_path. Toujours utiliser des chemins absolus.

Le paramtre include_path est un paramtre du fichier php.ini qui indique o aller chercher le fichier inclure. Ce paramtre dfinit une liste de chemins spars par des : sous Linux/ UNIX, mais par des ; sous Windows. Dans ce cas, il vous faudra modifier le fichier php.ini pour chaque bibliothque ajoute (et pour chacun des serveurs).

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur le fichier php.ini.
Ce paramtre include_path peut toutefois tre modifi au niveau du script (avant de faire lappel include() ou require()) grce la fonction ini_set(), selon le modle ini_set("include_path","<nouvelle liste de rpertoires>");.

Construction automatique de chemins absolus premire vue, lide de toujours prciser des chemins absolus lorsque lon dsire inclure des fichiers peut sembler extrmement contraignante. En effet, cela signifie, en thorie, que si lon souhaite dplacer lespace hbergeant lensemble des scripts (ou installer les scripts sur une autre machine proposant une autre arborescence), tous les chemins seront modifier. Mais heureusement, en pratique, il est possible de construire dynamiquement ces chemins absolus. En effet, la constante __FILE__ retourne le chemin absolu et le nom du fichier inclus. Le chemin absolu du fichier ayant un chemin relatif (au fichier inclus) cheminRelatif/fichier.php sera alors :
dirname(__FILE__)."/cheminRelatif/fichier.php"

Il suffit donc de remplacer lintuitif


include("cheminRelatif/fichier.php");

par
include(dirname(__FILE__)."/cheminRelatif/fichier.php").

212

Les inclusions de fichiers

Cas derreur et code retour


Si le script inclure nest pas trouv alors :
j j

Linstruction include() gnrera un message derreur de type "alerte" (WARNING) et le droulement du script principal se poursuivra. Linstruction require() gnrera un message derreur de type "fatale" (FATAL) et le droulement du script principal sinterrompra.

Si une erreur est leve (mme une erreur de type "fatale") dans un script inclus, cela ninterrompt pas pour autant lexcution du script principal (que ce soit avec include() ou require()).

3. Le langage PHP

Linstruction include() retourne un code derreur, ce qui nest pas le cas de linstruction
require().

Par dfaut, le code retour de linstruction include() est : TRUE en cas de succs et FALSE en cas dchec. Mais il est galement possible de gnrer son propre code retour (en cas de succs de linclusion) en sortant du script inclus par linstruction return() suivie de la valeur retourner (comme nous le ferions pour une simple fonction).

Listing 3.32 : include_05.php


<?php $retour = include("include_05_inc.php"); echo "Code retourn par le fichier inclus = $retour<br />"; ?>

Listing 3.33 : include_05_inc.php


<?php echo "* Je suis le fichier inclus,<br />"; echo "je me contente dafficher ce message<br />"; echo "et de retourner 5<br />"; return 5; ?>

affichera donc :
* Je suis le fichier inclus, je me contente dafficher ce message et de retourner 5 Code retourn par le fichier inclus = 5

Diffrences entre include() et require() Depuis la version 4.0.2, les instructions include() et require() ne diffrent que sur deux des points voqus dans ce chapitre :
j j

Comportement en cas dinexistence du fichier inclure ; Prsence ou non dun code retour.

213

Chapitre 3

Le langage PHP

Un cas dutilisation pratique mais potentiellement dangereux


La fonction include() est souvent utilise pour muler lutilisation de frames sans faire appel la balise HTML <frame>. Dans ce cas, la page principale du site contient, gnralement, un en-tte, un ou des menus (dans un bandeau suprieur, gauche ou droit), le contenu et, ventuellement, une ligne de copyright. Le tout pouvant prendre la forme dun tableau, o , quasiment, seule la partie "contenu" change (dune page lautre). Lide consiste alors fournir au script principal un paramtre indiquant quelle page de contenu afficher (techniquement, cela consiste en un simple include). Ce qui donne peu de choses prs (je vous laisse fignoler) le code suivant :

Listing 3.34 : include_frame01.php

3. Le langage PHP

<html> <body> <table width="100%"> <tr><td colspan="3" align="center">Entte</td></tr> <tr><td>Menu Gauche</td> <td> <?php include($_GET["url"]); ?> </td> <td>Menu Droit</td> </tr> <tr><td colspan="3" align="center">Copyright</td></tr> </table> </body> </html>

qui pourra tre appel comme suit :


include_frame01.php?url="accueil.html" include_frame01.php?url="mavie.html

Pourquoi viter la balise <frame> ? Le problme que lon peut rencontrer en utilisant des frames HTML est li au fait que ce qui apparat dans le navigateur nest pas le rsultat de linterprtation dune seule URL mais de plusieurs (celle qui dfinit les frames et celles qui dfinissent leur contenu). Ainsi, les moteurs de recherche, lorsquils indexent des sites contenant des frames, ne font pas de distinction entre ces diffrentes URL ce qui bien souvent les amne proposer une rorientation vers une des frames hors de son contexte, masquant gnralement la frame qui contient le menu principal, et empchant ainsi la navigation sur le site. Il existe de nombreux moyens de contourner ce problme : lutilisation du Javascript en est un, mais lidal est certainement de navoir quune page unique.

214

Les inclusions de fichiers

Cependant, ce type dimplmentation pose de srieux problmes de scurit. En effet, rien nempche un pirate dappeler lui-mme
include_frame01.php?url=http://www.sitedupirate.com/scriptmechant.txt.

Et si scriptmechant.txt affiche (mais nexcute pas) un texte contenant un script PHP, ce script sera excut sur VOTRE serveur au moment de linclude. Le pirate pourra alors faire ce que bon lui semble sur VOTRE serveur, commencer par excuter une commande afin darchiver du code source de votre site (et rcuprer ainsi vos mots de passe daccs la base de donnes). Dans ce cas de figure, la premire prcaution prendre consiste donc empcher linclusion de fichiers distants. Une solution simple et doublement utile consiste faire prcder la commande include() dun test dexistence du fichier par file_exists(). Cela vous vitera, dune part, de tenter dinclure des fichiers qui nexistent pas et, dautre part, comme file_exists() retourne FALSE dans le cas de fichiers distants, dinclure de tels fichiers.

3. Le langage PHP

Listing 3.35 : include_frame02.php


<html> <body> <table width="100%"> <tr><td colspan="3" align="center">Entte</td></tr> <tr><td>Menu Gauche</td> <td> <?php if (file_exists($_GET["url"])) include($_GET["url"]); ?> </td> <td>Menu Droit</td> </tr> <tr><td colspan="3" align="center">Copyright</td></tr> </table> </body> </html>

Vous voil rassur ? Eh bien, vous avez tort ! Ce nest pas parce que le fichier est sur votre serveur et quil existe (et quil est accessible depuis votre compte) que vous tes labri. Eh oui, les pirates sont de petits malins (cest dailleurs bien souvent par dfi que les pirates svissent). La plupart des serveurs web sont configurs pour tracer les vnements ( titre statistique ou de surveillance). Avec Apache, les fichiers de traces sont, par dfaut, access_log et error_log : ils contiennent gnralement (selon la configuration) lURL de la page demande, ladresse IP du client, etc. Lun est destin aux accs russis, lautre aux accs ayant chous. videmment, ces fichiers sont lisibles par le serveur et un appel file_exists() sur ces fichiers retournera TRUE. Si le pirate fait pointer $url sur ces fichiers, ils seront donc inclus. Vous me direz "oui, mais quest-ce que a va lui apporter de lire le contenu de ce fichier ?". premire vue rien, sinon que... je vous lai dit, ils sont malins !. Il lui suffit de trouver le moyen dinclure dans ces fichiers (et plutt dans le fichier error_log) le code PHP quil souhaite excuter. Pour cela, il suffit quil appelle une URL bidon dans laquelle il intgre le code (ex. : http://www.siteattaque.com/<moncode>). Et voil, le tour est jou !

215

Chapitre 3

Le langage PHP

Conclusion, il faut galement sassurer que le fichier inclus ne pourra tre, dune manire ou dune autre, un fichier altr par un pirate (ex. : contenu dun livre dor sil est stock dans un fichier et non dans une base de donnes). Si vous ne crez aucun fichier (style livre dor) dans lespace de votre serveur, vous pouvez alors certainement vous protger de ce type dattaque en remplaant le test prcdant par
if (eregi("^".$_SERVER["DOCUMENT_ROOT"], realPath($url))) ...

qui

vrifiera

que

le

chemin

rel

de

lURL

spcifie

commence

bien

par

$_SERVER["DOCUMENT_ROOT"] (la racine du serveur web).

3. Le langage PHP

Les pirates Noubliez pas : il y a probablement plus de mauvais administrateurs rseaux et de mauvais programmeurs que de pirates mal intentionns. De plus, les attaques que lon peut subir apprennent gnralement plus quelles ne causent de dsagrments (hormis une grosse perte de temps).

3.10. Les classes, les objets


Avec la version 5, PHP se tourne un peu plus vers le monde des langages orients objets (notez limportance, ici, du terme "orient"). Ce nest toutefois pas un langage objets comme peut l"tre Eiffel et contrairement aux autres langages orients objets, tels que C++ ou Java, PHP reste un langage de script.

Le langage Eiffel Cr par Bertrand Meyer, le langage Eiffel a trouv sa place dans le milieu universitaire en tant quoutil denseignement de la "philosophie" objet des langages de programmation. Son typage trs fort le rend particulirement intransigeant.
Avant dexpliquer comment cela se gre au niveau de PHP, il peut tre intressant de rappeler ce quest la programmation objet. Lide est davoir un langage de programmation o les donnes dune mme nature et les fonctions qui permettent de les manipuler sont intimement lies au sien dentits appeles objets. Les classes associes ces objets auront une fonction dinitialisation (appele "constructeur"), des attributs et des fonctions (proprits) qui leur sont propres (appels mthodes). Toutes ces entits rpondront aux exigences de lobjet. Prenons un exemple simple : une boutique dinformatique. On pourra dfinir un ordinateur partir de plusieurs classes :
j j j

Une classe Ordinateur (on appellera ordinateur lassociation dun botier, dun cran, dun clavier et dune souris) ; Une classe Boitier (on estime quun botier est dj quip) ; Une classe Ecran ;

216

Les classes, les objets

j j

Une classe Clavier ; Une classe Souris.

Chacune de ces classes comportera un certain nombre dattributs et de mthodes :


j j j j j
Souris : une souris sera dfinie par son prix et son modele. On ajoutera deux fonctions permettant de modifier le prix et le modle : modifierPrix(), modifierModele(). Clavier : dans un premier temps, nous nous contenterons des mmes informations que celles dfinies pour la classe Souris. Ecran : idem. Boitier : idem mais modifierDetails().

nous ajouterons un attribut details et la fonction

3. Le langage PHP

Ordinateur : on peut associer un identifiant unique un ordinateur identifiant, et une mthode pour calculer son prix calculerPrix() en fonction des lments qui le constitue. Quatre attributs pourront dfinir chacune des pices dun ordinateur : boitier, ecran, clavier, souris.

Alors que la plupart des attributs seront de type simple: rel (pour le prix), chane de caractres (pour le modle); La classe Ordinateur, elle, utilise des attributs boitier, ecran, clavier, souris qui sont des types complexes: savoir les classes prcdemment dfinies. La cration dun objet (instanciation dune classe) passe par lappel dune mthode particulire appele constructeur. Le constructeur des classes Souris, Clavier et Ecran aura comme paramtres le prix et le modle. Le constructeur de la classe Boitier aura comme paramtres le prix, le modle et une description. La classe Ordinateur aura un constructeur ayant comme attributs un botier, un cran, un clavier et une souris. Ce qui donne en notation "abstraite" :

Classe Ordinateur
Constructeur :
j

ordinateur (botier : BOITIER, cran : ECRAN, clavier : CLAVIER, souris : SOURIS).

Attributs :
j j j j
boitier : BOITIER ; ecran : ECRAN ; clavier : CLAVIER ; souris : SOURIS.

Fonctions :
j
calculerPrix() : REAL

217

Chapitre 3

Le langage PHP

Classe Boitier
Constructeur :
j

botier (modele : STRING, details : STRING, prix : REAL).

Attributs :
j j j
modele : STRING ; details : STRING ; prix : REAL.

3. Le langage PHP

Fonctions :
j j j
modifierModele (modele:STRING) : VOID ; modifierDetails (details : STRING) : VOID ; modifierPrix (details:STRING) : VOID.

Classe Ecran
Constructeur :
j

cran (modele : STRING, prix : REAL).

Attributs :
j j
modele : STRING ; prix : REAL.

Fonctions:
j j
modifierModele (modele : STRING) : VOID ; modifierPrix (details : STRING) : VOID.

Classe Clavier
Constructeur :
j

clavier (modele : STRING, prix : REAL).

Attributs :
j j
modele : STRING ; prix : REAL.

Fonctions :
j
modifierModele (modele : STRING) : VOID ;

218

Les classes, les objets

modifierPrix (details : STRING) : VOID.

Classe Souris
Constructeur :
j

souris (modele : STRING, prix : REAL).

Attributs :
j j
modele : STRING ; prix : REAL.

3. Le langage PHP

Fonctions :
j j
modifierModele (modele : STRING) : VOID ; modifierPrix (details : STRING) : VOID.

Ce modle dfinit simplement un ordinateur tel quil a t dcrit. Lavantage de ce type de programmation, cest quil est trs facilement modifiable et corrigible. Sil est dcid que le calcul du cot dun ordinateur nest plus la simple addition des pices le composant, mais le cot des pices plus un cot de montage, il suffit de modifier la mthode calculerPrix() de la classe Ordinateur. Nous verrons par la suite quil est possible de faire bien mieux encore en se servant de ce qui est appel lhritage.

la POO en deux mots Ceci nest quun aperu de la programmation oriente objet (POO) ; un aperu qui na dailleurs pas dautre ambition que dinitier. Il existe de nombreux livres et sites Internet qui en parlent longuement, de manire gnrale ou associ un langage en particulier.

Dnir une classe


Il est dusage de dfinir une seule classe par fichier, mais cela nest pas obligatoire. Voici le squelette dune classe :
<?php class Ordinateur { // on placera ici le constructeur, les attributs et les mthodes. } ?>

219

Chapitre 3

Le langage PHP

Une classe, un fichier Une classe par fichier est sans aucun doute la meilleure faon de sy retrouver : le nom du fichier peut ainsi prendre le nom de la classe (ventuellement suffix par "_class"), et il est alors trs facile de retrouver la classe sur laquelle on veut travailler.

stdClass Vous ne devez en aucun cas appeler une classe stdClass, ce nom tant rserv PHP. 3. Le langage PHP

Les constructeurs
Un constructeur est une mthode (fonction) appele lors de linstanciation (la cration dun objet), qui sert gnralement initialiser des attributs. Le nom du constructeur doit tre "__construct".

Compatibilit ascendante Avec PHP 4, le nom du constructeur devait tre identique au nom de la classe. Ne vous inquitez pas ! Ce nest pas parce que vous avez, dans vos tiroirs, des scripts crits en objet pour PHP 4, que vous devez ncessairement vous empresser de les corriger pour les faire fonctionner avec PHP 5. En fait, si la mthode __construct nest pas trouve, linterprteur continuera rechercher une mthode portant le mme nom que la classe et sen servira comme constructeur.
<?php class Ordinateur { // on placera ici les attributs. function { echo echo echo echo echo } __construct($boitier, $ecran, $clavier, $souris) "Le constructeur a t appel avec les paramtres:<br />"; $boitier."<br />"; $ecran."<br />"; $clavier."<br/>"; $souris."<br />";

// on placera ici les mthodes. } ?>

Pour crer un objet, il suffit dutiliser linstruction new comme suit :

220

Les classes, les objets

$monOrdinateur = new Ordinateur($monBoitier, $monEcran, $monClavier, $maSouris);

Lexemple ici suppose que $monBoitier, $monEcran, $monClavier et $maSouris sont de type chane de caractres (ce qui nest pas ce que lon souhaite terme). A tout moment, il vous est possible de vrifier si un objet appartient (ou drive dune) classe donne en faisant appel linstruction instanceOf.
<?php // Nous supposons que la classe MaClasse a t dfinie prcdemment $obj = new MaClasse(); if ($obj instanceOf MaClasse) { echo "Oui, cest bien le type dobjet que jattendais"; } else { echo "Mais cest quoi cet objet ?"; } ?>

3. Le langage PHP

Les attributs
Les attributs sont des variables ou des constantes associes un objet. Ils sont prcds du mot-cl public, protected ou private.
<?php class Ordinateur { public $boitier; public $ecran; public $clavier; public $souris; function __construct($boitier, $ecran, $clavier, $souris) { $this->boitier = $boitier; $this->ecran = $ecran; $this->clavier = $clavier; $this->souris = $souris; } // on placera ici les mthodes. } ?>

var PHP4 Du temps de PHP4, les modificateurs de porte: public, protected et private nexistaient pas. Il fallait alors utiliser le mot cl var (qui reste toutefois compatible avec PHP 5 et qui se comporte comme public)

221

Chapitre 3

Le langage PHP

Dans cet exemple, le constructeur joue bien son rle dinitialisation. $this est lobjet courant. $this>boitier fait donc appel lattribut boitier de linstance "courante" de Ordinateur. Les attributs ayant t dclars public, ils sont accessibles depuis "tout endroit du code": savoir au sein de la classe (via $this>boitier) tout comme en dehors de la classe par linstruction :
$monBoitier = $monOrdinateur->boitier;

Et comme nous le verrons plus tard, un attribut public est galement accessible depuis une classe drive (Cf. hritage).

3. Le langage PHP

Appel dattributs Une erreur courante consiste crire $monOrdinateur>$boitier au lieu de $monOrdinateur>boitier. Bien entendu, la premire version ne peut fonctionner, car elle devient $monOrdinateur>"" si $boitier nest pas dfini.

Les constantes
Il est possible de dfinir des constantes au sein dune classe, pour cela, il suffit dutiliser linstruction const. Celles ci sont alors uniquement accessibles via un appel statique (MonObjet::MA_CONSTANTE). Notez quune constante dfinie au niveau de la classe sera prioritaire sur une constante portant le mme nom, mais dfinie en dehors de la classe via linstruction define.
<?php class Divers { const MODE_RAPIDE = "rapide" const MODE_PRECIS = "precis"; } ?> echo Divers::MODE_RAPIDE."<br />";

Valeur initiale des attributs Comme pour les variables statiques des fonctions, il nest pas possible dinitialiser les valeurs des variables en faisant appel des oprateurs (ex: public $val = 5 + 7;) ou des fonctions (ex: public $val = sqrt(25);).

attributs statiques
Au besoin, vous pourrez galement utiliser le modificateur "static" qui permet de dfinir une variable partage par toutes les instances de lobjet. Une variable statique sadresse selon le schma MonObjet::$maVariable.

222

Les classes, les objets

<?php class Divers { static $compteur = 0; function incrementeCompteur() { self::$compteur++; } function afficheCompteur() { echo self::$compteur; } } $obj1 = new Divers(); $obj1->incrementeCompteur(); $obj2 = new Divers(); $obj1->afficheCompteur(); $obj2->afficheCompteur();

3. Le langage PHP

?>

affichera donc :
2 2

Ce qui montre bien que la variable statique est partage par les deux instances.

On nest jamais mieux servi que par soi-mme Dans le cas dun attribut ou dune mthode statique, pour faire rfrence la classe courante vous devez utiliser linstruction self::.

Les mthodes
Les mthodes sont des fonctions propres une classe donne qui permettent de manipuler ou accder aux attributs dun objet. Elles se dclarent comme des fonctions mais sont dfinies au sein dune classe.
<?php class Ordinateur { public $boitier; public $ecran; public $clavier; public $souris; function __construct($boitier, $ecran, $clavier, $souris) { $this->boitier = $boitier;

223

Chapitre 3

Le langage PHP

$this->ecran = $ecran; $this->clavier = $clavier; $this->souris = $souris; } // La fonction calculer_prix renvoie la somme des prix des composants function calculerPrix() { $boitier = $this->boitier; $ecran = $this->ecran; $clavier = $this->clavier; $souris = $this->souris; return $boitier->prix+$ecran->prix+$clavier->prix+$souris->prix; } ?>

3. Le langage PHP

Lappel une mthode se fait selon le schma suivant:


$monObject->maMethode();

Noms de mthodes Deux classes peuvent avoir les mmes noms de mthodes, vu quelles sont prcdes, lors de leur appel, dun objet typ. Aucune confusion nest alors possible.
Les remarques, prsentes dans le chapitre sur les fonctions, concernant la porte des variables (globales, statiques ou locales) sappliquent exactement de la mme manire pour les mthodes.

Noms de mthodes rservs Afin de ne pas prendre le risque de rentrer en conflit avec des mthodes (appeles "fonctions magiques") utilises pour le fonctionnement interne de PHP, vous ne devez pas faire prcder le nom de vos mthodes par "__".

Les mthodes statiques


Une mthode ne faisant pas appel un attribut de lobjet (ou une autre mthode non statique) est dit statique.
<?php class Souris { function afficher() { echo "Cet objet reprsente une souris dordinateur"; } } ?>

224

Les classes, les objets

Pour appeler une telle mthode, il est inutile de crer un objet (par un appel new). Il est donc possible dutiliser loprateur :: (au lieu de >) . Ainsi, le script suivant aura pour effet dafficher "Cet objet reprsente une souris dordinateur" sans pour autant avoir eu besoin de crer un objet Souris.
<?php Souris::afficher(); ?>

Passage par rfrence et drfrencement


Passage par rfrence
Avec PHP 5, les objets sont systmatiquement passs par rfrence (comme dans un langage tel que Java) et non plus par copie. Il nest donc pas ncessaire de faire prcder le nom du paramtre dun & comme ce ft le cas avec PHP 4. Ainsi, lexemple suivant :

3. Le langage PHP

Listing 3.36 : Exemple


<?php class MaClasse { var $msg; function MaClasse() { $this->msg = "Message par dfaut"; } } function modifieMessage($objet) { $objet->msg = "Message modifi par la fonction"; } $obj = new MaClasse(); modifieMessage($obj); echo $obj->msg; }

retournera
Message modifi par la fonction

alors quavec PHP 4, il retournait


Message par dfaut

puisque la modification portait sur une copie de lobjet.

225

Chapitre 3

Le langage PHP

Objet retour Bien que cela soit plus difficile dmontrer, cest galement vrai pour les objets retourns par les fonctions (par return). Dans ce cas, ce nest pas une copie de lobjet cr dans la fonction qui est retourn, mais une rfrence sur lobjet.
En fait, ce sont toutes les manipulations dobjets qui se font par rfrence (comme cest traditionnellement le cas avec un langage de programmation orient objet) et non plus par copie. Ainsi le code suivant :
<?php $obj = new MaClasse(); $obj2 = $obj1; $obj2->msg = "Message attribu \$obj2"; echo $obj1->msg; ?>

3. Le langage PHP

retournera:
Message attribu $obj2

Alors quavec PHP 4, il retournerait :


Message par dfaut

Drfrencement
A supposer que lune des mthodes de lobjet retourne un objet comme par exemple la mthode suivante:
function recupereEcran() { return $ecran; }

Il est dsormais possible de rcuprer en un seul appel la valeur dun attribut de lobjet ainsi retourn en utilisant la syntaxe $ordinateur>recupereEcran()>prix. On parle alors de drfrencement.

PHP 4 et le drfrencement Notez bien que cela ntait pas possible avec PHP 4. Nous tions alors contraints de passer par une variable intermdiaire, selon le modle suivant: $ecran = $ordinateur>recupereEcran(), puis $ecran>prix. Lappel suivant tait, en revanche, tout fait valide $ordinateur>ecran>prix.

226

Les classes, les objets

Typage
Sans que PHP ne soit devenu un langage fortement typ avec la venue de la version 5. Celle-ci permet toutefois de prciser le type (uniquement sil sagit dun objet) des paramtres des mthodes. Comme le montre lexemple suivant (la classe Boitier est dcrite un peu plus loin):
function changerBoitier(Boitier $boitier) { $this->boitier = $boitier; }

En cas de passage de paramtre dun mauvais type, lerreur ne sera pas dtecte lors de la compilation mais lors de lexcution de la mthode. Il sagit alors dune erreur de niveau "fatal" et non une exception qui est leve.

3. Le langage PHP

Modicateurs de mthodes
Sur le mme principe que pour les attributs, la dclaration des mthodes peut tre affine grce aux modificateurs "private", "protected" ou par dfaut "public" pour ce qui est de la porte et "final" pour ce qui est des droits en modification (voir hritage).

Lhritage
Si lon reprend lensemble des classes (La classe Ordinateur ayant t prcdemment dfinie) nous obtenons:

Classe Boitier
<?php class Boitier { public $modele; public $details; public $prix; // Constructeur function __construct($modele, $prix, $details) { $this->modele = $modele; $this->details = $details; $this->prix = $prix; } // Mthodes. function modifierModele($modele) { $this->modele = $modele; } function modifierDetails($details)

227

Chapitre 3

Le langage PHP

{ $this->details = $details; } function modifierPrix($prix) { $this->prix = $prix; } ?>

Classe Ecran
3. Le langage PHP
<?php class Ecran { public $modele; public $prix; // Constructeur function __construct($modele, $prix) { $this->modele = $modele; $this->prix = $prix; } // Mthodes. function modifierModele($modele) { $this->modele = $modele; } function modifierPrix($prix) { $this->prix = $prix; } ?>

Classe Clavier
<?php class Clavier { public $modele; public $prix; // Constructeur function __construct($modele, $prix) { $this->modele = $modele; $this->prix = $prix; }

228

Les classes, les objets

// Mthodes. function modifierModele($modele) { $this->modele = $modele; } function modifierPrix($prix) { $this->prix = $prix; } ?>

3. Le langage PHP

Classe Souris
<?php class Souris { public $modele; public $prix; // Constructeur function __construct($modele, $prix) { $this->modele = $modele; $this->prix = $prix; } // Mthodes. function modifierModele($modele) { $this->modele = $modele; } function modifierPrix($prix) { $this->prix = $prix; } ?>

Ces quatre dernires classes se ressemblant normment, il serait prfrable de crer une classe commune Composant. Cest lobjet de ce sous-chapitre. La programmation objet permet de faire de lhritage. On parle dhritage lorsquune classe bnficie (hrite) des proprits (mthodes et attributs) dune autre. La classe qui hrite des proprits pourra implmenter dautres proprits ; on dit alors quelle "tend" la classe parente. Dans notre exemple, nous allons crer une classe Composant dont hriteront les classes Boitier, Clavier et Souris.

229

Chapitre 3

Le langage PHP

Classe Composant
<?php class Composant { public $modele; public $prix; // Constructeur function __construct($modele, $prix) { $this->modele = $modele; $this->prix = $prix; } // Mthodes. function modifierModele($modele) { $this->modele = $modele; } function modifierPrix($prix) { $this->prix = $prix; } ?>

3. Le langage PHP

Maintenant, si les classes Boitier, Clavier et Souris hritent de la classe Composant, elles vont considrablement se simplifier. Pour cela, il suffit de prciser "extends <classe parente>" lors de la dclaration de la classe.

Classe Souris
<?php class Souris extends Composant { } ?>

Cette dclaration suffit dfinir la classe Souris comme fait prcdemment. Cette classe vide peut sembler inutile, mais elle peut savrer trs utile si lon veut ajouter une information sur le nombre de boutons ou sur le fait quelle soit sans fil, par exemple (information qui naurait pas de sens pour les autres composants). Nous verrons avec la classe Boitier comment ajouter des mthodes propres une classe.

Classe Clavier
<?php class Clavier extends Composant {

230

Les classes, les objets

} ?>

Ce fichier suffit dfinir la classe Clavier comme fait prcdemment. De mme que pour la classe Souris, il pourrait tre intressant dajouter le nombre de touches ou le fait que ce soit un clavier avec ou sans fil.

Classe Boitier
<?php class Boitier extends Composant { private $details; // Constructeur function __construct($modele, $prix, $details) { new Composant($modele,$prix); $this->details = $details; } // Mthodes. function modifierDetails($details) { $this->details = $details; } } ?>

3. Le langage PHP

Ainsi

dfini, la classe Boitier bnficie des mthodes modifierModele() et modifierPrix() dfinies dans la classe Composant. Mais comme la classe que nous souhaitons obtenir est "plus riche" que la classe Composant dont elle hrite, il a fallu redfinir le constructeur, et ajouter une mthode et un attribut. La classe Ordinateur reste inchange. Dans le cas de lhritage, la classe parente peut tre rfrence laide du mot-cl parent. Ainsi, linstruction parent::modifierModele() fera appel la fonction modifierModele() de la classe parente mme si celle-ci a t redfinie au niveau de la classe fille.

Hritage et appel du constructeur Lorsque la classe qui hrite ne redfinit pas le constructeur, alors cest le constructeur de la classe parente qui est appel. Lorsque la classe qui hrite redfinit le constructeur, alors cest le constructeur de la classe fille qui est appel, sans que le soit le constructeur de la classe parente ( moins dun appel explicite parent::__construct()). Ce comportement est diffrent de celui de certains langages, et de Java en particulier.

231

Chapitre 3

Le langage PHP

Hritage multiple Il nest pas certain que PHP intgre un jour lhritage multiple mais comme le prouve Java, on peut trs bien vivre sans (tout en svitant bien des soucis).

Rcriture de mthode
Comme nous lavons vu avec lexemple de la classe Boitier, une classe fille peut trs bien r-crire une mthode de la classe mre. Dans ce cas, la signature de la mthode reste inchang mais son comportement pourra tre totalement (ou en partie modifi).

3. Le langage PHP

Si vous ne souhaitez pas que vous ou un quelconque utilisateur de votre classe ne fasse une grosse bourde en rcrivant maladroitement une des mthodes de la classe alors dclarez l final .
<?php class ClassMereAvecUneMethodeCritique { final function methodeCritique() { // Cest une methode critique a ne surtout pas // r-crire. } } ?>

Porte des attributs et mthodes (public, protected, private)


Comme cela a t voqu prcdemment, les attributs et les mthodes peuvent tre dclars public", "protected" ou "private". Un attribut ou une mthode dclar public est accessible librement. Un attribut ou une mthode dclar private nest accessible que depuis une mthode de la classe dans laquelle il a t dfini. Un attribut ou une mthode dclar protected nest accessible que depuis une mthode de la classe dans laquelle il a t dfini ou dune classe en hritant. Lutilisation de ces modificateurs de porte nest pas ngliger. Il peut tre par exemple ncessaire de rendre des attributs private ou protected afin dobliger lutilisation dune mthode pour affecter ces valeurs. Ces mthodes appeles accesseurs pourront au besoin pr-traiter la demande ou en contrler la validit avant de modifier ou retourner la valeur de lattribut.
<?php class Composant { private $modele; private $prix; // Constructeur

232

Les classes, les objets

function __construct($modele, $prix) { $this->modele = $modele; $this->prix = $prix; } // Mthodes. function modifierModele($modele) { if ($modele == "inconnu") $modele = NULL; $this->modele = $modele; }

3. Le langage PHP

function modifierPrix($prix) { if ($prix < 0) $prix = 0; $this->prix = $prix; } ?>

Avec cette classe, lappel $monBoitier>prix = 10; nest plus possible. Il faut ncessairement passer par la mthode modifierPrix() comme suit $monBoitier>modifierPrix(10); ce qui permettra de vrifier que le prix indiqu nest pas ngatif.

Les interfaces
Lorsquelle est correctement matrise, la programmation oriente objet permet de faire des choses vraiment formidables. Il est ainsi possible de crer des classes (et leurs mthodes) qui manipulent des objets de faon tout fait gnrique sans en connatre leur implmentation exacte mais en sappuyant simplement sur les mthodes quils proposent. Dans ce cas, il faut toutefois sassurer que les objets manipuls implmentent effectivement ces mthodes. Pour sen assurer, il suffit alors de dfinir une interface dcrivant lensemble des mthodes qui doivent tre implmentes.
<?php interface MonInterface { public function afficher(); } ?>

Nous avons ici dcrit linterface dune classe devant implmenter une mthode afficher(). Les classes prtendant implmenter cette interface devront alors le prciser avec le mot cl implements.
<?php class ClasseQuiImplemente implements MonInterface { function afficher() { echo "Moi quand jaffiche cest lcran"; }

233

Chapitre 3

Le langage PHP

} ?>

Une telle classe pourra alors tre utilise par la classe suivante:
<?php class ClasseQuiFaitLeTraitement { var $obj; function __construct($obj) { $this->obj = obj; } function traitement() { // Quelques lignes de traitement puis $this->obj->afficher(); } } $objAffichage = new ClasseQuiImplemente(); $objTraitement = new ClasseQuiFaitLeTraitement($objAffichage) $objTraitement->traitement(); ?>

3. Le langage PHP

Les classes abstraites


Un peu dans le mme esprit que les interfaces, il existe galement les classes abstraites. Il sagit alors de classes qui peuvent implmenter un certain nombre de mthodes et laisse le soin dautres dimplmenter un certain nombre dautres mthodes alors dclares comme abstract (abstraites). Une classe contenant des mthodes abstraites est elle-mme abstraite et ne peut tre instancie. Une classe abstraite ne peut tre que drive (par hritage). Lexemple prcdent donnerait alors
<?php abstract class MaClasseAbstraite { abstract public function afficher(); function autreMethode() { // Eventuellement une methode qui // a t implmente ici } } class ClasseQuiImplemente extends MaClasseAbstraite { function afficher() { echo "Moi quand jaffiche cest lcran"; } }

234

Les classes, les objets

class ClasseQuiFaitLeTraitement { var $obj; function __construct(MaClasseAbstraite $obj) { $this->obj = obj; } function traitement() { // Quelques lignes de traitement puis $this->obj->afficher(); } } $objAffichage = new ClassQuiImplemente(); $objTraitement = new ClasseQuiFaitLeTraitement($objAffichage) $objTraitement->traitement(); ?>

3. Le langage PHP

Vous noterez que dans ce cas, il est possible de vrifier que le classe passe en paramtre du constructeur hrite bien de la classe abstraite (et donc implmente bien la mthode afficher()).

Les exceptions
Lensemble des langages de programmation oriente objet offrent une alternative lhabituel code derreur retourn par une fonction: la place, lorsquune classe lve une erreur, elle interrompt son droulement et redonne la main au programme appelant en mettant un objet appel Exception. PHP nchappe pas cette rgle. La gnration de ces "messages" est alors contrle et gre dans un bloc try... catch..

Listing 3.37 : exception.php


<?php class ObjetMathematique { function division($a, $b) { if ($b == 0) throw new Exception("Division par zero.", 10); else return $a/$b; } } try { $obj = new ObjetMathematique(); echo $obj->division(4, 2)."<br />\n"; echo $obj->division(4, 0)."<br />\n"; echo $obj->division(8, 4)."<br />\n"; } catch (Exception $ex) { echo "getMessage() ".$ex->getMessage()."<br />\n";

235

Chapitre 3

Le langage PHP

echo "getCode() ".$ex->getCode()."<br />\n"; echo "getFile() ".$ex->getFile()."<br />\n"; echo "getLine() ".$ex->getLine()."<br />\n"; echo "getTrace() "; var_dump($ex->getTrace()); echo "<br />\n"; echo "getTraceAsString() ".$ex->getTraceAsString()."<br />\n"; } ?>

Cela retournera alors :


2<br /> getMessage() Division par zero.<br /> getCode() 10<br /> getFile() /usr/local/apache/htdocs/regtest/poo/_exception.php<br /> getLine() 7<br /> getTrace() array(1) { [0]=> array(6) { ["file"]=> string(51) "/usr/local/apache/htdocs/regtest/poo/_exception.php" ["line"]=> int(15) ["function"]=> string(8) "division" ["class"]=> string(17) "ObjetMathematique" ["type"]=> string(2) "->" ["args"]=> array(2) { [0]=> int(4) [1]=> int(0) } } } <br /> getTraceAsString() #0 /usr/local/apache/htdocs/regtest/poo/_exception.php(15): ObjetMathematique->division(4, 0) #1 {main}<br />

3. Le langage PHP

En effet, lorsque nous avons appel la mthode division avec un diviseur gal 0, la mthode a lev une exception grce linstruction throw. Ceci a donc mis un terme lexcution de la mthode ainsi qu celle du bloc try du programme appelant, lexcution se poursuivant par le bloc catch correspondant lobjet exception gnr. (Ici, nous navons quun bloc catch, mais il est possible den avoir autant quil y a dexceptions diffrentes). Le reste du programme ( la suite du bloc try...catch) se droule alors normalement.

236

Les classes, les objets

Dans cet exemple, nous avons utilis la classe prdfinie Exception, nous aurions galement pu dfinir notre propre classe dexception condition quelle hrite de Exception. La classe Exception prsente un constructeur permettant de prciser un message derreur ainsi quun code derreur.

Exception->__construct()
Instancie un objet Exception.

3. Le langage PHP

Syntaxe $message $codeErreur

new Exception([string $message [, int $codeErreur]]) Message derreur. Code derreur.

Cette classe possde de nombreuses mthodes:

Exception->getMessage()
Retourne le message derreur de lException. Syntaxe retour string getMessage() Message derreur.

Exception->getCode()
Retourne le code derreur de lException. Syntaxe retour int getCode() Code derreur.

Exception->getFile()
Retourne le nom du fichier dans lequel lException a t leve. Syntaxe retour string getFile() Nom du fichier.

237

Chapitre 3

Le langage PHP

Exception->getLine()
Retourne le numro de la ligne du fichier o lException a t leve. Syntaxe retour int getLine() Ligne dans le fichier.

3. Le langage PHP

Exception->getTrace()
Retourne le tableau des enchanements des appels de fonctions ayant conduit lException. Syntaxe retour array getTrace() Tableau index contenant une entre par fonction dans la pile dappel. Chacune des valeurs de ce tableau est un tableau associatif contenant les cls: file, prcisant le nom du fichier contenant lappel; .line, prcisant la ligne o a eu lieu lappel, function, prcisant le nom de la fonction (ou mthode) appele, class, prcisant le nom de la classe implique, type, prcisant le type dappel (ex: -> pour un appel de mthode non statique) et enfin args, prcisant les paramtres passs la fonction.

PHP 4 (ne) fait (pas) Exception PHP 4 ne grait pas les exceptions.

Les fonctions de manipulation des objets


PHP propose un ensemble de fonctions applicables des objets. Il sagit essentiellement de fonctions dintrospection: cest dire des fonctions retournant des informations sur un objet comme par exemple la liste des attributs et mthodes quil expose.

get_class()
Retourne le nom de la classe dont lobjet spcifi est une instance. Syntaxe $objet retour string get_class(object $objet) Objet dont vous souhaitez dterminer la classe. Nom de la classe ou FALSE en cas dchec.

238

Les classes, les objets

class_exists()
Vrifie si une classe existe ou non. Syntaxe $classe $chargement Automatique retour boolean class_exists(string $classe [, boolean $chargementAutomatique]) Nom de la classe que vous souhaitez tester. TRUE (valeur par dfaut) si vous souhaitez utiliser le chargement automatique de la classe (cf. __autoload), FALSE sinon.

3. Le langage PHP

TRUE si la classe existe, FALSE sinon.

get_class_methods()
Retourne la liste des mthodes exposes par une classe ou un objet. Syntaxe $classe retour array get_class_methods(mixed $classe) Nom de la classe ou une instance (lobjet directement). Tableau index ayant pour valeurs les noms des mthodes ou NULL si la classe nexiste pas.

method_exists()
Vrifie si un objet expose une mthode donne ou non. Syntaxe $objet boolean method_exists(object $objet, string $methode) Objet que vous souhaitez tester (contrairement get_class_method() il nest pas possible de spcifier le nom de la classe la place). Nom de la mthode. TRUE si la mthode existe, FALSE sinon.

$classe retour

get_class_vars()
Retourne la liste des attributs dune classe et leur valeur (initiale).

239

Chapitre 3

Le langage PHP

Syntaxe $classe retour

array get_class_vars(string $classe) Nom de la classe (contrairement get_class_method() il nest pas possible de spcifier lobjet directement). Tableau index ayant pour cls les noms des attributs et pour valeur la valeur initiale des attributs ou FALSE si la classe nexiste pas.

get_object_vars()
3. Le langage PHP
Retourne la liste des attributs dun objet et leur valeur. Syntaxe $objet retour array get_object_vars(object $objet) Objet dont vous souhaitez obtenir la liste de valeur des attributs. Tableau index ayant pour cls les noms des attributs et pour valeur la valeur des attributs ou FALSE en cas derreur.

Dautres fonctions sont plus spcifiquement lies la notion dhritage.

get_parent_class()
Retourne le nom de la classe mre de la classe teste. Syntaxe $classe retour string get_parent_class(mixed $classe) Nom de la classe ou instance (lobjet directement). Nom de la classe mre ou FALSE en cas derreur.

is_subclass_of()
Vrifie si un objet hrite dune classe donne ou non. Syntaxe $objet $classe retour boolean is_subclass_of(object $objet, string $classe) Objet tester. Nom de la classe dont lobjet est susceptible dhriter. TRUE si lobjet hrite bien de la classe indique, FALSE sinon.

Il est galement possible de rcuprer la liste de lensemble des classes et interfaces connues du script.

240

Les classes, les objets

get_declared_classes()
Retourne la liste des classes connues (on y retrouve videmment stdClass, Exception, etc.). Syntaxe retour array get_declared_classes() Tableau index ayant pour valeurs les noms des classes.

get_declared_interfaces()
Retourne la liste des interfaces connues. Syntaxe retour array get_declared_interfaces() Tableau index ayant pour valeurs les noms des interfaces.

3. Le langage PHP

Programmation avance
Mmoriser des objets
Il est parfois intressant de stocker un objet dans un fichier (une variable de session ou encore une base de donnes). Ce nest pas, a priori, une tche aise, mais elle se rvle trs simple sil est possible de transformer un objet en chane de caractres et une chane de caractres en objet. Cest ce que lon appelle la srialisation et la dsrialisation. La srialisation seffectue laide de la fonction serialize() ; lopration inverse laide de la fonction unserialize(). Pour pouvoir relire cette chane de caractres et la transformer en objet, la classe doit tre dfinie au moment de lopration de dsrialisation. Dans lexemple suivant, nous sauvegarderons un objet souris, puis nous le rcuprerons dans un autre script en se servant dun fichier texte pour mmoriser cet objet.

Listing 3.38 : sauvegarde.php


<?php // Inclusion du contenu du fichier Souris.php // contenant la dfinition de la classe include("Souris.php"); $souris = new Souris("Souris Facile",9.98); $chaine_souris = serialize($souris); $fichier = fopen("sauvegarde", "w"); // Le fichier sauvegarde // est ouvert en criture

241

Chapitre 3

Le langage PHP

fputs($fichier, $chaine_souris); fclose($fichier); ?>

// Le contenu de la chane de // caractres est crit // Le fichier est referm

Listing 3.39 : lecture.php


<?php // Il est indispensable dinclure la dfinition de la classe // Souris pour que unserialize() fonctionne correctement include("Souris.php");

3. Le langage PHP

$souris = implode("", @file("sauvegarde")); //la chane stocke // est rcupre unserialize($souris); // la chane est transforme en son objet associ

// $souris se traite dsormais comme un objet. $souris->modifier_prix(9.99); ?>

Les sessions Dans le cas des sessions, si vous utilisez la fonction session_register() sur un objet, celui-ci est automatiquement srialis. Il faut donc faire bien attention inclure la dfinition de la classe dans chacun des fichiers accessibles ds le moment o lobjet est enregistr en session. Sinon celui-ci se transforme en objet de classe stdClass et na aucune utilit, car, alors, aucune des mthodes nest accessible.

__sleep
La fonction __sleep() est appele avant toute srialisation. Cette fonction renvoie un tableau des valeurs mmoriser. Elle permet de nindiquer que les valeurs utiles stocker et de fermer les connexions aux bases de donnes par exemple.

__wakeup
La fonction unserialize() fait appel cette mthode au moment de recrer lobjet. Cela peut permettre de rtablir des connexions aux bases de donnes par exemple.
<?php class Test { var $attribut1; var $attribut2; var $attribut3; function Test($attribut1, $attribut2) {

242

Les classes, les objets

$this->attribut1=$attribut1; $this->attribut2=$attribut2; $this->attribut3=$attribut1+$attribut2; } function __sleep() { return array(attribut1, attribut2); } function __wakeup() { $this->attribut3 = $this->attribut1 + $this->attribut2; }

3. Le langage PHP

} ?>

En faisant ceci, on conomise en mmoire, car $attribut3, qui peut tre calcul partir de $attribut1 et $attribut2, nest pas stock (en effet, la fonction __sleep ordonne de ne stocker que les attributs attribut1 et attribut2). Il est cependant recalcul au moment de reconstituer lobjet.

Destruction des objets


Lorsquun objet nest plus utilis (ou tout simplement lorsque la fin du script arrive), les objets sont dtruits. Jusqualors, il ntait pas possible de demander PHP dexcuter certaines fonctions (ex. : fermeture dun fichier, dconnexion dune base de donnes, etc.) avant de dtruire dfinitivement lobjet. Cest dsormais possible en crivant une mthode __destruct() contenant le code excuter avant la destruction de lobjet.
<?php class ObjetMortBruyante { var $msg; function __construct() { $this->msg = "Je suis un objet qui ne sait pas mourir en silence"; } function __destruct() { echo "Arrgggg.... je meurs"; } } $obj = new ObjetMortBrutante(); // la fin du script entraine la destruction de lobjet ?>

Ce script retournera donc :


Arrgggg.... je meurs

indiquant bien que la mthode __destruct() a t appele.

243

Chapitre 3

Le langage PHP

__destruct() et lhritage En cas dhritage, tout comme pour le constructeur, le destructeur de la classe parente nest pas appel automatiquement. Si vous souhaitez appeler ce dernier vous devrez inclure un appel parent::__destruct().

Clonage
Avec larrive de PHP 5 et de son moteur Zend2, il est dsormais possible de prciser comme doit se faire la copie dun objet en crant une mthode __clone().

3. Le langage PHP

Il est alors possible par exemple de rinitialiser certaines valeurs (les caractristiques propres la copie) tout en demandant la copie de certaines autres (les caractristiques gnrales de lobjet copi). Pour accder aux donnes de lobjet copi, vous devrez faire appel $that (qui joue le rle du $this mais pour lobjet copi).

This or That ? Nous devons avouer notre perplexit sur ce point. Il se trouve que dans les premires documentations et premires implmentations de PHP 5. Il fallait effectivement utiliser $that. Cependant, lexemple suivant qui fonctionnait tel que nous lavions imagin prcdemment ne fonctionne pas exactement pareil avec PHP 5.0.1.
Ainsi lexemple suivant :
<?php class ObjetMutant() { var $msg, $msg2; function ObjetMutant() { $this->msg = "Je suis un mutant"; $this->msg2 = "et je reste un mutant."; } function __clone() { $this->msg = "Jai mut"; $this->msg2 = $that->msg2; } } $obj = new ObjetMutant(); $obj2 = clone $obj; echo $obj->msg." ".$obj->msg2."<br />"; echo $obj2->msg." ".$obj2->msg2."<br />"; ?>

retournera donc (ou tout du moins retournait) :


Je suis mutant et je reste un mutant. Jai mut et je reste un mutant.

244

Les classes, les objets

Il retourne dsormais
Je suis mutant et je reste un mutant. Jai mut

A moins de remplacer le $that par un $this. Quoiquil en soit, une chose est sure, lappel de linstruction clone, la mthode __clone() a bien t excute. Notez, que la mthode __clone() ne peut tre appele directement.

Nouvelles mthodes "internes"


PHP 5 utilise de nouvelles mthodes internes. En particulier lors de la rcupration du contenu dun attribut selon le schma $objet>attribut, PHP retournera la valeur de lattribut sil existe, sinon il appellera la mthode __get() avec pour paramtre le nom de lattribut. Mthode quil est possible de redfinir.
<?php class MaClasse { var $attr1; function __contruct() { $attr1 = "demo"; } function __get($nom) { return "Dsol, $nom nest pas un attribut connu"; } } $obj = new MaClasse(); echo $obj->attr1; echo $obj->attr2; ?>

3. Le langage PHP

retournera donc: demo Dsol, attr2 nest pas un attribut connu Il en est de mme avec laffectation de valeur une variable et la mthode interne __set() ainsi que pour lappel de mthode et la fonction __call(). Dans ce dernier cas, la mthode reoit deux paramtres, le premier tant le nom de la mthode appele et le second tant un tableau index des paramtres de lappel.

autres fonctions
Il est prvu de pouvoir dfinir son propre traitement lorsquil est fait rfrence une classe qui nexiste pas. Pour cela, il suffit de redfinir la fonction __autoload() qui accepte pour unique paramtre le nom de la classe appele. Notez toutefois qu lissu de lappel cette fonction, linstanciation dun objet de la classe invoque devra tre possible sinon le script sarrtera avec

245

Chapitre 3

Le langage PHP

un message derreur. En fait, cette fonction pour objectif principal de vous permettre dinclure au vol le fichier contenant la dclaration de la classe.

Les tableaux en POO


PHP propose un objet appel ArrayObject charg de manipuler un tableau comme nimporte quel objet.

3. Le langage PHP

ArrayObject->__construct()
Instancie un objet ArrayObject. Syntaxe $tableau new ArrayObject([mixed $tableau]) Lobjet ArrayObject peut tre initialis aussi bien avec un autre objet ArrayObject quavec un tableau "classique".

Sil nest pas pr-rempli lors de lappel du constructeur, lobjet peut tre aliment par des appels successif la mthode append().

ArrayObject->append()
Ajoute un lment un objet ArrayObject. Syntaxe $valeur void append(mixed $valeur) Elment ajouter lobjet ArrayObject.

Cette mthode prsente toutefois linconvnient majeur de ne pas permettre de prciser la cl associe la valeur. Pour cela, nous privilgierons la mthode offsetSet().

ArrayObject->offsetSet()
Ajoute un lment un objet ArrayObject en prcisant la cl associe. Syntaxe $cle $valeur void offsetSet(mixed $cle, mixed $valeur) Cl associe llment ajouter lobjet ArrayObject. Elment ajouter lobjet ArrayObject.

A linverse, il est possible de rcuprer la valeur associe une cl par

246

Les classes, les objets

ArrayObject->offsetGet()
Retourne llment dun objet ArrayObject associ une cl donne. Syntaxe $cle retour mixed offsetGet(mixed $cle) Cl associe llment rcuprer. Elment associ la cl dans lobjet ArrayObject.

Pour supprimer un lment du tableau on fera appel

3. Le langage PHP

ArrayObject->offsetUnset()
Supprime llment dun objet ArrayObject associ une cl donne. Syntaxe $cle void offsetUnset(mixed $cle) Cl associe llment supprimer.

Il est galement possible den vrifier lexistence

ArrayObject->offsetExists()
Teste la prsence dun lment dun objet ArrayObject associ une cl donne. Syntaxe $cle retour boolean offsetExists(mixed $cle) Cl rechercher. TRUE, si un des lments du tableau est associ la cl, FALSE sinon.

Il est videmment, tout moment possible de vrifier la taille du tableau

ArrayObject->count()
Retourne le nombre dlment contenu dans un objet ArrayObject. Syntaxe retour int count() Nombre dlments dans le tableau.

247

Chapitre 3

Le langage PHP

Les itrateurs de tableau


Afin de parcourir le contenu dun tableau, PHP met disposition un objet ArrayIterator. Celui ci peut tre obtenu en appelant la mthode getIterator() dun ArrayObject.

ArrayObject->getIterator()
Retourne un itrateur sur un objet ArrayObject.

3. Le langage PHP

Syntaxe retour

ArrayIterator getIterator() Itrateur sur lArrayObject.

Lobjet ArrayIterator agit comme un pointeur sur un lment du tableau. Pointeur qui permet de progresser du premier lment au dernier.

ArrayIterator->valid()
Vrifie que litrateur pointe toujours sur un lment de lobjet ArrayObject. Syntaxe retour boolean valid() TRUE si litrateur pointe sur un lment du tableau, FALSE sinon.

ArrayIterator->current()
Retourne llment "courant" du tableau (celui sur lequel litrateur pointe). Syntaxe retour mixed current() Valeur de llement du tableau actuellement point.

ArrayIterator->key()
Retourne la cl de llment "courant" du tableau (celui sur lequel litrateur pointe). Syntaxe retour mixed key() Cl de llement du tableau actuellement point.

248

Les classes, les objets

ArrayIterator->next()
Dplace litrateur sur llment suivant du tableau. Syntaxe void next() Ainsi typiquement le parcours dun tableau seffectue comme ceci:
<?php $tableau["cle1"] = "element1"; $tableau["cle2"] = "element2"; $tableau["cle3"] = "element3"; $monArrayObject = new ArrayObject($tableau); echo "Ce tableau contient ".$monArrayObject->count()." echo "Jutilise un iterateur pour le parcourir:<br />"; $iterateur = $monArrayObject->getIterator(); while ($iterateur->valid()) { echo "cle = ". $iterateur->key() . " valeur = ". $iterateur->current() . "<br />"; $iterateur->next(); } ?> elements.<br />";

3. Le langage PHP

Ceci dit litrateur peut tre utilis pour naviguer librement au sein du tableau.

ArrayIterator->seek()
Dplace le pointeur de litrateur sur un lment quelconque du tableau. Syntaxe $position void seek(int $position) Position dans le tableau (0 = premier lment) o doit tre dplac le pointeur de litrateur.

ArrayIterator->rewind()
Dplace le pointeur de litrateur sur le premier lment du tableau. Equivalent de seek(0). Syntaxe void rewind()

249

Chapitre 3

Le langage PHP

Listing 3.40 : arrayObject.php


<?php $tableau[] = "element1"; $tableau[] = "element2"; $tableau[] = "element3"; $monArrayObject = new ArrayObject($tableau); $monAutreArrayObject = new ArrayObject($monArrayObject); echo "Ce tableau contient ".$monArrayObject->count()." elements.<br />"; echo "Jutilise un iterateur pour le parcourir:<br />"; $iterateur = $monAutreArrayObject->getIterator(); echo "Je saute directement au 2eme element:<br />"; $iterateur->seek(1); echo $iterateur->current()."<br />"; echo "Je reviens au premier:<br />"; $iterateur->rewind(); echo $iterateur->current()."<br />"; ?>

3. Le langage PHP 250

Chapitre 4

Les en-ttes HTTP


4.1 4.2 4.3 4.4 4.5 Principe gnral . . . . . . . . . . . . . . . . . Gestion personnalise de len-tte HTTP . . Cookies . . . . . . . . . . . . . . . . . . . . . . . Sessions . . . . . . . . . . . . . . . . . . . . . . Mise en cache avant mission des donnes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 258 261 271 287

Principe gnral

utilisation explicite ou implicite des en-ttes va vous permettre de rediriger un client vers un autre site, et dutiliser des cookies ou des variables de session afin de stocker (temporairement) des informations. Mais, avant daborder ces chapitres, il est important de bien comprendre le fonctionnement du dialogue client-serveur avec HTTP.

4.1.

Principe gnral
Historique Le protocole HTTP (HyperText Transfer Protocol), mis en uvre lors de lchange dinformations entre le client et le serveur, est une norme cre en 1990 par Tim Berners-Lee (qui est prsent prsident du Consortium du World Wide Web appel plus communment W3C). Ce protocole est bas sur un systme de communication par requtes/rponses. 4. Les en-ttes HTTP

Ainsi, le client se connecte sur le serveur, sur un port spcifique (gnralement le port 80), pour envoyer un message (que lon appelle requte). Ce dernier doit respecter un schma prcis rgi par une norme : ce doit tre une mthode (de type GET, POST, HEAD, PUT, DEL ou TRACE) suivie dune URI (adresse Internet). Au besoin, le client complte la requte laide dun message de type MIME (Multipurpose Internet Mail Extension). Il indique ainsi les informations particulires dont il a besoin, dcline son identit (signature du client) et indique la version du protocole utilis. Le serveur, quant lui, renvoie ensuite une rponse comprenant un en-tte HTTP comportant diverses informations sur le serveur et sur comment le client doit analyser le rsultat, suivi du corps du document.

Figure 4.1 : On peut schmatiser une requte HTTP comme ceci

Le client envoie donc un en-tte HTTP comprenant dans lordre :


j

Une ligne de requte : elle comprend le type de document demand ainsi que la mthode et la version du protocole quil lui est demand dutiliser. Cette ligne peut tre schmatise comme ceci : <METHODE> <URL> <VERSION>.

253

Chapitre 4

Les en-ttes HTTP

Tableau 4.1 : Les diffrentes mthodes pouvant tre utilises


Mthode POST GET HEAD Signification La mthode POST est utilise pour une soumission de donnes vers une URI cible. La mthode GET est utilise pour rcuprer un contenu identifi par lURI spcifie. La mthode HEAD est identique la mthode GET sauf quelle ne rclame que len-tte du document spcifi. Le document lui-mme nest ainsi pas renvoy. Permet le dpt dun fichier donn directement sur le serveur distant. Commande demandant au serveur distant de dtruire un document indiqu lURI spcifie. Version HTTP/1.0 HTTP/1.0 HTTP/1.0

PUT DELETE TRACE

HTTP/1.1 HTTP/1.1

4. Les en-ttes HTTP

La mthode TRACE permet au client de voir ce qui est reu HTTP/1.1 par le serveur. Son utilisation est utile dans les phases de test ou de diagnostic. Cette mthode est rserve pour une utilisation par un proxy pouvant dynamiquement tre bascul vers un tunnel (ex. : un tunnel SSL). HTTP/1.1

CONNECT

Les en-ttes de la requte (autant de lignes que ncessaire) : ces lignes facultatives (hormis linformation Host dans le cas du protocole HTTP/1.1) permettent de donner des informations complmentaires la requte, comme lorigine du client et lidentification (ou signature) de ce client (nom du navigateur, systme dexploitation, etc.). Ces informations (une par ligne) sont donnes comme un identifiant suivi immdiatement de deux points :, une espace et de sa valeur : <IDENTIFIANT>: <valeur>.

Tableau 4.2 : Exemple den-ttes pouvant tre utiliss


Identifiant (en-tte) Accept AcceptCharset Date From Host Referer UserAgent Signification Type de contenu que le navigateur est susceptible daccepter (ex. : text/html, audio/xaiff, image/jpeg, etc.). Le type de caractre que le navigateur attend en rponse (ex : ISO-8859-1). Date et heure du client (ex. : Sat, 27 Apr 2002 15:59:53 GMT) Spcifie une adresse e-mail pour le client. Nom de la machine cliente. Adresse de la page depuis laquelle la requte a t effectue. Chane didentification du client (ex. : Mozilla/5.001 [windows; U; NT4.0; enus] Gecko/25250101 pour un navigateur Mozilla sur un systme Windows NT4.0).

254

Principe gnral

Vous pouvez vous reporter lannexe "En-ttes et variables externes" pour une liste plus complte den-ttes.
j

Le corps de la requte : ces lignes sont utilises dans le cas dune mthode de type POST pour lenvoi de donnes (comme les paramtres dun formulaire).

Comme aucune explication ne vaut un bon exemple, ouvrez un client telnet en ligne de commande,
telnet www.linux.org 80

et tapez la commande suivante :


GET / HTTP/1.0

Pour valider votre requte, finissez en tapant deux fois sur la touche [Entre].

4. Les en-ttes HTTP

Le client telnet de Windows Notez que le client telnet de Windows ne permet pas de visualiser ce que vous rentrez depuis le clavier. Alors, ne vous trompez pas dans la commande, et respectez bien les majuscules et minuscules.
Figure 4.2 : Voici une page telle quelle est envoye par un serveur web

Vous voyez apparatre la rponse du serveur (ici, le code source de la page). Ce qui nous intresse dans le cas prsent, ce sont les premires lignes de ce document, savoir len-tte de la page. Si vous voulez ne voir que cet en-tte, rentrez la commande HEAD / HTTP/1.0. Ainsi seul lentte renvoy par le serveur saffichera dans le client telnet.
HTTP/1.1 200 OK Date: Sat, 27 Apr 2002 15:59:53 GMT Server: Apache/1.3.24 (Unix) (Red-Hat/Linux) mod_ssl/2.8.8 OpenSSL/0.9.6b mod_perl/1.26 Cache-Control: max-age=60 Expires: Sat, 27 Apr 2002 16:00:53 GMT

255

Chapitre 4

Les en-ttes HTTP

Pragma: no-cache Connection: close Content-Type: text/html <HTML> ...

Vous remarquez quil y a une ligne vide entre len-tte et le corps du document. Cest ce saut de ligne qui signale la fin de len-tte HTTP et indique que ce qui suit est le corps du document. Ainsi, une fois envoy, len-tte ne peut plus tre modifi. Vous verrez dans ce chapitre que le langage PHP permet des modifications de len-tte, mais cause une erreur si vous essayez de le modifier aprs lenvoi du dbut du document. Vous pouvez excuter prsent, toujours laide de votre client telnet, la commande suivante :
telnet www.linux.org 80 GET / HTTP/1.1 host:www.linux.org

4. Les en-ttes HTTP

Comme indiqu prcdemment, le protocole HTTP/1.1 rclame une information supplmentaire host. En effet, cette dernire mouture de HTTP a permis ladoption des htes virtuels, cest--dire que plusieurs noms de domaines peuvent se partager une mme adresse IP. Dautres avantages du protocole 1.1 sur le 1.0 sont rpertoris dans la RFC2616.

Les RFC Pour toutes les informations complmentaires sur les protocoles HTTP/1.0 et HTTP/ 1.1, consultez les RFC (Request For Comment). Ces documents ont la particularit de reprsenter une notice pour une documentation gnrale, un standard ou la description dun protocole. Il est noter que lcriture mme dune RFC est dfinie dans une autre RFC (la RFC1543). Pour HTTP/1.0, la RFC1945 est disponible ladresse http://abcdrfc.free.fr/rfc-vf/ rfc1945.html (traduction franaise). Pour HTTP/1.1, la RFC2616 est disponible (en anglais) ladresse http://www.w3.org/Protocols/rfc2616/rfc2616.html. Ces documentations trs compltes vous apprendront tout ce quil faut savoir pour effectuer un change de donnes entre un navigateur Internet et un serveur web.
Voyons prsent ce que signifie cette rponse (i.e. comment le navigateur interprte ce message).
j

La premire ligne indique le code de retour. Ici le code 200 signifie que tout sest bien pass. Tous les internautes connaissent au moins un autre code : le tristement clbre 404, qui comme vous le savez, signifie que le serveur na pas trouv la page demande.

256

Principe gnral

Tableau 4.3 : Les diffrentes catgories de code que peut renvoyer un serveur web et leurs significations
Intervalle de code 100 199 200 299 300 399 400 499 500 599 Signification Les informations sont retournes. La requte a t traite avec succs. Demande de redirection. La requte est incomplte. Indique une erreur du serveur HTTP.

Vous pouvez vous reporter lannexe sur les "Codes derreur HTTP" pour une liste plus dtaille. 4. Les en-ttes HTTP
Puis vient une srie de valeurs prcdes par un nom de paramtre. Avant de poursuivre, voici quelques paramtres den-tte possibles. Cette liste est non exhaustive, mais comprend les paramtres les plus courants quun serveur peut renvoyer.

Tableau 4.4 : Quelques-uns des messages que peut renvoyer un serveur dans son en-tte
Identifiant den-tte ContentEncoding ContentLanguage ContentLength Description Cest le type de codage du document renvoy (ex. : compress, xgzip, xzip, etc.). Cest le langage utilis dans le corps de la rponse ("fr" pour franais, "en" pour anglais, "it" pour italien, etc.). Cest la longueur de la rponse. Cette valeur est donne en octets. Cette donne permet au client dtre certain quil a bien reu la totalit du document. Cest le type MIME du document (ex. : text/html, image/gif, application/postscript, text/plain, audio/basic, video/mpeg, etc.). Date du serveur au dbut du transfert des donnes. Date limite de validit du document (particulirement utile dans le cas de lutilisation dun cache). Demande la redirection vers une nouvelle URL. Nom ou signature du serveur qui renvoie les informations.

ContentType

Date Expires Location Server

Vous pouvez vous reporter lannexe "En-ttes et variables externes" pour un liste plus complte den-ttes.

257

Chapitre 4

Les en-ttes HTTP

Nous pouvons maintenant revenir notre exemple et analyser sa rponse. Cet en-tte nous apprend donc plusieurs choses :
j j

La deuxime ligne de notre exemple indique simplement la date et lheure du serveur web. La ligne suivante est la signature du serveur web. Dans notre exemple, le serveur hbergeant le site de Linux.org nous signale quil tourne sous le systme dexploitation Linux (est-ce tonnant ?) avec le serveur Apache et que celui-ci est compil avec les modules SSL et Perl. La ligne Cachecontrol nest valide que pour la version 1.1 du protocole HTTP. Cette ligne indique comment un client, et en particulier un proxy cache, doit traiter cette page (si le proxy doit mettre en cache la page, la relire chaque fois, et combien de temps le cache de la page est valide. Ici, la page peut tre archive pendant 60 secondes au plus.) Pour les navigateurs utilisant le protocole HTTP/1.0, le serveur renvoie deux lignes la suite qui permettent de dfinir la gestion du cache et la dure de celle-ci. Enfin, la ligne ContentType indique votre client web le type MIME de ce qui lui est envoy. Cela peut tre du texte, de lHTML, une image, un fichier son, etc.

j j

4. Les en-ttes HTTP

Vous pouvez consulter lannexe sur "Les types MIME" pour une liste plus complte des types.

4.2.

Gestion personnalise de len-tte HTTP

Dune manire gnrale, avec PHP, il est possible de prciser la valeur des paramtres spcifis dans len-tte, grce la fonction header().

header()
Spcifie un lment de len-tte de la rponse HTTP. Syntaxe $ligneEntete $remplace $reponseHTTP void header(string $ligneEntete [, boolean $remplace [, int $reponseHTTP]]) Information ajouter len-tte. TRUE si cette ligne doit remplacer la valeur donne prcdemment au mme paramtre den-tte, FALSE (par dfaut) si elle doit tre ajoute. Permet de forcer la reponse HTTP (par exemple 404 pour simuler une page manquante). Cette option est apparue avec la version 4.3.0 de PHP.

Headers already sent... Comme cela a dj t voqu, ds que des informations (corps du document) sont envoyes au navigateur, len-tte est envoy au pralable. Par consquent, il nest plus question, ce moment-l, de demander des modifications de cet en-tte. 258

Gestion personnalise de len-tte HTTP

Concrtement, vous ne devez absolument pas "afficher" le moindre message avant un appel header(). Donc : pas de echo(), print(), etc., pas de message derreur et aucun code HTML ou texte quelconque, en dehors des balises <?php ... ?>. Faites galement attention ne pas laisser traner despaces ou de lignes blanches avant ou aprs les balises <?php ... ?> des fichiers inclus avant lappel header().
Si besoin, vous disposez dune fonction permettant de dterminer si len-tte a dj t envoy au client.

headers_sent()
Teste si len-tte HTTP a dj t envoy au client.

4. Les en-ttes HTTP

Syntaxe $fichier

boolean headers_sent([string &$fichier [, int &$ligne]]) Si cette option est passee et quil a dj t crit sur la sortie, alors $fichier contiendra le nom du fichier dans lequel lcriture a commence (option disponible depuis PHP 4.3.0). Si cette option est passee et quil a dj t crit sur la sortie, alors $ligne contiendra le numero de la ligne dans lequel lcriture a commence (option disponible depuis PHP 4.3.0). TRUE si len-tte a dj t mis, FALSE sinon.

$ligne

retour

Voici un court exemple de cette fonction :


<?php // rien ne va sur la sortie for ($i=0; $i<10; $i++) { // ici encore, rien nest "ecrit" } $fichier="none"; $ligne=0; echo "Par contre la lentete est envoye a cause de echo()\n"; if (headers_sent(&$fichier, &$ligne)==true) echo "Lentete a ete envoye par $fichier a la ligne $ligne\n"; else echo "Lentete na pas ete envoye\n"; ?>

Dont le rsultat serait le suivant :


Par contre la lentete est envoye a cause de echo() Lentete a ete envoye par c:\program files\apache group\apache\htdocs\tests\headers_sent.php a la ligne 9

Les exemples dapplications sont nombreux ; nous en dtaillerons trois dans ce chapitre.

259

Chapitre 4

Les en-ttes HTTP

Redirection
Il nest pas rare davoir rediriger le visiteur vers telle ou telle page en fonction de certains paramtres. Par exemple, si le visiteur est un homme, il peut tre intressant de lenvoyer vers le rayon homme dun magasin de vtements. Lutilisation des en-ttes permet, entre autres, ce type de manipulation. Pour cela, il suffit dutiliser len-tte Location avec, pour paramtre, ladresse vers laquelle rediriger le navigateur. Voici la syntaxe de la rorientation vers http://www.php.net:
header("Location: http://www.php.net");

La version 1.1 du protocole HTTP ncessite, comme paramtre, un chemin absolu. Si vous souhaitez faire une redirection au sein mme de votre serveur vers un chemin relatif la position du script appel et tre conforme cette norme, voici un moyen de transformer une adresse relative en chemin absolu laide du langage PHP.

4. Les en-ttes HTTP

header("Location: http://".$_SERVER[SERVER_NAME] ."/".dirname($_SERVER[PHP_SELF]) ."/".$chemin_relatif);

PHP se charge non seulement denvoyer len-tte au navigateur, mais il lui retourne galement le code 302 correspondant REDIRECT. Il est galement possible de retourner directement un code au navigateur. Si vous voulez renvoyer le code 404 correspondant au code derreur dun fichier inexistant, il suffit dcrire :
header("HTTP/1.0 404 Not Found");

Voici un exemple de script redirigeant le navigateur du client en fonction du sexe de la personne ; on imagine que la variable $sexe a t indique prcdemment.
<?php if ($sexe == "homme") { header("Location: rayon_homme.html"); } else { header("Location: rayon_femme.html"); } ?>

Dclaration du type MIME


PHP est principalement utilis pour gnrer du code HTML mais, comme nous le verrons par la suite, il permet galement de gnrer toutes sortes de documents et notamment des images. Or, par dfaut, la configuration de PHP veut que le serveur dclare que le document mis est un document de type text/html. Dans tous les cas o le document mis nest pas une page HTML, il convient donc den prciser le type, comme dans lexemple suivant (sil sagit dune image gif) :
header("Content-type: image/gif");

260

Cookies

Vous pouvez vous reporter lannexe sur "Les types MIME" pour avoir une liste plus complte des valeurs possibles.

Gestion des caches (des navigateurs)


Gnralement, les navigateurs (et ventuellement les systmes intermdiaires comme les proxys) utilisent des caches pour stocker localement des documents (HTML, images, etc..) rcuprs afin de ne pas avoir les redemander aux serveurs lorsque ceux-ci sont rappels (ex. : un logo que lon trouve sur toutes les pages). Si cela acclre grandement laffichage des pages dun site, il arrive quen certaines circonstances cela devienne un problme. Le cas de figure le plus flagrant est certainement celui o le document est conserv une semaine dans le cache du navigateur, alors que vous mettez jour la page quotidiennement. En fait, les navigateurs sont gnralement configurs pour vrifier une fois par jour si le document demand diffre de celui du cache. De ce fait, quelle que soit votre faon de procder en tant que concepteur de sites web, vous tes relativement labri dune plainte de ce ct-l. Le problme est plus "grave" si certains de vos scripts retournent un rsultat diffrent en fonction de variables de sessions ou de donnes externes (base de donnes) qui varient dun instant lautre, car lappel au script, lui, ne varie pas (pas de paramtre GET diffrent dun appel lautre et pas de paramtre POST). Le nom et les paramtres du script ne variant pas, le navigateur ira systmatiquement prendre la version disponible dans le cache au lieu daller chercher sa nouvelle variante. Dans ce cas, il est donc prfrable de demander au navigateur (et autres proxys) de ne pas garder de version du document dans son cache, grce aux appels suivants :
header("Cache-Control: no-cache"); header("Pragma: no-cache");

4. Les en-ttes HTTP

4.3.

Cookies

Les cookies ont t introduits par la socit Netscape dans le but de stocker des informations sur la machine cliente, ce qui permet de personnaliser un site en fonction de lidentit et des prfrences du visiteur. Ces cookies contiennent les informations que le client a bien voulu communiquer (en ayant, par exemple, rpondu un questionnaire sur ses gots). Votre site peut alors trs bien se servir de ces informations pour faciliter le parcours du visiteur. Un site de vtements peut, par exemple, demander le sexe du client et le style de vtements quil recherche pour ensuite le rediriger directement (et ce chaque nouvelle connexion) vers le rayon sport homme si cela correspond au profil enregistr dans le cookie.

Plus dinformations sur les cookies Les cookies sont dfinis dans la RFC 2109 disponible en anglais ladresse suivante : http://www.faqs.org/rfcs/rfc2109.html ou encore http://www.netscape.com/newsref/std/cookie_spec.html.

261

Chapitre 4

Les en-ttes HTTP

Gnralits
Utilisation
Les cookies doivent tre utiliss pour des informations de faible importance (pour compter, par exemple, le nombre de visites dun client). Un bon site doit pouvoir se passer des cookies pour fonctionner : on peut les utiliser, mais cela ne doit pas mettre en pril le fonctionnement du site si lutilisateur les refuse. En effet, il faut avoir lesprit que les informations sont stockes ct client, do labsence de garantie de prennit des informations.
j

Chaque navigateur a son propre systme de gestion des cookies : deux navigateurs sur la mme machine impliquent deux systmes de gestion des cookies (information en double et problmes de mise jour...). Du fait que lutilisateur peut lui-mme changer la valeur des cookies, le programmeur na aucune garantie de "last value" (cest--dire que lon ne peut pas tre certain de rcuprer la valeur qui a t stocke prcdemment). Enfin, la fonction de gestion des cookies peut tre active ou dsactive au niveau du navigateur ou simplement refuse par le visiteur.

4. Les en-ttes HTTP

Fonctionnement
Les instructions permettant la gestion des cookies sont places dans les en-ttes HTTP. Lors de lcriture dun cookie, le serveur envoie la requte HTTP et le navigateur se charge dcrire ou de modifier le cookie.

Stockage
Les cookies sont stocks de faon diffrente sur les divers navigateurs. Pour nvoquer que des deux principaux navigateurs, Internet Explorer utilise un fichier recensant tous les cookies et un fichier par cookie, tandis que Netscape utilise un seul fichier pour tous les cookies.

Cration
Pour que le serveur demande la cration dun cookie sur le poste client, len-tte de la rponse HTTP doit contenir une ligne avec la syntaxe suivante :
Set-Cookie : <NOM_COOKIE>=<valeur>; domain=<nom_de_domaine>; expires=<DATE>

Il existe dautres attributs disponibles pour dfinir un cookie ; ils sont prsents dans le tableau suivant :

262

Cookies

Tableau 4.5 : Attributs dfinissant un cookie


Attribut NOM_COOKIE Valeur VALEUR_COOKIE Type Description moins de passer par NOM_COOKIE est le seul lencodage URL, le nom et attribut obligatoire. la valeur dun cookie ne peuvent pas contenir les caractres point-virgule ;, virgule ,, et espace . Date au format : Jour_en_anglais, JJMoiAA HH:MM:SS GMT Par exemple : Saturday, 03Aug02 09:14:23 GMT est une date valide. Expires permet de dfinir une date de validit. Une fois cette date passe, la valeur du cookie ne doit plus tre prise en compte et le cookie peut tre effac par le navigateur.

Expires

DATE

4. Les en-ttes HTTP

Domain

Nom de domaine Adresse Internet contenant deux fois le caractre point (.). Xxx.xxxxxxx.xxx Par exemple : www.toutestfacile.com est une adresse valide ; php.toutestfacile.com galement. Chemin /chemin/ Par exemple : /php/ est valide.

Si le nom de domaine est laiss vide (cest gnralement le cas), le nom du serveur appelant est assign par dfaut. Il nest possible de spcifier que son propre nom de domaine ou de sous-domaine. Cet attribut permet de dfinir un sous-rpertoire o le cookie est valide, afin de rduire son champ daction. En effet, en spcifiant lattribut path, le cookie ne sera accessible que dans le sous-rpertoire dfini. Cet attribut permet de spcifier que le cookie ne pourra tre envoy que si la connexion est scurise par SSL ou S-http.

Path

Secure

Aucun

Les limites des cookies


j j j

Un cookie ne pourra excder 4 Ko. Un client ne pourra grer plus de 300 cookies. Un serveur ne pourra crer plus de 20 cookies sur un client.

263

Chapitre 4

Les en-ttes HTTP

Accs
Quand un client se connecte sur un site pour lequel il possde dj des cookies, ceux-ci sont directement envoys dans len-tte de la requte HTTP. Ce dernier contient alors une ligne ayant laspect suivant :
Cookie : <NOM1>=<valeur1> ; <NOM2>=<valeur2> ; ...

Le moyen de rcuprer cette information dpendra alors du script utilis (CGI, ASP, PHP, etc.).

Disponibilit Un cookie ntant disponible que lorsque le client le communique au serveur, un cookie dfini dans un script ne sera disponible que des scripts chargs par la suite (et non pas dans la page courante). 4. Les en-ttes HTTP

En PHP
Pour envoyer un cookie, il suffit dutiliser la fonction setCookie().

setCookie()
Dfinit un cookie qui sera ajout aux autres lments de len-tte HTTP. Syntaxe boolean setCookie(string $nomCookie [, string $valeurCookie [, int $dateExpiration [, string $chemin [, string $domaine [, boolean $securite]]]]]) Nom du cookie. Valeur du cookie. Date dexpiration du cookie (vous pouvez indiquer NULL si vous ne souhaitez pas spcifier ce paramtre). Il doit sagir dun timestamp UNIX tel que peuvent retourner les fonctions time() ou mktime(). Rpertoire de validit du cookie dans le site (vous pouvez indiquer NULL si vous ne souhaitez pas spcifier ce paramtre). Domaine de validit du cookie (vous pouvez indiquer NULL si vous ne souhaitez pas spcifier ce paramtre). TRUE si vous souhaitez que ce cookie ne soit communiqu que lors de lutilisation de connexions scurises (SSL ou SHTTP), FALSE (valeur par dfaut) sinon. TRUE en cas de succs, FALSE sinon.

$nomCookie $valeurCookie $dateExpiration

$chemin $domaine $securite

retour

Seul lattribut $nomCookie est obligatoire. Si cest le seul attribut dfini, alors le cookie correspondant sera dtruit sur la machine cliente.

264

Cookies

setCookie(), header(), mme combat Utiliser setCookie() revient spcifier des donnes de len-tte. La remarque que lon a vue pour la fonction header() sapplique donc l aussi : aucun lment du document ne doit avoir t mis avant lappel setCookie().

Erreur frquente Les cookies doivent tre effacs avec les mmes paramtres que lors de leur cration.

Ordre dappel En PHP 4 les appels setCookie() se font dans lordre naturel, de haut en bas, alors quen PHP 3 les appels se faisaient dans lordre inverse. Ainsi, pour effacer un cookie avant de dclarer une nouvelle valeur, il faut mettre linsertion avant leffacement en PHP 3 et faire le contraire en PHP 4.
Voici quelques exemples de cration de cookies :
// exemple simple sans date de validit setcookie("test", "ceci est un test"); // exemple dun cookie valide pour une heure setcookie("test", "ceci est un test", time()+3600); // exemple dun cookie valide uniquement // dans les pages scurises de http://www.toutestfacile.com/php setcookie("test", "ceci est un test", NULL, "/php/", ".toutestfacile.com", TRUE);

4. Les en-ttes HTTP

Une fois le cookie dfini, son contenu est disponible lors de lappel des scripts suivants, $_COOKIE["nomDuCookie"] (ou dans $HTTP_COOKIE_VARS directement dans ["nomDuCookie"] pour les versions de PHP<4.1.0).

Du pass faisons table rase Dans les versions de PHP antrieures 4.2.0, la configuration par dfaut fixait le paramtre register_globals du fichier php.ini on (activ). Pour des raisons de scurit (voques dans le chapitre traitant des variables externes) cela nest plus le cas. Avec loption register_globals active, le contenu du cookie tait directement disponible dans une variable portant le nom du cookie ($nomDuCookie).

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur le fichier php.ini.

265

Chapitre 4

Les en-ttes HTTP

Un tour de magie connatre Par dfaut, le fichier de configuration php.ini active loption magic_quote_gpc, et ceci pour les paramtres GET, POST et les cookies. Ceci a pour effet dautomatiquement "chapper" les apostrophes. Autrement dit, cela ajoute un anti-slash devant les apostrophes des paramtres passs par les mthodes GET, POST et les cookies. Si cest trs pratique pour stocker le paramtre en base de donnes, cela peut devenir gnant pour un affichage dans le document. Si vous souhaitez supprimer ces anti-slashes, il vous suffit dappliquer la fonction stripSlashes() sur ces valeurs.
Il est possible de stocker directement plusieurs valeurs dun tableau. Un cookie sera cr par entre dans le tableau. Au moment de rcuprer ces valeurs, il suffira dy accder comme pour nimporte quel autre tableau. Par exemple, pour stocker ce tableau contenant trois valeurs :
setcookie ("tableau[un]", "valeur1"); setcookie ("tableau[deux]", "valeur2"); setcookie ("tableau[trois]", "valeur3");

4. Les en-ttes HTTP

Pour afficher ces valeurs, il suffit dcrire :


while (list ($cle, $valeur) = each ($_COOKIE["tableau"])) { echo "$cle: $valeur<br>\n"; }

Exemple utilisant des cookies


Mise en situation
Lexemple est celui dun magasin dinstruments de musique voulant offrir la possibilit ses clients de mettre des articles dans un panier virtuel (les utilisateurs refusant les cookies ne pourront pas utiliser ce panier). Les fonctionnalits de ce panier virtuel seront simples. Il faudra tre en mesure dajouter des articles un un, de vider le panier et de calculer le montant total des articles contenus dans le panier. Pour simplifier, on considrera que ce vendeur ne propose que trois articles : une guitare, une basse et une batterie (ce qui est suffisant pour monter un groupe). Les informations lies au panier seront stockes dans des cookies sous la forme dun tableau.

Agencement des chiers


Pour cet exemple, nous utiliserons quatre fichiers :
j j j

Une page daccueil accueil.html. Une page dinitialisation initialisation.php qui sera en charge dinitialiser les cookies permettant la gestion du panier. Une page pour ajouter un article ajout_article.php, cette page sera la page principale pour linterface, et cest l que lutilisateur ajoutera des articles, videra son panier ou calculera le montant de celui-ci.

266

Cookies

Une page pour calculer le montant total du panier calcul_total.php. Ce fichier calculera la somme des montants des articles prsents virtuellement dans le panier. Lutilisateur aura alors le choix dajouter dautres articles ou de vider son panier.

Voici un graphe reprsentant les interactions entre les diffrents scripts.


Figure 4.3 : Les diffrents appels

4. Les en-ttes HTTP

j j j j j j

accueil.htm propose un lien vers initialisation.php. initialisation.php redirige vers ajout_article.php aprs avoir initialis les donnes. ajout_article.php propose un lien vers initialisation.php pour rinitialiser les donnes. chaque ajout darticle, ajout_article sappelle lui-mme pour se mettre jour. ajout_article propose un lien vers calcul_total.php. Et calcul_total.php propose des liens vers initialisation.php (pour repartir de zro) et ajout_article.php (pour complter le panier).

Contenu des chiers accueil.html


Listing 4.1 : accueil.html
<html> <head> <title>Mon magasin de musique</title> </head> <body bgcolor="#FFFFFF"> <p align="center"><b>Bienvenu chez MusicAGogo!!!</b></p> <p align="center">Votre panier est vide</p> <p align="center"> <a href="initialisation.php">cliquer ici pour le remplir </a> </p> </body> </html>

267

Chapitre 4

Les en-ttes HTTP

Le script daccueil est une simple page au format HTML, avec un lien vers le script dinitialisation des cookies.

initialisation.php
Listing 4.2 : initialisation.php
<?php setCookie("panier[guitare]", 0); setCookie("panier[basse]", 0); setCookie("panier[batterie]", 0); header("Location: ajout_article.php"); ?>

4. Les en-ttes HTTP

Le script dinitialisation met zro le tableau qui reprsentera notre panier. Une fois les trois valeurs du tableau initialises, le navigateur du client est redirig vers la page de linterface principale. Comme nous lavons dit prcdemment, la gestion des cookies est appele avant toute autre fonction den-tte.

ajout_article.php
Listing 4.3 : ajout_article.php
<?php $panier=$_COOKIE["panier"]; switch (@$_GET["ajout"]) { case "guitare": $panier["guitare"]++; setCookie("panier[guitare]", $panier["guitare"]); break; case "basse": $panier["basse"]++; setCookie("panier[basse]", $panier["basse"]); break; case "batterie": $panier["batterie"]++; setCookie("panier[batterie]", $panier["batterie"]); break; } ?> <html> <head> <title>Mon magasin de musique</title> </head> <body bgcolor="#FFFFFF"> <table border="4" cellspacing="4" cellpadding="4" align="center"> <tr align="center">

268

Cookies

<td>Ajouter</td> <td>Votre commande</td> </tr> <tr align="center"> <td> <a href="ajout_article.php?ajout=guitare">Une guitare</a> (199E) </td> <td><?php echo $panier["guitare"]?> guitare(s)</td> </tr> <tr align="center"> <td> <a href="ajout_article.php?ajout=basse">Une basse</a> (199E) </td> <td><?php echo $panier["basse"]?> basse(s)</td> </tr> <tr align="center"> <td> <a href="ajout_article.php?ajout=batterie">Une batterie</a> (2499E) </td> <td><?php echo $panier["batterie"]?> batterie(s)</td> </tr> </table> <p align="center"> <a href="initialisation.php">vider mon panier</a> </p> <p align="center"> <a href="calcul_total.php">calculer le total</a> </p> </body> </html> Figure 4.4 :

4. Les en-ttes HTTP

Interface principale

Aprs avoir rcupr la valeur du tableau contenue dans les cookies, une comparaison est effectue entre la valeur de la variable $ajout et les diffrentes chanes de caractres possibles. Ensuite, la valeur est incrmente puis stocke nouveau dans le cookie correspondant.

269

Chapitre 4

Les en-ttes HTTP

Cette page fait des appels elle-mme, ce qui permet dajouter constamment des articles. Un lien vers initialisation.php est disponible, qui a pour effet de remettre zro le contenu du panier. Un autre lien vers le calcul du montant du panier est disponible. Comme cela a dj t signal, la nouvelle valeur dun cookie nest disponible quaprs avoir recharg la page ou chang de page. Pour afficher dans ce script le nombre exact darticles contenus dans le panier, on ne peut faire appel la valeur courante du cookie (par $_COOKIE) ; cest donc le contenu de la variable du tableau $panier qui a t utilis (aprs avoir t incrment puis stock).

calcul_total.php
Listing 4.4 : calcul_total.php
<?php $panier = $_COOKIE["panier"]; $total = 0; $total += $panier["guitare"]*199; $total += $panier["basse"]*199; $total += $panier["batterie"]*2499; ?> <html> <head> <title>Mon magasin de musique</title> </head> <body bgcolor="#FFFFFF"> <p align="center">Le total de votre panier: <?php echo $total?> Euros.</p> <p align="center"> <a href="ajout_article.php">Modifier mon panier</a> </p> <p align="center"> <a href="initialisation.php">Vider mon panier</a> </p> </body> </html>

4. Les en-ttes HTTP

Ce script trs simple reprend les valeurs stockes dans le panier pour calculer le montant total de celui-ci. Deux liens sont disponibles : lun vers linitialisation (remise zro) des variables, lautre vers linterface principale.

270

Sessions

Figure 4.5 : Montant total

4.4.

Sessions

4. Les en-ttes HTTP

Les sessions proposes dans PHP depuis la version 4 permettent, comme les cookies, de stocker des informations spcifiques lutilisateur. Mais, alors que les cookies permettent de stocker des informations (en petite quantit) sur le poste du client pour une priode pouvant aller de quelques secondes plusieurs semaines, les sessions permettent de stocker autant dinformations que ncessaire. Pour cela, le serveur assigne au client un identifiant unique (appel identifiant de session) li une instance de navigateur sur une machine (adresse IP) donne. Du fait que le client peut tout moment arrter et relancer son navigateur ou changer dIP (aprs stre dconnect du rseau Internet), la dure de vie de la session nexcde quasiment jamais une journe. Les sessions ne sont donc utilises que pour conserver en mmoire des informations tout au long de la visite du client (mais pas plus longtemps). Par consquent, il est mme conseill de mettre un terme la session aprs une priode donne dinactivit (de lordre de 20 mn, temps au-del duquel on peut considrer que le visiteur a dfinitivement quitt le site) afin de librer les ressources. Vous avez certainement rencontr ce genre de situation o lon vous demande de vous identifier nouveau. En contrepartie, avec les sessions, vous pouvez tre sr que votre site fonctionnera quels que soient le navigateur et lattitude du visiteur (rappelons quun visiteur peut refuser un cookie). Lautre diffrence principale rside dans le fait que les sessions sont stockes sur le serveur ; le contrle des sessions est donc gr 100 % par lauteur des scripts (il ne peut y avoir de modification ou de suppression par le visiteur). Comme cela a dj t dit, chaque utilisateur est attribu un identifiant de session. Afin de garder la trace de ce dernier, lidentifiant est transmis de page en page. Cela peut se faire de deux faons :
j j

Par le navigateur qui, chaque appel au serveur, communiquera le cookie contenant lidentifiant de session que le serveur lui aura pralablement demand de crer. Par le serveur qui, pour chaque page gnre, compltera les URL relatives des liens (donc celles qui pointent vers le serveur lui-mme, mais pas les liens vers un site tiers) avec un paramtre indiquant lidentifiant de session (cest ce que lon appelle l"URL rewriting" ou la rcriture dURL).

271

Chapitre 4

Les en-ttes HTTP

La premire solution est la plus simple pour le serveur, mais elle ne peut tre utilise si le client refuse les cookies ; il faut alors se rabattre sur la seconde. Comme nous le verrons un peu plus loin, ceci peut se faire tant manuellement quautomatiquement. Pour chaque page ncessitant lutilisation de variables de sessions, il faudra appeler la fonction session_start() afin de permettre au serveur de dterminer si un identifiant de session a dj t assign au visiteur. Si cest le cas, il lui suffit de le rcuprer soit dans le cookie soit depuis lURL, tout comme les valeurs des diffrentes variables ; sinon, il doit le crer, et le serveur doit demander la gnration dun cookie. Si celle-ci choue, il optera alors pour la rcriture dURL.

session_start()
Rclame lutilisation de variables de sessions au cours du script.

4. Les en-ttes HTTP

Syntaxe retour

boolean session_start() TRUE

session_start() et cookie() : ami-ami Il va de soi que si lidentifiant de session doit tre stock dans un cookie, alors les contraintes dutilisation de session_start() sont les mmes que celles de cookie(). Ainsi, session_start() ne peut plus tre appel une fois le dbut du document mis (i.e. une fois len-tte HTP envoy).
Il sera possible de se passer de lappel session_start() si PHP est configur de telle sorte que le paramtre session.auto_start de php.ini soit activ (i.e. mis 1).

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur le fichier php.ini.

la manire des cookies, les variables de sessions sont disponibles directement dans le tableau $_SESSION. Pour accder une valeur donne, il suffit donc dappeler quelque chose comme $_SESSION["maVariable"] (ou $HTTP_SESSION_VARS["maVariable"] pour les versions de PHP infrieures 4.1).

Du pass faisons table rase Dans les versions de PHP antrieures 4.2.0, la configuration par dfaut fixait le paramtre register_globals du fichier php.ini on (activ). Pour des raisons de scurit (voques dans le chapitre traitant des variables externes) cela nest plus le cas.

272

Sessions

Avec loption register_globals active, le contenu de la variable de session tait directement disponible dans une variable portant le nom de la variable de session ($nomVariableSession).

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur le fichier php.ini.
Voici un exemple dutilisation. Il sagit tout simplement dun compteur qui est incrment chaque appel de la page (si la variable de session nexiste pas, cest quil sagit dune nouvelle session et le compteur est initialis la valeur 0).
<?php session_start(); if (!isset($_SESSION[maVariable])) { $_SESSION[maVariable] = 0; } else { $_SESSION[maVariable]++; } echo $_SESSION[maVariable]; ?>

4. Les en-ttes HTTP

Pour grer les sessions de faon optimale, il est possible de configurer PHP laide des nombreuses options offertes par le fichier de configuration.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur le fichier php.ini.
Ces options peuvent tre visualises par un simple appel phpinfo().
Figure 4.6 : phpinfo()

273

Chapitre 4

Les en-ttes HTTP

Jusqu la version 4.1.1 (comprise), lutilisation de la rcriture (automatique) dURL ne pouvait se faire que si PHP avait t compil avec loption enabletranssid. Il fallait en outre lactiver ou la dsactiver avec loption session.usetranssid, introduite dans la version 4.0.3 ( positionner 1 pour lactiver, 0 sinon). Depuis la version 4.2.0, lutilisation de la rcriture (automatique) dURL ne ncessite plus lutilisation de directives de compilation. Lactivation de ce procd ne dpend plus que de loption session.usetranssid (qui est, par dfaut, active). La liste des balises HTML contrles est dfinie dans le paramtre url_rewriter.tags et, outre le fait que iframe napparaisse pas dans la liste, il faut garder lesprit que tous les liens crs par des fonctions Javascript (par exemple) ne profiteront pas de cette manipulation. Il faudra donc ncessairement ajouter manuellement lidentifiant de session lURL (si lon souhaite que cela fonctionne avec les navigateurs refusant les cookies) pour ces liens.

Exemple utilisant des sessions


4. Les en-ttes HTTP

Mise en situation
Reprenons le mme exemple que pour les cookies, cest--dire celui dun magasin de musique vendant trois instruments et proposant un panier virtuel aux visiteurs de son site Internet.

Contenu des chiers accueil.html


Listing 4.5 : accueil.html
<html> <head> <title>Mon magasin de musique</title> </head> <body bgcolor="#FFFFFF"> <p align="center"><b>Bienvenu chez MusicAGogo!!!</b></p> <p align="center">Votre panier est vide</p> <p align="center"> <a href="initialisation.php">cliquer ici pour le remplir </a> </p> </body> </html>

Le script daccueil est une simple page au format HTML, avec un lien vers le script dinitialisation des sessions.

274

Sessions

initialisation.php
Listing 4.6 : initialisation.php
<?php session_start(); $_SESSION[panier] = array("guitare"=>0, "basse"=>0, "batterie"=>0); header("Location: ajout_article.php"); ?>

Une fois la session existante rappele ou cre, le tableau panier est initialis et stock dans la session ; le navigateur du client est ensuite redirig vers la page dajout dlments au panier. Ce script fonctionnera tel quel condition que lutilisateur accepte les cookies. Si ce nest pas le cas, il fonctionnera galement si la rcriture (automatique) dURL est active (sachant que ce script ne contient que des URL relatives). Vous constaterez alors que les URL (qui saffichent dans la barre du navigateur) ont t compltes pour ajouter un identifiant de session. Dans les autres cas, si vous souhaitez que votre script fonctionne mme si le visiteur refuse les cookies, il faut ajouter lURL la chane de caractres stocke dans la constante SID (pour raliser manuellement ce que loption session.use_trans_sid = 1 permet). Ce qui donne :
header("Location: ajout_article.php?".SID);

4. Les en-ttes HTTP

La constante SID est compose de la concatnation du nom de lidentifiant de session (disponible via la fonction session_name() et qui par dfaut vaut "PHPSESSID"), dun signe gal et de la valeur de lidentifiant de session (disponible via la fonction session_id()). Ainsi, SID vaut session_name()."=".session_id().

ajout_article.php
Listing 4.7 : ajout_article.php
<?php session_start(); $panier=$_SESSION[panier]; switch (@$_GET["ajout"]) { case "guitare": $panier["guitare"]++; break; case "basse": $panier["basse"]++; break; case "batterie": $panier["batterie"]++; break; } $_SESSION[panier] =

275

Chapitre 4

Les en-ttes HTTP

?>

array("guitare" => $panier["guitare"], "basse" => $panier["basse"], "batterie"=> $panier["batterie"]);

<html> <head> <title>Mon magasin de musique</title> </head> <body bgcolor="#FFFFFF"> <table border="4" cellspacing="4" cellpadding="4" align="center"> <tr align="center"> <td>Ajouter</td> <td>Votre commande</td> </tr> <tr align="center"> <td><a href="ajout_article.php?ajout=guitare"> Une guitare</a> (199E) </td> <td><?php echo $panier["guitare"]?> guitare(s)</td> </tr> <tr align="center"> <td><a href="ajout_article.php?ajout=basse"> Une basse</a> (199E) </td> <td><?php echo $panier["basse"]?> basse(s)</td> </tr> <tr align="center"> <td><a href="ajout_article.php?ajout=batterie"> Une batterie</a> (2499E) </td> <td><?php echo $panier["batterie"]?> batterie(s)</td> </tr> </table> <p align="center"><a href="initialisation.php"> vider mon panier</a></p> <p align="center"><a href="calcul_total.php"> calculer le total</a></p> </body> </html>

4. Les en-ttes HTTP

Une fois la session rappele, la variable $panier est rcupre, puis $ajout est teste afin dincrmenter la bonne valeur. Une fois ce test effectu, la session est mise jour avec les nouvelles valeurs. L encore, si votre serveur nest pas configur pour raliser automatiquement la rcriture dURL, vous devez complter les URL avec la constante SID si vous voulez quil fonctionne galement pour les clients refusant les cookies.

276

Sessions

calcul_total.php
Listing 4.8 : calcul_total.php
<?php session_start(); $panier = $_SESSION["panier"]; $total = 0; $total += $panier["guitare"]*199; $total += $panier["basse"]*199; $total += $panier["batterie"]*2499; ?> <html> <head> <title>Mon magasin de musique</title> </head> <body bgcolor="#FFFFFF"> <p align="center"> Le total de votre panier: <?php echo $total?> Euros. </p> <p align="center"> <a href="ajout_article.php">Modifier mon panier</a> </p> <p align="center"> <a href="initialisation.php">Vider mon panier</a> </p> </body> </html>

4. Les en-ttes HTTP

Ce script est plus simple comprendre que le prcdent. La session est rcupre puis la variable $panier en est extraite. Bien entendu, si besoin est, il faut prendre soin, l encore, de passer lidentifiant de session en paramtre.

Stockage personnalis des variables de sessions


Par dfaut les variables de sessions sont stockes dans des fichiers temporaires (comme lindique le paramtre session.save_handler du fichier php.ini fix la valeur "files"). En modifiant ce paramtre user, il est possible de redfinir soi-mme la faon dont seront gres les sessions.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur le fichier php.ini.
Il est, par exemple, possible de stocker les paramtres dans une base de donnes (lexemple que nous donnerons ici utilisera une base de donnes MySQL).

277

Chapitre 4

Les en-ttes HTTP

Vous pouvez vous reporter au chapitre "Lutilisation des bases de donnes" pour en savoir plus sur lutilisation de MySQL avec PHP.
Pour cela, nous crerons une table avec trois champs : lidentifiant de session, la date dexpiration, et la valeur des variables de sessions. Notez bien que les variables de sessions seront automatiquement srialises et dsrialises (autrement dit, toutes les valeurs seront regroupes en une chane de caractres et inversement. Voir plus loin les fonctions session_encode() et session_decode()) par PHP). Voici la syntaxe SQL pour la table sessions.
CREATE TABLE sessions ( idsession CHAR(32) NOT NULL, expiration INT(11) NOT NULL, valeur TEXT NOT NULL, PRIMARY KEY (idsession) );

4. Les en-ttes HTTP

Pour grer les sessions, PHP appelle six fonctions. Pour personnaliser lutilisation des sessions, il faut donc crer six fonctions auxquelles PHP fournira les paramtres, et indiquer PHP dutiliser ces fonctions en lieu et place des fonctions par dfaut.
boolean ouvrirSession($cheminSession, $nomSession)

Cette fonction permet dinitialiser la gestion de sessions. En paramtre, lon trouve le chemin (dans le cas dune gestion par fichiers) o stocker les sessions. Il sagit en fait du paramtre session.save_path du fichier php.ini qui peut contenir nimporte quelle information sans que ce soit ncessairement un chemin. $nomSession est le nom de la session tel quil est dfini dans le fichier de configuration de PHP sous le nom session.name (par dfaut, cest PHPSESSID). Elle devra retourner TRUE en cas de succs, FALSE sinon. Dans notre exemple, cette fonction servira tablir la connexion avec la base de donnes.
boolean fermerSession()

Cette fonction permet de librer dventuelles ressources occupes pour la gestion des sessions. Elle devra retourner TRUE en cas de succs, FALSE sinon. Dans notre exemple utilisant une connexion persistante, rien naura besoin dtre fait dans cette fonction. Sinon, nous aurions pu envisager de clore la connexion.
boolean ecrireSession($idSession, $valeur)

Cest cette fonction que lon va indiquer comment stocker les variables de sessions. $idSession est lidentifiant de session, qui servira stocker la session (il pourra servir dfinir le nom du fichier, qui sera donc unique, ou une entre en base de donnes...). $valeur est la valeur stocker dans la session ; elle est fournie srialise. Elle devra retourner TRUE en cas de succs, FALSE sinon.

278

Sessions

Dans notre exemple, cest ici quil faut faire linsertion en base de donnes en faisant attention de crer une nouvelle entre sil nexiste pas dentre pour cet identifiant, ou de modifier lentre existante.
mixed lireSession($idSession)

La fonction de lecture a pour paramtre un identifiant de session. Il faut retourner la valeur (srialise) sauvegarde, ou FALSE en cas derreur. Dans lexemple, il suffira de faire une recherche dans la table de la valeur correspondant la lidentifiant de session fourni.
boolean detruireSession($idSession)

Cette fonction dtruit la session dont lidentifiant est pass en paramtre. Elle devra retourner TRUE en cas de succs, FALSE sinon. Dans notre exemple, il suffira de supprimer lentre correspondant lidentifiant pass en paramtre.
boolean nettoyerSession($dureeVie)

4. Les en-ttes HTTP

Cest la fonction qui sera appele alatoirement pour nettoyer les sessions invalides. La dure de vie, dfinie dans le fichier de configuration par le paramtre session.gc_maxlifetime, est passe en paramtre. Elle devra retourner TRUE en cas de succs, FALSE sinon. Dans notre exemple, il suffira de supprimer toutes les entres dont la date dexpiration est passe. Enfin, pour indiquer PHP dutiliser les fonctions ainsi dfinies, vous devrez faire appel la fonction session_set_save_handler().

session_set_save_handler()
Indique PHP dutiliser des fonctions personnalises pour la gestion des sessions. Syntaxe void session_set_save_handler(function $ouvrirSession, function $fermerSession, function $lireSession, function $ecrireSession, function $detruireSession, function $nettoyerSession) Nom de la fonction appeler louverture de la session (cf. ci-avant). Nom de la fonction appeler la fermeture de la session (cf. ci-avant). Nom de la fonction appeler la lecture du contenu dune session. Nom de la fonction appeler la sauvegarde du contenu dune session. Nom de la fonction appeler la destruction du contenu dune session. Nom de la fonction appeler pour dtruire les sessions primes.

$ouvrirSession $fermerSession $lireSession $ecrireSession $detruireSession $nettoyerSession

279

Chapitre 4

Les en-ttes HTTP

session_mysql.php
Listing 4.9 : session_mysql.php
<?php define("HOTE", "localhost"); define("UTILISATEUR", "root"); define("MOT_DE_PASSE", "MotDePasse"); define("BASE_DE_DONNEES", "biblephp"); define("DUREE_VIE_SESSION", get_cfg_var("session.gc_maxlifetime")); $connexionSession = ""; function ouvrirSession($cheminSession, $nomSession) { global $connexionSession; $connexionSession = mysql_pconnect(HOTE, UTILISATEUR, MOT_DE_PASSE) or die("Impossible de se connecter la base de donnes"); mysql_select_db(BASE_DE_DONNEES, $connexionSession) or die("Base de donnes introuvable"); return TRUE; } function fermerSession() { return TRUE; } function ecrireSession($idSession, $valeur) { global $connexionSession; if (mysql_query("INSERT INTO sessions VALUES ($idSession, ".(time()+DUREE_VIE_SESSION).", $valeur)", $connexionSession)) { return TRUE; } else { return mysql_query("UPDATE sessions SET expiration = ".(time()+DUREE_VIE_SESSION).", valeur = $valeur WHERE idSession = $idSession", $connexionSession); } } function lireSession($idSession) { global $connexionSession; $requete = mysql_query("SELECT valeur FROM sessions WHERE idsession=$idSession AND expiration > " . time(),

4. Les en-ttes HTTP 280

Sessions

$connexionSession); if (list($valeur) = mysql_fetch_row($requete)) { return $valeur; } else { return FALSE; } } function detruireSession($idSession) { global $connexionSession; return mysql_query("DELETE FROM sessions WHERE idsession=$idSession", $connexionSession); } function nettoyerSession($dureeVie) { global $connexionSession; return mysql_query("DELETE FROM sessions WHERE expiration < " . time(), $connexionSession); } session_set_save_handler("ouvrirSession", "fermerSession", "lireSession", "ecrireSession", "detruireSession", "nettoyerSession"); ?>

4. Les en-ttes HTTP

Adapter le script votre environnement Les quatre constantes HOTE, UTILISATEUR, MOT_DE_PASSE et BASE_DE_DONNEES doivent tre renseignes selon votre configuration.
Compte tenu des remarques prcdentes, il nest pas difficile dcrire soi-mme ce type de script. La dure de vie dune session est rcupre depuis le fichier de configuration grce la fonction get_cfg_var(). Cette valeur nous servira dterminer la date dexpiration des sessions.

test.php
Ceci est un fichier permettant de tester la gestion des sessions telle quon vient de la dfinir.

Listing 4.10 : test.php


<?php include("session_mysql.php");

281

Chapitre 4

Les en-ttes HTTP

session_start(); if (!isset($_GET["valeur"])) { $_GET["valeur"] = 0; } if ( (!isset($_GET["action"])) ||(!isset($_SESSION["variableSession"]))) { $_GET["action"] = "initialiser"; } switch($_GET["action"]) { case "detruire": session_destroy(); break; case "gc": nettoyerSession(get_cfg_var("session.gc_maxlifetime")); break; case "incrementer": $_SESSION["variableSession"]++; break; case "initialiser": $_SESSION["variableSession"] = 0; break; } ?> <html> <head><title>Test</title></head> <body> <p> Valeur courante:<?php echo $_SESSION["variableSession"]?> <br /> <a href="test.php?action=incrementer"> Incrmenter la variable de session</a> <a href="test.php?action=detruire">Destruction de la session</a> <a href="test.php?action=gc">Forcer le gc</a> </p> </body>

4. Les en-ttes HTTP

Ce script trs simple se contente dafficher la valeur dune variable de session, et de proposer trois liens : un pour lincrmenter, un pour dtruire la session et un pour forcer lappel au garbage collector charg de supprimer les sessions primes.
Figure 4.7 : Interface de test

282

Sessions

Clore une session


Il nest gnralement pas possible de dterminer quand mettre fin une session. En effet, pour cela, il faudrait savoir quand le visiteur a quitt le site. Cest pourquoi il faut gnralement attendre la fin du dlai dexpiration pour voir les sessions disparatre. Toutefois, si vous proposez sur votre site un lien Dconnexion, il vous sera possible de faire proprement appel la fonction session_destroy() (Ce qui vitera en plus quun autre utilisateur partageant le mme poste de travail puisse accder au compte du prcdent).

session_destroy()
Dtruit les variables de la session en cours. Syntaxe retour boolean session_destroy(void)

4. Les en-ttes HTTP

TRUE en cas de succs, FALSE sinon.

Il est souhaitable de vider au pralable le contenu des variables de sessions. Ainsi le script de dconnexion pourra ressembler :
<?php session_start(); $_SESSION = array(); session_destroy(); echo "Au revoir, et bientt"; ?>

Les autres fonctions


Comme cela a t prcis, les variables composant une session sont srialises avant dtre stockes (par dfaut, dans un fichier), et dsrialises aprs avoir t rcupres. Pour raliser manuellement cette opration, vous devez faire appel aux fonctions session_code() et session_decode().

session_encode()
Srialise la session (convertit lensemble des variables de sessions en une chane de caractres unique). Syntaxe retour string session_encode(void) Chane encode avec le contenu de la session.

283

Chapitre 4

Les en-ttes HTTP

session_decode()
Dsrialise une chane de caractres contenant des variables de sessions (recrant ainsi lensemble des variables de la session). Syntaxe $variable retour boolean session_decode(string $variable) Chane de caractres dsrialiser. TRUE en cas de succs, FALSE sinon.

Dautres fonctions, moins souvent utilises, sont disponibles pour la gestion des sessions. Il est par exemple possible de remplacer lutilisation des paramtres habituellement dfinis dans le fichier php.ini par des paramtres fixs par le script.

4. Les en-ttes HTTP

session_module_name()
Permet de dfinir ou de connatre le gestionnaire de sessions utilis (habituellement dfini par le paramtre session.save_handler de php.ini). Syntaxe $gestionnaire string session_module_name([string $gestionnaire]) Indiquer (cf. session_set_save_handler()) : "files" si les donnes de session doivent tre stockes "simplement" dans des fichiers temporaires. user si elles doivent tre stockes en utilisant les fonctions personnalises. retour Le gestionnaire de sessions utilis savoir files" ou "user".

session_save_path()
Permet de dfinir ou de connatre lemplacement o seront sauves les sessions (habituellement dfini par le paramtre session.save_path de php.ini). Syntaxe $chemin retour string session_save_path([string $chemin]) Chemin que lon souhaite dfinir en tant que rpertoire pour stocker les sessions. Nom du rpertoire o sont stocks les fichiers temporaires de session.

284

Sessions

session_name()
Permet de dfinir ou de connatre le nom du paramtre de lURL contenant lidentifiant de session (habituellement dfini par le paramtre session.name de php.ini). Syntaxe $nomIdSession retour string session_name([string $nomIdSession]) Nouveau nom du paramtre didentifiant de session. Nom de lidentifiant de session (par dfaut PHPSESSID).

session_id()
Permet de dfinir ou de connatre lidentifiant de session attribu au visiteur. Syntaxe $idSession retour string session_id([string $idSession]) Nouvel identifiant de session utiliser. Identifiant de session utilis.

4. Les en-ttes HTTP

session_regenerate_id()
Permet de rgnrer un nouvel identifiant pour une mme session. Cette fonction a t introduite avec PHP 4.3.2. Syntaxe : retour boolean session_regenerate_id(void) TRUE si un nouvel identifiant a t rgnr, FALSE sinon.

Il est galement possible de connatre ou de fixer les paramtres du cookie charg de sauvegarder lidentifiant de session sur la machine du visiteur (sans tenir compte des paramtres dfinis dans le fichier php.ini).

session_get_cookie_params()
Permet de rcuprer les informations du cookie de session. Syntaxe retour array session_get_cookie_params(void) Tableau associatif contenant les informations du cookie. On y retrouve : "lifetime", la dure de vie du cookie. "path" le chemin o est stock le cookie. "domain" le domaine sur lequel le cookie est valable. "secure" un boolen indiquant si le cookie ne doit tre envoy que par une connexion scurise.

285

Chapitre 4

Les en-ttes HTTP

session_set_cookie_params()
Permet de dfinir les paramtres du cookie de session. Syntaxe $dureeVie $chemin $domaine void session_set_cookie_params(int $dureeVie [, string $chemin [, string $domaine]]) Nouvelle dure de vie en secondes (habituellement dfinie par le paramtre session.cookie_lifetime du fichier php.ini). Chemin o le cookie est valide (habituellement dfini par le paramtre session.cookie_path du fichier php.ini). Domaine de validit du cookie (habituellement dfini par le paramtre session.cookie_domain du fichier php.ini).

4. Les en-ttes HTTP

Les pages utilisant des variables de sessions prsentent gnralement un aspect diffrent dun appel lautre, sans que leur URL ne soit modifie. Pour que le visiteur puisse profiter des modifications apportes la page, il faut absolument interdire lutilisation du cache par le navigateur. Cest pour cela que, par dfaut, les pages faisant appel aux sessions demandent galement linterdiction de la mise en cache. Mais ces paramtres peuvent tre modifis avec la fonction suivante :

session_cache_limiter()
Permet de dfinir ou de connatre la restriction du cache applique (habituellement dfinie par le paramtre session.cache_limiter de php.ini). Syntaxe string session_cache_limiter([string $restriction_cache])

$restriction_cache Ce paramtre peut prendre les valeurs : "nocache" si lon souhaite que le client ne mette pas la page dans le cache. "public" (ou "private" qui est lgrement plus restrictif) pour autoriser la mise en cache. "private_no_expire" (depuis la version PHP 4.2.0) permet de ne pas envoyer len-tte Expire qui causait des problmes avec la restriction du cache. retour Retourne la restriction du cache en cours.

session_cache_expire()
Permet de dfinir ou de connatre la dure avant expiration du cache (habituellement dfinie par le paramtre session.cache_expire de php.ini). Cette fonction a t introduite partir de la version 4.2.0.

286

Mise en cache avant mission des donnes

Syntaxe $expirationCache retour

int session_cache_expire([int $expirationCache]) Nouvelle valeur (en secondes) dexpiration du cache. Retourne la valeur actuelle dexpiration du cache.

Vous disposez aussi de :

session_write_close()
Termine la session et enregistre les variables de sessions, ce qui est automatiquement fait la fin des scripts. Attention, dans ce cas, aucune rcriture dURL ne sera effectue. Syntaxe void session_write_close(void)

4. Les en-ttes HTTP

Les fonctions historiques


Les fonctions suivantes ne doivent plus tre utilises (pas avec le tableau $_SESSION, ni mme dailleurs avec $HTTP_SESSION_VARS) :
session_register() permettait de dfinir une variable globale comme tant une variable de session. Ainsi, register("maVariable"); faisait de $maVariable une variable de session. Avec lutilisation de $_SESSION["maVariable"], aucun doute nest possible. session_unregister() mettait simplement un terme lassociation entre la variable et une variable de session. Avec $_SESSION, il ny a videmment pas besoin dquivalent. session_is_registered() permettait de tester si une variable tait une variable de session. L encore, avec $_SESSION, il ny a pas besoin dquivalent. session_unset() permettait de librer le contenu des variables de sessions. Avec $_SESSION, il suffit de faire $_SESSION = array().

4.5.

Mise en cache avant mission des donnes

Les fonctions de base


Une srie de fonctions de contrle de sortie permet de grer soi-mme lmission des donnes. Habituellement, le fait de gnrer le document (avec les commandes echo ou print par exemple), et donc denvoyer len-tte HTTP avant de faire appel une fonction modifiant len-tte, aboutit inexorablement au message derreur suivant : "Cannot add header information - headers already sent". Il est possible dviter ceci en demandant de ne pas envoyer les lments du document au moment o ils sont gnrs, mais de le faire une fois tous les lments de len-tte dfinis. Pour cela, nous disposons des fonctions ob_start() et ob_end_flush().

287

Chapitre 4

Les en-ttes HTTP

ob_start()
Demande la mise en cache de ce qui va sur la sortie standard (ce qui est destin au client). Syntaxe $fonction void ob_start([function $fonction]) Fonction appliquer sur le contenu du cache (cf. compression des donnes).

ob_end_ush()
Met fin la mise en mmoire de la sortie et met le contenu du cache vers le navigateur.

4. Les en-ttes HTTP

Syntaxe

void ob_end_flush(void)

Ainsi, lexemple suivant ne gnrera pas derreur malgr lappel setCookie() aprs un echo.
<?php ob_start(); echo "Jenvoie du texte sur la sortie avant de definir un cookie"; setCookie("cookie", "je defini un cookie apres avoir ecrit du texte"); ob_end_flush(); ?>

Le fichier de configuration de PHP permet dactiver systmatiquement le systme de cache, grce au paramtre output_buffering. Cela revient alors placer ob_start() au dbut de chaque script, et ob_end_flush(), qui a pour effet dafficher le contenu du cache la fin.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur le fichier php.ini. Ne pas cder la facilit Mme si lutilisation du systme de cache permet de mlanger allgrement gnration du document et gnration de len-tte HTTP, il est fortement conseill (pour des raisons de performance) de se passer de lutilisation de ces fonctions (dans ce cadre-l). Dautant quil est gnralement facile de saffranchir de la difficult que cela pourrait engendrer. Il est de toute faon de bon usage de commencer un script par toutes les oprations de traitement avant les oprations de mise en page.

288

Mise en cache avant mission des donnes

Compression des donnes


La plupart des navigateurs, dont Internet Explorer et Netscape, permettent la dcompression transparente des donnes (les types de compression supports sont prciss dans la variable externe $_SERVER["HTTP_ACCEPT_ENCODING"]). Si le serveur dtecte que le navigateur du client supporte la compression Gzip (par exemple), il peut dcider denvoyer des donnes compresses celui-ci, qui les dcompressera avant de les afficher. Cette procdure sera totalement transparente pour lutilisateur qui ne verra quun gain en terme de temps de tlchargement des pages. Bien entendu, cette procdure demandera un petit peu plus de travail au serveur, mais si celui-ci est suffisamment puissant, son utilisation est avantageuse question rapidit. Pour cela, il suffit de spcifier le paramtre "fonction de compression" de la fonction ob_start(). Cette fonction qui peut tre une fonction personnalise doit accepter un paramtre de type chane de caractres, et simplement en retourner la version compresse. Voici un morceau de script mettre en dbut de chacun de vos scripts pour utiliser la compression Gzip.
<?php function compression($sortie) { // Cette fonction ne fait que retourner la compression de la chane // de caractres prcise en paramtre. return gzencode($sortie); } // Vrification du support de gzip par le client if (strstr($_SERVER[HTTP_ACCEPT_ENCODING], gzip)) { // Dbut de mise en mmoire en fournissant comme paramtre // la fonction appliquer sur la sortie ob_start("compression"); // Prvient le navigateur que les donnes sont compresses. header("Content-Encoding: gzip"); } ?>

4. Les en-ttes HTTP

Gzip Vous devrez avoir compil PHP avec loption --with-zlib pour pouvoir effectivement profiter de la compression Gzip.
La fonction compression() passe en paramtre ob_start() est appele juste avant lenvoi du rsultat. Bien videmment, ici, nous aurions pu nous passer de la fonction compression() et crire directement ob_start("gzencode"). Qui plus est, depuis la version 4.0.4, PHP propose une fonction appele ob_gzhandler() permettant de compresser les donnes en fonction du navigateur, en utilisant soit Deflate soit Gzip (voire ne compressant pas). Tout le script prcdent peut donc se rduire :
<?php ob_start("ob_gzhandler"); ?>

289

Chapitre 4

Les en-ttes HTTP

Si vous souhaitez utiliser systmatiquement la fonction ob_gzhandler(), vous pouvez alors vous dispenser dajouter cette ligne au dbut de tous les scripts, simplement en modifiant le fichier de configuration php.ini pour avoir la ligne suivante :
output_handler = ob_gzhandler

Mais jusquo peut-on aller dans la simplification ? ce stade, on ne peut plus faire grand chose... Lexemple du premier script reste cependant utile dans certains cas, que vous pouvez imaginer vous-mme. Il est en effet facultatif dutiliser une fonction de compression, alors pourquoi ne pas, par exemple, appliquer une fonction qui rendra plus lisible le code HTML retourn pour dboguer vos scripts ? Il est galement envisageable de ne produire que du XML et dappliquer une feuille de styles au moment du rendu.

Optimisation des temps de rponse


4. Les en-ttes HTTP
Il est tout moment possible de faire appel au contenu du cache, ce qui peut se rvler vraiment trs intressant. Lutilisation la plus intressante apparat lorsque vous proposez un site contenant des pages dont le contenu peut prendre un certain temps tre gnr (parce quil fait appel une base de donnes, que le traitement des donnes est relativement long, etc.), mais qui varie peu dans le temps (dont le mme rsultat pourra tre propos diffrents visiteurs sur une priode donne). Dans ce cas, plutt que de renouveler les oprations de traitement (et daccs la base de donnes) chaque appel, il est prfrable de gnrer le document (pour le premier visiteur) et de le stocker sous sa forme HTML (ou image, ou autre) afin de restituer le fichier tout prt pour les visiteurs suivants. Il faudra simplement prendre soin de recrer ce document intervalles rguliers concidant avec la frquence de mise jour des donnes. Voyons maintenant comme procder. La fonction permettant de rcuprer le contenu du cache sappelle ob_get_content().

ob_get_contents()
Rcupre le contenu actuel du cache. Syntaxe retour string ob_get_contents(void) Contenu du cache, ou FALSE si la gestion du cache nest pas active.

Ainsi, afin de stocker le contenu dun document dans un fichier, il suffit dappeler le script suivant :

Listing 4.11 : cache_01.php


<?php ob_start();

290

Mise en cache avant mission des donnes

// Insrez ici, le code du script tel quil serait // sans lutilisation de cache // Exemple echo "Jai t mis en cache ".strftime("%d/%m/%y %H:%M:%S"); echo "Jai t mis en cache ".strftime("%d/%m/%y %H:%M:%S"); $contenuCache = ob_get_contents(); ob_end_flush(); $fd = fopen("cache.html", "w"); if (!$fd) die("Impossible douvrir le fichier de cache"); fwrite($fd, $contenuCache); fclose($fd); ?>

En plus dtre affich, le contenu sera alors galement stock dans un fichier cache.html. Pour que cela soit utile, reste dterminer quand le fichier doit tre recr et quand il doit tre affich tel quel. Pour connatre la date de dernire mise jour du fichier, nous pourrons faire appel la fonction filemtime(). Il suffira alors de voir sil date de plus de tant de temps (disons, titre dexemple, 2 mn).

4. Les en-ttes HTTP

Listing 4.12 : cache_01.php


<?php $fichierCache = "cache.html"; if (@filemtime($fichierCache)<time()-2*60) { // Oul... a commence dater ob_start(); // Insrez ici, le code du script tel quil serait // sans lutilisation de cache // Exemple echo "Jai t mis en cache ". // strftime("%d/%m/%y %H:%M:%S"); echo "Jai t mis en cache ".strftime("%d/%m/%y %H:%M:%S"); $contenuCache = ob_get_contents(); ob_end_flush(); $fd = fopen($fichierCache, "w"); if ($fd) { fwrite($fd, $contenuCache); fclose($fd); } } else { include($fichierCache); } ?>

291

Chapitre 4

Les en-ttes HTTP

Vous pouvez vous reporter aux sections "Dates" et "Fichiers" pour plus de dtails sur les fonctions strftime(), time(), filemtime(), fopen(), fwrite() et fclose().
Notez que, cette fois-ci, nous passons sous silence les cas o le fichier cache na pu tre cr. En effet, il vaut mieux ce moment-l ne pas polluer le document retourn (tant pis, nous ne profiterons tout simplement pas de leffet de cache). Notez galement quen labsence du fichier de cache (ou si celui-ci nest pas lisible), la fonction filemtime() retournera un message derreur que nous masquons par un @. La valeur retour de filemtime() sera alors FALSE qui, converti en entier, vaut 0 et sera donc infrieur la date limite ; le fichier cache sera donc bien recr. Il est galement envisageable dutiliser le cache juste pour rcuprer ce quune fonction met sur la sortie standard, sans que lon veuille pour autant que cela apparaisse dans le document. Pour cela, vous devrez utiliser la fonction ob_end_clean().

4. Les en-ttes HTTP

Gestion du cache interne


Par dfaut, les lments des documents mettre vers un client sont mis dans un cache interne avant dtre envoys au navigateur (ceci afin doptimiser les transferts de donnes). Ce qui fait que les donnes ne seront pas mises disposition du client ds quelles seront prtes, mais ds que le cache sera plein (ou que lexcution du script sera termine). En de rares circonstances, cela peut tre frustrant. Imaginez que vous utilisez un script PHP pour effectuer un long travail de traitement. Vous aurez certainement envie de suivre son volution en affichant rgulire "tant de % raliss". Malheureusement, il sagit l dune chane de caractres bien trop courte pour esprer voir le cache se remplir rapidement et tre inform de lavance du traitement avant la fin du script. Pour pallier cet inconvnient, il suffit de demander lenvoi du contenu de cache interne, mme si celui-ci nest pas plein. Ceci se ralise par un appel la fonction flush() que vous appellerez chaque fois que vous voulez envoyer le contenu du cache. Il est galement possible de demander que lappel flush() se fasse systmatiquement (ds quune nouvelle ligne est ajoute au document). Pour cela, vous utiliserez la fonction ob_implicit_flush().

ob_implicit_ush()
Active ou dsactive lenvoi implicite. Quand lenvoi implicite est activ, les donnes sont envoyes ds que possible. Syntaxe $active ob_implicit_flush([boolean $active]) TRUE (valeur par dfaut) pour activer, FALSE pour dsactiver.

292

Mise en cache avant mission des donnes

Syntaxe retour

boolean headers_sent(void) TRUE si len-tte a dj t mis, FALSE sinon.

Partie de cache-cache Lutilisation des fonctions flush() et ob_implicit_flush() nimplique pas la disponibilit immdiate des donnes au niveau de laffichage du navigateur. En effet, aprs PHP, le serveur et le navigateur peuvent, eux aussi, dcider de mettre les donnes dans un cache.
Quoi quil en soit, dans un environnement de travail de type "Linux + Apache + Mozilla" le script suivant,

Listing 4.13 : flush_02.php


<?php set_time_limit(0); ob_implicit_flush(); for ($i=0; $i<=100; $i++) { echo "$i%<br />"; sleep(1); } ?>

4. Les en-ttes HTTP

affiche 1 %, 2 %, etc. intervalles rguliers dune seconde, alors que la variante de ce script (flush_01.php) ne faisant pas appel ob_implicit_flush() naffiche rien pendant une longue priode (probablement 100 secondes) avant dafficher toutes les lignes dun bloc. Nous avons d, ici, faire appel set_time_limit() pour autoriser lexcution dun script de plus de 30 secondes.

Les autres fonctions


Ces fonctions sont galement disponibles, mais nont pas t vues prcdemment.

ob_get_length()
Retourne le nombre de caractres contenus dans le cache. Syntaxe return string ob_get_length(void) Longueur du contenu du cache, ou FALSE si la gestion nest pas active.

293

Chapitre 4

Les en-ttes HTTP

ob_ush()
Permet denvoyer le contenu du cache au navigateur, puis de vider le cache sans pour autant mettre fin la mise en cache. Cette fonction a t introduite dans la version 4.2.0 de PHP. Syntaxe void ob_flush(void)

ob_clean()
Vide le contenu du cache sans pour autant mettre fin la mise en cache. Cette fonction a t introduite dans la version 4.2.0 de PHP. Syntaxe void ob_clean(void)

4. Les en-ttes HTTP

ob_get_level()
Retourne le degr dimbrication des mises en cache (i.e. nombre dappels ob_start()). Cette fonction a t introduite dans la version 4.2.0 de PHP. Syntaxe retour int ob_get_level(void) Le degr dimbrication des mises en cache.

294

Chapitre 5

Les techniques de programmation


5.1 5.2 Rgles de codage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 Sparation du code et de la mise en page . . . . . . . . . . . . . . . . . . . . . . . . . 307

Rgles de codage

5.1.

Rgles de codage

Contrairement ce que lon peut trouver avec le langage Java, les auteurs de PHP ne suggrent pas vritablement de rgles de codage. Cependant, en marge du dveloppement du moteur PHP, les auteurs de PHP group contribuent galement la ralisation dune bibliothque de scripts PHP baptise PEAR. Et, dans le cadre de ce projet, quelques rgles de codage ont t dictes. Ce sont principalement ces recommandations que nous allons prsenter ici, tout en les compltant et les amliorant (souvent en gardant lesprit Java). Ces rgles de codage, souvent issues du simple bon sens, sont destines faciliter la lecture du code (notamment par un dveloppeur autre que lauteur principal du script), mais aussi rduire les risques derreur de programmation.

Prsentation du code
Il est ainsi suggr :
j j j

Dcrire des lignes de code ne dpassant pas 80 caractres (et idalement ne dpassant pas 70 caractres) pour en faciliter la lecture lcran et sur papier. Dindenter le code avec quatre espaces (sans tabulations) afin de conserver la mme mise en page quelle que soit la configuration de lditeur.

5. Les techniques de programmation

De mettre une espace de part et dautre dun signe gal dune affectation de valeur une variable (voire plusieurs dans le cas dune srie daffectations pour un alignement plus lisible). Ce quil faut faire :
$var1 = fonction(); $variable2 = 21

Ce quil ne faut pas faire :


$variable2=21;

Dinsrer une espace entre les lments des structures de contrle et les parenthses ouvrantes, afin de les diffrencier dun appel de fonction. Ce quil faut faire :
if (condition) { code1; }

Ce quil ne faut pas faire :


if(condition) { code1; }

Ce quil faut faire :


if ((cond1) && (cond2) ) { code1; }

297

Chapitre 5

Les techniques de programmation

Ce quil ne faut pas faire :


if ((cond1)&&(cond2)) { code1; }

Dutiliser des accolades mme pour les structures de contrle ne contenant quune seule ligne. Ceci afin dviter tout oubli le jour o une ligne devra tre ajoute. Ce quil faut faire :
if (condition1) { code1; }

Ce quil ne faut pas faire :


if (condition1) code1;

De ne pas mettre despace entre le nom de la fonction et la parenthse ouvrante prcdant les paramtres. Ce quil faut faire :
maFonction($param1)

5. Les techniques de programmation

Ce quil ne faut pas faire :


maFonction ($param1)

De sparer chaque paramtre dune fonction par une virgule suivie dune espace (mais pas despace entre la parenthse ouvrante et le premier paramtre). Ce quil faut faire :
maFonction($param1, $param2)

Ce quil ne faut pas faire :


maFonction ($param1,$param2)

De positionner laccolade ouvrante de dclaration dune fonction juste au dessous du "f" de


function et de commencer le corps de la fonction aprs avoir indent.

Ce quil faut faire :


function maFonction() { return "blabla"; }

Ce quil ne faut pas faire :


function maFonction() { return "blabla"; }

298

Rgles de codage

Programmation
j j

Toujours utiliser les balises <?php ?> (et non <? ?> ou toute autre alternative). Les paramtres optionnels (avec des valeurs par dfaut) des fonctions doivent tre les derniers paramtres de la fonction (du moins couramment omis au plus couramment omis). Ce quil faut faire :
function maFonc($p1, $p2 = "bla") { return $p1.$p2; }

Ce quil ne faut pas faire :


function maFonc($p1 = "bla", $p2) { return $p1.$p2; }

Les fonctions doivent toujours retourner une valeur cohrente (i.e. en cas dchec retourner clairement FALSE plutt que de ne pas retourner explicitement de valeur. En cas dappel une fonction ne retournant pas spcifiquement de valeur, retourner TRUE en cas de succs, et FALSE sinon). Utiliser de prfrence include_once() (plutt que include()) pour les fichiers inclure, mais dont on peut ventuellement se passer, et require_once() (plutt que require()) pour les fichiers ncessaires au bon fonctionnement du script. Se tenir inform des problmes de scurit lis lutilisation de certaines fonctions (cf. include et upload de fichiers).

5. Les techniques de programmation

Noms de classes, fonctions, variables et constantes


Les rgles de nommage de la bibliothque PEAR ne sont pas tout fait claires (du moins en ce qui concerne les classes et les variables). Mais une bonne pratique consiste respecter peu prs les mmes rgles que pour Java (mme si cela nest pas le cas pour les fonctions natives de PHP et si, dans certains cas, on peut tre amen sen carter).

Les classes
Les noms de classes commencent par quelques lettres en majuscules indiquant le projet auquel elles appartiennent (ex. : SPP pour "Super Projet PHP") suivies dun underscore et du nom dcrivant le rle de la classe. Ce nom ne comporte pas dunderscore et est essentiellement crit en minuscules. Seules les premires lettres des mots composant le nom sont en majuscules. La lettre suivant lunderscore est, elle, une minuscule. Un nom de classe doit toujours commencer par une majuscule (ce qui est assur ici par labrviation du nom du projet). Ce qui donne, par exemple :
class SPP_maClasse() { }

299

Chapitre 5

Les techniques de programmation

Les mthodes
Les noms de mthodes ne doivent pas commencer par une majuscule. Elles sont essentiellement crites en minuscules. Seules les premires lettres des mots composant le nom sont en majuscules. Il est conseill de distinguer les mthodes internes (uniquement utilises par la classe) des mthodes externes (pouvant tre appeles par le dveloppeur) en faisant prcder les noms de mthodes internes par un underscore.
class SPP_superClasse { function _fonctionInterne() { // commence par un underscore } function superFonction() { // pas de prfixe dans ce cas } }

5. Les techniques de programmation

Les fonctions
Nous appliquerons aux fonctions (autres que les mthodes) les mmes rgles de nommage que celles appliques aux classes.
function MA_superFonction() { }

Les variables
Les noms de variables suivent les mmes rgles que celles des noms de mthodes.
$maSuperVariable $_maVariablePrivee

En revanche, pour les variables globales, les rgles de nommage PEAR suggrent de respecter les mmes rgles que pour les noms de classes, mais en les faisant prcder dun underscore. ($_PEAR_destructor_object_list est cit en exemple, alors quil serait prfrable dutiliser le nom $_PEAR_destructorObjectList.)

Les constantes
Les noms des constantes sont en majuscules, et, dans ce cas, chaque mot est spar par un underscore. L encore, les noms doivent tre prcds du nom, abrg et en majuscules, de la bibliothque.
define("SPP_SUPER_CONSTANTE", 20);

300

Rgles de codage

Commentaires
Ah ! les commentaires... Il faut distinguer deux types de commentaires. Il y a les commentaires destins aux personnes qui vont devoir utiliser les classes et fonctions. Il sagit dans ce cas de dcrire lobjectif de la classe ou fonction ainsi que son interface (description des paramtres dentre et sortie). Puis il y a les commentaires destins aux personnes qui seront charges de la maintenance du code. Dans ce cas, il sagit plutt de dcrire les algorithmes et les diverses subtilits qui ont t mis en place pour que la fonction fasse ce que lon attend delle. Dans le premier cas, les dveloppeurs de PEAR suggrent dinclure dans les scripts des commentaires respectant la convention PHPDoc (fortement inspire de JavaDoc). Dans le second cas, il est suggr dutiliser soit la convention /* */, soit // (au choix du programmeur, mais pas #).

PHPDoc(umentor)
Installation
PHPDoc est plus ou moins un standard dcriture repris du monde Java. Dans PEAR, on retrouve deux implmentations, une appele PHPDoc et lautre PHPDocumentor. PHPDocumentor est le gnrateur de documentation recommand pour diverses raisons telles que la gnration de fichier PDF, labsence dutilisation de base de donnes, possibilit de dfinir ses propres balises En outre PHPDoc nest plus en dveloppement. Pour installer PHPDocumentor une fois PEAR install il suffit de taper pear install phpdocumentor.

5. Les techniques de programmation

PHP4/5 Pour utiliser PHPDocumentor avec PHP5 il vous faudra utiliser au minimum la version 1.3.0 autrement toute version est utilisable pour PHP4.

Syntaxe des commentaires


Tout comme pour JavaDoc, les lignes de commentaire doivent prcder les dclarations de classes, fonctions, etc. selon le schma suivant :
/** * Description succincte * * Description dtaille * * @param <type du parametre> */

description

Ces commentaires doivent apparatre avant les instructions class (dclaration dune classe), function (dclaration dune fonction), var (dclaration dune variable), define (dclaration dune constante), include, include_once, require, require_once (inclusion de fichiers).

301

Chapitre 5

Les techniques de programmation

Les mots-cls valides sont :


j j
@access suivi de "private" ou "public" pour indiquer si une classe, une fonction ou une variable est prive ou publique (par dfaut, elles seront considres comme prives). @author suivi du nom de lauteur et ventuellement de le-mail mis entre < et > (ne peut pas tre utilis pour include, include_once, require et require_once). Le champ e-mail est cens tre optionnel. En pratique, sil nest pas mis, le nom de lauteur napparat pas. @const suivi du nom de la constante et ventuellement de la description (valable uniquement pour define). @deprecated suivi dun commentaire prcisant depuis quand (date ou version) llment comment est dprci (ne peut tre utilis pour include, include_once, require et require_once). @global, pour prciser le rle dune variable globale utilise dans une fonction, suivi du type de la variable (pour les objets, prcisez "object " suivi du nom de lobjet), lui-mme suivi du nom de la variable, enfin ventuellement suivi de la description (valable uniquement pour function). @package, pour prciser quelle bibliothque appartient une classe, suivi du nom de la bibliothque (valable uniquement pour class). @param, pour prciser le rle dun argument dune fonction, suivi du type de la variable (pour les objets prcisez "object " suivi du nom de lobjet), suivi du nom de la variable, ventuellement suivi de la description (valable uniquement pour function). @return, pour prciser le contenu de la valeur retourne par une fonction, suivi du type de la variable (pour les objets prcisez "object " suivi du nom de lobjet), ventuellement suivi de la description (valable uniquement pour function). @see, pour faire rfrence une autre fonction, une autre mthode de la classe ou une variable, suivi du nom de llment point. Le nom de la fonction doit inclure les parenthses ouvrante puis fermante. Cela insre alors un lien hypertexte dans la documentation (ne peut tre utilis pour include, include_once, require et require_once). @since, pour indiquer la date/version dintroduction de llment, suivi de la date ou de lidentifiant de version (ne peut tre utilis pour include, include_once, require et require_once). @static, pour indiquer quune mthode peut tre considre comme statique (appel MonObjet::maMethode() possible). Valable uniquement pour function. @throws, pour indiquer quelles erreurs peuvent tre leves. @var, pour indiquer le rle dune variable, suivi du type de la variable (pour les objets prcisez "object" suivi du nom de lobjet), suivi du nom de la variable, ventuellement suivi de la description (valable uniquement pour var). @version, pour indiquer le numro de version, suivi dune chane de caractres totalement libre indiquant le numro de version.

j j

j j

5. Les techniques de programmation

j j j

302

Rgles de codage

Un seul ou plusieurs fichiers Contrairement PHPDoc, avec PHPDocumentor il est possible de dfinir plusieurs classes dans un mme fichier mais cela reste tout de mme dconseill pour des raisons de lisibilit (sauf cas particuliers).

Listing 5.1 : sources/phpdoc_demo01.php


<?php /** * @const SPP_maConstante Une bien belle constante */ define("SPP_MA_CONSTANTE", 20); $_SPP_maVariableGlobale = "SPP"; /** * Classe super pratique * * L, je pourrais dcrire ce que fait cette * classe mais comme je nen ai aucune ide * je mabstiendrais. * * @author Damien HEUTE <damien@toutestfacile.com> * @package SuperProjetPHP * @access public * @version 2.0 * @since 2002-07-01 */ class SPP_maClasse { /** * @var string monParametre Paramtre de sauvegarde */ var $monParametre;

5. Les techniques de programmation

/** * @param monObjet object SPP_autreClasse Object a sauvegarder * @return boolean TRUE si OK, FALSE sinon * @see vieilleFonction() */ function sauve($monObjet) { /** * @global string Une variable globale. */ global $_SPP_maVariableGlobale;

303

Chapitre 5

Les techniques de programmation

return $mon0bjet->sauve($_SPP_mavariableGlobale. $this->monParametre); } /** * @static * @param texte string Texte a afficher */ function affiche($texte) { echo $texte; } /** * @deprecated 2.3 */ function vieilleFonction() { // ne plus utiliser depuis version 2.3 } }

5. Les techniques de programmation

/** * maFonction * * @param parametre1 string blabla */ function maFonction($parametre1) { } ?>

Listing 5.2 : sources/phpdoc_demo02.php


<?php /** * Une classe vraiment bidon * * @package SuperProjetPHP */ class SPP_autreClasse { } ?>

304

Rgles de codage

En-tte de fichier Dans le cadre du projet PEAR, un en-tte de fichier est suggr. Cela tant fortement dpendant du projet, nous naborderons pas ce point ici.

Gnration de la documentation
La gnration de la documentation est trs simple, elle peut se faire "en ligne" ou "hors ligne" cest--dire avec les fichiers sources sur le serveur ou dans tout autre rpertoire. Il y a deux possibilits pour gnrer la documentation, soit en ligne de commande soit par une interface web. Linconvnient de linterface web est quil faut linstaller sur le serveur et quelle ne permet de gnrer de la documentation que sur les fichiers prsents sur le serveur. Nous allons donc voir uniquement le mode en ligne de commande. Entrons tout de suite dans le vif du sujet avec un exemple ou dans le rpertoire courant il y a le rpertoire sources qui contient vos fichiers sources (dans notre exemple nous reprenons les fichiers dcrit prcdemment) et que lon veuille gnrer une documentation HTML dans un nouveau rpertoire appel documentation:
phpdoc d sources t documentation

5. Les techniques de programmation

Voila, le tour est jou, voici le contenu du rpertoire documentation:

Figure 5.1 : Contenu du rpertoire documentation

Et un aperu de la documentation gnre (voir fig. 5.2) : Comme nous lavons dj prciser, PHPDocumentor permet de gnrer des fichiers PDF, ici nous navons rien prciser et donc le rendu obtenu est par dfaut HTML avec la mise en page de PHPDocumentor.

305

Chapitre 5

Les techniques de programmation

5. Les techniques de programmation

Figure 5.2 : Aperu de la documentation

Voyons diffrentes options disponibles pour loutil phpdoc:


j j j j j j j j
-f ou --filename: nom du ou des fichiers spars par une virgule analyser. (vous pouvez utiliser * ou ?) -d ou --directory: nom du ou des rpertoires spars par une virgule analyser. -t ou --target: rpertoire o crer la documentation. (il sera cre sil nexiste pas dj) -i ou --ignore: liste de fichiers ignorer. -q ou --quiet: naffiche pas dinformations lors de lanalyse. -ti ou --title: titre de la documentation (Generated Documentation par dfaut) -h ou --help: permet dobtenir une aide sur phpdoc. -o ou --output: dfini le mode de gnration. Cest cette option qui vous permet de gnrer de lHTML, du PDF, du DocBook Pour choisir il suffit daller dans le rpertoire

306

Sparation du code et de la mise en page

Converters de PHPDocumentor et de dfinir le chemin vers le convertisseur que vous

voulez. ce jour il y a le choix entre: CHM:default, HTML:frames, HTML:Smarty, PDF:default, XML:DocBook. Il est galement possible de crer votre propre mode.

Autres options Il existe dautres options mais moins souvent utilises.

5.2.

Sparation du code et de la mise en page

Pour des raisons de maintenance, ou tout simplement parce que les bons dveloppeurs ne font pas ncessairement de bons designers (et rciproquement), il est gnralement souhaitable de sparer le code de la mise en page. Ce principe gnral doit galement sappliquer au code PHP. Toutefois, sil est vident que lon ne va pas intgrer un gros bloc de traitement au milieu dun script daffichage, la mise en pratique de cette rgle est souvent bien illusoire. En effet, comme tout langage de programmation de pages web, PHP se situe la frontire entre le code et la mise en page. Par consquent, il nest pas rare que les instructions daffichage ne se bornent pas afficher une image par-ci et le contenu dune variable par-l. Plus frquemment, les informations afficher sont une liste dinformations (peut-tre issues dune base de donnes), chaque information pouvant avoir des attributs qui vont influencer la faon dont elle doit tre affiche (par exemple, sil sagit dune liste de noms de personnes, on pourra peut-tre vouloir afficher une petite icne indiquant sil sagit dun homme ou dune femme). Dans ce cas, invitablement, le script charg de laffichage devra contenir des instructions de boucle ainsi que des tests (pour avoir un affichage conditionnel selon les attributs). moins, videmment, que ce ne soit le script charg du traitement de linformation qui retourne du code HTML (et gre donc les problmes de mise en page). mon sens, la meilleure solution pour distinguer autant que possible le code de la mise en page consiste faire judicieusement appel des objets et fonctions stocks dans des scripts "bibliothques". Nous ne pouvons toutefois pas taire les autres solutions ( base de modles ou templates) proposes notamment au travers des bibliothques PHPLib et PEAR.

5. Les techniques de programmation

Utilisation des objets et de linstruction include


Le principe est simple : il suffit davoir un ou plusieurs scripts PHP ne contenant que des objets ou fonctions proposant des interfaces simples, et qui retourneront des donnes aisment manipulables par le ou les scripts chargs de la mise en page. On pourra ainsi imaginer avoir des mthodes comme :

MaBD->rechercheVisiteurs()
Exemple de fonction qui rechercherait une liste de visiteurs dans une base de donnes partir dun critre quelconque, et retournerait $nb valeurs partir de la $debut-ime.

307

Chapitre 5

Les techniques de programmation

Syntaxe retour

array rechercheVisiteurs(string $critere, int $debut, $nb) Tableau dobjet Visiteur, ou FALSE en cas dchec.

Le script charg de laffichage pourrait alors avoir lallure suivante :


<?php // Inclusion de toutes les bibliothques ncessaires require_once("bibliotheque1_inc.php"); // Initialisation de toutes les variables ncessaires $liste = MaBD::rechercheVisiteurs($critere, $debut, 10); ?> <html> <body> <table> <?php if ($liste) for ($i=0; $i<count($liste); $i++) { ?> <tr> <td> <?php if ($liste[$i]->sexe=="M") { echo "<img src=\"homme.gif\">"; } else { echo "<img src=\"femme.gif\">"; } ?> </td> <td><?php echo $liste[$i]->prenom; ?></td> <td><?php echo $liste[$i]->nom; ?></td> </tr> <?php } ?> </table> </body> </html>

5. Les techniques de programmation

Comme vous le voyez, nous sommes loin dun script quasiment exempt de code. Mais il ny a pas de miracle esprer ! Il est galement possible de faire appel aux possibilits offertes par les instructions include() et require() pour scinder une page complexe en plusieurs lments (fichiers) ddis un sous-ensemble de la page. Ainsi, de nombreux scripts sont conus selon le modle :
<?php include("entete_inc.php"); // Corps de la page include("pieddepage_inc.php"); ?>

308

Sparation du code et de la mise en page

dans lequel le fichier entete_inc.php (plus couramment appel header.php) contient gnralement le titre du site, le logo, et, ventuellement, des barres de menu horizontale et latrale gauche (chacun de ces lments pouvant aussi tre dans des fichiers distincts). Le fichier pieddepage_inc.php (plus couramment appel footer.php) contient, quant lui, lindication de copyright et, ventuellement, une barre de menu latrale droite. Lutilisation de ces techniques offre de nombreux avantages :
j j j

Elles sont trs simples mettre en uvre. Elles facilitent la rutilisation du code. Elles sont relativement satisfaisantes en terme de sparation des rles.

Utilisation des modles (templates)


Avec la bibliothque PHPLib
Installation
Vous devrez, dans un premier temps, vous procurer la bibliothque PHPLib sur le site Internet http://sourceforge.net/projects/phplib (elle se trouve galement sur le CD-ROM fourni). Il sagit simplement dun fichier phplib-7.4-pre1.tar.gz dcompresser dans le rpertoire de votre choix. Ce fichier contient juste une srie de scripts PHP (inutile donc de recompiler PHP). Pour utiliser cette bibliothque en toute libert, il suffit dajouter le rpertoire contenant la bibliothque au chemin de recherche spcifi par le paramtre include_path du fichier php.ini. Cela peut galement se faire en utilisant la fonction set_ini() (utilise comme suit : set_ini("include_path", $nouvelleValeurIncludePath);) au dbut de chaque script faisant appel la bibliothque PHPLib. Pour utiliser les modles, il suffira alors dinclure le script template.inc disponible dans le rpertoire php. Si vous navez pas modifi le contenu dinclude_path, peu importe, vous naurez qu prciser le chemin complet vers ce fichier lors de linclude.

5. Les techniques de programmation

Introduction
La sparation code/mise en page avec PHPLib prend un tout autre aspect. Le designer pourra crer des fichiers semblables des fichiers HTML classiques, dans lesquels il aura, en plus, intgr des mots-cls (entre accolades) ou dfini des blocs (par des commentaires HTML). Ces fichiers HTML seront alors traits par un script crit par le dveloppeur faisant appel la bibliothque PHPLib, afin de remplacer les mots-cls et les blocs par leurs valeurs. Exemple de fichier modle (cr par le designer) :

Listing 5.3 : modeles/phplib_01.tpl


<html> <head> <title>{TITRE}</title> </head>

309

Chapitre 5

Les techniques de programmation

<body> <h3>{TITRE}</h3> <table border="1"> <!-- BEGIN blocLigne --> <tr> <td>{SEXE}</td> <td>{PRENOM}</td> <td>{NOM}</td> </tr> <!-- END blocLigne --> </table> <center>{COPYRIGHT}</center> </body> </html>

Exemple de fichier de substitution mot-cl/code (cr par le dveloppeur) :

Listing 5.4 : phplib_01.php


<?php require_once("../phplib-7.4-pre1/php/template.inc");

5. Les techniques de programmation

// Instanciation dun objet Template // en prcisant que : // * les fichiers de modele // sont stocks dans le rpertoire modeles // * les mots cls non reconnus // seront conservs $modele = new Template("modeles", "keep"); // Associe un identifiant au fichier modle $modele->set_file("idModele", "phplib_01.tpl"); // Dfinit les valeurs associes aux mots cls $modele->set_var(array("TITRE" => "Modles avec PHPLib", "COPYRIGHT" => "Copyright 2002")); // Extrait du fichier identifi par "idModele" // le block nomm "blocLigne" et le remplace par // le mot cl "lignes" $modele->set_block("idModele", "blocLigne", "lignes"); // A titre dexemple // remplace les mots cls du bloc ligne // par diffrentes valeurs $modele->set_var(array("SEXE" => "<img src=\"homme.gif\">", "PRENOM" => "Pierre", "NOM" => "Dupond")); $modele->parse("lignes", "blocLigne", true); $modele->set_var(array("SEXE" => "<img src=\"femme.gif\">",

310

Sparation du code et de la mise en page

"PRENOM" => "Anne", "NOM" => "Durand")); $modele->parse("lignes", "blocLigne", true); $modele->set_var(array("SEXE" => "<img src=\"homme.gif\">", "PRENOM" => "Jean", "NOM" => "Bon")); $modele->parse("lignes", "blocLigne", true); // procde aux substitutions // et stocke le rsultat dans une variable // "resultat" $modele->parse("resultat", "idModele"); // affiche le rsultat $modele->p("resultat");

?>

Ceci affichera alors :


Figure 5.3 : Exemple dutilisation de modles avec PHPLib

5. Les techniques de programmation

Comme vous pouvez le constater, le designer na absolument pas besoin de connatre le langage PHP. En revanche, la tche du dveloppeur est sensiblement plus complexe (comme celle du serveur). Ce dernier doit apprendre un "nouveau langage", celui de la manipulation des modles.

La base
Lutilisation des modles PHPLib commence par linstanciation dun objet Template selon la syntaxe suivante :

Template
Objet modle de PHPLib. Syntaxe Template Template(string $repertoireModeles, string $modeErreur) Chane de caractres indiquant quel doit tre le comportement lorsque des mots-cls inconnus sont rencontrs. Cet argument doit prendre une des valeurs suivantes :

$repertoireModeles Rpertoire o sont situs les fichiers de modles. $modeErreur

311

Chapitre 5

Les techniques de programmation

"keep" si le mot-cl doit tre restitu dans le flux de sortie. "comment" si le mot-cl doit tre mis en commentaire dans le flux de sortie. "remove" (valeur par dfaut) si le mot-cl doit tre ignor (et ne pas paratre dans le flux de sortie). Toutes les manipulations venir sappuient sur des mots-cls (les chanes de caractres intgres au code HTML du modle, y compris les noms de blocs) et des noms de variables (ni plus ni moins des chanes de caractres reprsentant des portions du modle). Il nest pas rare que ces deux notions se confondent. Mme si, dans une utilisation "normale", cette mthode nest appele qu la fin du traitement, voici la mthode permettant dafficher le contenu dune variable. Dans notre cas, elle sera galement utilise pour dmontrer les proprits des diffrentes mthodes de lobjet Template.

Template->p()
Affiche le contenu de la variable indique. Cette fonction est gnralement utilise pour afficher le rsultat final.

5. Les techniques de programmation

Syntaxe $variable

void p(string $variable) Nom de la variable dont on veut afficher le contenu.

Lutilisation la plus "primitive" des modles consiste remplacer des mots-cls (en absence de blocs) par des valeurs. Cette opration seffectue en deux tapes : 1. 2. Dfinition des valeurs par lesquelles les mots-cls doivent tre remplacs. Remplacement proprement dit.

Template->set_var()
Donne une valeur un ou plusieurs mots-cls. Syntaxe Syntaxe $motCle $valeur void set_var(string $motCle, string valeur) void set_var(array $tableauAssociatif) Mot-cl auquel vous souhaitez donner une valeur. Valeur associe au mot-cl.

$tableauAssociatif Tableau associatif contenant autant de couples ($motCle => $valeur) que de valeurs dfinir.

312

Sparation du code et de la mise en page

Ainsi, la succession dappels :


$modele->set_var("TITRE", "Mon TITRE"); $modele->set_var("COPYRIGHT", "Copyright 2002");

sera avantageusement remplace par :


$modele->set_var(array("TITRE" => "Mon Titre", "COPYRIGHT" => "Copyright 2002"));

La substitution proprement dite des mots-cls par les valeurs seffectue via un appel la mthode parse().

Template->parse()
Remplace les mots-cls contenus dans une variable par leurs valeurs, et associe ou ajoute le rsultat un mot-cl. Syntaxe $motCle $variable $modeAjout void parse(string $motCle, $string $variable, boolean $modeAjout)

5. Les techniques de programmation

Mot-cl remplacer ou complter. Variable pour laquelle les mots-cls doivent tre remplacs par leurs valeurs. Mettre TRUE si le mot-cl doit tre complt, FALSE sil doit tre remplac.

Dans le premier cas que nous tudions, la variable devra reprsenter le fichier modle lui-mme (cest bien dans cet ensemble que les mots-cls doivent tre remplacs par des valeurs). Il faut donc associer, au pralable, un nom de variable au fichier modle. Pour cela, vous devez faire appel la mthode set_file().

Template->set_le()
Associe des noms de variables (raccourcis) des noms de fichiers. Syntaxe $variable $nomFichier void set_file(string $variable, string $nomFichier) Variable associe au nom de fichier. Nom du fichier.

La mthode set_file() propose galement linterface suivante :

313

Chapitre 5

Les techniques de programmation

Template->set_le()
Associe des noms de variables (raccourcis) des noms de fichiers. Syntaxe void set_file(array $tableauAssociatif) $tableauAssociatif Tableau associatif contenant autant de couples ($variable => $nomFichier) que didentifiants crer. Ce qui nous permet de raliser notre premier script de transformation de modles ; script que nous appliquerons au modle que nous avons vu prcdemment.

Listing 5.5 : phplib_02.php


<?php require_once("../phplib-7.4-pre1/php/template.inc"); // Instanciation dun objet Template // en prcisant que : // * les fichiers de modele // sont stocks dans le rpertoire modeles // * les mots cls non reconnus // seront conservs $modele = new Template("modeles", "keep");

5. Les techniques de programmation

// Dfinit les valeurs associes aux mots cls $modele->set_var(array("TITRE" => "Modles avec PHPLib", "COPYRIGHT" => "Copyright 2002")); // Associe un identifiant au fichier modle $modele->set_file("idModele", "phplib_01.tpl"); // Remplace les mots cls par leurs valeurs // et stocke le rsultat dans une variable // "resultat" $modele->parse("resultat", "idModele"); // affiche le rsultat ?> $modele->p("resultat");

Dans ce cas, nous aurons alors comme rsultat (au niveau du code HTML gnr) :

314

Sparation du code et de la mise en page

Figure 5.4 : Code HTML issu de lutilisation de modles avec PHPLib

Vous pouvez constater que les mots-cls ont bien t remplacs par leurs valeurs, sauf videmment ceux qui nont pas t traits par ce premier script, et qui appartiennent des blocs dont nous allons, ds maintenant, dtailler le fonctionnement.

Utilisation des blocs


Comme cela a t suggr en introduction de ce chapitre (dans lexemple), il est possible de dfinir des blocs de donnes. Les blocs sont dclars par des commentaires HTML contenant les instructions BEGIN et END.
<!-- BEGIN nomBloc --> <!-- END nomBloc -->

5. Les techniques de programmation

La premire opration lie la manipulation de ces blocs consiste, gnralement, appeler linstruction set_block().

Template->set_block()
Remplace, dans une variable (reprsentant gnralement un bloc), un bloc par un mot-cl et associe ce bloc la variable de mme nom. Syntaxe $variable $nomBloc $motCl void set_block(string $variable, string $nomBloc [, string $motCle]) Nom de la variable dans laquelle est recherch le bloc. Nom du bloc (i.e. mot-cl prcis dans le commentaire dfinissant le bloc). Mot-cl venant en remplacement du bloc. Si ce paramtre est omis, il prendra la mme valeur que $nomBloc.

Cest gnralement dans le cadre de lutilisation de blocs que le mode "ajout" de la mthode parse() prend tout son sens. Il est en effet alors possible de remplacer un (unique) mot-cl par une liste de valeurs. Voir le script phplib_01.php prsent en introduction de ce chapitre.

315

Chapitre 5

Les techniques de programmation

Diverses mthodes

Template->set_root()
Permet de modifier le chemin de recherche des modles. Syntaxe void set_root(string $repertoireModele) $repertoireModele Nouveau chemin de recherche des modles.

Template->set_unknowns()
Permet de modifier le comportement lorsque des variables inconnues sont rencontres. Syntaxe $modeErreur void set_unknowns(string $modeErreur) Chane de caractres indiquant le comportement tenir lorsque des mots-cls inconnus sont rencontrs. Cet argument doit prendre une des valeurs suivantes : "keep" si le mot-cl doit tre restitu dans le flux de sortie. "comment" si le mot-cl doit tre mis en commentaire dans le flux de sortie. "remove" (valeur par dfaut) si le mot-cl doit tre ignor (et ne pas paratre dans le flux de sortie).

5. Les techniques de programmation

Template->subst()
Retourne la variable indique pour laquelle les mots-cls connus ont t remplacs par leurs valeurs. Les mots-cls inconnus seront laisss inchangs (quel que soit le mode derreur slectionn). Syntaxe $variable string subst(string $variable) Nom de la variable retourner.

Template->psubst()
Affiche le rsultat que retourne subst().

316

Sparation du code et de la mise en page

Syntaxe $variable

string psubst(string $variable) Nom de la variable afficher.

Template->nish()
Retourne la variable indique pour laquelle les mots-cls connus ont t remplacs par leurs valeurs. Les mots-cls inconnus sont traits selon le mode derreur slectionn. Syntaxe $variable string finish(string $variable) Nom de la variable retourner.

Template->get_vars()
Retourne un tableau associatif des variables dfinies, les cls tant les noms des variables. Syntaxe retour array get_vars()

5. Les techniques de programmation

Le tableau association "nom de variable" => "valeur".

Template->get_undened()
Retourne un tableau (associatif) des mots-cls rencontrs nayant pas de valeurs associes. Syntaxe retour array get_undefined() Le tableau associatif "nom de variable" => "nom de variable".

haltMsg()
Il sagit cette fois dune fonction et non dune mthode appele accompagne dun message en cas derreur. Cette fonction peut tre rcrite par vos soins. Syntaxe $messageErreur void haltMsg(string $messageErreur) Message derreur.

317

Chapitre 5

Les techniques de programmation

Avec la bibliothque PEAR


Installation
Linstallation de la bibliothque PEAR ne ncessite quasiment aucun effort. En effet, celle-ci tant livre avec PHP, il suffit dajouter le rpertoire contenant la bibliothque (ex. : /usr/local/ lib/php par dfaut sous Linux) au chemin de recherche spcifi par le paramtre include_path du fichier php.ini. Cela peut galement se faire en utilisant la fonction set_ini() (utilise comme suit : set_ini("include_path", $nouvelleValeurIncludePath);) au dbut de chaque script faisant appel la bibliothque PEAR. Nous supposerons par la suite que vous avez intgr PEAR au chemin de recherche spcifi dans php.ini. Pour utiliser les modles, il suffira alors dinclure le script IT.php disponible dans le rpertoire HTML.

Utilisation
La bibliothque PEAR (livre avec PHP) propose quant elle une solution fort similaire celle propose par PHPLib. Lune delle, base sur la classe IntegratedTemplate ncessite toutefois moins de manipulations de variables, ce qui simplifie, entre autres, lutilisation des blocs.

5. Les techniques de programmation

Lexemple prsent en introduction de la bibliothque PHPLib devient alors : exemple de fichier modle (cr par le designer) :

Listing 5.6 : modeles/pear_01.tpl


<html> <head> <title>{TITRE}</title> </head> <body> <h3>{TITRE}</h3> <table border="1"> <!-- BEGIN blocLigne --> <tr> <td>{SEXE}</td> <td>{PRENOM}</td> <td>{NOM}</td> </tr> <!-- END blocLigne --> </table> </body> </html>

Exemple de fichier de substitution mot-cl/code (cr par le dveloppeur) :

318

Sparation du code et de la mise en page

Listing 5.7 : pear_01.php


<?php require_once("HTML/IT.php"); // Instanciation dun objet IntegratedTemplate // en prcisant que : // * les fichiers de modele // sont stocks dans le rpertoire "modeles" $modele = new IntegratedTemplate("modeles"); // Charge le fichier modele $modele->loadTemplateFile("pear_01.tpl"); // Defini les valeurs associes au mot cl $modele->setVariable("TITRE","Modles avec PEAR"); // Selectionne le bloc "blocLigne" // pour les prochaines manipulations $modele->setCurrentBlock("blocLigne"); // A titre dexemple // remplace les mots cls du bloc ligne // par diffrentes valeurs $modele->setVariable(array("SEXE" => "<img src=\"homme.gif\">", "PRENOM" => "Pierre", "NOM" => "Dupond")); $modele->parseCurrentBlock("blocLigne"); $modele->setVariable(array("SEXE" => "<img src=\"femme.gif\">", "PRENOM" => "Anne", "NOM" => "Durand")); $modele->parseCurrentBlock("blocLigne"); $modele->setVariable(array("SEXE" => "<img src=\"homme.gif\">", "PRENOM" => "Jean", "NOM" => "Bon")); $modele->parseCurrentBlock("blocLigne"); // affiche le rsultat $modele->show();

5. Les techniques de programmation

?>

La base
Lutilisation des modles PEAR/IntegratedTemplate commence par linstanciation dun objet IntegratedTemplate selon la syntaxe suivante :

319

Chapitre 5

Les techniques de programmation

IntegratedTemplate
Objet modle de PEAR/IntegratedTemplate. Syntaxe IntegratedTemplate IntegratedTemplate([string $repertoireModeles])

$repertoireModeles Rpertoire o sont situs les fichiers de modles. Toutes les manipulations venir sappuient sur des mots-cls ou noms de blocs intgrs au code HTML du modle, que lon pourra appeler "variable". Mme si, dans une utilisation normale, cette mthode nest appele qu la fin du traitement, voici la mthode permettant dafficher le contenu dune variable. Dans notre cas, elle sera galement utilise pour dmontrer les proprits des diffrentes mthodes de lobjet IntegratedTemplate.

IntegratedTemplate->show()
5. Les techniques de programmation
Affiche le contenu dune variable (bloc ou mot-cl) indique. Cette fonction est gnralement utilise sans paramtre pour afficher le rsultat final. Syntaxe $variable void show([string $variable]) Nom de la variable (bloc ou mot-cl) dont on veut afficher le contenu.

Le chargement dun modle se fait via la mthode setTemplate() ou plus probablement loadTemplateFile().

IntegratedTemplate->setTemplate
Charge un modle bas sur une simple chane de caractres. Syntaxe $modele boolean setTemplate(string $modele [, boolean $supprimeVariablesInconnues [, boolean $supprimeBlocsVides]])) Le modle.

$supprimeVariables Inconnues TRUE (par dfaut) si vous souhaitez que les variables (mot-cls) non dfinis soient supprims (en sortie), FALSE sinon. $supprimeBlocsVides TRUE (par dfaut) si vous souhaitez que les blocs vides soient supprims (en sortie), FALSE sinon. retour TRUE en cas de succs, FALSE sinon.

320

Sparation du code et de la mise en page

IntegratedTemplate->loadTemplateFile()
Charge un modle stock dans un fichier. Syntaxe $nomFichier boolean loadTemplateFile(string $nomFichier [, boolean $supprimeVariablesInconnues [, boolean $supprimeBlocsVides]]) Nom du fichier modle.

$supprime VariablesInconnues TRUE (par dfaut) si vous souhaitez que les variables (mots-cls) non dfinies soient supprimes (en sortie), FALSE sinon. $supprimeBlocsVides TRUE (par dfaut) si vous souhaitez que les blocs vides soient supprims (en sortie), FALSE sinon. retour TRUE en cas de succs, FALSE sinon.

Lutilisation la plus "primitive" des modles consiste remplacer des mots-cls (ventuellement contenus dans un bloc) par des valeurs. Cette opration seffectue en trois tapes : 1. 2. 3. Slection du bloc ;

5. Les techniques de programmation

Dfinition des valeurs par lesquelles les mots-cls doivent tre remplacs ; Remplacement proprement dit.

La slection du bloc se fait naturellement par un appel la mthode setCurrentBloc().

IntegratedTemplate->setCurrentBloc()
Slectionne un bloc pour les manipulations venir. Syntaxe $bloc void setCurrentBloc([string $bloc]) Nom du bloc. Si ce paramtre est omis, cest alors le modle complet qui devient le bloc courant.

IntegratedTemplate->setVariable()
Donne une valeur un ou plusieurs mots-cls. Syntaxe Syntaxe $motCle $valeur void setVariable(string $motCle, string valeur) void setVariable(array $tableauAssociatif) Mot-cl auquel vous souhaitez donner une valeur. Valeur associe au mot-cl.

321

Chapitre 5

Les techniques de programmation

$tableauAssociatif Tableau associatif contenant autant de couples ($motCle => $valeur) que de valeurs dfinir. Ainsi, la succession dappels :
$modele->setVariable("TITRE", "Mon TITRE"); $modele->setVariable("COPYRIGHT", "Copyright 2002");

sera avantageusement remplace par :


$modele->setVariable(array("TITRE" => "Mon Titre", "COPYRIGHT" => "Copyright 2002"));

La substitution proprement dite des mots-cls par leurs valeurs seffectue via un appel la mthode parseCurrentBlock().

IntegratedTemplate->parseCurrentBlock()
Remplace les mots-cls contenus dans le bloc courant par leurs valeurs.

5. Les techniques de programmation

Syntaxe retour

boolean parseCurrentBlock(void) TRUE en cas de succs, FALSE sinon.

Diverses mthodes

IntegratedTemplate->setRoot()
Permet de modifier le chemin de recherche des modles. Syntaxe void setRoot(string $repertoireModele) $repertoireModele Nouveau chemin de recherche des modles.

IntegratedTemplate->parse()
Remplace les mots-cls contenus dans une variable par leurs valeurs. Syntaxe $variable $modeRecursif retour boolean parse([string $variable] [, boolean $modeRecursif]) Variable contenant les mots-cls remplacer. Par dfaut, le modle complet. ignorer, au moins pour linstant. TRUE en cas de succs, FALSE sinon.

322

Sparation du code et de la mise en page

IntegratedTemplate->get()
Retourne le contenu dune variable pour laquelle les mots-cls ont t remplacs par leurs valeurs. Syntaxe $variable retour string get([string $variable]) Variable dont on veut retourner le contenu. Si ce paramtre est omis, cest tout le modle qui est retourn. Contenu de la variable (ou bloc).

IntegratedTemplate->touchBlock()
Empche la suppression dun bloc vide, mme si loption a t positionne. Syntaxe $bloc boolean touchBlock(string $bloc) Bloc conserver.

5. Les techniques de programmation 323

Chapitre 6

Les fonctions mathmatiques


6.1 6.2 Les fonctions mathmatiques et les constantes . . . . . . . . . . . . . . . . . . . . . . 327 Calculs de prcision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348

Les fonctions mathmatiques et les constantes

C
6.1.

ette partie traite du calcul mathmatique. Mme si vous serez souvent amen utiliser ces fonctions pour des oprations lmentaires, sachez quil est galement possible deffectuer des calculs de prcision.

Les fonctions mathmatiques et les constantes

La bibliothque mathmatique fournit des constantes et des fonctions qui vous serviront si vous souhaitez faire du calcul. Attention cependant : pour la gestion des grands nombres ou des nombres devant comporter de nombreuses dcimales, vrifiez que les valeurs que vous manipulez peuvent tre gres soit par les entiers (integer entre -2147483648 et 2147483647) soit par les rels (double ; et respectivement long et double en C). Dans le cas contraire, vous devrez faire appel aux calculs de prcision qui feront lobjet du chapitre suivant.

Constantes
La bibliothque mathmatique met disposition dix-sept constantes utiles pour les calculs mathmatiques.

Tableau 6.1 : Les constantes


Constante M_SQRT2 M_SQRT3 M_SQRT1_2 Trigonomtrie M_PI M_PI_2 M_PI_4 M_1_PI M_2_PI M_SQRTPI M_2_SQRTPI Logarithme M_E M_LOG2E M_LOG10E M_LN2 M_LN10 M_LNPI 2.7182818284590452354 1.4426950408889634074 0.43429448190325182765 0.69314718055994530942 2.30258509299404568402 1.14472988584940017414 E Logarithme binaire de e Logarithme dcimal de e Logarithme nprien de 2 Logarithme nprien de 10 Logarithme nprien de Pi (PHP4.0.2 et +) 3.14159265358979323846 1.57079632679489661923 0.78539816339744830962 0.31830988618379067154 0.63661977236758134308 1.77245385090551602729 1.12837916709551257390 Pi Pi/2 Pi/4 1/Pi 2/Pi Racine carre de Pi (PHP4.0.2 et +) 2 sur racine carre de Pi (PHP4.0.2 et +) Valeur 1.41421356237309504880 1.73205080756887729352 0.70710678118654752440 Description Racine carre de 2 (PHP4.0.2 et +) Racine carre de 3 (PHP4.0.2 et +) 1 sur racine carre de 2 ou encore racine carre de 2 sur 2 (PHP4.0.2 et +)

6. Les fonctions mathmatiques 327

Chapitre 6

Les fonctions mathmatiques

Constante Autre M_EULER

Valeur 0.57721566490153286061

Description Constante dEuler (PHP4.0.2 et +)

Fonctions
Test de validit
PHP propose quelques fonctions permettant de dterminer si une valeur (retourne par une fonction) est finie, infinie (cas dune division par 0) ou indfinie (cas dune racine carr de -1). Vous disposez ainsi de :

is_nite()
Indique si une valeur est finie ou non. Syntaxe $valeur retour boolean is_finite(double $valeur) Valeur tester. TRUE si la valeur est finie, FALSE sinon.

6. Les fonctions mathmatiques

is_innite()
Teste si une valeur est infinie. Syntaxe $valeur retour boolean is_infinite($valeur) Valeur tester. TRUE si la valeur est infinie, FALSE sinon.

is_nan()
Teste si une valeur est indfinie. Syntaxe $valeur retour boolean is_nan($valeur) Valeur tester. TRUE si la valeur est indfinie, FALSE sinon.

328

Les fonctions mathmatiques et les constantes

Listing 6.1 : is_xxx.php


<?php if (is_finite(3)) echo "3 est fini<br />"; else echo "3 nest pas fini<br />"; if (is_finite(pow(0,-1))) echo "1/0 est fini<br />"; else echo "1/0 nest pas fini<br />"; if (is_finite(sqrt(-1))) echo "racine carre de -1 est fini<br />"; else echo "racine carre de -1 nest pas fini<br />"; if (is_infinite(3)) echo "3 est infini<br />"; else echo "3 nest pas infini<br />"; if (is_infinite(pow(0,-1))) echo "1/0 est infini<br />"; else echo "1/0 nest pas infini<br />"; if (is_infinite(sqrt(-1))) echo "racine carre de -1 est infini<br />"; else echo "racine carre de -1 nest pas infini<br />"; if (is_nan(3)) echo "3 est indfini<br />"; else echo "3 nest pas indfini<br />"; if (is_nan(pow(0,-1))) echo "1/0 est indfini<br />"; else echo "1/0 nest pas indfini<br />"; if (is_nan(sqrt(-1))) echo "racine carre de -1 est indfini<br />"; else echo "racine carre de -1 nest pas indfini<br />"; ?>

Cela retournera :
3 est fini 1/0 nest pas fini racine carre de -1 nest pas fini 3 nest pas infini 1/0 est infini racine carre de -1 nest pas infini 3 nest pas indfini 1/0 nest pas indfini racine carre de -1 est indfini

6. Les fonctions mathmatiques

Avec les oprateurs Dans les versions actuelles de PHP, cela ne sapplique quaux valeurs retournes par les fonctions et non par les oprateurs. Ainsi 1/0 retournera FALSE accompagn dun message derreur, or FALSE converti en entier donne 0, qui est fini. Vous aurez donc la surprise de constater que is_finite(1/0) retourne TRUE et non FALSE comme attendu.

329

Chapitre 6

Les fonctions mathmatiques

Trigonomtriques

pi()
Cette fonction retourne une valeur approximative de Pi. 3.1415926535898 (revient utiliser M_PI). Syntaxe retour double pi(void) Valeur approximative de Pi.

cos()
Retourne la valeur du cosinus de langle exprim en radians. Syntaxe $angle retour double cos(double $angle) Angle exprim en radians. Cosinus de langle.

acos()
6. Les fonctions mathmatiques
Retourne larc cosinus de la valeur donne (larc cosinus tant langle pour lequel le cosinus vaut $cos). Syntaxe $cos retour double acos(double $cos) Valeur sans unit. Angle en radians.

Voici un exemple de script utilisant les fonctions cos(), acos() et pi(), ainsi que les constantes M_PI et M_SQRT1_2 :
<?php echo echo echo echo echo echo echo echo echo echo ?> "cos(M_PI):".cos(M_PI)."<br />"; "cos(pi()):".cos(pi())."<br />"; "cos(M_PI/2):".cos(M_PI/2)."<br />"; "cos(3*M_PI/2):".cos(3*M_PI/2)."<br />"; "cos(M_PI/4):".cos(M_PI/4)."<br />"; "cos(3*M_PI/4):".cos(3*M_PI/4)."<br />"; "cos(-M_PI/4):".cos(-M_PI/4)."<br />"; "cos(-3*M_PI/4):".cos(-3*M_PI/4)."<br />"; "acos(M_SQRT1_2):".acos(M_SQRT1_2)."<br />"; "acos(-M_SQRT1_2):".(-M_SQRT1_2)."<br />";

330

Les fonctions mathmatiques et les constantes

Voici le rsultat obtenu :


cos(M_PI):-1 cos(pi()):-1 cos(M_PI/2):6.1230317691119E-017 cos(3*M_PI/2):-1.8369095307336E-016 cos(M_PI/4):0.70710678118655 cos(3*M_PI/4):-0.70710678118655 cos(-M_PI/4):0.70710678118655 cos(-3*M_PI/4):-0.70710678118655 acos(M_SQRT1_2):0.78539816339745 acos(-M_SQRT1_2):-0.78539816339745
M_PI et pi() retournent tous les deux la mme valeur. Les valeurs de cos(Pi/2) et cos(3*Pi/ 2) retournent un rsultat proche de 0, mais pas 0. En effet, la valeur de Pi tant approximative,

celle du cosinus est affecte.


Cos(Pi/4) et cos(Pi/4) retournent la moiti de la racine carre de 2. Cos(3*Pi/4) et cos(-3*Pi/4) sont opposs comme prvu. acos(racine carre de 2 sur 2) retourne Pi/4 et acos(-racine carre de 2 sur 2) retourne Pi/4.

sin()
Retourne la valeur du sinus de langle exprim en radians. Syntaxe $angle retour double sin(double $angle) Angle en radians. Sinus de langle.

6. Les fonctions mathmatiques

asin()
Retourne larc sinus de la valeur donne (larc cosinus tant langle pour lequel le sinus vaut $sin). Syntaxe $sin retour double asin(double $sin) Valeur sans unit. Angle en radians.

tan()
Retourne la valeur de la tangente de langle exprime en radians. Syntaxe $angle retour double tan(double $angle) Angle en radians. Tangente de langle.

331

Chapitre 6

Les fonctions mathmatiques

atan()
Retourne larc tangente de la valeur donne (larc tangente tant langle pour lequel la tangente vaut $tan). Syntaxe $tan retour double atan(double $tan) Valeur sans unit. Angle en radians compris entre PI/2 et PI/2.

atan2()
Retourne larc tangente de $sin/$cos en tenant compte de leurs signes afin de dterminer de faon plus prcise langle. Syntaxe $sin $cos retour double atan2(double $sin, double $cos) Valeur sans unit. Valeur sans unit. Angle en radians compris entre PI et PI inclus. [PI;PI].

6. Les fonctions mathmatiques

deg2rad()
Retourne en radians un angle exprim en degrs. Syntaxe $angle retour double deg2rad(double $angle) Angle en degrs. Angle en radians.

rad2deg()
Retourne en degrs un angle exprim en radians. Syntaxe $angle retour double rad2deg(double $angle) Angle en radians. Angle en degrs.

332

Les fonctions mathmatiques et les constantes

Logarithmiques

exp()
Retourne lexponentiel de la valeur donne. Syntaxe $reel retour double exp(double $reel) Valeur relle. Exponentiel $reel.

log()
Retourne le logarithme nprien de la valeur donne. Syntaxe $reel retour double log(double $reel) Valeur relle dont on veut connatre le logarithme nprien. Valeur relle du logarithme nprien de $reel.

log10()
Retourne le logarithme dcimal. Syntaxe $reel retour double log10(double $reel) Valeur relle dont on veut connatre le logarithme dcimal. Logarithme dcimal de $reel.

6. Les fonctions mathmatiques

cosh()
Retourne la valeur du cosinus hyperbolique de langle, autrement dit (exp($angle) + exp($angle))/2. Syntaxe $angle retour double cosh(double $angle) Angle hyperbolique. Cosinus hyperbolique de langle.

333

Chapitre 6

Les fonctions mathmatiques

acosh()
Retourne larc cosinus hyperbolique de la valeur donne (larc cosinus hyperbolique tant langle pour lequel le cosinus hyperbolique vaut $cosh). Syntaxe $cosh retour double acosh(double $cosh) Valeur sans unit. Angle hyperbolique.

sinh()
Retourne la valeur du sinus hyperbolique de langle, autrement dit (exp($angle) exp($angle))/2. Syntaxe $angle retour double sinh(double $angle) Angle hyperbolique. Sinus hyperbolique de langle.

asinh()
6. Les fonctions mathmatiques
Retourne larc sinus hyperbolique de la valeur donne (larc sinus hyperbolique tant langle hyperbolique pour lequel le sinus hyperbolique vaut $sinh). Syntaxe $sinh retour double asinh(double $sinh) Valeur sans unit. Angle hyperbolique.

tanh()
Retourne la valeur de la tangente hyperbolique de langle. Syntaxe $angle retour double tanh(double $angle) Angle hyperbolique. Tangente hyperbolique de langle.

334

Les fonctions mathmatiques et les constantes

atanh() (non disponible sous Windows)


Retourne larc tangente hyperbolique de langle donn (larc tangente hyperbolique tant langle hyperbolique pour lequel la tangente hyperbolique vaut $tanh). Syntaxe $tanh retour double atanh(double $tanh) Valeur sans unit. Angle hyperbolique.

Puissance

pow()
Cette fonction retourne $base la puissance $exposant. Syntaxe $base $exposant retour numeric pow(numeric $base, numeric $exposant) Nombre lever. Puissance. Entier si possible, sinon rel pouvant valoir NAN si la puissance ne peut tre calcule (ex. : racine carre dun nombre ngatif).

Voici un exemple dutilisation de la fonction pow() :

6. Les fonctions mathmatiques

Listing 6.2 : pow.php


<?php // exemple simple: 2^3 echo pow(2, 3); echo "<br />"; // exemple simple: (-1)^10 echo pow(-1, 10); echo "<br />"; // exemple derreur: racine de -4 echo pow(-4, 0.5); ?>

(-4)^0.5

En sortie, on obtiendra :
8 1 NAN

335

Chapitre 6

Les fonctions mathmatiques

sqrt()
Cette fonction retourne la racine carre de la valeur entre en paramtre. Syntaxe $reel retour double sqrt(double $reel) Valeur dont on veut connatre la racine carre. Racine carre de $reel.

Voici un exemple dutilisation de la fonction sqrt() :

Listing 6.3 : sqrt.php


<?php echo echo echo echo ?> sqrt(4)."<br />"; sqrt(9)."<br />"; sqrt(5)."<br />"; sqrt(-3)."<br />";

En sortie, on obtiendra :
2 3 2.2360679774998 NAN

6. Les fonctions mathmatiques

Distance entre deux points Pour calculer la distance entre le point A de coordonnes (x1,y1) et B de coordonnes (x2,y2), il suffit de faire sqrt(pow(x2x1,2)+pow(y2y1,2)).

Arrondi

ceil()
Arrondit lentier suprieur. Cette fonction retourne lentier directement suprieur. Lentier retourn est malgr tout considr de type double, car ce type permet de traiter des nombres plus grands que les int. Syntaxe $reel retour double ceil(double $reel) Valeur arrondir. Valeur arrondie mais de type rel.

336

Les fonctions mathmatiques et les constantes

Voici un exemple dutilisation de la fonction ceil() :

Listing 6.4 : ceil.php


<?php echo echo echo echo echo echo echo echo echo echo ?> ceil(3.0)."<br ceil(3.1)."<br ceil(3.2)."<br ceil(3.3)."<br ceil(3.4)."<br ceil(3.5)."<br ceil(3.6)."<br ceil(3.7)."<br ceil(3.8)."<br ceil(3.9)."<br />"; />"; />"; />"; />"; />"; />"; />"; />"; />";

En sortie, on obtiendra :
3 4 4 4 4 4 4 4 4 4

6. Les fonctions mathmatiques

oor()
Arrondit lentier infrieur. Cette fonction retourne lentier directement infrieur. Lentier retourn est malgr tout considr de type double, car ce type permet de traiter des nombres plus grands que les int. Syntaxe $reel retour double floor(double $reel) Valeur arrondir. Valeur arrondie mais de type rel.

Voici un exemple dutilisation de la fonction floor() :

Listing 6.5 : floor.php


<?php echo floor (3.0)."<br />"; echo floor (3.1)."<br />"; echo floor (3.2)."<br />";

337

Chapitre 6

Les fonctions mathmatiques

echo echo echo echo echo echo echo ?>

floor floor floor floor floor floor floor

(3.3)."<br (3.4)."<br (3.5)."<br (3.6)."<br (3.7)."<br (3.8)."<br (3.9)."<br

/>"; />"; />"; />"; />"; />"; />";

En sortie, on obtiendra :
3 3 3 3 3 3 3 3 3 3

round()
Arrondit selon les rgles dusage en mathmatiques.

6. Les fonctions mathmatiques

Sil ny a quun argument, cette fonction retourne lentier le plus proche. Sil y a deux arguments elle retourne la valeur arrondie selon la prcision donne en second argument. Syntaxe $reel $precision retour double round(double $reel [, int $precision]) Valeur arrondir. Prcision souhaite (nombre de chiffres aprs la virgule). Nombre arrondi selon la prcision dsire.

Voici un exemple dutilisation de la fonction round() :

Listing 6.6 : round.php


<?php echo echo echo echo echo echo echo echo echo echo round round round round round round round round round round (3.0)."<br (3.1)."<br (3.2)."<br (3.3)."<br (3.4)."<br (3.5)."<br (3.6)."<br (3.7)."<br (3.8)."<br (3.9)."<br />"; />"; />"; />"; />"; />"; />"; />"; />"; />";

338

Les fonctions mathmatiques et les constantes

echo echo echo echo echo echo echo echo echo ?>

round round round round round round round round round

(3.123456789,1)."<br (3.123456789,2)."<br (3.123456789,3)."<br (3.123456789,4)."<br (3.123456789,5)."<br (3.123456789,6)."<br (3.123456789,7)."<br (3.123456789,8)."<br (3.123456789,9)."<br

/>"; />"; />"; />"; />"; />"; />"; />"; />";

En sortie, on obtiendra :
3 3 3 3 3 4 4 4 4 4 3.1 3.12 3.123 3.1235 3.12346 3.123457 3.1234568 3.12345679 3.123456789

6. Les fonctions mathmatiques

En effet, quand le chiffre de rang infrieur est suprieur ou gal cinq, la rgle est darrondir au chiffre suprieur.

Hasard
Nombre pseudo-alatoire Lordinateur ne connat pas le hasard. Mais, comme il est parfois utile de gnrer un nombre alatoirement, il a fallu trouver une astuce pour faire comme si lordinateur en tait capable. Pour arriver ce rsultat, il a fallu gnrer une suite (la plus longue possible) de nombres rpondant des critres statistiques prcis. Lorsque lon a besoin dun nombre alatoire, le systme va piocher un nombre dans cette liste (le suivant dans la liste). Mais, si lon ny prend garde, aprs chaque redmarrage du logiciel, le nombre retourn risque dtre toujours le premier lment de la liste. Pour pallier ce problme, il faudrait donc choisir alatoirement (on se mord la queue) lendroit o commencer dans la liste. Pour choisir de faon plus ou moins alatoire

339

Chapitre 6

Les fonctions mathmatiques

cet endroit, il est gnralement fait appel lheure (les microsecondes). Comme tout ceci nest pas proprement parler du hasard, il est plus rigoureux de parler de nombre pseudo-alatoire que de nombre alatoire.
PHP propose deux types de fonctions : les classiques et les fonctions prfixes par mt_ (utilisant un autre algorithme).

Fonctions "classiques"

srand()
Initialise les gnrateurs de nombres alatoires. Attention de ne pas utiliser cette fonction avant tous les appels dans une boucle par exemple. Il est prfrable de ne lutiliser quune fois avant la gnration de plusieurs valeurs alatoires. Syntaxe $seed void srand([int $seed]) Une valeur quelconque qui doit changer dune fois sur lautre. On a pour habitude de prendre le nombre de microsecondes depuis la dernire seconde entire. srand((double)microtime()*1000000).

rand()
6. Les fonctions mathmatiques
Gnrateur de nombres alatoires. Sans arguments, elle renvoie un nombre entre 0 et la valeur maximale que peut retourner la fonction (i.e. getRandMax()). Sinon, elle renvoie un nombre compris entre les deux valeurs (incluses) fournies. Depuis PHP 4.2.0, il nest plus ncessaire de faire appel au pralable srand(), puisque cet appel est effectu automatiquement sil na pas dj eu lieu. Syntaxe $min $max retour int rand([int $min, int $max]) Plus petite valeur que doit retourner la fonction. Plus grande valeur que doit retourner la fonction. Un entier entre minimum et maximum inclus.

getRandMax()
Retourne la plus grande valeur pouvant tre atteinte par la fonction rand(). Syntaxe retour int getRandMax(void) Plus grande valeur que peut retourner la fonction rand().

340

Les fonctions mathmatiques et les constantes

Voici un exemple utilisant les fonctions getRandMax(), srand() et rand().

Listing 6.7 : rand.php


<?php echo "getRandMax()=".getRandMax()."<br />"; srand((double)microtime()*1000000); echo rand()."<br />"; echo rand()."<br />"; echo rand()."<br />"; echo rand()."<br />"; echo rand(0, 2)."<br />"; echo rand(0, 2)."<br />"; echo rand(0, 2)."<br />"; echo rand(0, 2)."<br />"; echo rand(0, 2)."<br />"; echo rand(0, 2)."<br />"; echo rand(0, 2)."<br />"; echo rand(0, 2)."<br />"; ?>

Le rsultat obtenu est le suivant (bien entendu, part la premire ligne, il varie dune excution lautre) :
getRandMax()=32767 1282 31943 31613 7866 0 1 2 0 2 1 0 2

6. Les fonctions mathmatiques

Fonctions "mt"

mt_srand()
Initialise le gnrateur de nombres alatoires. Attention de ne pas utiliser cette fonction avant tous les appels dans une boucle par exemple. Il est prfrable de ne lutiliser quune fois avant la gnration de plusieurs valeurs alatoires. Syntaxe $seed void mt_srand([int $seed]) Valeur quelconque qui doit changer dune fois sur lautre. On a pour habitude de prendre le nombre de microsecondes depuis la dernire seconde entire. mt_srand((double)microtime()*1000000).

341

Chapitre 6

Les fonctions mathmatiques

mt_rand()
Gnrateur de nombres alatoires.
mt_rand est une alternative la fonction rand. Elle est bien plus rapide (environ quatre fois)

et utilise la mthode de Mersenne Twister. Sans arguments, elle renvoie un nombre entre 0 et la valeur maximale que peut retourner la fonction (i.e. mt_getRandMax()). Sinon, elle renvoie un nombre compris entre les deux valeurs fournies incluses. Depuis PHP 4.2.0, il nest plus ncessaire de faire appel au pralable mt_srand(), puisque cet appel est effectu automatiquement sil na pas dj eu lieu. Syntaxe $min $max retour int mt_rand([int $min, int $max]) Plus petite valeur que doit retourner la fonction. Plus grande valeur que doit retourner la fonction. Entier entre minimum et maximum inclus.

mt_getRandMax()
Retourne la plus grande valeur pouvant tre atteinte par la fonction mt_rand(). Syntaxe int mt_getRandMax(void) Plus grande valeur que peut retourner mt_rand(). retour

6. Les fonctions mathmatiques

Voici un exemple utilisant les fonctions mt_getRandMax(), mt_srand() et mt_rand() :

Listing 6.8 : mt_rand.php


<?php echo "mt_getRandMax()=".mt_getRandMax()."<br />"; mt_srand((double)microtime()*1000000); echo mt_rand()."<br />"; echo mt_rand()."<br />"; echo mt_rand()."<br />"; echo mt_rand()."<br />"; echo mt_rand(0,2)."<br />"; echo mt_rand(0,2)."<br />"; echo mt_rand(0,2)."<br />"; echo mt_rand(0,2)."<br />"; echo mt_rand(0,2)."<br />"; echo mt_rand(0,2)."<br />"; echo mt_rand(0,2)."<br />"; echo mt_rand(0,2)."<br />"; ?>

342

Les fonctions mathmatiques et les constantes

Le rsultat obtenu est le suivant (bien entendu, part la premire ligne, il varie dune excution lautre).
mt_getRandMax()=2147483647 617390894 505571108 175954693 741777589 2 0 1 1 2 0 2 0

Autres

lcg_value()
Gnrateur de congruence combine linaire. Cette fonction retourne un nombre pseudo-alatoire compris entre 0 et 1. Elle combine deux nombres de priode 2^31-85 et 2^31-249. La priode de cette fonction est gale au produit de ces deux nombres premiers soit (2^31-85)*(2^31-249). Syntaxe retour double lcg_value() Rel pseudo-alatoire compris entre 0 et 1.

6. Les fonctions mathmatiques

Voici un exemple utilisant la fonction lcg_value() :

Listing 6.9 : lcg.php


<?php echo(lcg_value()."<br />"); echo(lcg_value()."<br />"); echo(lcg_value()."<br />"); echo(lcg_value()."<br />"); echo(lcg_value()."<br />"); echo(lcg_value()."<br />"); $a = 3; $b = 7; // Voici une formule pour obtenir un nombre echo(floor($a + lcg_value()*($b-$a+1))."<br echo(floor($a + lcg_value()*($b-$a+1))."<br echo(floor($a + lcg_value()*($b-$a+1))."<br echo(floor($a + lcg_value()*($b-$a+1))."<br ?>

entre $a et $b inclus />"); />"); />"); />");

343

Chapitre 6

Les fonctions mathmatiques

Voici le rsultat retourn :


0.30513436806404 0.068577150355096 0.57782412638032 0.9158474922213 0.0046724566600712 0.1675198682609 7 3 4 6

Conversion de bases

base_convert()
Retourne un nombre converti dune base dans une autre. Syntaxe $nombre $depuisBase $versBase retour string base_convert(string $nombre, int $depuisBase, int $versBase) Nombre convertir crit en base $depuisBase. Base dorigine entre 2 et 36. Base darrive entre 2 et 36. Nombre en base $versBase.

6. Les fonctions mathmatiques

binDec()
Retourne la conversion dun nombre binaire infrieur 2147483647 (31 bits 1) en nombre de base 10 (dcimal). Syntaxe $binaire retour int binDec(string $binaire) Nombre binaire de moins de 32 bits. Nombre en base 10.

decBin()
Retourne la conversion dun nombre dcimal (i.e. base 10) infrieur 2147483647 (31 bits 1) en nombre de base 2 (binaire). Syntaxe $decimal retour string decBin(int $decimal) Nombre dcimal (i.e. base 10) infrieur 2147483647. Nombre en base 2.

344

Les fonctions mathmatiques et les constantes

decHex()
Retourne la conversion dun nombre dcimal (i.e. base 10) infrieur 2147483647 (31 bits 1 ou encore 7FFFFFFF en hexadcimal) en nombre de base 16. Syntaxe $decimal retour string decHex(int $decimal) Nombre dcimal (i.e. base 10) infrieur 2147483647. Nombre en base 16.

hexDec()
Retourne la conversion dun nombre hexadcimal infrieur 7FFFFFFF (31 bits 1 ou encore 2147483647 en dcimal) en nombre dcimal (i.e. base 10). Syntaxe $hexadecimal retour int hexDec(string $hexadecimal) Nombre dcimal infrieur 7FFFFFFF. Nombre dcimal (i.e. base 10).

decOct()
6. Les fonctions mathmatiques
Retourne la conversion dun nombre dcimal (i.e. base 10) infrieur 2147483647 (31 bits 1 ou encore 17777777777 en octal) en nombre de base 8. Syntaxe $decimal retour string decOct(int $decimal) Nombre dcimal (i.e. base 10) infrieur 2147483647. Nombre en base 8.

octDec()
Retourne la conversion dun nombre octal infrieur 17777777777 (31 bits 1 ou encore 2147483647 en dcimal) en nombre dcimal (i.e. base 10). Syntaxe $octal retour int octDec(string $octal) Nombre octal infrieur 17777777777. Nombre dcimal (i.e. base 10).

345

Chapitre 6

Les fonctions mathmatiques

Voici un exemple utilisant toutes ces fonctions de conversion de bases.

Listing 6.10 : bases.php


<?php echo echo echo echo echo echo echo echo echo ?> base_convert("28", 10, 2)."<br />"; // 11100 base_convert("28", 10, 8)."<br />"; // 34 base_convert("28", 10, 16)."<br />"; // 1c decBin(28)."<br />"; // 11100 binDec("11100")."<br />"; // 28 decOct(28)."<br />"; // 34 octDec("34")."<br />"; // 28 decHex(28)."<br />"; // 1c hexDec("1c")."<br />"; // 28

Et le rsultat retourn est :


11100 34 1c 11100 28 34 28 1c 28

6. Les fonctions mathmatiques

Autres

abs()
Cette fonction retourne la valeur absolue de largument. Si largument est un rel, la valeur retourne est un rel ; sinon, cest un entier. Syntaxe $nombre retour mixed abs(mixed $nombre) Valeur relle ou entire. Valeur absolue du nombre.

max()
Retourne le plus grand lment. Syntaxe $arg1 mixed max(mixed $arg1 [, mixed $arg2, ...[, mixed $argn]]) Un tableau, une chane de caractres, un rel ou un entier.

346

Les fonctions mathmatiques et les constantes

$arg2 $argn retour

Une chane de caractres, un rel ou un entier si $arg1 nest pas un tableau. Une chane de caractres, un rel ou un entier si $arg1 nest pas un tableau. Le plus grand lment du tableau si largument est un tableau. Si tous les arguments sont de type string, la valeur retourne est la dernire valeur par rapport lordre alphabtique. Si tous les arguments numriques sont de type int, cest un entier qui est retourn ; sinon cest un rel.

min()
Retourne le plus petit lment. Syntaxe $arg1 $arg2 $argn retour mixed min(mixed $arg1 [, mixed $arg2, ... [, mixed $argn]) Un tableau, une chane de caractres, un rel ou un entier. Une chane de caractres, un rel ou un entier si $arg1 nest pas un tableau. Une chane de caractres, un rel ou un entier si $arg1 nest pas un tableau. Le plus petit lment du tableau si largument est un tableau. Si tous les arguments sont de type string, la valeur retourne est la premire valeur par rapport lordre alphabtique. Si tous les arguments numriques sont de type int, cest un entier qui est retourn ; sinon cest un rel.

6. Les fonctions mathmatiques

number_format()
Formate un nombre. Cette fonction prend un, deux ou quatre paramtres. Sil ny a quun paramtre, il sera format sans dcimal et avec une virgule sparant les milliers. Sil y a deux paramtres, le deuxime argument est le nombre de dcimales afficher. Elles sont alors spares par une virgule. Sil y a quatre paramtres, les deux premiers sont les mmes que dans le cas de deux paramtres, les suivants sont les sparateurs de dcimales et de milliers. Syntaxe $nombre $decimales $delimiteur $milliers retour string number_format(double $nombre [, int $decimales [, string $delimiteur , string $milliers]]) Nombre formater. Nombre de dcimales afficher. Sparateur de dcimales (, en franais, . en anglais). Sparateur de milliers ( en franais, , en anglais). Chane de caractres du nombre format.

347

Chapitre 6

Les fonctions mathmatiques

Voici un exemple dutilisation de la fonction number_format() :

Listing 6.11 : numberf.php


<?php $number = 123456789.12345; // exemple avec un seul argument echo number_format($number); echo "<br />"; // exemple avec deux arguments echo number_format($number, 3); echo "<br />"; // exemple de notation anglaise avec 4 arguments echo number_format($number, 3, ., ,); echo "<br />"; // exemple de notation franaise avec 4 arguments echo number_format($number, 3, ,, ); ?>

En sortie, on obtiendra :
123,456,789 123,456,789.123 123,456,789.123 123 456 789,123

6.2.
6. Les fonctions mathmatiques

Calculs de prcision

Les calculs de prcision utilisent la bibliothque BCMath.

Installation
Sous Windows
La version distribue par PHP inclut le support de la bibliothque BCMath (cest galement vrai pour le kit EasyPHP). Vous naurez donc rien faire de particulier pour en profiter.

Sous Linux
Assurez-vous davoir compil PHP avec loption enablebcmath.

Vous pouvez vous reporter au chapitre "Installation" pour plus de dtails sur la compilation de PHP.

348

Calculs de prcision

Vrication
Vous pouvez vous assurer que la bibliothque BCMath est bien disponible par un simple script contenant <?php phpinfo(); ?> et qui doit laisser apparatre :
Figure 6.1 :

phpinfo()

Utilisation
Avec la bibliothque BCMath, les nombres sont reprsents par des chanes de caractres. Ils ne sont donc pas a priori limits en taille et, par consquent, nont pas de limite thorique en prcision.

bcscale()
Dfinit la prcision par dfaut (remplace le paramtre bcmath.scale du fichier php.ini). Syntaxe $precision retour boolean bcscale(int $precision) Entier exprimant le nombre de dcimales par dfaut. TRUE.

bcadd()
Ajoute deux nombres. Syntaxe $operande1 $operande2 $precision retour string bcadd(string $operande1, string $operande2 [, int $precision]) Chane de caractres reprsentant un nombre. Chane de caractres reprsentant un nombre. Nombre de dcimales. Chane de caractres reprsentant $operande1+$operande2.

6. Les fonctions mathmatiques

bcsub()
Soustrait deux nombres. Syntaxe $operande1 $operande2 $precision retour string bcsub(string $operande1, string $operande2 [, int $precision]) Chane de caractres reprsentant un nombre. Chane de caractres reprsentant un nombre. Nombre de dcimales. Chane de caractres reprsentant $operande1$operande2.

349

Chapitre 6

Les fonctions mathmatiques

bcmul()
Multiplie deux nombres. Syntaxe $operande1 $operande2 $precision retour string bcmul(string $operande1, string $operande2 [, int $precision]) Chane de caractres reprsentant un nombre. Chane de caractres reprsentant un nombre. Nombre de dcimales. Chane de caractres reprsentant $operande1*$operande2.

bcdiv()
Divise deux nombres. Syntaxe $operande1 $operande2 $precision retour string bcdiv(string $operande1, string $operande2 [, int $precision]) Chane de caractres reprsentant un nombre. Chane de caractres reprsentant un nombre. Nombre de dcimales. Chane de caractres reprsentant $operande1/$operande2.

6. Les fonctions mathmatiques

bcmod()
Retourne le reste dune division. Syntaxe $operande1 $operande2 retour string bcmod(string $operande1, string $operande2) Chane de caractres reprsentant un nombre. Chane de caractres reprsentant un nombre. Chane de caractres reprsentant $operande1 % $operande2.

bcpow()
lve un nombre une puissance. Syntaxe $operande1 $operande2 string bcpow(string $operande1, string $operande2 [, int $precision]) Chane de caractres reprsentant un nombre. Chane de caractres reprsentant un nombre.

350

Calculs de prcision

$precision retour

Nombre de dcimales. Chane de caractres reprsentant $operande la puissance $operande2.

bcsqrt()
Retourne la racine carre dun nombre. Syntaxe $operande $precision retour string bcsqrt(string $operande [, int $precision]) Chane de caractres reprsentant un nombre. Nombre de dcimales. Chane de caractres reprsentant la racine carre de loprande.

bccomp()
Compare deux nombres. Syntaxe $operande1 $operande2 $precision retour int bccomp(string $operande1, string $operande2 [, int $precision]) Chane de caractres reprsentant un nombre. Chane de caractres reprsentant un nombre.

6. Les fonctions mathmatiques

Nombre de dcimales. 0 si les deux nombres sont identiques, 1 si $operande1 est plus grand que $operande2, sinon 1.

Voici un exemple de calcul utilisant la bibliothque BCMath.

Listing 6.12 : precision.php


<?php bcscale(10); $a = "12345678901234567890"; $b = "12345678"; echo "Addition:<br />"; echo ($a + $b)."<br />"; echo bcadd($a, $b)."<br />"; echo "Soustraction:<br />"; echo ($a - $b)."<br />"; echo bcsub($a, $b)."<br />"; echo "Multiplication:<br />"; echo ($a * $b)."<br />"; echo bcmul($a , $b)."<br />"; echo "Division:<br />";

351

Chapitre 6

Les fonctions mathmatiques

echo echo echo echo echo echo echo echo echo echo echo ?>

($a / $b)."<br />"; bcdiv($a, $b)."<br />"; "Restant de la division:<br />"; ($a % $b)."<br />"; bcmod($a, $b)."<br />"; "Exposant:<br />"; pow($a, 2)."<br />"; bcpow($a, 2)."<br />"; "Racine carre:<br />"; sqrt($a)."<br />"; bcsqrt($a)."<br />";

Et le rsultat retourn est le suivant : Addition: 1.23456789012E+19 12345678901246913568.0000000000 Soustraction: 1.23456789012E+19 12345678901222222212.0000000000 Multiplication: 1.52415776406E+26 152415776406035777639079420 Division: 1000000073E+12 1000000073000.0059850904 Restant de la division: 11681353 73890 Exposant: Warning: Invalid argument(s) passed to pow() in precision.php on line 21 152415787532388367501905199875019052100 Racine carre: 3513641828.82 3513641828.8201442530 On peut remarquer lerreur conscutive un calcul du reste de la division sans prendre garde aux limites de prcision de PHP ; qui plus est, PHP refuse de calculer la puissance si lon ne passe pas par BCMath.

6. Les fonctions mathmatiques

Affichage des nombres Pour une valeur donne, le nombre de chiffres affichs dpend de la configuration de PHP et, en particulier, du paramtre precision du fichier php.ini. Cette remarque ne sapplique videmment pas aux valeurs retournes par BCMath, qui sont, de toute faon, des chanes de caractres.

352

Chapitre 7

La manipulation des chanes de caractres


7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 Gnralits . . . . . . . . . . . . . . . . . . . . . . Fonctions de gestion des chanes de caractres Comparaison de chanes de caractres . . . . . Gestion des caractres spciaux . . . . . . . . . Manipulation des balises HTML . . . . . . . . . Insertion de motifs . . . . . . . . . . . . . . . . . Fusion et dcoupe . . . . . . . . . . . . . . . . . . Expressions rgulires . . . . . . . . . . . . . . . Adapter le texte la langue du visiteur . . . . . .. . .. .. .. .. .. .. .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 363 376 385 395 401 402 409 431

Gnralits

7.1.

Gnralits

Ce chapitre est peut-tre le plus important, lutilisation des chanes de caractres tant en effet invitable pour produire le code HTML dsir. Les chanes de caractres peuvent tre encadres soit par des apostrophes () soit par des guillemets ("). Lorsque vous utilisez des guillemets, vous pouvez intgrer directement des noms de variables au sein de la chane de caractres, et celles-ci seront subtitues par leurs valeurs. Ce nest pas le cas si vous utilisez les apostrophes. Ainsi,
<?php $monNom = "Emma"; echo "Bonjour $monNom <br />"; echo Bonjour $monNom <br />; ?>

affichera :
Bonjour Emma Bonjour $monNom

Dans le cas de lutilisation des guillemets, nous aurons donc besoin de faire appel aux squences dchappement afin de pouvoir afficher le signe $. Mais ceci concerne galement les caractres suivants :

Tableau 7.1 : Squences dchappement


Notation \n \r \t \\ \$ \" Description Changement de ligne. Retour chariot.

7. La manipulation des chanes de caractres

Tabulation. Pour afficher \ (et viter la confusion avec le caractre dchappement). Pour afficher $ (et viter la confusion avec linterprtation dune variable). Pour afficher " (et viter la confusion avec la fin de la chane de caractres).

La seule squence dchappement disponible lors de lutilisation des apostrophes et la suivante : \. Elle met fin la confusion quil pourrait y avoir avec la dclaration de fin de chane. Si lon veut utiliser des guillemets lintrieur dautres guillemets, il est vident que cela pose problme, comme dans lexemple suivant :
"Coluche a dit "Plus on est de fous moins ya de riz", pas faux..."

Lanalyseur syntaxique de PHP va reconnatre une premire chane "Coluche a dit " puis des lettres quil ne saura pas interprter Plus on est de fous moins ya de riz, et, enfin, une chane de caractres ", pas faux...".

355

Chapitre 7

La manipulation des chanes de caractres

Cest pourquoi il faut prciser que le caractre " est un caractre afficher. Pour cela, il a t dcid dy ajouter \. La phrase dexemple scrit donc :
"Coluche a dit \"Plus on est de fous moins ya de riz\", pas faux..."

Et, pour afficher \, il faut donc prciser que ce nest pas le caractre dchappement en le doublant : \\.

Chemins de fichiers Windows \\ est notamment utiliser pour les chemins windows. "C:\monRepertoire\monFichier.php" scrit "C:\\monRepertoire\\monFichier.php".

\\ Pour crire \\, il suffit de doubler chacun des caractres. On obtient donc \\\\ et ainsi de suite Cette mthode permet de garder la libert dutiliser tous les caractres.
Le script suivant nous montre comment utiliser les squences dchappement :

Listing 7.1 : cc01.php


<?php echo "1 - Facile"; echo "\n"; echo 2 - Facile; echo "\n"; echo "3 - Cest plus dur"; echo "\n"; echo 4 - C\est plus dur; echo "\n"; $variable="valeur"; echo "5 - $variable"; echo "\n"; echo 6 - $variable; echo "\n"; echo "7 - \$variable"; echo "\n"; echo "8 - citation \"PHP est facile\""; echo "\n"; echo 9 - citation "PHP est facile"; echo "\n"; // pour afficher \" avec les guillemets: echo "10 - \\\""; ?>

7. La manipulation des chanes de caractres

Voici le rsultat obtenu dans le code source gnr :

356

Gnralits

1 - Facile 2 - Facile 3 - Cest plus dur 4 - Cest plus dur 5 - valeur 6 - $variable 7 - $variable 8 - citation "PHP est facile" 9 - citation "PHP est facile" 10 - \"

Pour accder des lments dune base de donnes, il faut particulirement faire attention lutilisation des apostrophes. Par exemple :
"SELECT * FROM matable WHERE monchamp=$valeur"

posera problme si $valeur contient une apostrophe. Heureusement, la fonction addSlashes() ajoute le caractre dchappement devant les caractres problmatiques. Il faut donc crire :
"SELECT * FROM matable WHERE monchamp=".addSlashes($valeur).""

Le mme genre de problme se retrouve lorsque lon veut, par exemple, donner une valeur par dfaut dans un champ HTML. Une fonction spcifique existe, qui sappelle htmlSpecialChars().
echo "<input type=\"hidden\" name=\"variable\" value=\"".htmlSpecialChars($maVariable)."\" />"

Par dfaut, PHP est configur avec loption magic_quotes_gpc active. Ainsi, les valeurs passes par les mthodes GET, POST et les cookies voient leurs apostrophes automatiquement prcdes dun anti-slash (il nest alors plus ncessaire de faire appel addSlashes() pour les utiliser dans des requtes SQL). Il est possible de faire de mme pour les fichiers et les bases de donnes, en utilisant le paramtre similaire magic_quotes_runtime.

7. La manipulation des chanes de caractres

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur la configuration de PHP.
Rappelons que loprateur de concatnation est le point . et que loprateur .= est galement valide. Ainsi "Langage "."PHP" vaut "Langage PHP".

Afficher du texte
Il existe plusieurs faons dafficher une chane de caractres. La manire la plus simple est lutilisation de echo. Lcriture sur plusieurs lignes peut se faire au moyen de <<< suivis dun identifiant de fin de texte, qui ne sera pas dans le texte crire. Lidentifiant plac la fin du texte doit obligatoirement commencer sur la premire colonne du fichier.

357

Chapitre 7

La manipulation des chanes de caractres

Voici diffrents cas dutilisation de echo :


<?php $variable = "valeur\n"; echo $variable; echo "$variable"; echo "variable"," ",$variable; echo "On peut aussi crire sur plusieurs lignes\n"; echo <<<END On peut aussi crire sur plusieurs lignes de cette faon\n END; echo <<<TEXTE On peut aussi crire sur plusieurs lignes de cette faon TEXTE; ?>

Et voici le rsultat de sortie :


valeur valeur variable valeur On peut aussi crire sur plusieurs lignes On peut aussi crire sur plusieurs lignes de cette faon On peut aussi crire sur plusieurs lignes de cette faon

7. La manipulation des chanes de caractres 358

Gnralits

Une fonction trs proche de la commande echo sappelle print(). La diffrence est tellement infime que beaucoup se demandent o elle se trouve. print() est une fonction qui retourne un boolen, elle renvoie TRUE quand laffichage sest effectu.
echo est lgrement plus rapide que print(), dans la mesure o cette fonction ne retourne rien. Mais la diffrence reste minime.

Les deux fonctions printf() et sprintf() permettent respectivement dafficher et de retourner une chane de caractres formate.

printf()
Affiche une chane de caractres (ventuellement accompagne de valeurs) selon un format donn. Syntaxe $format $valeurs void printf(string $format [, mixed $valeurs]) Chane dcrivant le format attendu. Les valeurs formater.

sprintf()
Retourne une chane de caractres (ventuellement accompagne de valeurs) selon un format donn. Syntaxe $format $valeurs retour string sprintf(string $format [, mixed $valeurs]) Chane dcrivant le format attendu. Les valeurs formater. La chane formate.

7. La manipulation des chanes de caractres

Les lments formats sont dfinis par le signe % suivi de diffrents caractres (ex. :%03.2f) dont voici une description :
j

Le premier est facultatif. Il sert dterminer le caractre qui complte les caractres manquants ; par dfaut, il vaut le caractre despacement. Pour dfinir ce paramtre, il suffit de le faire prcder dune apostrophe (inutile pour le chiffre 0). (Cela peut, par exemple, permettre dafficher un nombre sur trois chiffres, mme sil est infrieur 100). Le deuxime paramtre est lui aussi optionnel. Il dtermine si le rsultat doit tre align droite ou gauche. Par dfaut, il sera align droite ; pour le faire aligner gauche, il suffit de placer le signe . Le troisime paramtre est lui aussi optionnel. Il dtermine le nombre de caractres minimum retourner.

359

Chapitre 7

La manipulation des chanes de caractres

Le quatrime paramtre est lui aussi optionnel. Il dtermine le nombre de dcimales afficher pour les rels. Ce paramtre na bien sr aucun effet sur les autres types ; il est prcd dun point. Le cinquime paramtre est obligatoire. Il dfinit selon quel type largument doit tre trait puis reprsent. Voici les diffrents types possibles :

Tableau 7.2 : Les diffrents types


Lettre b c d u f o s x X Trait Entier Entier Entier Entier Rel Entier Tel quel Entier Entier Reprsent Binaire Caractre avec sa valeur ASCII Nombre dcimal sign Nombre dcimal non sign Rel Nombre octal Chane de caractres Nombre hexadcimal Nombre hexadcimal en majuscules

criture du caractre % Pour crire le caractre %, il suffit de le doubler afin dviter la confusion. Au moment de laffichage un seul apparatra.
Voici quelques exemples utiles :

7. La manipulation des chanes de caractres

Listing 7.2 : sprintf.php


<?php echo "Date<br /> "; printf("%02d/%02d/%04d", 1, 7, 2002); echo "<br />Pi avec 7 dcimales<br />"; printf("%.7f", M_PI); echo "<br />Ecriture dune chane<br />"; printf(".:%s:.", "Salut !"); echo "<br />Ecriture dune chane avec 20 printf(".:%20s:.", "Salut"); echo "<br />Ecriture dune chane avec 20 " align gauche<br />"; printf(".:%-20s:.", "Salut"); echo "<br />Ecriture dune chane avec 20 " complt par des -<br />"; printf(".:%-20s:.", "Salut"); echo "<br />Ecriture dune chane avec 20

caractres minimum<br />"; caractres minimum,".

caractres minimum,".

caractres minimum,".

360

Gnralits

" align gauche, complt par des -<br />"; printf(".:%--20s:.", "Salut"); echo "<br />Ecriture de %<br />"; printf("%%"); ?>

Et voici le rsultat obtenu :


Date 01/07/2002 Pi avec 7 dcimales 3.1415927 Ecriture dune chane .:Salut !:. Ecriture dune chane avec .: Salut:. Ecriture dune chane avec .:Salut :. Ecriture dune chane avec .:---------------Salut:. Ecriture dune chane avec des .:Salut---------------:. Ecriture de % %

20 caractres minimum 20 caractres minimum, align gauche 20 caractres minimum, complt par des 20 caractres minimum, align gauche, complt par

La fonction vPrintf() permet dafficher un tableau. Elle fonctionne de la mme manire que printf().

vPrintf()
7. La manipulation des chanes de caractres
Affiche une chane de caractres formate et construite partir de donnes stockes dans un tableau. Syntaxe $format $tableau retour Voici un exemple :
<?php $tableau=array("Element 1", "Element 2", "Element 3"); vPrintf("%2\$s|%1\$s|%3\$s", $tableau); ?>

boolean vPrintf(string $format, array $tableau) Voir description de printf(). Tableau afficher. Un boolen.

dont le rsultat obtenu est le suivant :


Element 2|Element 1|Element 3

361

Chapitre 7

La manipulation des chanes de caractres

vSPrintf()
Retourne une chane de caractres formate et construite partir de donnes stockes dans un tableau. Syntaxe $format $tableau retour string vSPrintf(string $format, array $tableau) Voir description de vPrintf(). Tableau afficher. La chane de caractres.

sscanf()
Permet de faire lanalyse lexicale dune chane de caractres (i.e. de rcuprer les informations qui la composent). Syntaxe $chaine $format $variableSortieN retour mixed sscanf(string $chaine, string $format[, string &$variableSortie1 [, string &$variableSortie2[, ]]] Chane de caractres dont on veut rcuprer des lments. Format de la chane analyser. Variables dans lesquelles vous souhaitez stocker les diffrents lments extraits de la chane de caractres. Tableau avec les diffrentes parties reconnues de la chane de caractres, ou le nombre de sous-chanes reconnues si des des variables sont passes par rfrence.

7. La manipulation des chanes de caractres

Un exemple dutilisation de sscanf() :


<?php $phrase = "Jai 25 ans et je suis Franais"; $tableau = sscanf($phrase, "Jai %d ans et je suis %s"); echo $tableau[0]."<br />\n"; echo $tableau[1]."<br />\n"; list($age, $nationalite) = sscanf($phrase, "Jai %d ans et je suis %s"); echo $age."<br />\n"; echo $nationalite."<br />\n"; $refage=0; $refnat=""; echo sscanf($phrase, "Jai %d ans et je suis %s", &$refage, &$refnat) ." lments<br />\n"; echo $refage."<br />\n"; echo $refnat."<br />\n";

?>

362

Fonctions de gestion des chanes de caractres

Et le rsultat obtenu :
25 Franais 25 Franais 2 lments 25 Franais

Manipuler les caractres

chr()
Retourne le caractre dun code ASCII. Syntaxe $codeAscii retour string chr(int $codeAscii) Code ASCII du caractre afficher. Caractre correspondant au code ASCII pass en paramtre.

ord()
Retourne le code ASCII du premier caractre dune chane. Syntaxe $chaine retour int ord(string $chaine) Chane dont on veut le caractre ASCII du premier caractre. Code ASCII du premier caractre.

7. La manipulation des chanes de caractres

7.2.

Fonctions de gestion des chanes de caractres

Extraction et substitution
Extraction

substr()
Retourne une partie dune chane de caractres. Syntaxe $chaine string substr(string $chaine, int $debut [,int $nbCaracteres]) Chane de caractres de laquelle vous souhaitez extraire une partie.

363

Chapitre 7

La manipulation des chanes de caractres

$debut

Indice du caractre de dpart. (Le premier caractre ayant lindice 0, si la valeur est ngative, le compte se fait depuis la droite, le dernier caractre ayant lindice -1). La sous-chane demande.

retour

Listing 7.3 : substr.php


<?php echo substr("abcdefghij", echo "<br />"; echo substr("abcdefghij", echo "<br />"; echo substr("abcdefghij", echo "<br />"; echo substr("abcdefghij", echo "<br />"; echo substr("abcdefghij", ?> 2); 0, 3); 1, 4); 5, 20); -3, 2);

Et le rsultat obtenu est le suivant :


cdefghij abc bcde fghij hi

Parfois, nous ne sommes pas en mesure de connatre par avance la position recherche dans une chane de caractres. Les fonctions suivantes ne ncessitent pas de connatre dindex. La fonction strstr() permet de retrouver la premire occurrence dun caractre ou dune chane de caractres dans une autre chane de caractres.

7. La manipulation des chanes de caractres

strstr()
Permet de rcuprer la partie dune chane de caractres situe partir de la premire occurrence dune sous-chane. Syntaxe $chaine $souschaine retour string strstr(string $chaine, string $souschaine) Chane de caractres do vous souhaitez extraire une partie. Chane de caractres dfinissant le dbut. Une sous-chane de $chaine comprenant $souschaine et la fin de $chaine.

Listing 7.4 : strstr.php


<?php echo "strstr:".strstr("Voici un exemple stupide dexemple", "exemple");

364

Fonctions de gestion des chanes de caractres

echo "\n"; echo "strstr:".strstr("thomas@toutestfacile.com", "@"); ?>

En sortie, nous obtiendrons :


strstr:exemple stupide dexemple strstr:@toutestfacile.com

strchr()
strchr() est un alias de strstr(), cest--dire que ces deux fonctions sont en tous points identiques.
strstr() est une fonction sensible aux majuscules/minuscules. Pour ne pas prendre en compte la casse, il faut utiliser stristr(), qui fonctionne de la mme faon.

Listing 7.5 : stristr.php


<?php echo "strstr:".strstr("Voici un exemple stupide dexemple", "Exemple"); echo "\n"; echo "stristr:".stristr("Voici un exemple stupide dexemple", "Exemple"); ?>

En sortie, nous obtiendrons :


strstr: stristr:exemple stupide dexemple

Dans le cas o nous avons utilis strstr(), la sous-chane de caractres "Exemple" na pas t trouve cause de la majuscule.

7. La manipulation des chanes de caractres

Dans le cas o la sous-chane est prsente plusieurs fois, il est possible de rcuprer la partie situe aprs la dernire occurrence laide de strrchr().

strrchr()
Permet de rcuprer la partie dune chane de caractres situe partir de la dernire occurrence dune autre chane. Syntaxe $chaine $souschaine retour
<?php

string strrchr(string $chaine, string $souschaine) Chane de caractres do vous souhaitez extraire une partie. Chane de caractres dfinissant le dbut. Une sous-chane de $chaine comprenant $souschaine et la fin de $chaine.

365

Chapitre 7

La manipulation des chanes de caractres

echo strrchr("Voici un exemple stupide dexemple", "exemple"); echo "\n"; echo strrchr("article 1,article 2, article 3", ","); ?>

Et voici le rsultat obtenu :


e , article 3

Substitution

substr_replace()
Retourne une chane de caractres issue dune chane dans laquelle une partie a t remplace par une autre. Permet galement dinsrer du texte. Syntaxe $chaine $substitution $debut string substr_replace(string $chaine, string $substitution, int $debut [, int $nbCaracteres]) Chane de caractres dans laquelle vous souhaitez remplacer du texte. Chane de caractres que vous souhaitez crire la place. Indice du caractre de dpart. (Le premier caractre ayant lindice 0, si la valeur est ngative, le compte se fait depuis la droite, le dernier caractre ayant lindice -1). Nombre de caractres remplacer. La chane de caractres modifie.

$nbCaracteres retour

7. La manipulation des chanes de caractres

Listing 7.6 : substrreplace.php


<?php echo substr_replace("abCDEF", "AB", 0, 2); echo "<br />"; echo substr_replace("100000 Euros", ",", -9, 0); ?> ABCDEF 100,000 Euros

Il est possible dutiliser cette fonction afin de rduire des chanes de caractres. Par exemple, pour modifier "cette trop longue phrase" en "cette trop longue ph", il suffit dcrire :
substr_replace("cette trop longue phrase", "...", 20)

Il est assez rare que nous connaissions par avance la position des caractres dans la chane. Bien plus souvent, il sagit dun mot ou dune expression que nous souhaitons remplacer par un(e) autre. Il est, par exemple, possible dimaginer que lon souhaite remplacer les mots vulgaires dun forum par (censur). La fonction qui va nous le permettre sappelle str_replace().

366

Fonctions de gestion des chanes de caractres

str_replace()
Cette fonction permet de remplacer des occurrences par dautres. Syntaxe $motif $remplacement $chaine mixed str_replace(mixed $motif, mixed $remplacement, mixed $chaine [, int &$nombreRemplacements]) Une chane de caractres ou un tableau de chanes de caractres dsignant le ou les lments rechercher. Une chane de caractres ou un tableau de chanes de caractres dsignant le ou les lments qui remplaceront les lments de $motif. Une chane de caractres ou un tableau de chanes de caractres dsignant le ou les lments modifier.

$nombreRemplacements Cette fonction ecrira dans la variable $nombre_remplacements, le nombre de remplacements effectus dans la chane de caractres. (Cette option nexiste que depuis la version 5.0.0 de PHP) retour La chane de caractres ou le tableau de chanes de caractres modifi.

Lutilisation la plus simple consiste remplacer une sous-chane par une autre dans une chane de caractres. Voici un code source dexemple :

Listing 7.7 : strreplace1.php


<?php $phrase = "Jessicasse-croutes dans mon panier"; echo $phrase."<br />"; $phrase = str_replace("Jessica", "Jai 6 ca", $phrase); echo $phrase."<br />"; ?>

7. La manipulation des chanes de caractres

Et le rsultat :
Jessicasse-croutes dans mon panier Jai 6 casse-croutes dans mon panier

Si $chaine est un tableau, le remplacement seffectue sur tous les lments du tableau. En retour, nous obtenons alors un tableau des chanes de caractres modifies. Voici un code source dexemple :

Listing 7.8 : strreplace2.php


<?php $phrases = array("Jessicasse-croutes dans mon panier", "Jessicanapes dans mon salon", "Jessicadeaux sous mon sapin"); echo $phrases[0]."<br />"; echo $phrases[1]."<br />"; echo $phrases[2]."<br />";

367

Chapitre 7

La manipulation des chanes de caractres

$phrases = str_replace("Jessica", "Jai 6 ca", $phrases); echo $phrases[0]."<br />"; echo $phrases[1]."<br />"; echo $phrases[2]."<br />"; ?>

Et le rsultat :
Jessicasse-croutes dans mon panier Jessicanapes dans mon salon Jessicadeaux sous mon sapin Jai 6 casse-croutes dans mon panier Jai 6 canapes dans mon salon Jai 6 cadeaux sous mon sapin

Il est galement possible de tirer partie de cette fonction pour effectuer plusieurs modifications dun seul coup, en utilisant des tableaux pour les variables $motif et $remplacement. Voici un code source dexemple :

Listing 7.9 : strreplace3.php


<?php $phrases = array ("Jessicasse-croutes dans mon panier et Jean ai dautres dans mon placard", "Jessicanapes dans mon salon et Jean ai un dans la chambre"); echo $phrases[0]."<br />"; echo $phrases[1]."<br />"; $phrases = str_replace(array("Jessica","Jean"), array("Jai 6 ca", "jen"), $phrases); echo $phrases[0]."<br />"; echo $phrases[1]."<br />"; ?>

7. La manipulation des chanes de caractres

Et le rsultat :
Jessicasse-croutes dans mon panier et Jean ai dautres dans mon placard Jessicanapes dans mon salon et Jean ai un dans la chambre Jai 6 casse-croutes dans mon panier et jen ai dautres dans mon placard Jai 6 canapes dans mon salon et jen ai un dans la chambre

Pour ne remplacer que des caractres, comme par exemple pour retirer les accents, on pourrait utiliser str_replace(), mais on peut galement utiliser la fonction strtr().

Remplacement insensible la casse Si vous possedez la version 5.0.0 ou suprieure de PHP, vous pouvez utiliser la fonction str_ireplace() qui se comporte comme str_replace hormis quelle est remplacera galement les chanes de caractres ayant une casse diffrente. (minuscules/majuscules)

368

Fonctions de gestion des chanes de caractres

strtr() (syntaxe 1)
Retourne une chane de caractres dans laquelle certains caractres ont t remplacs par dautres. Syntaxe $chaine $depuis $vers retour string strtr(string $chaine, string $depuis, string $vers) Chane de caractres o les modifications doivent tre effectues. Chane de caractres indiquant tous les caractres modifier. Chane de caractres indiquant les caractres qui devront remplacer ceux de $depuis. La chane modifie.

Voici un exemple qui permet de supprimer les accents dans une phrase.

Listing 7.10 : strtr1.php


<?php $phrase = "Les accents sur , , , , , vont tre supprims"; echo $phrase."<br />"; $phrase = strtr($phrase, "", "aeiouaeiouaeiou"); echo $phrase; ?>

Voici le rsultat obtenu :


Les accents sur , , , , , vont tre supprims Les accents sur a, e, e, u, e, o vont etre supprimes

Une autre syntaxe existe, qui consiste dclarer un tableau associatif. Cela permet de remplacer des chanes de caractres par dautres.

7. La manipulation des chanes de caractres

strtr() (syntaxe 2)
Retourne une chane de caractres dans laquelle certains caractres ont t remplacs par dautres. Syntaxe $chaine $remplacement retour string strtr(string $chaine, array $remplacement) Chane de caractres o les modifications doivent tre effectues. Tableau associatif ayant pour cls les chanes de caractres remplacer, et pour valeurs les chanes de substitution correspondantes. La chane modifie.

Voici un exemple utilisant cette syntaxe :

369

Chapitre 7

La manipulation des chanes de caractres

Listing 7.11 : strtr2.php


<?php $phrase = "Les accents sur , , , , , vont tre supprims"; echo $phrase."<br />"; $remplacements = array( => a, => e, => e, => u, => e, => o, vont tre => ont ts ); $phrase=strtr($phrase , $remplacements); echo $phrase; ?>

Et voici le rsultat obtenu :


Les accents sur , , , , , vont tre supprims Les accents sur a, e, e, u, e, o ont t supprims

Fonctions statistiques (longueur et nombre doccurrences)

strlen()
Retourne la longueur dune chane de caractres. Syntaxe $chaine int strlen(string $chaine) Chane de caractres dont vous souhaitez connatre le nombre de caractres. Nombre de caractres de la chane.

7. La manipulation des chanes de caractres

retour

<?php echo strlen("Texte de 22 caracteres"); ?>

Et le rsultat est :
22

substr_count()
Cette fonction compte le nombre doccurrences dune sous-chane dans une autre.

370

Fonctions de gestion des chanes de caractres

Syntaxe $chaine $motif retour

int substr_count(string $chaine, string $motif) Chane de caractres o retrouver le motif. Motif rechercher. Le nombre de fois o le motif apparat.

Listing 7.12 : c06-substrcount.php


<?php echo substr_count("toto","toto"); echo "<br />"; echo substr_count("toto","to"); echo "<br />"; echo substr_count("Je me demande combien il y a de e dans cette phrase","e"); echo "<br />"; ?>

Et voici le rsultat obtenu :


1 2 10

count_chars()
Permet de compter les occurrences des caractres dans une chane de caractres. Syntaxe $chaine $mode mixed count_chars(string $chaine [, int $mode]) Chane dont vous souhaitez compter le nombre doccurrences des caractres. Au choix : 0 (par dfaut) renvoie le nombre doccurrences de tous les caractres ayant un code ASCII compris entre 0 et 255. 1 ne renvoie que les caractres prsents dans la chane. 2 ne renvoie que les caractres absents de la chane. 3 renvoie une chane de caractres des caractres utiliss. 4 renvoie une chane de caractres des caractres inutiliss. Un tableau associatif o les cls sont les codes ASCII des caractres, ou une chane de caractres selon le mode choisi.

7. La manipulation des chanes de caractres

retour

Voici un exemple de script pour commenter cette fonction :


<?php $phrase="Cette phrase contient plusieurs e, t, c et p"; echo "*** Code=0:\n"; print_r(count_chars($phrase));

371

Chapitre 7

La manipulation des chanes de caractres

echo "*** Code=1:\n"; print_r(count_chars($phrase,1)); echo "*** Code=2:\n"; print_r(count_chars($phrase,2)); echo "*** Code=3:\n"; echo count_chars($phrase,3)."\n"; ?>

Dont le rsultat attendu est :


*** Code=0: Array ( [0] => 0 [5] => 0 [10] => 0 [15] => 0 [20] => 0 [25] => 0 [30] => 0 [35] => 0 [40] => 0 [45] => 0 [50] => 0 [55] => 0 [60] => 0 [65] => 0 [70] => 0 [75] => 0 [80] => 0 [85] => 0 [90] => 0 [95] => 0 [100] => 0 [105] => 2 [110] => 2 [115] => 3 [120] => 0 [125] => 0 [130] => 0 [135] => 0 [140] => 0 [145] => 0 [150] => 0 [155] => 0 [160] => 0 [165] => 0 [170] => 0 [175] => 0 [180] => 0 [185] => 0 [190] => 0

[1] => 0 [6] => 0 [11] => 0 [16] => 0 [21] => 0 [26] => 0 [31] => 0 [36] => 0 [41] => 0 [46] => 0 [51] => 0 [56] => 0 [61] => 0 [66] => 0 [71] => 0 [76] => 0 [81] => 0 [86] => 0 [91] => 0 [96] => 0 [101] => [106] => [111] => [116] => [121] => [126] => [131] => [136] => [141] => [146] => [151] => [156] => [161] => [166] => [171] => [176] => [181] => [186] => [191] =>

[2] => 0 [7] => 0 [12] => [17] => [22] => [27] => [32] => [37] => [42] => [47] => [52] => [57] => [62] => [67] => [72] => [77] => [82] => [87] => [92] => [97] => 7 [102] 0 [107] 1 [112] 6 [117] 0 [122] 0 [127] 0 [132] 0 [137] 0 [142] 0 [147] 0 [152] 0 [157] 0 [162] 0 [167] 0 [172] 0 [177] 0 [182] 0 [187] 0 [192]

[3] => 0 [4] => 0 [8] => 0 [9] => 0 0 [13] => 0 [14] => 0 0 [18] => 0 [19] => 0 0 [23] => 0 [24] => 0 0 [28] => 0 [29] => 0 8 [33] => 0 [34] => 0 0 [38] => 0 [39] => 0 0 [43] => 0 [44] => 2 0 [48] => 0 [49] => 0 0 [53] => 0 [54] => 0 0 [58] => 0 [59] => 0 0 [63] => 0 [64] => 0 1 [68] => 0 [69] => 0 0 [73] => 0 [74] => 0 0 [78] => 0 [79] => 0 0 [83] => 0 [84] => 0 0 [88] => 0 [89] => 0 0 [93] => 0 [94] => 0 1 [98] => 0 [99] => 2 => 0 [103] => 0 [104] => 0 [108] => 1 [109] => 3 [113] => 0 [114] => 2 [118] => 0 [119] => 0 [123] => 0 [124] => 0 [128] => 0 [129] => 0 [133] => 0 [134] => 0 [138] => 0 [139] => 0 [143] => 0 [144] => 0 [148] => 0 [149] => 0 [153] => 0 [154] => 0 [158] => 0 [159] => 0 [163] => 0 [164] => 0 [168] => 0 [169] => 0 [173] => 0 [174] => 0 [178] => 0 [179] => 0 [183] => 0 [184] => 0 [188] => 0 [189] => 0 [193] => 0 [194]

=> => => => => => => => => => => => => => => => => => =>

1 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

7. La manipulation des chanes de caractres 372

Fonctions de gestion des chanes de caractres

[195] [200] [205] [210] [215] [220] [225] [230] [235] [240] [245] [250] [255]

=> => => => => => => => => => => => =>

0 0 0 0 0 0 0 0 0 0 0 0 0

[196] [201] [206] [211] [216] [221] [226] [231] [236] [241] [246] [251]

=> => => => => => => => => => => =>

0 0 0 0 0 0 0 0 0 0 0 0

[197] [202] [207] [212] [217] [222] [227] [232] [237] [242] [247] [252]

=> => => => => => => => => => => =>

0 0 0 0 0 0 0 0 0 0 0 0

[198] [203] [208] [213] [218] [223] [228] [233] [238] [243] [248] [253]

=> => => => => => => => => => => =>

0 0 0 0 0 0 0 0 0 0 0 0

[199] [204] [209] [214] [219] [224] [229] [234] [239] [244] [249] [254]

=> => => => => => => => => => => =>

0 0 0 0 0 0 0 0 0 0 0 0

) *** Code=1: Array ( [32] => 8 [101] => 7 [111] => 1 [117] => 2 ) *** Code=2: Array ( [0] => 0 [5] => 0 [10] => 0 [15] => 0 [20] => 0 [25] => 0 [30] => 0 [36] => 0 [41] => 0 [47] => 0 [52] => 0 [57] => 0 [62] => 0 [68] => 0 [73] => 0 [78] => 0 [83] => 0 [88] => 0 [93] => 0 [100] => 0 [109] => 0 [121] => 0 [126] => 0 [131] => 0 [136] => 0 [141] => 0 [146] => 0

[44] => 2 [104] => 1 [112] => 3

[67] => 1 [97] => 1 [99] => 2 [105] => 2 [108] => 1 [110] => 2 [114] => 2 [115] => 3 [116] => 6

[1] => 0 [6] => 0 [11] => 0 [16] => 0 [21] => 0 [26] => 0 [31] => 0 [37] => 0 [42] => 0 [48] => 0 [53] => 0 [58] => 0 [63] => 0 [69] => 0 [74] => 0 [79] => 0 [84] => 0 [89] => 0 [94] => 0 [102] => [113] => [122] => [127] => [132] => [137] => [142] => [147] =>

[2] => 0 [7] => 0 [12] => [17] => [22] => [27] => [33] => [38] => [43] => [49] => [54] => [59] => [64] => [70] => [75] => [80] => [85] => [90] => [95] => 0 [103] 0 [118] 0 [123] 0 [128] 0 [133] 0 [138] 0 [143] 0 [148]

[3] => 0 [4] => 0 [8] => 0 [9] => 0 0 [13] => 0 [14] => 0 0 [18] => 0 [19] => 0 0 [23] => 0 [24] => 0 0 [28] => 0 [29] => 0 0 [34] => 0 [35] => 0 0 [39] => 0 [40] => 0 0 [45] => 0 [46] => 0 0 [50] => 0 [51] => 0 0 [55] => 0 [56] => 0 0 [60] => 0 [61] => 0 0 [65] => 0 [66] => 0 0 [71] => 0 [72] => 0 0 [76] => 0 [77] => 0 0 [81] => 0 [82] => 0 0 [86] => 0 [87] => 0 0 [91] => 0 [92] => 0 0 [96] => 0 [98] => 0 => 0 [106] => 0 [107] => 0 [119] => 0 [120] => 0 [124] => 0 [125] => 0 [129] => 0 [130] => 0 [134] => 0 [135] => 0 [139] => 0 [140] => 0 [144] => 0 [145] => 0 [149] => 0 [150]

7. La manipulation des chanes de caractres

=> => => => => => => =>

0 0 0 0 0 0 0 0

373

Chapitre 7

La manipulation des chanes de caractres

[151] [156] [161] [166] [171] [176] [181] [186] [191] [196] [201] [206] [211] [216] [221] [226] [231] [236] [241] [246] [251]

=> => => => => => => => => => => => => => => => => => => => =>

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

[152] [157] [162] [167] [172] [177] [182] [187] [192] [197] [202] [207] [212] [217] [222] [227] [232] [237] [242] [247] [252]

=> => => => => => => => => => => => => => => => => => => => =>

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

[153] [158] [163] [168] [173] [178] [183] [188] [193] [198] [203] [208] [213] [218] [223] [228] [233] [238] [243] [248] [253]

=> => => => => => => => => => => => => => => => => => => => =>

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

[154] [159] [164] [169] [174] [179] [184] [189] [194] [199] [204] [209] [214] [219] [224] [229] [234] [239] [244] [249] [254]

=> => => => => => => => => => => => => => => => => => => => =>

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

[155] [160] [165] [170] [175] [180] [185] [190] [195] [200] [205] [210] [215] [220] [225] [230] [235] [240] [245] [250] [255]

=> => => => => => => => => => => => => => => => => => => => =>

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

) *** Code=3: ,Cacehilnoprstu

strspn()
Cette fonction retourne le nombre de caractres du dbut de la chane passe en premier paramtre, dont tous les caractres sont compris dans la chane fournie en second paramtre.

7. La manipulation des chanes de caractres

Syntaxe $chaine $caracteres $debut $nbCaracteres retour Un exemple :

int strspn(string $chaine, string $caracteres [, int $debut [, int $nbCaracteres]]) Chane tudier. Ensemble de caractres. Indice du premier caractre de $chaine a tudier. Nombre de caractres a partir de $debut sur lesquels faire le compte. Le nombre de caractres du dbut de la chane, dont tous les caractres appartiennent $caracteres.

<?php echo strspn("7490875253 Voila 10 chiffres", "1234567890"); ?>

dont le rsultat est :


10

374

Fonctions de gestion des chanes de caractres

strcspn()
Cette fonction retourne le nombre de caractres du dbut de la chane passe en premier paramtre, dont aucun caractre nest compris dans la chane fournie en second paramtre. Syntaxe $chaine $caracteres $debut $nbCaracteres retour int strcspn(string $chaine, string $caracteres [ int $debut [, int $nbCaracteres]]) Chane tudier. Ensemble de caractres. Indice du premier caractre de $chaine a tudier. Nombre de caractres a partir de $debut sur lesquels faire le compte. Le nombre de caractres du dbut de la chane, dont aucun caractre nappartient $caracteres.

Un exemple :
<?php echo strcspn("22 caracteres avant le: ou ! ou ?", ":!?"); ?>

avec comme rsultat :


22

Fonctions de position
Il est galement utile de pouvoir rcuprer lindex dun caractre dans une chane :

7. La manipulation des chanes de caractres

strpos()
Retourne la position du premier caractre de la premire occurrence dune chane dans une autre, partir dun certain index. Syntaxe $chaine $souschaine $index retour int strpos(string $chaine, string $souschaine [int $index]) Chane de caractres dans laquelle rechercher la sous-chane. Chane de caractres rechercher. Index de la chane partir duquel la recherche doit seffectuer. Lindex du premier caractre de la sous-chane. Retourne FALSE si la sous-chane nest pas trouve.

<?php echo strpos("Index du premier caractre dune chane de". " caractres","caractre");

375

Chapitre 7

La manipulation des chanes de caractres

echo "\n"; echo strpos("Index du premier caractre dune chane de". " caractres","caractre",0); echo "\n"; echo strpos("Index du premier caractre dune chaine de". " caractres","caractre",30); ?>

Voici le rsultat obtenu :


17 17 43

Retour de la fonction Il vaut mieux comparer le rsultat FALSE (en utilisant loprateur ===) avant de se servir de la valeur retourne, car la confusion entre le premier caractre (dindice 0) et la valeur FALSE est possible.

strrpos()
Retourne la position de la dernire occurrence dun caractre dans une chane de caractres. Syntaxe $chaine $caractere int strrpos(string $chaine, char $caractere) Chane dans laquelle rechercher le caractre. Caractre dont on veut lindice. La position de la dernire occurrence du caractre dans la chane.

7. La manipulation des chanes de caractres

retour

<?php echo strrpos("Index du premier caractere dune chaine de caracteres",e); ?>

Voici le rsultat obtenu :


51

7.3.

Comparaison de chanes de caractres

Il est possible de comparer deux chanes de caractres en utilisant simplement loprateur ==. Cependant, il peut tre galement intressant de comparer des chanes semblables laide de fonctions permettant dautres moyens de comparaison que la stricte galit de deux chanes.

376

Comparaison de chanes de caractres

galite des valeurs et des types Si vous souhaitez comparer une variable une chane de caractres en utilisant loprateur ==, assurez-vous que la variable est bien de type string. Vous risqueriez, sinon, davoir des surprises.

Comparaison par ordre alphabtique


Il est ainsi possible de comparer deux chanes selon leur ordre alphabtique.

strcmp()
Compare deux chanes de caractres partir de lordre alphabtique. Syntaxe $chaine1 $chaine2 retour int strcmp(string $chaine1, string $chaine2) Chane comparer. Chane comparer. 1 si la chane 1 est place avant la chane 2 dans lordre alphabtique, 1 dans le cas contraire et 0 si les deux chanes sont identiques.

<?php echo strcmp("abc", "bcd")."\n"; echo strcmp("aa", "aaa")."\n"; echo strcmp("_mot", "mot")."\n"; echo strcmp("mot_", "mot")."\n"; echo strcmp("mot", "mot")."\n"; ?>

7. La manipulation des chanes de caractres

Voici le rsultat obtenu :


-1 -1 -1 1 0

Pour ne comparer que les premiers caractres, il suffit dutiliser la fonction suivante :

strncmp()
Compare les premiers caractres de deux chanes de caractres partir de lordre alphabtique.

377

Chapitre 7

La manipulation des chanes de caractres

Syntaxe $chaine1 $chaine2 $nbCaracteres retour

int strncmp(string $chaine1, string $chaine2, int $nbCaracteres) Chane comparer. Chane comparer. Nombre de caractres comparer. 1 si les $nbCaracteres premiers caractre de chane 1 sont placs avant la chane 2 dans lordre alphabtique, 1 dans le cas contraire et 0 si les $nbCaracteres premiers caractres des deux chanes sont identiques.

<?php echo strncmp("aa", "aaa", 2)."\n"; echo strncmp("aa", "aaa", 3)."\n"; echo strncmp("abcdg", "abcef", 3)."\n"; echo strncmp("abcdg", "abcef", 4)."\n"; ?>

Le rsultat obtenu est alors le suivant :


0 -1 0 -1

strcoll()
Compare deux chanes de caractres selon la configuration locale du serveur. Si la configuration courante est C ou POSIX, alors cette fonction est identique strcmp().

7. La manipulation des chanes de caractres

Syntaxe

int strcoll(string $chaine1, string $chaine2)

Les fonctions strcmp() et strncmp() ont leurs quivalents insensibles la casse ; ce sont les fonctions strcasecmp() et strncasecmp().

strcasecmp()
Compare deux chanes de caractres partir de lordre alphabtique sans tenir compte de la casse. Syntaxe $chaine1 $chaine2 retour int strcasecmp(string $chaine1, string $chaine2) Chane comparer. Chane comparer. 1 si la chane 1 est place avant la chane 2 dans lordre alphabtique, 1 dans le cas contraire et 0 si les deux chanes sont identiques.

378

Comparaison de chanes de caractres

strncasecmp()
Compare les premiers caractres de deux chanes de caractres partir de lordre alphabtique sans tenir compte de la casse. Syntaxe $chaine1 $chaine2 $nbCaracteres retour int strncasecmp(string $chaine1, string $chaine2, int $nbCaracteres) Chane comparer. Chane comparer. Nombre de caractres comparer. 1 si les $nbCaracteres premiers caractre de chane 1 sont placs avant la chane 2 dans lordre alphabtique, 1 dans le cas contraire et 0 si les $nbCaracteres premiers caractres des deux chanes sont identiques.

Un algorithme de "comparaison naturelle" est galement disponible. Voici sa description :

strnatcmp()
Compare deux chanes utilisant un algorithme cens ordonner des chanes de caractres comme le ferait un tre humain. Syntaxe $chaine1 $chaine2 retour int strnatcmp(string $chaine1, string $chaine2) Chane comparer. Chane comparer. 1 si la chane 1 est place avant la chane 2 dans lordre "naturel", 1 dans le cas contraire et 0 si les deux chanes sont identiques.

7. La manipulation des chanes de caractres

Pour mettre en avant la diffrence entre strcmp() et strnatcmp(), le script suivant trie un tableau selon les deux mthodes.
<?php $tableau1 = $tableau2 = array (image5.jpg, image4.jpg, image12.jpg, image8.jpg, image1.jpg, image43.jpg, image14.jpg); echo "Ordre standard:\n"; usort($tableau1, "strcmp"); print_r($tableau1); echo "\nOrdre naturel:\n"; usort($tableau2, "strnatcmp"); print_r($tableau2); ?>

379

Chapitre 7

La manipulation des chanes de caractres

Voici le rsultat obtenu :


Ordre standard: Array ( [0] => image1.jpg [1] => image12.jpg [2] => image14.jpg [3] => image4.jpg [4] => image43.jpg [5] => image5.jpg [6] => image8.jpg ) Ordre naturel: Array ( [0] => image1.jpg [1] => image4.jpg [2] => image5.jpg [3] => image8.jpg [4] => image12.jpg [5] => image14.jpg [6] => image43.jpg )

Une fonction quivalente, mais insensible la casse, existe. Elle sappelle strnatcasecmp().

strnatcasecmp()
7. La manipulation des chanes de caractres
Compare deux chanes utilisant un algorithme cens ordonner des chanes de caractres comme le ferait un tre humain. Cette fonction est insensible la casse. Syntaxe $chaine1 $chaine2 retour int strnatcasecmp(string $chaine1, string $chaine2) Chane comparer. Chane comparer. 1 si la chane 1 est place avant la chane 2 dans lordre "naturel", 1 dans le cas contraire et 0 si les deux chanes sont identiques.

<?php $tableau1 = $tableau2

= array (Image5.jpg, image4.jpg, Image12.jpg, image8.jpg, Image1.jpg, image43.jpg, Image14.jpg); echo "Ordre standard:\n";

380

Comparaison de chanes de caractres

usort($tableau1, "strcmp"); print_r($tableau1); echo "\nOrdre naturel:\n"; usort($tableau2, "strnatcasecmp"); print_r($tableau2); ?>

Voici le rsultat obtenu :


Ordre standard: Array ( [0] => Image1.jpg [1] => Image12.jpg [2] => Image14.jpg [3] => image4.jpg [4] => image43.jpg [5] => Image5.jpg [6] => image8.jpg ) Ordre naturel: Array ( [0] => Image1.jpg [1] => image4.jpg [2] => Image5.jpg [3] => image8.jpg [4] => Image12.jpg [5] => Image14.jpg [6] => image43.jpg )

7. La manipulation des chanes de caractres

Vous pouvez galement utiliser les fonctions min() et max(), dcrites dans le chapitre "PHP et les mathmatiques", pour dterminer la chane de caractres ayant la premire ou la dernire position dans un classement alphabtique dune liste de chanes.

Comparaison orthographique

similar_text()
Permet de comparer deux chanes en estimant leurs ressemblances. Cette fonction est sensible la casse.

381

Chapitre 7

La manipulation des chanes de caractres

Syntaxe $chaine1 $chaine2 $pourcentage retour

int similar_text(string $chaine1, string $chaine2, [double &$pourcentage]) Une des deux chanes comparer. La chane avec laquelle on veut comparer la premire. Si une rfrence est passe en paramtre, la valeur en % y sera dclare. Le nombre de caractres en commun.

<?php $chaine1 = "Une des chaines a comparer"; $chaine2 = "Lautre des chaines a comparer"; echo similar_text($chaine1, $chaine2)."\n"; $pourcentage = 0; echo similar_text($chaine1, $chaine2, &$pourcentage)."\n"; echo $pourcentage."\n"; echo similar_text("aaa", "AAA", &$pourcentage)."\n"; echo $pourcentage."\n"; ?>

Voici le rsultat obtenu : 24 24 85.714285714286 0 0

Mthode utilise La mthode utilise est celle de Oliver [1993] qui est dcrite ladresse suivante : http://citeseer.nj.nec.com/oliver93decision.html. 7. La manipulation des chanes de caractres
Il existe une autre mthode permettant de mesurer la distance entre deux chanes de caractres, cest la distance de Levenshtein. Le calcul est ici moins gourmand que le prcdent.

levenshtein()
Calcule la distance de Levenshtein entre deux chanes de caractres. La distance de Levenshtein se dfinit comme tant le plus petit nombre de caractres remplacer dans la premire chane pour obtenir la seconde. Syntaxe $chaine1 $chaine2 $coutInsert int levenshtein(string $chaine1, string $chaine2 [, int $coutInsert, int $coutRemplace, int $coutSupprime]) Chane comparer. Chane comparer. Cot dune insertion.

382

Comparaison de chanes de caractres

$coutRemplace $coutSupprime retour

Cot dun remplacement. Cot dune suppression. Distance de Levenshtein, ou 1 si lune des deux chanes fait plus de 255 caractres.

<?php $chaine1 = "Une des chanes comparer"; $chaine2 = "Lautre des chanes comparer"; echo levenshtein($chaine1, $chaine2)."\n"; echo levenshtein($chaine1, $chaine2, 2, 3, 1)."\n"; echo levenshtein("aaa", "AAA")."\n"; ?>

Voici le rsultat obtenu :


5 11 3

Comparaison phonique
Les fonctions prsentes ici ne permettent pas une comparaison directe, mais permettent de dfinir une valeur base sur la consonance dun mot.

soundex()
Permet de calculer une valeur partir de la prononciation dune chane de caractres. La particularit de cette valeur est que deux mots ayant la mme consonance auront le mme "soundex". Attention, cette fonction est adapte la prononciation anglaise. Syntaxe $chaine retour string soundex(string $chaine) Chane de caractres dont on veut calculer la valeur soundex. Le "soundex".

7. La manipulation des chanes de caractres

Listing 7.13 : soundex.php


<?php echo echo echo echo echo echo echo echo echo soundex("serial killer"); "<br />"; soundex("seriol quilleur"); "<br />"; soundex("Welcome"); "<br />"; soundex("ouelcome"); "<br />"; soundex("elephant");

383

Chapitre 7

La manipulation des chanes de caractres

echo echo echo echo ?>

"<br />"; soundex("elefant"); "<br />"; soundex("elefante");

Le rsultat de ce script est le suivant :


S642 S642 W425 O425 E415 E415 E415

metaphone()
Cette fonction est trs similaire soundex(). Elle a le mme objectif, mais utilise une reprsentation et un algorithme diffrents. Syntaxe $chaine retour string metaphone(string $chaine) Chane de caractres dont vous souhaitez le "metaphone". Une valeur dpendant de la faon de prononcer la chane de caractres.

Listing 7.14 : metaphone.php


<?php echo echo echo echo echo echo echo echo echo echo echo echo echo ?> metaphone("serial killer"); "<br />"; metaphone("seriol quilleur"); "<br />"; metaphone("Welcome"); "<br />"; metaphone("ouelcome"); "<br />"; metaphone("elephant"); "<br />"; metaphone("elefant"); "<br />"; metaphone("elefante");

7. La manipulation des chanes de caractres

Dont le rsultat est :


SRLKLR SRLKLR WLKM

384

Gestion des caractres spciaux

OLKM ELFNT ELFNT ELFNT

7.4.

Gestion des caractres spciaux

Ajout du caractre dchappement


Il est parfois utile dencoder des chanes de caractres. Cest le cas, par exemple, pour chapper certains caractres spciaux.

addSlashes()
Permet lchappement de certains caractres. Concrtement, il sagit des caractres : , ", \ et NUL (\0). Syntaxe $chaine retour string addSlashes(string $chaine) Chane de caractres modifier. La chane avec les caractres spciaux chapps.

<?php $chaine="Cest \ Cool"; echo $chaine; echo "\n"; echo addSlashes($chaine); ?>

7. La manipulation des chanes de caractres

Voici le rsultat obtenu :


Cest \ Cool C\est \\ Cool

magic_quotes_gpc Par dfaut, les magic quotes (apostrophes magiques) sont actives, cest--dire que les apostrophes sont automatiquement prcdes du signe \ lorsque les valeurs sont passes un script par la mthode GET, POST ou par cookie.
Une fonction trs similaire, appele quoteMeta(), permet galement lchappement de certains caractres.

385

Chapitre 7

La manipulation des chanes de caractres

quoteMeta()
Permet dchapper les caractres : ., \, +, ?, ^, $, [, ], (, ). Syntaxe $chaine retour string quoteMeta(string $chaine) Chane transformer. Chane transforme.

addCSlashes()
Retourne une chane de caractres en ajoutant des \ devant les caractres prciss. Les caractres ayant un code ASCII infrieur 32, ou suprieur 126, sont convertis leur valeur octale. Syntaxe $chaine $listeCaracteres retour string addCSlashes(string $chaine, string $listeCaracteres) Chane de caractres transformer. Liste des caractres chapper. Chane transforme.

7. La manipulation des chanes de caractres

<?php $chaine="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; echo $chaine; echo "\n"; echo addcslashes($chaine,"A..z"); echo "\n"; echo addcslashes($chaine,"G..f"); ?>

Et voici le rsultat obtenu :


ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z\a\b\c\d\e\f\g\h\i\j\k\l\m\n \o\p\q\r\s\t\u\v\w\x\y\z ABCDEF\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z\a\b\c\d\e\fghijklmnopqrstuvwxyz

Caractres spciaux Le fait dajouter un \ peut transformer certaines caractres en caractres spciaux, cest le cas de 0, a, b, f, n, r, t et v.

Suppression du caractre dchappement


Les fonctions inverses existent bien videmment. Elles permettent de supprimer les \.

386

Gestion des caractres spciaux

stripSlashes()
Retire les slashes ajouts par la fonction addSlashes(). Syntaxe $chaine retour string stripSlashes(string $chaine) Chane de caractres pour laquelle vous souhaitez retirer les \. La chane sans les \ dchappement.

<?php $chaine="Cette chaine contient des et des \."; echo $chaine; echo "\n"; echo addSlashes($chaine); echo "\n"; echo stripSlashes(addslashes($chaine)); ?>

Ce qui donne en retour :


Cette chaine contient des et des \. Cette chaine contient des \ et des \\. Cette chaine contient des et des \.

De la mme manire, le rsultat obtenu par addCSlashes() est obtenu par stripCSlashes().

stripCSlashes()
7. La manipulation des chanes de caractres
Fonction inverse de addCSlashes(). Syntaxe $chaine retour string stripCSlashes(string $chaine) Chane dont vous souhaitez retirer les \ dchappement. Chane sans les \ dchappement.

Dans lexemple suivant, nous ne nous sommes pas mfis des caractres spciaux. Observez le rsultat obtenu :
<?php $chaine="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; echo $chaine; echo "\n"; echo addCSlashes($chaine,"G..f"); echo "\n"; echo stripCSlashes(addCSlashes($chaine,"G..f")); ?>

387

Chapitre 7

La manipulation des chanes de caractres

Rsultat obtenu :
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ABCDEF\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z\a\b\c\d\e\fghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZhcdehghijklmnopqrstuvwxyz

Conversion des caractres en code HTML


Dans le cas de lcriture de pages HTML, il peut tre utile de transformer certains caractres spciaux en leurs quivalents HTML. Cest le cas des caractres &, ", , < et >, qui peuvent tre remplacs respectivement par &amp;, &quot;, &apos;, &lt; et &gt;.

htmlSpecialChars()
Retourne une chane de caractres pour laquelle les caractres spciaux de lHTML ont t convertis. Cela ne concerne pas les caractres accentus. Syntaxe $chaine $apostrophes string htmlSpecialChars(string $chaine [, int $apostrophes [, string $encodage]]) Chane de caractres transformer. Au choix : ENT_COMPAT (par dfaut), pour que cette fonction ne transforme que les guillemets et laisse les apostrophes telles quelles. ENT_QUOTES, pour transformer les apostrophes et guillemets. ENT_NOQUOTES, pour ne transformer ni les apostrophes ni les guillemets. $encodage Par dfaut il vaut "ISO-8859-1". La chane transforme. retour

7. La manipulation des chanes de caractres

Utilit Cette fonction est notamment utile pour les forums ou livres dor, par exemple. En effet, si un utilisateur utilise lun de ces caractres, il est souhaitable que ceux-ci rapparaissent tels quels par la suite.
Voici un exemple :

Listing 7.15 : htmlspecialchars.php


<html> <head><title>HTMLSpecialChars</title></head> <body> <p> <?php $chaine = "Un message avec du HTML <i> &, , \"

et des </i>";

388

Gestion des caractres spciaux

echo $chaine."<br />\n"; echo htmlspecialchars($chaine); ?> </p> </body> </html>

Voici le code source obtenu :


<html> <head><title>HTMLSpecialChars</title></head> <body> <p> Un message avec du HTML <i> &, , " et des </i><br /> Un message avec du HTML &lt;i&gt; &amp;, , &quot; et des &lt;/i&gt;</p> </body> </html>

Et, donc, le rsultat du navigateur :


Un message avec du HTML &, , " et des Un message avec du HTML <i> &, , " et des </i>

Une autre fonction trs similaire permet de transformer tous les caractres spciaux en leurs quivalents HTML. Elle sappelle htmlEntities().

htmlEntities()
Retourne une chane de caractres pour laquelle tous les caractres spciaux (y compris les caractres accentus) ont t convertis en leurs quivalents HTML.

7. La manipulation des chanes de caractres

Syntaxe $chaine $apostrophes

string htmlEntities(string $chaine[, int $apostrophes [, string $encodage]]) Chane de caractres transformer. Au choix : ENT_COMPAT (par dfaut), pour que cette fonction ne transforme que les guillemets et laisse les apostrophes telles quelles. ENT_QUOTES, pour transformer les apostrophes et les guillemets. ENT_NOQUOTES, pour ne transformer ni les apostrophes ni les guillemets. Par dfaut, il vaut "ISO-8859-1". La chane transforme.

$encodage retour

Voici le script dexemple :

389

Chapitre 7

La manipulation des chanes de caractres

Listing 7.16 : htmlentities.php


<html> <head><title>HTMLEntities</title></head> <body> <p> <?php $chaine = "Un message avec du HTML <i> &, , \" echo $chaine."<br />\n"; echo htmlEntities($chaine); ?> </p> </body> </html>

et des </i>";

Voici le rsultat obtenu lcran :


Un message avec du HTML &, , " et des Un message avec du HTML <i> &, , " et des </i>

et voici le code source correspondant :


<html> <head><title>HTMLEntities</title></head> <body> <p> Un message avec du HTML <i> &, , " et des </i><br /> Un message avec du HTML &lt;i&gt; &amp;, &egrave;, &quot; &lt;/i&gt;</p> </body> </html>

et des

7. La manipulation des chanes de caractres

get_html_translation_table()
Permet de placer, dans un tableau associatif, les tables de conversion des caractres spciaux en leurs quivalents HTML, utilises par les fonctions htmlSpecialChars() et htmlEntities(). Syntaxe $table array get_html_translation_table(int $table [, int $apostrophes]) Table rcuprer, au choix : HTML_ENTITIES, pour la table utilise par htmlEntities(). HTML_SPECIALCHARS, pour la table utilise htmlSpecialChars(). Au choix : ENT_COMPAT (par dfaut), pour que cette fonction ne transforme que les guillemets et laisse les apostrophes telles quelles.

par

$apostrophes

390

Gestion des caractres spciaux

ENT_QUOTES, pour transformer les apostrophes et les guillemets. ENT_NOQUOTES, pour ne transformer ni les apostrophes ni les guillemets. retour Un tableau associatif ayant pour cls les caractres spciaux, et pour valeurs leurs quivalents HTML.

Voici un script dexemple :

Listing 7.17 : get_html_translation_table.php


<?php print_r(get_html_translation_table(HTML_ENTITIES)); print_r(get_html_translation_table(HTML_SPECIALCHARS)); ?>

dont le rsultat est :


Array ( [ ] => &nbsp; [] => &iexcl; [] => &cent; [] => &pound; [] => &curren; [] => &yen; [] => &brvbar; [] => &sect; [] => &uml; [R] => &copy; [] => &ordf; [ ] => &laquo; [w] => &not; [-] => &shy; [T] => &reg; [-] => &macr; [] => &deg; [] => &plusmn; [_] => &sup2; [`] => &sup3; [] => &acute; [] => &micro; [] => &para; [] => &middot; [q] => &cedil; [^] => &sup1; [] => &ordm; [ ] => &raquo; [] => &frac14; [] => &frac12; [] => &frac34; [] => &iquest; [] => &Agrave;

7. La manipulation des chanes de caractres 391

Chapitre 7

La manipulation des chanes de caractres

[] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [v U] [] [] [] ] [Y [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] []

=> => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => =>

&Aacute; &Acirc; &Atilde; &Auml; &Aring; &AElig; &Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc; &Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times; &Oslash; &Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave; &aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave; &eacute; &ecirc; &euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde; &ograve; &oacute; &ocirc;

7. La manipulation des chanes de caractres 392

Gestion des caractres spciaux

[] [] [] [] [] [] [] [] [y ] [] [&] ["] [<] [>] ) Array ( [&] ["] [<] [>] )

=> => => => => => => => => => => => => =>

&otilde; &ouml; &divide; &oslash; &ugrave; &uacute; &ucirc; &uuml; &yacute; &thorn; &amp; &quot; &lt; &gt;

=> => => =>

&amp; &quot; &lt; &gt;

nl2br()
Retourne une chane de caractres dans laquelle les retours chariot ont t transforms en balises de retours de lignes HTML (<br />). Syntaxe $chaine retour string nl2br(string $chaine) Chane de caractres transformer. La chane transforme.

7. La manipulation des chanes de caractres

Listing 7.18 : nl2br.php


<html> <head><title>nl2br</title></head> <body> <p> <?php $chaine = "Un message avec des retours de ligne"; echo $chaine."<br />\n"; echo nl2br($chaine); ?> </p> </body> </html>

393

Chapitre 7

La manipulation des chanes de caractres

Voici la sortie lcran :


Un message avec des retours de ligne Un message avec des retours de ligne

Et voici le code HTML gnr :


<html> <head><title>nl2br</title></head> <body> <p> Un message avec des retours de ligne<br /> Un message avec <br /> des retours <br /> de ligne</p> </BODY> </HTML>

Modification depuis PHP 4.3.2 Le comportement de cette fonction a lgrement t modifi pour supporter tout types de retours la ligne. Danciens scripts peuvent donc se comporter diffrement sur une version rcente de PHP.

7. La manipulation des chanes de caractres

Conversion dun alphabet un autre

convert_cyr_string()
Retourne une chane convertie dun alphabet cyrillique vers un autre. Syntaxe $chaine $depuis $vers retour string convert_cyr_string(string $chaine, string $depuis, string $vers) Chane transformer. Alphabet cyrillique de dpart. Alphabet cyrillique voulu. La chane de caractres transforme.

Les valeurs de $depart et $vers sont prendre parmi les suivantes :

394

Manipulation des balises HTML

Tableau 7.3 : Codes des alphabets cyrilliques


Code k w i a d m Dsignation koi8-r windows-1251 iso8859-5 x-cp866 x-cp866 x-mac-cyrillic

hebrev()
Retourne un texte converti de lhbreu en texte lisible. Cette fonction naffecte, hormis les caractres de ponctuation, que les caractres dont le code ASCII est compris entre 224 et 251. Syntaxe $chaineHebreu retour string hebrev(string $chaineHebreu [, int $caracteresParLigne]); Chane transformer. La chane transforme.

$caracteresParLigne Nombre de caractres maximum par ligne.

hebrevc()
Cette fonction a le mme effet que hebrev(), mais transforme, en plus, les caractres \n en <br />\n. Syntaxe $chaineHebreu retour string hebrevc(string $chaineHebreu [, int $caractresParLigne]); Chane de caractres transformer. La chane transforme.

7. La manipulation des chanes de caractres

$caracteresParLigne Nombre de caractres maximum par ligne.

7.5.

Manipulation des balises HTML

Une fonction trs utile permet de supprimer les balises PHP et HTML pour, par exemple, retirer les balises ajoutes par des visiteurs dun forum. Elle sappelle strip_tags().

395

Chapitre 7

La manipulation des chanes de caractres

strip_tags()
Retourne une chane de caractres pour laquelle les balises PHP et HTML ont t supprimes. Syntaxe $chaine $balisesPermises retour string strip_tags(string $chaine[, string $balisesPermises]) Chane de caractres transformer. Chane compose de la concatnation des balises HTML ne pas supprimer. La chane transforme.

Voici un petit exemple :


<?php $chaine="Du texte avec <b>du gras</b>, <i>de litalique</i> et du <u>soulign&eacute;</u>"; echo $chaine."\n<br />"; echo strip_tags($chaine)."\n<br />"; echo strip_tags($chaine,"<b>")."\n<br />"; echo strip_tags($chaine,"<b><u>")."\n<br />"; ?>

dont voici le rsultat :


Du texte <br />Du <br />Du <br />Du <br /> avec <b>du texte avec texte avec texte avec gras</b>, <i>de litalique</i> et du <u>soulign&eacute;</u> du gras, de litalique et du soulign&eacute; <b>du gras</b>, de litalique et du soulign&eacute; <b>du gras</b>, de litalique et du <u>soulign&eacute;</u>

7. La manipulation des chanes de caractres

Amlioration depuis PHP 4.3.2 Cette fonction a t amliore et gre mieux les signes < et > qui ne sont pas des balises.

get_meta_tags() (ne fonctionne pas sous Windows)


Permet dextraire les balises dune chane de caractres, et de les mettre dans un tableau. Syntaxe $nomFichier $cheminInclusion retour array get_meta_tags(string $nomFichier [, boolean $cheminInclusion]) Nom du fichier traiter. TRUE si le fichier doit tre recherch dans les chemins standard dinclusion. Tableau associatif ayant pour cls les noms des balises "meta" et, pour valeurs, les contenus des attributs "content" de ces mmes balises.

396

Manipulation des balises HTML

Voici un script dexemple suivi du fichier de test :

Listing 7.19 : get_meta_tags.php


<?php $tableau = get_meta_tags("test.html"); print_r($tableau); ?>

Le fichier de test :

Listing 7.20 : test.html


<head> <meta name="author" content="Damien, Laurent, PEM et Thomas"> <meta name="tags" content="Livre PHP"> </head>

Et le rsultat obtenu :
Array ( [author] => Damien , Laurent, PEM et Thomas [tags] => Livre PHP )

Suppression des espaces


Certaines fonctions permettent deffacer les espaces superflues en dbut et/ou fin de chanes de caractres.

7. La manipulation des chanes de caractres

trim()
Retourne une chane de caractres sans les espaces (ou autres caractres) de dbut et de fin. Syntaxe $chaine $listeCaracteres retour string trim(string $chaine [, string $listeCaracteres]) Chane de caractres transformer. Caractres supprimer (cette option nexiste que depuis la version 4.1.0 de PHP). La chane transforme.

Par dfaut, voici un tableau des caractres supprims :

397

Chapitre 7

La manipulation des chanes de caractres

Tableau 7.4 : Caractres supprims par dfaut


Caractre \0 \t \n \x0B \r (espace) Code ASCII (en dcimal puis hexadcimal) 0 (0x00) 9 (0x09) 10 (0x0A) 11 (0x0B) 13 (0x0D) 32 (0x20) Description Caractre NUL. Tabulation horizontale. Nouvelle ligne. Tabulation verticale. Retour chariot. Caractre despacement.

Voici un script dexemple :

Listing 7.21 : trim.php


<?php $chaine="\t\t \t Le texte important \t\t"; echo "Chane de dpart:\n"; echo $chaine."\n"; echo "Chane aprs avoir utilis la fonction trim() sans paramtre:\n"; echo trim($chaine)."\n"; echo "Chane aprs avoir utilis la fonction trim() avec paramtre:\n"; echo trim($chaine,"\t")."\n"; ?>

7. La manipulation des chanes de caractres

Et voici le rsultat obtenu (pour quil soit lisible, nous avons remplac manuellement les tabulations par \t :
Chane de dpart: \t\t \t Le texte important \t\t Chane aprs avoir utilis la fonction trim() sans paramtre: Le texte important Chane aprs avoir utilis la fonction trim() avec paramtre: \t Le texte important

398

Manipulation des balises HTML

ltrim()
Retourne une chane de caractres dans laquelle toutes les espaces (ou autres caractres) de dbut de chane ont t supprimes. Syntaxe $chaine $listeCaracteres retour string ltrim(string $chaine [, string $listeCaracteres]) Chane de caractres transformer. Caractres supprimer (cette option nexiste que depuis la version 4.1.0 de PHP). La chane transforme.

rtrim()
Retourne une chane de caractres dans laquelle toutes les espaces de fin de chane ont t supprimes. Syntaxe $chaine $listeCaracteres retour string ltrim(string $chaine[, string $listeCaracteres]) Chane de caractres transformer. Caractres supprimer (cette option nexiste que depuis la version 4.1.0 de PHP). La chane transforme.

rtrim() possde un alias appel chop().

Modication de casse
Pour changer la casse des caractres, il existe quatre fonctions strToUpper(), strToLower(), ucFirst() et enfin ucWords(). Un script regroupant ces quatre fonctions sera prsent aprs le dtail de celles-ci.

7. La manipulation des chanes de caractres

strToUpper()
Retourne une chane dans laquelle tous les caractres ont t mis en majuscules. Syntaxe $chaine retour string strToUpper(string $chaine) Chane de caractres transformer. La chane transforme en majuscules.

399

Chapitre 7

La manipulation des chanes de caractres

strToLower()
Retourne une chane dans laquelle tous les caractres ont t mis en minuscules. Syntaxe $chaine retour string strToLower(string $chaine) Chane de caractres transformer. La chane transforme en minuscules.

ucFirst()
Retourne une chane de caractres dans laquelle le premier caractre de la chane a t mis en majuscule (sans que les autres ne soient changs). Syntaxe $chaine retour string ucFirst(string $chaine) Chane de caractres transformer. La chane transforme.

ucWords()
Retourne une chane de caractres dans laquelle le premier caractre de chacun des mots a t mis en majuscule (sans que les autres ne soient changs). Syntaxe $chaine retour string ucWords(string $chaine) Chane de caractres transformer. La chane transforme.

7. La manipulation des chanes de caractres

Voici quelques lignes de code prsentant ces fonctions :

Listing 7.22 : majuscules.php


<?php $chaine="cette ChaiNe serA transFormee."; echo strtolower($chaine)."<br />\n"; echo strtoupper($chaine)."<br />\n"; echo ucfirst($chaine)."<br />\n"; echo ucwords($chaine)."<br />\n"; ?>

Et voici le rsultat obtenu :


cette CETTE Cette Cette chaine CHAINE ChaiNe ChaiNe sera SERA serA SerA transformee. TRANSFORMEE. transFormee. TransFormee.

400

Insertion de motifs

7.6.

Insertion de motifs

chunk_split()
Retourne une chane de caractres dans laquelle un motif (par dfaut, un retour la ligne) a t insr espaces rguliers. Syntaxe $chaine $pas $separateur retour string chunck_split(string $chaine [, int $pas [, string $separateur]]) Chane de caractres transformer. Nombre de caractres aprs lesquels insrer le sparateur. (par dfaut 73). Caractres utiliss pour sparer deux blocs. La chane transforme.

Voici un script dexemple (trs simple) :

Listing 7.23 : chunk_split


<?php echo chunk_split("abcdefghijklmnopqrstuvwxyz0123456789",6,"<br />\n"); echo chunk_split("a1b2233e34",2,":"); ?>

Et le rsultat obtenu :
abcdef ghijkl mnopqr stuvwx yz0123 456789 a1:b2:23:3e:34:

7. La manipulation des chanes de caractres

wordWrap()
Permet dinsrer des coupures rgulirement. Syntaxe $chaine $largeur $cassure $coupure retour string wordWrap(string $chaine [, int $largeur [, string $cassure [, bool $coupure]]]) Chane de caractres transformer. Nombre de caractres aprs lesquels insrer les caractres de cassure (73 par dfaut). Chane de caractres servant la cassure (\n par dfaut). Indique si un mot doit tre ou non coup. La chane de caractres transforme.

401

Chapitre 7

La manipulation des chanes de caractres

str_pad()
Permet de complter une chane de caractres par un motif. Syntaxe $chaine $longueurFinale $motif $alignement string str_pad(string $chaine, int $longueurFinale [, string $motif [, int $alignement]]) Chane de caractres transformer. Longueur que fera la chane de caractres aprs transformation. Motif pour le remplissage (caractre despacement par dfaut). Au choix : STR_PAD_RIGHT (par dfaut), si le motif doit tre rpt droite de la chane. STR_PAD_LEFT, si le motif doit tre rpt gauche de la chane. STR_PAD_BOTH, si le motif doit tre rpt de part et dautre de la chane. retour La chane de caractres transforme.

Voici un script dexemple trs simple :

Listing 7.24 : str_pad.php


<?php echo echo echo echo ?> "[".str_pad("Cool", "[".str_pad("Cool", "[".str_pad("Cool", "[".str_pad("Cool", 10)."]\n"; 10, " ", STR_PAD_LEFT)."]\n"; 10, " ", STR_PAD_BOTH)."]\n"; 10, "-=", STR_PAD_BOTH)."]\n";

Et le rsultat obtenu :

7. La manipulation des chanes de caractres

[Cool ] [ Cool] [ Cool ] [-=-Cool-=-]

7.7.

Fusion et dcoupe

implode()
Permet, partir dun tableau, de reconstituer une chane de caractres.

402

Fusion et dcoupe

Syntaxe $entreElements $tableau retour

string implode([string $entreElements,] array $tableau) Chane de caractres placer entre deux lments du tableau. Chane vide par dfaut depuis PHP 4.3.0. Tableau de chanes de caractres. La chane de caractres reconstitue.

Listing 7.25 : explode.php


<?php print_r(explode("\n","Ceci\nest\nune\nphrase en plusieurs\nlignes")); print(implode(" ", explode("\n","Ceci\nest\nune\nphrase en plusieurs\nlignes"))); ?>

Voici le rsultat de ce script :


Array ( [0] => Ceci [1] => est [2] => une [3] => phrase en plusieurs [4] => lignes ) Ceci est une phrase en plusieurs lignes

explode()
Permet de retourner un tableau contenant les morceaux de chanes spars par un dlimiteur dfini par le programmeur. Syntaxe $separateur $chaine $limite retour array explode(string $separateur, string $chaine [, int $limite]) Chane de caractres sparant les diffrents blocs. Chane de caractres transformer. Nombre maximal de blocs, le restant tant mis dans le dernier bloc. Le tableau index en question.

7. La manipulation des chanes de caractres

strtok()
Permet de parcourir une chane morceau par morceau, par appels successifs la fonction.

403

Chapitre 7

La manipulation des chanes de caractres

Syntaxe $chaine $separateur

string strtok(string $chaine, string $separateur) Chane de caractres parcourir. Dfinit les caractres sparant deux morceaux ; nimporte lequel des caractres de sparation est considr comme une coupure entre deux sous-chanes. Un des morceaux.

retour

Voici quelques exemples :

Listing 7.26 : strtok.php


<?php //exemple 1 $sousChaine=strtok("Element 1|Element 2|Element 3","|"); while ($sousChaine) { echo $sousChaine."<br />\n"; $sousChaine=strtok("|"); } //exemple 2 $sousChaine=strtok("Element 1|Element 2|Element 3"," |"); while ($sousChaine) { echo $sousChaine."<br />\n"; $sousChaine=strtok(" |"); } //exemple 3 echo strtok("Element 1|Element 2|Element 3","|")."<br />\n"; echo strtok(" ")."<br />\n"; echo strtok("n")."<br />\n"; ?>

Et voici le rsultat :

7. La manipulation des chanes de caractres

Element Element Element Element 1 Element 2 Element 3 Element Element 2|Eleme

1 2 3

404

Fusion et dcoupe

Autres...

str_repeat()
Permet de rpter une chane. Syntaxe $chaine $nb retour string str_repeat(string $chaine, int $nb) Chane de caractres rpter. Nombre de fois o la chane doit tre rpte. La chane de caractres rpte.

Voici un code dexemple :

Listing 7.27 : str_repeat.php


<?php echo str_repeat(":-",20); echo str_repeat(":-) ",10); ?>

Et le rsultat correspondant :
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-) :-) :-) :-) :-) :-) :-) :-) :-) :-)

strrev()
Retourne une chane de caractres dans laquelle lordre des caractres a t invers. Syntaxe $chaine retour Voici un exemple :
<?php $chaine="Et se resservir ivresse reste"; echo $chaine."<br />\n"; echo strrev($chaine)."<br />\n"; function estUnPalindrome($chaine) { return ($chaine==strrev($chaine)) ? "$chaine est un palindrome" : "$chaine nest pas un palindrome"; }

7. La manipulation des chanes de caractres

string strrev(string $chaine) Chane retourner. Chane inverse.

405

Chapitre 7

La manipulation des chanes de caractres

echo echo echo echo echo ?>

estUnPalindrome("ici")."<br />\n"; estUnPalindrome("chocolat")."<br />\n"; estUnPalindrome("radar")."<br />\n"; estUnPalindrome("rotor")."<br />\n"; estUnPalindrome("voiture")."<br />\n";

dont voici le rsultat :


Et se resservir ivresse reste etser esservi rivresser es tE ici est un palindrome chocolat nest pas un palindrome radar est un palindrome rotor est un palindrome voiture nest pas un palindrome

str_rot13()
Effectue une permutation circulaire sur les lettres de lalphabet, chacune des lettres tant dcale de treize places ; ainsi a deviendra n. Syntaxe $chaine retour string str_rot13(string $chaine) Chane de caractres transformer. Chane de caractres transforme.

Voici un script dexemple :

7. La manipulation des chanes de caractres

Listing 7.28 : str_rot13.php


<?php echo str_rot13("abcdefghijklmnopqrstuvwxyz")."\n"; echo str_rot13("ABCDEFGHIJKLMNOPQRSTUVWXYZ")."\n"; echo str_rot13(str_rot13("abcdefghijklmnopqrstuvwxyz"))."\n"; ?>

dont le rsultat est :


nopqrstuvwxyzabcdefghijklm NOPQRSTUVWXYZABCDEFGHIJKLM abcdefghijklmnopqrstuvwxyz

Cryptage Mme si cela pourrait ressembler une fonction de cryptage, il nen est rien vu que cette fonction est trs facilement rversible (il suffit de lappliquer elle-mme).

406

Fusion et dcoupe

Somme de contrle et cryptage

crc32()
Calcul dune somme de contrle sur 32 bits de la chane de caractres. Ce calcul est particulirement utile pour vrifier quune chane de caractres na pas t altre (suite une dficience logicielle ou matrielle, ou encore un acte de malveillance). Syntaxe $chaine retour Voici un exemple : int crc32(string $chaine) Chane dont vous souhaitez la "checksum". Checksum sur 32 bits.

Listing 7.29 : crc32.php


<?php echo echo echo echo echo ?> crc32("Chaine de caracteres"); "<br />\n"; crc32("Chaine"); "<br />\n"; crc32("Test");

dont le rsultat serait :


169821353 -1820961062 2018365746

7. La manipulation des chanes de caractres

md5()
Retourne une version crypte dune chane de caractres base sur le calcul du md5 (chane hexadcimale de 32 caractres). Syntaxe $chaine retour string md5(string $chaine) Chane de caractres dont vous souhaitez calculer le md5. md5 de la chane.

Listing 7.30 : md5.php


<?php echo md5("Calcul de md5"); echo "<br />\n"; echo md5("Un autre calcul de md5"); ?>

407

Chapitre 7

La manipulation des chanes de caractres

dont le rsultat est :


15c620ee8e52f6143383138a079bf54b 05c411550c749adc841fa0f2f9a2cc13

crypt()
Retourne une version crypte dune chane de caractres base sur la fonction dencryptage DES. Syntaxe $chaine $sel string crypt(string $chaine [, string $sel]) Chane dont vous souhaitez le cryptage. Chane de deux caractres permettant de calculer la cl (si aucune nest fournie, PHP se charge den crer une alatoirement). Pour comparer une chane une chane crypte, vous devrez utiliser comme valeurs les deux premiers caractres de la chane crypte (ou la chane crypte entire, sachant que seuls les deux premiers caractres seront pris en compte). Cl obtenue partir de la chane de caractres et du sel.

Retour

Listing 7.31 : crypt.php


<?php $motDePasseInitiale = "motDePasse"; $cle = crypt($motDePasseInitiale); echo $cle."<br />\n"; $motDePassePropose = "motDePasse"; if (crypt($motDePassePropose, $cle) == $cle) echo "Le mot de passe est bon"; else echo "Le mot de passe est faux"; ?>

7. La manipulation des chanes de caractres

Le rsultat est :
t.Gvi9zyHUxp2 Le mot de passe est bon

Cryptologie Les fonctions md5() et crypt() sont de vritables fonctions de cryptage. De ce fait, elles ne sont pas rversibles. La comparaison dune chane de caractres avec une autre stocke sous sa forme crypte doit toujours se faire en cryptant la chane fournie, et en comparant le rsultat obtenu avec la version stocke (et non en dcryptant la version stocke et en comparant le rsultat avec la chane fournie). Pour la fonction crypt(), qui ncessite un paramtre supplmentaire, vous devrez utiliser la version crypte, comme cela est fait dans lexemple prcdent.

408

Expressions rgulires

7.8.

Expressions rgulires

Une expression rgulire sert faire lanalyse lexicale (parser) dune chane de caractres. Elle va servir, par exemple, reprer une valeur dans une chane, ou encore reprer des sous-chanes particulires. Pour cela, il va falloir dfinir un motif que lon appelle expression rgulire. Il existe deux normes pour dfinir une expression rgulire, Perl et POSIX. Entre Perl et POSIX, les diffrences sont minimes. Si vous connaissez les expressions rgulires du monde UNIX, alors vous connaissez dj la norme POSIX.

Perl
Gnralits La plus simple
La plus simple des expressions rgulires est une sous-chane de caractres compose de chiffres, de lettres et despaces. Lexpression rgulire "morceau rechercher" pourra servir rechercher la sous-chane "morceau rechercher" dans une chane.

Les mtacaractres
Le point
Un caractre trs utile est le point ".". Dans une expression rgulire, il remplace nimporte quel caractre. Par exemple, "PHP. est la dernire version" est une expression regulire pour "PHP3 est la dernire version" ou "PHP4 est la dernire version", mais ne fonctionnera pas pour "PHP 10 est la dernire version", car 10 est sur deux caractres. (Inversement "PHP.. est la dernire version" fonctionnera pour la version 10, mais pas pour les versions 3 et 4.) Utiliser le point tel quel peut poser problme si lon veut rechercher le caractre point, et uniquement celui-ci. En effet, pour rechercher "3.14", il ne faudra pas crire "3.14", sans quoi les expressions "3F14", "3214", "3:14" seront reconnues par cette expression rgulire. Pour utiliser le caractre point, il faut le faire prcder du caractre dchappement: "\". Pour rechercher "3.14" il faut donc crire "3\.14".

7. La manipulation des chanes de caractres

Le point dinterrogation
Le point dinterrogation permet dindiquer la prsence dau plus une occurrence dun caractre. Le point dinterrogation est mettre aprs le caractre en question. Voici quelques exemples : "chanes? de caractres" reconnatra "chanes de caractres" et "chane de caractres". "points? et interrogations?" permettra de reconnatre "points et interrogations" "points et interrogation", "point et interrogations" et "point et interrogation".

409

Chapitre 7

La manipulation des chanes de caractres

Pour utiliser le caractre ? en tant que simple caractre (et non comme mtacaractre), il faut le faire prcder de \.

Le signe plus
Le signe plus (+) permet dindiquer la prsence dune ou plusieurs occurrences dun caractre. Le signe plus est mettre aprs le caractre en question. Voici quelques exemples : "Whaoo+" reconnatra "Whaoo", "Whaooo", "Whaoooo" mais pas "Whao". "coo+l" servira pour reconnatre "cool", "coool", "cooooooool" mais pas "col". Pour utiliser le caractre + en tant que simple caractre (et non comme mtacaractre), il faut le faire prcder de \.

Le signe multiplier
Le signe multiplier (*)permet dindiquer la prsence daucune, dune ou de plusieurs occurrences dun caractre. Le signe multiplier est mettre aprs le caractre en question. Voici quelques exemples: "Whao*" reconnatra "Wha", "Whao", "Whaoo" "cooo*l" servira pour reconnatre "cool", "coool", "cooooooool" Pour utiliser le caractre * en tant que simple caractre (et non comme mtacaractre), il faut le faire prcder de \.

Combinaison de mtacaractres
Le point peuttre combin avec les signes ?, + ou *. Cela permettra dindiquer, par exemple, la prsence de nimporte quel caractre au moins une fois dans le cas du signe +. Voici quelques exemples :

7. La manipulation des chanes de caractres

"Cest .*bien" servira pour "Cest trs bien", "Cest vraiment bien", "Cest rien bien" et mme "Cest bien".

Exemples
Voici une srie dexemples. Les expressions rgulires peuvent vite devenir complexes lire ; il suffit de procder par tapes pour viter les erreurs :

Tableau 7.5 : Exemples dexpressions rgulires


Expression a.z Dfinition Caractre a suivi dun seul caractre suivi de z Exemples reconnus az abz a_z azz a.z Exemples non reconnus az abcz a_-z abz

a\.z

Caractre a suivi du caractre . suivi de z

410

Expressions rgulires

Expression a.+z

Dfinition Caractre a suivi dau moins un caractre suivi de z Caractre a suivi dau moins un caractre . suivi de z Caractre a suivi dau moins un caractre + suivi de z Caractre a suivi dun ou daucun caractre b puis dun caractre c ou plus, puis dventuellement 1 ou plusieurs d puis dun e

Exemples reconnus abz abcz azzz a.z a..z az a+z a++z a+++z abcde acde abccccccde abce abccccce abcddddde

Exemples non reconnus az

a\.+z

az

a\++

az

ab?c+d*e

bcde abcd abde abbcde

Pour affiner la recherche, il est possible de dfinir certains types de caractres.

Tableau 7.6 : Ensembles de caractres


Notation \d \D \w \W \s \S \b \B \nnn Dfinition Tout caractre numrique (0, 1, 2, 3, 4, 5, 6, 7, 8, 9). Tout caractre non numrique. Tout caractre alphanumrique et le signe soulign _. Tout caractre qui nest pas alphanumrique ni le caractre soulign _. Tous les caractres despacement (espace, tabulation, retour chariot) et tout autre caractre qui nutiliserait pas dencre sur une imprimante. Tous les caractres qui ne sont pas des caractres despacement. Tous les caractres qui entourent un mot (caractres despacement, dbut et fin de ligne, ponctuation). Lensemble des caractres qui ne sont pas dans \b. Permet de dfinir un caractre par son code ASCII en base 8.

7. La manipulation des chanes de caractres

Voici une nouvelle srie dexemples illustrant ce que lon peut dfinir avec ces ensembles de caractres.

411

Chapitre 7

La manipulation des chanes de caractres

Tableau 7.7 : Exemples


Expression \w+@\w+\.com Dfinition Une srie de caractres alphanumriques (ou _) puis le signe @ puis une autre srie de caractres alphanumrique (ou _) suivi de .com. Un nombre cinq chiffres. Exemples reconnus Exemples non reconnus

thomas@toutestfacile thomas@toutestfacile.fr .com thomas@toutestfacile toto.com

\d\d\d\d\d\ \b\d\w\D\w\ d\s\W\d

01234 34534

0123 abcde 0a1b1 -2 0abc1 d2

Le dbut de ligne suivi dun 0abc1 -2 chiffre puis dun caractre 0_aa1 %2 alphanumrique, puis dun caractre qui nest pas un chiffre, puis dun caractre alphanumrique, puis dun chiffre, dun caractre despacement, dun caractre non alphanumrique et enfin dun chiffre.

Il est galement possible de prciser les nombres minimum et maximum doccurrences dun caractre en utilisant une notation entre accolades, les deux valeurs tant spares par une virgule.
ab{2,4}c signifie : un caractre a suivi de deux quatre caractres b puis du caractre c.

Pour permettre une alternative, il suffit dutiliser le caractre |.


ab|ac signifie : soit la chane ab, soit la chane ac et aucune autre.

7. La manipulation des chanes de caractres

Enfin, pour permettre certains caractres ou une certaine plage de caractres, on peut utiliser des crochets.
a[bcde]f permettra de reconnatre abf, acf, adf et aef mais pas abcf par exemple.

Pour dfinir une certaine plage de caractres, il suffit de placer un signe entre les caractres dlimitant la plage.
a[be]f est quivalent lexemple prcdent.

Pour ajouter le signe la liste des caractres possibles, il suffit de le placer juste avant le crochet fermant.
a[be]f permettra de reconnatre abf, acf, adf, aef et af.

Lutilisation des crochets peut galement permettre dexclure certains caractres en utilisant le caractre dexclusion ^.
[^bc]oule permettra de reconnatre foule, roule mais pas boule ni coule.

lintrieur des crochets, les rgles dchappement ne sappliquent pas de la mme manire ; seuls les caractres [, ] et \ doivent tre prcd du signe \.

412

Expressions rgulires

Tableau 7.8 : Dautres exemples


Expression [02468]{3,5} Dfinition Un nombre de trois cinq caractres compos de chiffres pairs. Exemples reconnus 24804 8602 666 a_111 g_753 Exemples non reconnus 135 1222 20 7_765 4_a33

[az]_[09]{3,3} Une lettre minuscule suivie du signe _ puis dexactement trois chiffres. [\[\]\\]+ Une composition de caractres [, ] et \. Un ou plusieurs caractres alphanumriques ou ., _, suivi de @, de un ou plusieurs caractres alphanumriques, dun point puis de deux ou trois lettres.

\[]\][]\][ [\] \\\]][[[

[a]

[azAZ09._] +@[azAZ09]+ \.[azAZ]{2,3}

livrephp@toutestfacile.com @toutestfacile.com manuel@brazil.br toto@_.com thomas.heute@toutestfacile .com

Dbut et n de ligne
En dehors des crochets, le caractre ^ permet de dfinir le dbut dune chane. Le caractre $, lui, dsigne la fin dune chane.
abc reconnatra "abc", "dabc", "dabce". ^abc reconnatra "abc" et "abcd".

7. La manipulation des chanes de caractres

^abc$ reconnatra "abc" (uniquement).

Les options
Les expressions rgulires Perl sont gnralement crites entre deux slashes /. Les caractres avant le premier slash et ceux aprs le dernier permettent de spcifier quelques options. Le caractre avant le premier slash est sans effet avec les fonctions PHP. Celui situ aprs le dernier slash peut tre par exemple un :
j j j

i afin de prciser que la recherche doit tre insensible la casse. s afin que le mtacaractre . concerne galement les retours la ligne. Dautres valeurs encore.

413

Chapitre 7

La manipulation des chanes de caractres

Les fonctions PHP Filtrage par expression rgulire

preg_grep()
Retourne un tableau ne contenant que les lments vrifiant une expression rgulire. Syntaxe $expReg $chaines retour array preg_grep(string expReg, array $chaines) Lexpression rgulire filtrante. Chanes de caractres vrifier. Tableau sans les valeurs ne vrifiant pas lexpression rgulire.

Listing 7.32 : preg_grep.php


<?php $chaines = array( "toto@blabla.fr", "toto$blabla.fr", "toto$blabla.com", "toto_titi@blabla.com", ); print_r(preg_grep("/[a-zA-Z0-9._-]+@[a-zA-Z0-9]+\.[a-zA-Z]{2,3}/", $chaines)); ?>

dont le rsultat est :


Array ( [0] => toto@blabla.fr [3] => toto_titi@blabla.com )

7. La manipulation des chanes de caractres

Substitution par expression rgulire

preg_replace()
Recherche une portion de chane de caractres correspondant une expression rgulire et la remplace.

414

Expressions rgulires

Syntaxe $motif

mixed preg_replace(mixed $motif, mixed $remplacement, mixed $chaine[, int $limite]) Lexpression rgulire rechercher. Peut tre un tableau ; dans ce cas, si $remplacement est un tableau, alors les motifs seront remplacs par llment de mme index de $remplacement. Chane de substitution ; si celui-ci est une chane de caractres, alors tous les motifs trouvs seront remplacs par cette chane. Chane de caractres o effectuer les modifications. Si $chaine est un tableau, alors la recherche seffectue sur tous les lments du tableau. Si cet argument est spcifi, alors au plus $limite occurrences seront remplaces. $chaine modifie (sera un tableau si $chaine en est un).

$remplacement $chaine $limite retour

Voici un code source dexemple :

Listing 7.33 : preg_replace.php


<?php echo preg_replace("/\d+/", "...des chiffres...", "En 2000, 1123442 serveurs ...")."<br />\n"; $chaines=array("En 2000, 1123442 serveurs ...", "12 elephants sur un arbre"); print_r($chaines)."<br />\n"; print_r(preg_replace("/\d+/", "...des chiffres...", $chaines)); $motifs = array("/([a-zA-Z0-9._-]+)@([a-zA-Z0-9]+)\.com/", "/([a-zA-Z0-9._-]+)@([a-zA-Z0-9]+)\.fr/"); $remplacement = array("Une adresse en .com", "Une adresse en .fr"); $chaine = "test@toutestfacile.com et test@toutestfacile.fr"; echo $chaine."<br />\n"; print_r(preg_replace($motifs, $remplacement, $chaine)); ?>

7. La manipulation des chanes de caractres

dont le rsultat est :


En ...des chiffres..., ...des chiffres... serveurs ...<br /> Array ( [0] => En 2000, 1123442 serveurs ... [1] => 12 elephants sur un arbre ) Array ( [0] => En ...des chiffres..., ...des chiffres... serveurs ... [1] => ...des chiffres... elephants sur un arbre ) test@toutestfacile.com et test@toutestfacile.fr<br /> Une adresse en .com et Une adresse en .fr

415

Chapitre 7

La manipulation des chanes de caractres

Pour rutiliser un motif captur en remplacement, il suffit dy faire appel avec la syntaxe \\n, o n est la position du motif captur. Par exemple :

Listing 7.34 : preg_replace2.php


<?php echo preg_replace("/(\d+)/", "\\1", "En 2000, 1123442 serveurs ..."). "<br />\n"; ?>

dont le rsultat est :


En 2000, 1123442 serveurs ...

preg_replace() vs. str_replace() Bien quil soit possible dutiliser preg_replace() la place de str_replace(), il est tout de mme prfrable, pour des raisons de rapidit, dutiliser str_replace()lorsque le motif recherch savre tre une chane ne faisant intervenir aucun joker. Bien entendu, la diffrence ne se fera ressentir que si cette fonction est appele de nombreuses fois.

preg_replace_callback()
Cette fonction est semblable la prcdente, si ce nest quelle permet dappeler une fonction avec, en paramtre, les motifs capturs. Syntaxe $motif mixed preg_replace_callback(mixed $motif, mixed $fonction, mixed $subject [, int $limite]) Lexpression rgulire rechercher. Peut tre un tableau ; dans ce cas, si $remplacement est un tableau, alors les motifs seront remplacs par llment de mme index de $remplacement. Fonction appeler qui fera la transformation partir des motifs capturs. Chane de caractres o effectuer les modifications. Si $chaine est un tableau, alors la recherche seffectue sur tous les lments du tableau. Si cet argument est spcifi, alors au plus $limite occurrences seront remplaces. $chaine modifie (sera un tableau si $chaine en est un).

7. La manipulation des chanes de caractres

$fonction $chaine $limite retour

416

Expressions rgulires

Dcoupe par expression rgulire

preg_split()
Permet de casser une chane en sous-lments en prcisant le dlimiteur par une expression rgulire. Syntaxe $motif $chaine $limite $mode array preg_split(string $motif, string $chaine [, int $limite [, int $mode]]) Lexpression rgulire qui servira de dlimiteur. Chane de caractres casser. Nombre limite de sous-chanes. Options pouvant tre cumules par OU logique (|). PREG_SPLIT_NO_EMPTY : seules les chanes non vides seront retournes. PREG_SPLIT_DELIM_CAPTURE : les expressions entre parenthses entre les dlimiteurs de motifs seront aussi captures. Le tableau index des sous-chanes.

retour Voici un exemple :

Listing 7.35 : preg_split.php


<?php print_r(preg_split("/[:;-]/", "element 1:element 2-element 3;element 4")); ?>

dont le rsultat est :

7. La manipulation des chanes de caractres

Array ( [0] [1] [2] [3] )

=> => => =>

element element element element

1 2 3 4

Extraction par expression rgulire

preg_match()
Recherche un motif dans une chane de caractres.

417

Chapitre 7

La manipulation des chanes de caractres

Syntaxe $motif $chaine $resultat

int preg_match(string $motif, string $chaine [, array &$resultat [, int $option]) Le motif retrouver. Chane de caractres dans laquelle rechercher le motif. Variable dans laquelle sera copi un tableau index dont llment dindice 0 est le motif en entier, llment 1 le premier lment captur (entre parenthses), llment 2 le deuxime, etc. Seul PREG_OFFSET_CAPTURE est disponible. Cette option nest disponible que depuis PHP 4.3.0 Le nombre dlments capturs, ou FALSE si une erreur sest produite.

$option retour

Listing 7.36 : preg_match()


<?php echo preg_match("/([a-zA-Z0-9._-]+)@([a-zA-Z0-9]+)\.([a-zA-Z]{2,3})/", "Voici mon adresse: biblephp@exemple.com, elle est bidon",$elements); print_r($elements); ?>

dont le rsultat est :


1 Array ( [0] [1] [2] [3] )

=> => => =>

biblephp@exemple.com biblephp exemple com

7. La manipulation des chanes de caractres

preg_match_all()
Recherche un motif dans une chane de caractres, et ritre la recherche sur tout le reste de la chane de caractres. Syntaxe $motif $chaine $resultat $option int preg_match_all(string $motif, string $chaine, array &$resultat [, int $option]) Le motif rechercher. La chane de caractres rechercher. Le tableau o stocker les rsultats. Permet entre autres de dfinir lordre dans lequel ranger les rsultats. Cela peut tre dfini par les constantes : PREG_PATTERN_ORDER : $resultat[0] sera un tableau index contenant les motifs en entier, $resultat[1] sera un tableau contenant les premiers motifs entre parenthses.

418

Expressions rgulires

PREG_SET_ORDER : $resulat[0] sera un tableau des motifs entre parenthses de la premire sous-chane reconnue. PREG_OFFSET_CAPTURE est galement disponible depuis PHP 4.3.0, elle peut tre combine lune des deux prcdentes. retour Retourne le nombre de motifs retrouvs, ou FALSE si une erreur sest produite.

Listing 7.37 : preg_match_all.php


<?php echo preg_match_all("/<(\w*)>([^<]*)<\/\w*>/", "<b>Gras</b><i>Italique</i><u>Souligne</u>", $resultat)."\n"; print_r($resultat); echo preg_match_all("/<(\w*)>([^<]*)<\/\w*>/", "<b>Gras</b><i>Italique</i><u>Souligne</u>", $resultat, PREG_PATTERN_ORDER )."\n"; print_r($resultat); echo preg_match_all("/<(\w*)>([^<]*)<\/\w*>/", "<b>Gras</b><i>Italique</i><u>Souligne</u>", $resultat, PREG_SET_ORDER )."\n"; print_r($resultat); ?>

Le rsultat de ce script est :


3 Array ( [0] => Array ( [0] => <b>Gras</b> [1] => <i>Italique</i> [2] => <u>Souligne</u> ) [1] => Array ( [0] => b [1] => i [2] => u ) [2] => Array ( [0] => Gras [1] => Italique [2] => Souligne ) )

7. La manipulation des chanes de caractres 419

Chapitre 7

La manipulation des chanes de caractres

3 Array ( [0] => Array ( [0] => <b>Gras</b> [1] => <i>Italique</i> [2] => <u>Souligne</u> ) [1] => Array ( [0] => b [1] => i [2] => u ) [2] => Array ( [0] => Gras [1] => Italique [2] => Souligne ) ) 3 Array ( [0] => Array ( [0] => <b>Gras</b> [1] => b [2] => Gras ) [1] => Array ( [0] => <i>Italique</i> [1] => i [2] => Italique ) [2] => Array ( [0] => <u>Souligne</u> [1] => u [2] => Souligne ) )

7. La manipulation des chanes de caractres 420

Expressions rgulires

Divers

preg_quote()
Permet dchapper les caractres spciaux (. ,\\, +, * ,?, [, ^, ], $, (, ), {, }, =, !, <, >, |, :) des expressions rgulires. Syntaxe $chaine $delimiteur retour string preg_quote(string $chaine [, string $delimiteur]) Chane de caractres dont vous souhaitez chapper les caractres spciaux. Caractre qui sera galement chapp. Une chane de caractres dont les caractres ne sont pas des caractres spciaux.

Voici un court exemple montrant limportance dchapper les caractres spciaux :

Listing 7.38 : preg_quote.php


<?php $chaine="2*3+4"; // retournera 0 car lexpression regulire filtre les expressions // dont la dfinition est : // "0 ou plus 2 suivi de au moins un 3 et dun 4" echo preg_match("/$chaine/","2*3+4")."\n"; echo preg_quote($chaine)."\n"; // Ici les caractres + et = seront chapps. echo preg_match("/".preg_quote($chaine)."/","2*3+4"); ?>

7. La manipulation des chanes de caractres

dont le rsultat est :


0 2\*3\+4 1

Posix
Les expressions rgulires de POSIX sont trs semblables celles en Perl ; elles sont utilises sous UNIX pour crer des scripts.

421

Chapitre 7

La manipulation des chanes de caractres

Gnralits
La plus simple
La plus simple des expressions rgulires est une sous-chane de caractres compose de chiffres, de lettres et despaces. Lexpression rgulire "morceau rechercher" pourra servir rechercher la sous-chane "morceau rechercher" dans une chane.

Les mtacaractres
Le point
Un caractre trs utile est le point ".". Dans une expression rgulire, il remplace nimporte quel caractre. Par exemple "PHP. est la dernire version" est une expression regulire pour "PHP3 est la dernire version" ou "PHP4 est la dernire version", mais ne fonctionnera pas pour "PHP 10 est la dernire version", car 10 est sur deux caractres. (Inversement "PHP.. est la dernire version" fonctionnera pour la version 10, mais pas pour les versions 3 ou 4). Utiliser le point tel quel peut poser problme si lon veut rechercher le caractre point, et uniquement celui-ci. En effet, pour rechercher "3.14", il ne faudra pas crire "3.14", sans quoi les expressions "3F14", "3214", "3:14" seront reconnues par cette expression rgulire. Pour utiliser le caractre point en tant que simple caractre (et non comme mtacaractre), il faut le prcder du caractres dchappement : "\". Pour rechercher "3.14" il faut donc crire "3\.14".

Le point dinterrogation
7. La manipulation des chanes de caractres
Le point dinterrogation permet dindiquer la prsence dau plus une occurrence dun caractre. Le point dinterrogation est mettre aprs le caractre en question. Voici quelques exemples : "chanes? de caractres" reconnatra "chanes de caractres" et "chane de caractres". "points? et interrogations?" permettra de reconnatre "points et interrogations" "points et interrogation", "point et interrogations" et "point et interrogation". Pour utiliser le caractre ? en tant que simple caractre (et non comme mtacaractre), il faut le faire prcder de \.

Le signe "plus"
Le signe "plus" (+) permet dindiquer la prsence dune ou plusieurs occurrences dun caractre. Le signe plus est mettre aprs le caractre en question. Voici quelques exemples : "Whaoo+" reconnatra "Whaoo", "Whaooo", "Whaoooo" mais pas "Whao". "coo+l" servira pour reconnatre "cool", "coool", "cooooooool" mais pas "col".

422

Expressions rgulires

Pour utiliser le caractre + en tant que simple caractre (et non comme mtacaractre), il faut le faire prcder de \.

Le signe multiplier
Le signe multiplier (*)permet dindiquer la prsence daucune ou de plusieurs occurrences dun caractre. Le signe multiplier est mettre aprs le caractre en question. Voici quelques exemples: "Whao*" reconnatra "Wha", "Whao", "Whaoo" "cooo*l" servira pour reconnatre "cool", "coool", "cooooooool" Pour utiliser le caractre * en tant que simple caractre (et non comme mtacaractre), il faut le faire prcder de \.

Combinaison de mtacaractres
Le point peut tre combin avec les signes ?, + ou *. Cela permettra dindiquer, par exemple, la prsence de nimporte quel caractre au moins une fois dans le cas du signe +. Voici quelques exemples : "Cest .*bien" servira pour "Cest trs bien", "Cest vraiment bien", "Cest rien bien" et mme "Cest bien".

Des exemples
Voici une srie dexemples. Les expressions rgulires peuvent vite devenir complexes lire ; il suffit de procder par tapes pour viter les erreurs :

Tableau 7.9 : Exemples


Expression a.z Dfinition Caractre a suivi dun seul caractre suivi de z Exemples reconnus az abz a_z azz a.z abz abcz azzz a.z a..z az a+z a++z a+++z Exemples non reconnus az abcz a_-z abz az

7. La manipulation des chanes de caractres

a\.z a.+z

Caractre a suivi du caractre . suivi de z Caractre a suivi dau moins un caractre suivi de z Caractre a suivi dau moins un caractre . suivi de z Caractre a suivi dau moins un caractre + suivi de z

a\.+z

az

a\++

az

423

Chapitre 7

La manipulation des chanes de caractres

Expression ab?c+d*e

Dfinition Caractre a suivi dun ou daucun caractre b puis dun caractre c ou plus, puis dventuellement 1 ou plusieurs d puis dun e

Exemples reconnus abcde acde abccccccde abce abccccce abcddddde

Exemples non reconnus bcde abcd abde abbcde

Pour affiner la recherche, il est possible de dfinir certains types de caractres, avec la notation suivante :

Tableau 7.10 : Ensembles de caractres


Notation [:digit:] [:^digit:] [:alpha:] [:^alpha:] [:alnum:] [:^alnum:] [:ascii:] [:^ascii:] [:lower:] [:upper:] [:print:] Dfinition Tout caractre numrique (0, 1, 2, 3, 4, 5, 6, 7, 8, 9). Tout caractre non numrique. Tout caractre alphabtique. Tout caractre non alphabtique. Tout caractre alphanumrique. Tout caractre non alphanumrique. Tout caractre alphanumrique. Tout caractre non alphanumrique. Tout caractre alphabtique en minuscule. Tout caractre alphabtique en majuscule. Tout caractre imprimable. Tout caractre alphanumrique en minuscule et le signe soulign _. Tout caractre qui nest pas alphanumrique en minuscule ni le caractre soulign _. Tous les caractres despacement (espace, tabulation, retour chariot) et tout autre caractre qui nutiliserait pas dencre sur une imprimante. Tous les caractres qui ne sont pas des caractres despacement. Tout caractre de ponctuation. Tout caractre hexadcimal ([0-9a-f]). Tout caractre de contrle.

7. La manipulation des chanes de caractres

[:word:] [:^word] [:space:] [:^space:] [:punct:] [:xdigit:] [:cntrl:]

Voici une nouvelle srie dexemples illustrant ce que lon peut dfinir avec ces ensembles de caractres.

424

Expressions rgulires

Tableau 7.11 : Exemples


Expression [[:word:]] +@[[:word:]] +\.com Dfinition Exemples reconnus Exemples non reconnus

Une srie de caractres thomas@toutestfacile thomas@toutestfacile.fr alphanumriques (ou .com toto.com _) puis le signe @ puis une autre srie de caractres alphanumrique (ou _) suivi de .com. 0a1b1 -2 0abc1 d2

[:digit:][:word:] Un chiffre suivi dun 0abc1 -2 [:^digit:][:word:] caractre 0_aa1 %2 [:digit:][:space:] alphanumrique puis [:^word:][:digit:] dun caractre qui nest pas un chiffre puis un caractre alphanumrique puis un chiffre, un caractre despacement, dun caractre non alphanumrique et enfin un chiffre

Il est galement possible de prciser les nombres minimum et maximum doccurrences dun caractre en utilisant une notation entre accolades, les deux valeurs tant spares par une virgule.
ab{2,4}c signifie : un caractre a suivi de deux quatre caractres b puis du caractre c.

Pour permettre une alternative, il suffit dutiliser le caractre |.


ab|ac signifie : soit la chane ab, soit la chane ac et aucune autre.

7. La manipulation des chanes de caractres

Enfin, pour permettre certains caractres ou une certaine plage de caractres, on peut utiliser des crochets.
a[bcde]f permettra de reconnatre abf, acf, adf et aef, mais pas abcf par exemple.

Pour dfinir une certaine plage de caractres, il suffit de placer un signe entre les caractres dlimitant la plage.
a[be]f est identique lexemple prcdent.

Pour ajouter le signe la liste des caractres, il suffit de le placer juste avant le crochet fermant.
a[be]f permettra de reconnatre abf, acf, adf, aef et af.

Lutilisation des crochets peut galement permettre dexclure certains caractres, en utilisant le caractre dexclusion ^.
[^bc]oule permettra de reconnatre foule, roule mais pas boule ni coule.

lintrieur des crochets, les rgles dchappement ne sappliquent pas de la mme manire ; seuls les caractres [, ] et \ doivent tre prcds du signe \.

425

Chapitre 7

La manipulation des chanes de caractres

Tableau 7.12 : Dautres exemples


Expression [02468]{3,5} Dfinition Un nombre de trois cinq caractres composs de chiffres pairs. Exemples reconnus 24804 8602 666 a_111 g_753 Exemples non reconnus 135 1222 20 7_765 4_a33

[az]_[09]{3,3} Une lettre minuscule suivie du signe _ puis dexactement trois chiffres. [\[\]\\]+ Une composition de caractres [, ] et \.

\[]\][]\][ [\] \\\]][[[

[a]

[azAZ09._] Un ou plusieurs +@[azAZ09] caractres +\.[azAZ]{2,3} alphanumriques ou ., _, suivi de @, de un ou plusieurs caractres alphanumriques, dun point puis de deux ou trois lettres.

livrephp@toutestfacile @toutestfacile.com .com toto@_.com manuel@brazil.br thomas.heute@toutestfacile .com

Dbut et n de ligne
En dehors des crochets, le caractre ^ permet de dfinir le dbut dune chane. Le caractre $ dsigne la fin dune chane.
abc reconnatra "abc", "dabc", "dabce".

7. La manipulation des chanes de caractres

^abc reconnatra "abc" et "abcd". ^abc$ reconnatra "abc" (uniquement).

Les fonctions PHP Substitution par expression rgulire

ereg_replace()
Permet de remplacer une partie de chane de caractres par une autre. Syntaxe $expression $remplacement string ereg_replace(string $expression, string $remplacement, string $chaine) Expression rgulire qui correspond la partie remplacer. Chane de substitution qui peut rcuprer les motifs capturs par \\n , o n est le numro du motif.

426

Expressions rgulires

$chaine retour

Chane dans laquelle remplacer une partie. La chane de caractres modifie.

Voici un script dexemple :


<?php echo ereg_replace("([[:alpha:]]+)@([[:alpha:]]+)\.com", "Premire partie de ladresse:\\1 Domaine:\\2", "webmaster@toutestfacile.com"); ?>

dont le rsultat est :


Premire partie de ladresse:webmaster Domaine:toutestfacile

ereg_replace() vs. str_replace() Bien quil soit possible dutiliser ereg_replace() la place de str_replace(), il est tout de mme prfrable, pour des raisons de rapidit, dutiliser str_replace()lorsque le motif recherch savre tre une chane ne faisant intervenir aucun joker. Bien entendu, la diffrence ne se fera ressentir que si cette fonction est appele de nombreuses fois.

eregi_replace()
Permet de remplacer une partie de chane de caractres par une autre expression rgulire insensible la casse. Syntaxe $expression $remplacement $chaine retour string eregi_replace(string $expression, string $remplacement, string $chaine) Expression rgulire qui correspond la partie remplacer. Chane de substitution qui peut rcuprer les motifs capturs par \\n, o n est le numro du motif. Chane dans laquelle remplacer une partie. La chane de caractres modifie.

7. La manipulation des chanes de caractres

Voici un script dexemple :

Listing 7.39 : eregi_replace.php


<?php echo ereg_replace("([[:alpha:]]+)@([[:alpha:]]+)\.com", "Premire partie de ladresse:\\1 Domaine:\\2", "webmaster@toutestfacile.Com"); ?>

427

Chapitre 7

La manipulation des chanes de caractres

dont le rsultat est :


Premire partie de ladresse:webmaster Domaine:toutestfacile

Extraction et comparaison par expression rgulire

ereg()
Permet de retourner les motifs capturs dune chane de caractres ou, tout simplement, de vrifier si cette dernire satisfait une expression rgulire. Syntaxe $expression $chaine $resultat retour int ereg(string $expression, string $chaine [, array &$resultat]) Expression rgulire vrifier. Chane dont on veut vrifier quelle correspond lexpression rgulire. Les motifs capturs sont stocks dans ce tableau. TRUE si la chane vrifie lexpression rgulire, FALSE sinon.

Voici un script dexemple :

Listing 7.40 : ereg.php


<?php echo (ereg("([[:alpha:]]+)@([[:alpha:]]+)\.com", "webmaster@toutestfacile.com")) ? "Ca matche" : "Ca matche pas"; echo "<br />\n"; echo (ereg("([[:alpha:]]+)@([[:alpha:]]+)\.com", "webmaster@toutestfacile.COM")) ? "Ca matche" : "Ca matche pas"; ?>

7. La manipulation des chanes de caractres

dont le rsultat est :


Ca matche Ca matche pas

eregi()
Permet de retourner les motifs capturs dune chane de caractres ou, tout simplement, de vrifier si cette dernire satisfait une expression rgulire, sans tenir compte de la casse (les minuscules et majuscules sont confondues). Syntaxe $expression int eregi(string $expression, string $chaine[, array $resultat]) Expression rgulire vrifier.

428

Expressions rgulires

$chaine $resultat retour

Chane dont vous souhaitez extraire des motifs, ou vrifier quelle correspond lexpression rgulire. Les motifs capturs sont stocks dans ce tableau. TRUE si la chane vrifie lexpression rgulire, FALSE sinon.

Voici un script dexemple :

Listing 7.41 : eregi.php


<?php echo (eregi("([[:alpha:]]+)@([[:alpha:]]+)\.com", "webmaster@toutestfacile.com")) ? "Ca matche" : "Ca matche pas"; echo "<br />\n"; echo (eregi("([[:alpha:]]+)@([[:alpha:]]+)\.com", "webmaster@toutestfacile.COM")) ? "Ca matche" : "Ca matche pas"; ?>

dont le rsultat est :


Ca matche Ca matche

Dcoupe par expression rgulire

split()
Permet de dcouper une chane de caractres en morceaux selon une expression rgulire. Syntaxe $expression $chaine $limite retour array split(string $expression, string $chaine [, int $limite]) Expression rgulire du sparateur. Chane dcouper. Nombre dlments maximum du tableau. Un tableau des diffrentes parties spares par lexpression rgulire.

7. La manipulation des chanes de caractres

Encore un petit exemple dapplication :

Listing 7.42 : split.php


<?php print_r(split("[:;,.]", "Comment,separer;des.elements,dune:chaine")); ?>

429

Chapitre 7

La manipulation des chanes de caractres

qui produira :
Array ( [0] [1] [2] [3] [4] [5] )

=> => => => => =>

Comment separer des elements dune chaine

spliti()
Permet de dcouper une chane de caractres en morceaux, lexpression rgulire ignorant la casse des caractres. Syntaxe $expression $chaine $limite retour array split(string $expression, string $chaine[, int $limite]) Expression rgulire du sparateur. Chane dcouper. Nombre dlments maximum du tableau. Un tableau des diffrentes parties spares par lexpression rgulire.

Divers

7. La manipulation des chanes de caractres

sql_regcase()
Permet de crer une expression rgulire ngligeant la casse. Syntaxe $chaine retour Encore un exemple : string sql_regcase(string $chaine) Chane de caractres. Une expression rgulire.

Listing 7.43 : sql_regcase.php


<?php echo sql_regcase("Cest Cool."); ?>

Et son rsultat :
[Cc][Ee][Ss][Tt] [Cc][Oo][Oo][Ll].

430

Adapter le texte la langue du visiteur

7.9.

Adapter le texte la langue du visiteur

Si vous souhaitez proposer le mme site web des visiteurs provenant de diffrents horizons linguistiques, vous devrez trouver une solution vous permettant dadapter le texte en fonction de la langue choisie. Une des solutions consiste utiliser la bibliothque gettext. Malheureusement, sans que nous puissions vritablement dterminer lorigine du problme, il se trouve que cette bibliothque na correctement fonctionn que dans un des trois environnements tests. Nous ne nous tendrons pas sur ce sujet, dautant quil est trs facile darriver au mme rsultat sans avoir utiliser la moindre bibliothque (ce qui garantit un fonctionnement dans nimporte quel environnement). En effet, il vous suffit de crer un script par langue que vous souhaitez proposer, chacun de ces scripts dfinissant un tableau associatif ayant pour cls les identifiants de message (qui pourraient tre les versions franaises du message) et pour valeurs les traductions. Ce qui donne, par exemple :

Listing 7.44 : lang_en_inc.php


<?php $msg["titre"] = "Welcome! This is our acme website"; $msg["Bonjour"] = "Hi"; $msg["Quoi de neuf?"] = "Whats up?"; ?>

Listing 7.45 : lang_fr_inc.php


<?php $msg["titre"] = "Bienvenue! Cest notre super site"; $msg["Bonjour"] = "Bonjour"; $msg["Quoi de neuf?"] = "Quoi de neuf?"; ?>

Il suffira alors dinclure le fichier correspondant la langue choisie, et de faire appel aux valeurs du tableau pour chaque affichage. Comme dans lexemple suivant :

7. La manipulation des chanes de caractres

Listing 7.46 : lang_accueil.php


<?php switch ($_GET["lang"]) { case "en" : { include("lang_en_inc.php"); break; } case "fr" : default : { include("lang_fr_inc.php"); break; } }

431

Chapitre 7

La manipulation des chanes de caractres

?> <html> <head> <title><?php echo $msg["titre"]; ?></title> </head> <body> <h1><?php echo $msg["Bonjour"]; ?></h1> <?php echo $msg["Quoi de neuf?"]; ?> </body> </html>

Ainsi, lappel lang_accueil.php?lang=fr (ou tout autre valeur de lang diffrente de "en") retournera :
Bonjour Quoi de neuf?

avec pour titre :


"Bonjour! Cest notre super site"

Alors que lappel lang_accueil.php?lang=en retournera :


Hi Whats up?

avec pour titre :


Welcome! This is our acme website

Mme si votre site nest quen franais, cette mthode peut prsenter des avantages, puisquen faisant ainsi, tous les textes sont centraliss dans un unique fichier (ce qui ne peut que simplifier les mises jour).

7. La manipulation des chanes de caractres

Dtection automatique de la langue prfre Si vous souhaitez dterminer automatiquement la langue prfre de votre visiteur, vous pourrez faire appel la variable externe $_SERVER["HTTP_ACCEPT _LANGUAGE"]. Celle-ci contient une liste des codes pays (sur deux lettres) spars par des virgules et dans lordre de prfrence. Vous pourrez alors dterminer la langue prfre supporte par votre site (ici, "en" et "fr") grce au script suivant :
<?php function languePreferree() { $langs = explode(",", $_SERVER["HTTP_ACCEPT_LANGUAGE"]); for ($i=0; (($i<count($langs))&&(!isset($lang))); $i++) { if (in_array($langs[$i], array("en", "fr"))) $lang = $langs[$i]; } return $lang; } ?>

432

Chapitre 8

La gestion des dates et des calendriers


8.1 8.2 8.3 Les fonctions de date et heure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435 Les dates et calendriers particuliers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444 Les gestionnaires dvnements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449

Les fonctions de date et heure

8.1.

Les fonctions de date et heure

Le langage PHP offre des fonctions similaires ce que lon peut rencontrer en C/C++. La plupart de ces fonctions sappuient sur une date dfinie par un entier correspondant au nombre de secondes coules depuis le 1er janvier 1970 00:00:00 (aussi appel epoch). Une date ainsi dfinie sera galement appele timestamp UNIX.

Jusquen 2037 Ce timestamp UNIX nest valable que dans la plage de temps comprise entre le 1er janvier 1970 et 2037.

Rcuprer une date au "format informatique"


Ainsi, gnralement, la premire opration raliser lorsque lon souhaite manipuler des dates consiste rcuprer la date voulue au format timestamp UNIX. Pour cela, nous disposons des fonctions time(), mktime() et strtotime().

time()
Retourne la date courante. Syntaxe retour int time(void) Nombre de secondes coules depuis le 1er janvier 1970.

mktime()
Retourne le timestamp de la date spcifie.

8. La gestion des dates et des calendriers

Syntaxe $heure $minute $seconde $mois $jour $annee retour

int mktime(int $heure, int $minute, int $seconde, int $mois, int $jour, int $annee) Lheure. Les minutes. Les secondes. Le mois. Le jour. Lanne. Nombre de secondes coules entre le 1er janvier 1970 et la date spcifie.

435

Chapitre 8

La gestion des dates et des calendriers

strtotime()
Retourne le timestamp dune date spcifie sous la forme dune chane de caractres et exprime en anglais. Syntaxe $date retour int strtotime(string $date) Date exprime en anglais. Nombre de secondes coules entre le 1er janvier 1970 et la date spcifie.

Listing 8.1 : datetime_01.php


<?php echo "Le timestamp actuel est ".time()."<br />"; echo "Le timestamp pour la date du 10/01/2001 18:15 est "; echo mktime(18, 15, 0, 1, 10, 2001)."<br />"; echo "Le timestamp pour la date du 10 Janvier 2001 18:15 est "; echo strtotime("10 January 2001 18:15")."<br />"; echo "Le timestamp pour la date du 2001-01-10 18:15 est "; echo strtotime("2001-01-10 18:15")."<br />"; ?>

retournera :
Le Le Le Le timestamp timestamp timestamp timestamp actuel est (valeur variable) pour la date du 10/01/2001 18:15 est 979146900 pour la date du 10 Janvier 2001 18:15 est 979146900 pour la date du 2001-01-10 18:15 est 979146900

Dates au format SQL Comme vous pouvez le constater, strtotime() permet de traiter des dates issues dune base de donnes (i.e. au format AAAAMMJJ hh:mm:ss).

8. La gestion des dates et des calendriers

Effectuer des oprations sur les dates


Lorsque vous avez une date au format timestamp UNIX (issue, par exemple, de la fonction time()), vous pouvez ajouter/soustraire des secondes, des minutes, des heures, des jours simplement en ajoutant/soustrayant le nombre de secondes correspondant.

Listing 8.2 : datetime_02a.php


<?php echo "Le timestamp dhier la mme heure est ".(time()-24*3600)."<br />"; ?>

436

Les fonctions de date et heure

Si, en revanche, vous voulez ajouter/soustraire des mois ou des annes, vous devrez dcomposer la date exprime en secondes depuis le 1er janvier 1970 en jours, mois, annes, heures, minutes et secondes. Pour cela, vous pouvez faire appel la fonction getDate().

getDate()
Retourne les diffrents champs dune date (ou de la date courante). Syntaxe $date retour array getDate([int $date]) Date exprime en nombre de secondes depuis 1970 (par dfaut, la date courante). Tableau associatif contenant (entre autres) les cls : "mday" jour. "mon" mois. "year" anne. "hours" heure. "minutes" minutes. "seconds" secondes.

Listing 8.3 : datetime_02b.php


<?php $tableauDate = getdate(); // Calcul de la date courante - 6 mois $tableauDate["mon"] = $tableauDate["mon"] - 6; if ($tableauDate["mon"] < 1) { $tableauDate["mon"] = $tableauDate["mon"] + 12; $tableauDate["year"] = $tableauDate["year"] - 1; } echo echo echo echo ?> "Il y a 6 mois, nous tions le "; $tableauDate["mday"]."/".$tableauDate["mon"]; "/".$tableauDate["year"]; "<br />";

8. La gestion des dates et des calendriers

Afficher des dates


Il existe diffrentes fonctions daffichage (ou, plus exactement, de reprsentation) des dates, mais toutes sappuient sur une date exprime en secondes depuis le 1er janvier 1970. Parmi elles, vous trouverez les fonctions date() et strftime().

437

Chapitre 8

La gestion des dates et des calendriers

date()
Reprsente une date (ou date courante) selon le format spcifi. Syntaxe $format $date retour string date(string $format [, ind $date]) Chane prcisant le format de reprsentation de la date en sappuyant sur les cls prsentes ci-aprs. Date exprime en nombre de secondes depuis 1970 (par dfaut, date courante). Chane de caractres reprsentant la date.

Dans le cadre de la fonction date(), les cls sont :

Tableau 8.1 : Les diffrentes cls pour reprsenter un format de date avec date()
Cl l D w d j S z F M m n Signification Pour le jour en toutes lettres (en anglais). Pour les trois premires lettres du jour (en anglais). Pour le jour de la semaine (0 = Dimanche, ..., 6 = Samedi). Pour le jour du mois, sur deux chiffres. Pour le jour du mois (sur un ou deux chiffres). Pour le suffixe sur deux lettres (en anglais) du nombre indiquant le jour. Pour le numro du jour dans lanne (0 = 1er Janvier). Pour le mois en toutes lettres (en anglais). Pour les premires lettres du mois (en anglais). Pour le mois, sur deux chiffres. Pour le mois (sur un ou deux chiffres). Pour le nombre de jours dans le mois. Pour lanne, sur quatre chiffres. Pour lanne, sur deux chiffres. Pour "1" si lanne est bissextile, "0" sinon. Pour lheure sur 12 heures (sur un ou deux chiffres). Pour lheure sur 24 heures (sur un ou deux chiffres). Pour lheure sur 12 heures, sur deux chiffres. Concernant les jours

Concernant les mois

8. La gestion des dates et des calendriers

t Y y L g G h

Concernant les annes

Concernant les heures

438

Les fonctions de date et heure

Cl H a A I T Z B i s r U Lexemple :

Signification Pour lheure sur 24 heures, sur deux chiffres. Pour "am" ou "pm". Pour "AM" ou "PM". Pour "1" en heure dt et "0" en heure dhiver. Pour le fuseau horaire. Pour le dcalage horaire GMT en secondes. Pour lheure internet Swatch. Pour les minutes, sur deux chiffres. Pour les secondes, sur 2 chiffres. Pour la date au format RFC 822 (Tue, 22 Jan 2002 11:09:42 +0100). Retourne simplement le timestamp.

Concernant les minutes Concernant les secondes Concernant la date dans son ensemble

Listing 8.4 : datetime_03a.php


<?php echo "Nous sommes le ".date("l j F Y")." "; echo "Il est ".date("H:i:s")."<br />"; ?>

pourra retourner quelque chose comme :


Nous sommes le Tuesday 9 July 2002 Il est 22:39:06

La fonction date() propose donc de nombreuses possibilits de formatage dune date, mais nous lui prfrons la fonction strftime() qui, elle, tient compte de la langue locale lors de la restitution dinformations en toutes lettres.

8. La gestion des dates et des calendriers

strftime()
Reprsente une date (ou la date courante) selon le format spcifi. Syntaxe $format string strftime(string $format [, int $date]) Chane prcisant le format de reprsentation de la date en sappuyant sur les cls prsentes ci-aprs.

439

Chapitre 8

La gestion des dates et des calendriers

$date retour

Date exprime en nombre de secondes depuis 1970 (par dfaut, la date courante). Chane de caractres reprsentant la date.

Dans le cadre de la fonction strftime(), les cls sont :

Tableau 8.2 : Les diffrentes cls pour reprsenter un format de date avec strftime()
Cl %A %a %d %e (*) %j %u (*) %w %B %b %h (*) %m %y %Y %H %I Signification Pour le jour en toutes lettres (dans la langue locale). Pour les trois premires lettres du jour (dans la langue locale). Pour le jour du mois, sur deux chiffres. Pour le jour du mois (sur un ou deux chiffres). Pour le numro du jour dans lanne, sur trois chiffres (1 = 1er janvier). Pour le jour de la semaine (1 = lundi, ..., 7 = dimanche). Pour le jour de la semaine (0 = dimanche, ..., 6 = samedi). Pour le mois en toutes lettres (dans la langue locale). Pour les trois premires lettres du mois (dans la langue locale). Comme %b. Pour le mois; sur deux chiffres. Pour lanne, sur deux chiffres. Pour lanne, sur quatre chiffres. Pour lheure sur 24 heures, sur deux chiffres. Pour lheure sur 12 heures, sur deux chiffres. Pour AM ou PM. Pour le fuseau horaire. Pour les minutes, sur deux chiffres. Pour les secondes, sur deux chiffres. Pour le numro de la semaine (1 = semaine du 1er dimanche de lanne). Pour le numro de la semaine (ISO 8601:1988), sur deux chiffres. Concernant le jour

Concernant le mois

Concernant lanne

Concernant lheure

8. La gestion des dates et des calendriers

%p %Z %M %S %U %V (*)

Concernant les minutes Concernant les secondes Concernant la semaine

440

Les fonctions de date et heure

Cl %W %C (*) %D (*) %r (*) %R (*) %T (*) %c %x %X Autre %n %t %% Lexemple :

Signification Pour le numro de la semaine (1 = semaine du 1er lundi de lanne). Pour le sicle, sur deux chiffres. Pour la date au format %m/%d/%y. Pour lheure au format %I:%M:%S %p. Pour lheure au format %H:%M. Pour lheure au format %H:%M:%S. Pour laffichage traditionnel de la date dans la langue locale (ex. : JJ/MM/AA hh:mm:ss en France). Pour laffichage traditionnel de la date dans la langue locale, sans lheure (ex. : JJ/MM/AA en France). Pour laffichage traditionnel de lheure dans la langue locale (ex. : hh:mm:ss en France). Pour insrer un retour la ligne. Pour insrer une tabulation. Pour afficher un pourcentage.

Concernant le sicle Concernant la date dans son ensemble

Listing 8.5 : datetime_03b.php


<?php setLocale(LC_TIME, "fr"); echo "Nous sommes le ".strftime("%A %d %B %Y")."<br />"; echo "Il est ".strftime("%H:%M:%S")."<br />";

?>

8. La gestion des dates et des calendriers

retournera quelque chose comme :


Nous sommes le mardi 09 juillet 2002 Il est 22:51:06

Portabilit Malheureusement, il est possible que votre bibliothque PHP ait t compile avec une bibliothque C ne supportant pas toutes ces options. Les cls marques dun astrisque ne sont pas disponibles dans les versions Windows, alors quelles le sont parfaitement sous Linux.

441

Chapitre 8

La gestion des dates et des calendriers

Les heures GMT


Les fonctions mktime(), date() et strftime() se dclinent en gmmktime(), gmdate() et gmstrftime(). Ces fonctions sutilisent exactement de la mme faon, mais :
j j
gmmktime() retourne le timestamp UNIX local (tenant compte du dcalage horaire) dune date donne en heures GMT. gmdate() et gmstrftime() retournent les valeurs GMT pour des dates exprimes localement (tenant compte du dcalage horaire).

Listing 8.6 : datetime_04.php


<?php echo "Le 1/1/2003 11:00:00 GMT donne "; echo strftime("%H:%M:%S",gmmktime(11,0,0,1,1,2003)); echo "localement <br />"; echo strftime("A %H:%M:%S ",mktime(12,0,0,1,1,2003)); echo "localement<br />"; echo gmstrftime("Il est %H:%M:%S",mktime(12,0,0,1,1,2003)); echo " GMT (daprs gmstrftime).<br />"; echo "Il est ".gmdate("H:i:s",mktime(12,0,0,1,1,2003)); echo " GMT (daprs gmdate).<br />";

?>

affichera :
Le 1/1/2003 11:00:00 GMT donne 12:00:00localement A 12:00:00 localement Il est 11:00:00 GMT (daprs gmstrftime). Il est 11:00:00 GMT (daprs gmdate).

Les microsecondes
8. La gestion des dates et des calendriers
PHP dispose de deux fonctions permettant de rcuprer lheure la microseconde prs. Il sagit des fonctions getTimeOfDay() et microtime().

getTimeOfDay()
Retourne les champs de la date courante, y compris les microsecondes. Syntaxe retour array getTimeOfDay(void) Tableau associatif contenant (entre autres) les cls : "sec" contenant le timestamp UNIX. "usec" contenant les microsecondes.

442

Les fonctions de date et heure

microtime()
Retourne une chane de caractres contenant les microsecondes de la date courante. Syntaxe retour string microtime(void) Chane de caractres contenant les microsecondes (0.xxxxxx), une espace puis le timestamp UNIX.

Listing 8.7 : datetime_05.php


<?php $top0=getTimeOfDay(); echo "Temps dexecution avec getTimeOfDay<br />"; $top1=getTimeOfDay(); $diff=($top1["usec"]+$top1["sec"]*1E6) ($top0["usec"]+$top0["sec"]*1E6); echo "Temps = $diff micro-secondes<br />"; list($usec0,$sec0)=explode(" ",microtime()); echo "Temps dexecution avec microtime<br />"; list($usec1,$sec1)=explode(" ",microtime()); $diff=($sec1+$usec1) - ($sec0+$usec0); echo "Temps = $diff secondes<br />"; ?>

Autres fonctions
Outre les fonctions permettant de rcuprer ou de formater des dates, heures et microsecondes, PHP propose la fonction checkDate() qui permet de contrler la validit dune date (en tenant compte notamment des annes bissextiles).

8. La gestion des dates et des calendriers

checkDate()
Teste la validit de la date. Syntaxe $mois $jour $annee retour boolean checkDate(int $mois, int $jour, int $annee) Le mois. Le jour. Lanne. TRUE si la date existe, FALSE sinon.

443

Chapitre 8

La gestion des dates et des calendriers

La fonction localTime() qui permet de rcuprer les diffrents champs dune date nest pas prsente en dtail ici, puisque ses fonctionnalits se retrouvent dans les fonctions prsentes prcdemment.

8.2.

Les dates et calendriers particuliers

Vous trouverez galement, avec le langage PHP, quelques fonctions vous permettant de dterminer, pour chaque anne, des dates particulires (en loccurrence celle de Pques), mais aussi des fonctions permettant de convertir des dates dun calendrier lautre (grgorien, julien, juif, rpublicain). Pour cela, vous devez faire appel la bibliothque Calendar.

Installation
Sous Windows
Que ce soit avec larchive de PHP Group ou avec EasyPHP, la bibliothque Calendar est active par dfaut.

Sous Linux
Lutilisation de cette bibliothque ncessite davoir compil PHP avec loption
enablecalendar.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur la compilation de PHP.

Vrication
8. La gestion des dates et des calendriers
Vous pouvez vrifier que le support de la bibliothque Calendar est effectif en appelant un script contenant simplement <?php phpinfo(); ?> et qui doit afficher :

Figure 8.1 : phpinfo()

Pques
Pour connatre la date correspondant Pques pour une anne donne, il suffit de faire appel la fonction easter_date().

444

Les dates et calendriers particuliers

easter_date()
Retourne la date de Pques pour lanne donne (ou lanne courante). Syntaxe $annee retour int easter_date([int $annee]) Anne considre (par dfaut, anne courante) entre 1970 et 2037. Timestamp UNIX de Pques.

Si, toutefois, vous souhaitez effectuer la mme opration pour une anne situe en dehors de la plage de validit du timestamp UNIX (i.e. avant le 1er janvier 1970 ou aprs 2037), vous devez faire appel easter_days().

easter_days()
Retourne le nombre de jours entre le 21 mars et Pques pour lanne donne (ou lanne courante). Syntaxe $annee retour int easter_days([int $annee]) Anne considre (par dfaut, anne courante). Nombre de jours.

Listing 8.8 : calendar_01.php


<?php setLocale(LC_TIME, "fr"); echo strftime("Cette anne, Pques tombe le %A %d %B<br />", easter_date()); echo strftime("En 2001, Pques tait le %A %d %B<br />", easter_date(2001)); // Pour les annes prcdant 1970 ou suivant 2037 // utiliser easter_days // La date de rfrence est le 21 Mars $jour = 21; $mois = 3; $annee = 1969; $nbJour = easter_days($annee); if ($nbJour > 10) { $mois++; $jour = $nbJour - 10; } else { $jour += $nbJour; } echo "En $annee, Pques cest le $jour/$mois<br />";

8. La gestion des dates et des calendriers

?>

retourne, en 2002,

445

Chapitre 8

La gestion des dates et des calendriers

Cette anne, Pques tombe le dimanche 31 mars En 2001, Pques tait le dimanche 15 avril En 1969, Pques cest le 6/4

Conversion dune date dun calendrier lautre


Toutes ces fonctions sappuient sur une date exprime dans le calendrier julien (et non le calendrier grgorien auquel nous sommes habitus). Mais, pour linstant, commenons par les fonctions de conversion de/vers le timestamp UNIX.

unixToJD()
Retourne le nombre de jours du calendrier julien partir de la date donne (ou, dfaut, la date courante) en timestamp UNIX. Syntaxe $date retour int unixToJD([timestamp $date]) Date en nombre de secondes depuis le 1er janvier 1970. Nombre de jours du calendrier julien.

JDToUnix()
Retourne la date en timestamp UNIX partir de la date donne en nombre de jours du calendrier julien. Syntaxe $dateJulien retour int JDToUnix(int $dateJulien) Date en nombre de jours du calendrier julien. Date en timestamp UNIX.

8. La gestion des dates et des calendriers

Informations sur les diffrents calendriers Vous trouverez plus dinformations sur ces diffrents calendriers ladresse : http://www.bdl.fr/Granpub/Calendriers.html.
Voici maintenant les autres fonctions de conversion de calendriers.

JDToGregorian()
Retourne une chane au format "mois/jour/anne" du calendrier grgorien, correspondant au nombre de jours donns dans le calendrier julien.

446

Les dates et calendriers particuliers

Syntaxe $jour retour

string JDToGregorian(int $jour) Nombre de jours dans le calendrier julien. Chane au format "mois/jour/anne" du calendrier grgorien.

gregorianToJD()
Retourne le nombre de jours du calendrier julien correspondant la date donne dans le calendrier grgorien. Syntaxe $mois $jour $annee retour int gregorianToJD(int $mois, int $jour, int $annee) Mois dans le calendrier julien. Jour dans le calendrier julien. Anne dans le calendrier julien. Nombre de jours du calendrier julien.

JDToJewish()
Retourne une chane au format "mois/jour/anne" du calendrier juif correspondant au nombre de jours donns dans le calendrier julien. Syntaxe $jour retour string JDToJewish(int $jour) Nombre de jours dans le calendrier julien. Chane au format "mois/jour/anne" du calendrier juif.

jewishToJD()
8. La gestion des dates et des calendriers
Retourne le nombre de jours du calendrier julien correspondant la date donne dans le calendrier juif. Syntaxe $mois $jour $annee retour int jewishToJD(int $mois, int $jour, int $annee) Mois dans le calendrier juif. Jour dans le calendrier juif. Anne dans le calendrier juif. Nombre de jours du calendrier julien.

447

Chapitre 8

La gestion des dates et des calendriers

JDToFrench()
Retourne une chane au format "mois/jour/anne" du calendrier rpublicain franais correspondant au nombre de jours donns dans le calendrier julien. Syntaxe $jour retour string JDToFrench(int $jour) Nombre de jours dans le calendrier julien. Chane au format "mois/jour/anne" du calendrier rpublicain franais.

frenchToJD()
Retourne le nombre de jours du calendrier julien correspondant la date donne dans le calendrier rpublicain franais (valable pour les dates du 22 septembre 1792 au 22 septembre 1806 du calendrier grgorien, mme si son utilisation a t abandonne le 31 dcembre 1805). Syntaxe $mois $jour $annee retour int frenchToJD(int $mois, int $jour, int $annee) Mois dans le calendrier rpublicain franais. Jour dans le calendrier rpublicain franais. Anne dans le calendrier rpublicain franais. Nombre de jours du calendrier julien.

JDToJulian()
Retourne la date du calendrier julien au format "mois/jour/anne" partir de la date exprime en nombre de jours. Syntaxe $jour string JDToJulian(int $jour) Nombre de jours dans le calendrier julien. Date du calendrier julien au format "mois/jour/anne".

8. La gestion des dates et des calendriers

retour

julianToJD()
Retourne la date du calendrier julien exprime en nombre de jours. Syntaxe $mois $jour int julianToJD(int $mois, int $jour, int $annee) Mois dans le calendrier julien. Jour dans le calendrier julien.

448

Les gestionnaires dvnements

$annee retour

Anne dans le calendrier julien. Nombre de jours.

Manipulation dune date dans le calendrier julien

JDMonthName()
Retourne en toutes lettres (en anglais) le nom du mois dans le calendrier prcis. Syntaxe $dateJulien $calendrier string JDMonthName(int $dateJulien, int $calendrier) Date exprime en nombre de jours du calendrier julien. Une des valeurs suivantes : 0 = grgorien (abrg aux trois premires lettres). 1 = grgorien. 2 = julien (abrg aux trois premires lettres). 3 = julien. 4 = juif. 5 = rpublicain franais (uniquement valable pour les dates allant du 22 septembre 1792 au 22 septembre 1806 du calendrier grgorien). retour Nom du mois.

JDDayOfWeek()
Retourne le nom (en anglais) du jour de la semaine ou son numro. Syntaxe $dateJulien $mode mixed JDDayOfWeek(int $dateJulien, int $mode) Date exprime en nombre de jours du calendrier julien. Une des valeurs suivantes : 0 = numro du jour (1 = dimanche). 1 = nom du jour. 2 = nom du jour abrg aux trois premires lettres. retour Numro du jour de la semaine (mode = 0), nom du jour sinon.

8. La gestion des dates et des calendriers

8.3.

Les gestionnaires dvnements

Jusqu larrive de PHP 5, PHP proposait des bibliothques permettant dinteragir avec des gestionnaires dvnements supportant le protocole ICAP (iCalendar Protocol).

449

Chapitre 8

La gestion des dates et des calendriers

Si vous utilisez PHP4, il vous est donc possible de crer votre propre interface Internet de suivi et dadministration de vos agendas. Cette interface vous sera alors accessible depuis nimporte quel poste disposant dun navigateur (et non pas seulement depuis les postes quips du logiciel client de la solution de gestionnaire dvnements retenue). Pour cela, vous devrez utiliser la bibliothque MCAL (Modular Calendar AccessLibrary). Celle-ci, en plus de supporter le protocole ICAP, permet dutiliser des fichiers locaux comme support des donnes. De plus, cette bibliothque a t dveloppe pour tre modulaire ce qui, en thorie du moins, lui permet de supporter dautres protocoles.

En savoir plus Le protocole ICAP est dfini par les RFC-2445 "Internet Calendaring and Scheduling Core Object Specification (iCalendar)" et RFC-2446 "iCalendar Transport-Independent Interoperability Protocol (iTIP)" disponibles en anglais aux adresses suivantes :
http://www.ietf.org/rfc/rfc2445.txt http://www.ietf.org/rfc/rfc2446.txt

Pour tre utilise, cette bibliothque doit au pralable tre rcupre, compile et intgre PHP.

Installation
Cette bibliothque nest pas disponible sous Windows.

Sous Linux
Pr-requis Pour pouvoir compiler cette bibliothque, il faut avoir install au pralable les outils de compilation et autres commandes telles que "flex".
La bibliothque MCAL est compose de deux lments :

8. La gestion des dates et des calendriers

j j

libmcal : la bibliothque proprement dite ; mcaldrivers : les modules de la bibliothque comprenant les pilotes pour le protocole ICAP et ceux pour les fichiers locaux (mstore).

Ces deux fichiers (disponibles sur le CD-ROM) peuvent tre tlchargs ladresse
http://sourceforge.net/projects/libmcal/.

Aprs les avoir copis dans un rpertoire donn (ex. : /usr/local/src/lib), dcompressez ces deux fichiers laide des commandes suivantes :
# # # # gunzip libmcal-0.7.tar.gz tar xvf libmcal-0.7.tar gunzip mcaldrivers-0.9.tar.gz tar xvf mcaldrivers-0.9.tar

450

Les gestionnaires dvnements

Puis, dplacez le contenu de mcaldrivers dans libmcal :


# mv mcal-drivers/* libmcal

Ensuite, passez la gnration des pilotes mstore et icap :


# # # # # # # cd libmcal cd mstore make cd .. cd icap make cd ..

Enfin, passez la gnration de la bibliothque :


# chmod +x configure # ./configure --with-mstore --with-icap # make

Un fichier libmcal.a est alors gnr. Il est maintenant possible de (re)compiler PHP aprs avoir ajout loption "--with-mcal=<chemin vers le rpertoire libmcal contenant libmcal.a>" (ex. : withmcal=/ usr/local/src/lib/libmcal ).

Vous pouvez consulter le chapitre "Prise en main" pour plus de dtails sur la compilation de PHP. Initialisation mstore Si vous souhaitez utiliser le module mstore (autrement dit utiliser un fichier local pour stocker vos agendas), il vous faut dabord crer un rpertoire pour hberger ces agendas, ainsi quun fichier de mots de passe. Pour cela, il suffit de suivre la procdure suivante :
# # # # mkdir chmod touch chmod /var/calendar 1777 /var/calendar /etc/mpasswd a+r /etc/mpasswd

8. La gestion des dates et des calendriers

Mstore utilisant un fichier de mots de passe au format identique celui dApache, vous devez utiliser la commande htpasswd fournie avec Apache pour le gnrer. Vous prendrez soin, ici, de remplacer la variable $APACHE_HOME par sa valeur (qui

pourra tre /usr/local/apache, /usr ou autre selon votre configuration).


# $APACHE_HOME/bin/htpasswd -b /etc/mpasswd <login> <mot de passe>

451

Chapitre 8

La gestion des dates et des calendriers

Vrication
Vous pouvez vrifier que le support de la bibliothque MCAL est effectif en appelant un script contenant simplement <?php phpinfo(); ?> et qui doit afficher :

Figure 8.2 : phpinfo()

Les fonctions
Il est possible de distinguer deux types de fonctions : celles qui permettent de manipuler les dates et celles qui permettent effectivement de manipuler les informations stockes dans les agendas. Les fonctions de manipulation de dates trouvent, pour la plupart, leur quivalent parmi les fonctions proposes par dfaut avec PHP. Il y a toutefois une petite diffrence, puisque, contrairement aux autres, les fonctions de la bibliothque MCAL sont galement valables pour des dates prcdant le 1er janvier 1970.

mcal_date_valid()
Teste la validit de la date. Syntaxe $annee $mois $jour retour boolean mcal_date_valid(int $annee, int $mois, int $jour) Anne. Mois. Jour. TRUE si la date est valide, FALSE sinon.

quivalent sans la bibliothque MCAL :

8. La gestion des dates et des calendriers

checkdate($mois, $jour, $annee);

mcal_time_valid()
Teste la validit de lheure. Syntaxe $heure $minute $seconde boolean mcal_time_valid(int $heure, int $minute, int $seconde) Heure. Minute. Seconde.

452

Les gestionnaires dvnements

retour

TRUE si lheure est valide, FALSE sinon.

quivalent sans la bibliothque MCAL :


( ($heure>=0 && $heure<24 ) && ($minute>=0 && $minute<60) && ($seconde>=0 && $seconde<60))

mcal_day_of_week()
Retourne le numro du jour dans la semaine de la date donne. Syntaxe $annee $mois $jour retour int mcal_day_of_week(int $annee, int $mois, int $jour) Anne. Mois. Jour. Numro du jour dans la semaine (0 = dimanche, ..., 6 = samedi). En fait, des constantes existent MCAL_SUNDAY, MCAL_MONDAY, MCAL_TUESDAY, MCAL_THURSDAY, MCAL_FRIDAY, MCAL_Saturday.

quivalent sans la bibliothque MCAL (pour les dates dans la limite de validit des timestamps) :
$tab = getdate(mktime(0, 0, 0, $mois, $jour, $annee)); return $tab["wday"];

mcal_day_of_year()
Retourne le numro du jour dans lanne de la date donne. Syntaxe $annee $mois $jour retour int mcal_day_of_year(int $annee, int $mois, int $jour) Anne. Mois. Jour. Numro du jour dans lanne (1 = 1er janvier, ...).

8. La gestion des dates et des calendriers

quivalent sans la bibliothque MCAL (pour les dates dans la limite de validit des timestamps) :
$tab = getdate(mktime(0, 0, 0, $mois, $jour, $annee)); return $tab["yday"] + 1;

453

Chapitre 8

La gestion des dates et des calendriers

mcal_date_compare()
Compare deux dates. Syntaxe $annee1 $mois1 $jour1 $annee2 $mois2 $jour2 retour int mcal_date_compare(int $annee1, int $mois1, int $jour1, int $annee2, int $mois2, int $jour2) Anne de la 1re date comparer. Mois de la 1re date comparer. Jour de la 1re date comparer. Anne de la 2e date comparer. Mois de la 2e date comparer. Jour de la 2e date comparer. 1 si la 1re date est antrieure la seconde, 0 si elles sont identiques, 1 sinon.

quivalent sans la bibliothque MCAL (pour les dates dans la limite de validit des timestamps) :
$diff = mktime(0, 0, 0, $mois1, $jour1, $annee1) mktime(0, 0, 0, $mois2, $jour2, $annee2); if ($diff == 0) return 0; return $diff>0?1:-1;

mcal_is_leap_year()
Teste si lanne est bissextile. Syntaxe $annee retour boolean mcal_is_leap_year(int $annee) Anne. TRUE si lanne est bissextile, FALSE sinon.

8. La gestion des dates et des calendriers

quivalent sans la bibliothque MCAL :


return checkdate(2, 29, $annee);

mcal_days_in_month()
Retourne le nombre de jours dans le mois en tenant compte des annes bissextiles.

454

Les gestionnaires dvnements

Syntaxe $mois $bissextile retour

int mcal_days_in_month(int $mois, boolean $bissextile) Mois. Indiquez TRUE sil sagit dune anne bissextile, FALSE sinon. Nombre de jours dans le mois.

quivalent sans la bibliothque MCAL :


if ($mois == 2) { if ($bissextile) { return 29; } else { return 28; } } if (checkdate($mois, 31, 2000)) { return 31; } else { return 30; }

Une utilisation courante de ces fonctions consiste afficher un calendrier (annuel, mensuel, etc.).

8. La gestion des dates et des calendriers

Figure 8.3 : Calendrier annuel

455

Chapitre 8

La gestion des dates et des calendriers

Figure 8.4 : Calendrier mensuel

Ce rsultat peut tre obtenu avec le script suivant :

Listing 8.9 : mcal_01_inc.php


<?php class MCAL_Agenda { /** * Affiche une anne sous forme de calendrier */ function afficheAnnee($annee) { $labelMois = array(1 => "Janv.", "Fvr.", "Mars", "Avril", "Mai", "Juin", "Juil.", "Aot", "Sept.", "Oct.", "Nov.", "Dc."); $labelJour = array("Di.","Lu.","Ma.","Me.","Je.","Ve.","Sa."); echo "<table cellspacing=\"10\">\n"; echo "<tr><td colspan=\"12\" align=\"center\">$annee</td></tr>\n"; // Affiche les enttes de colonnes (les mois) echo "<tr>"; for ($mois = 1; $mois <= 12; $mois++) { echo "<td>".$labelMois[$mois]."</td>"; } echo "</tr>\n"; // Complte chaque mois echo "<tr>"; for ($mois = 1; $mois <= 12; $mois++) { // Donne une couleur de fond diffrente pour les mois // pairs et les mois impairs if (($mois % 2) == 0) { $cssClass = "moisPair"; } else { $cssClass = "moisImpair"; } echo "<td class=\"$cssClass\">\n"; echo "<table cellspacing=\"0\" cellpadding=\"0\">"; // Dtermine le nombre de jours dans le mois // en tenant compte des annes bissextiles

8. La gestion des dates et des calendriers 456

Les gestionnaires dvnements

$nbJour = mcal_days_in_month($mois,mcal_is_leap_year($annee)); for ($jour = 1; $jour <= $nbJour; $jour++) { echo "<tr>"; echo "<td align=\"left\">"; // Determine de quel jour il sagit // pour lafficher en toutes lettres echo $labelJour[mcal_day_of_week($annee,$mois,$jour)]."</td>"; $cssClass = "date"; echo "<td align=\"right\" class=\"$cssClass\">"; echo "$jour</td>"; echo "</tr>"; } // Ajoute des blancs en bas de tableau si necessaire for ($jour = $nbJour + 1; $jour <= 31; $jour++) { echo "<tr><td>&nbsp;</td><td>&nbsp;</td></tr>"; } echo "</table>\n"; echo "</td>"; } echo "</tr>"; echo "</table>\n"; } /** * Affiche un mois sous forme de calendrier */ function afficheMois($mois, $annee, $mcal="") { $labelMois = array(1 => "Janvier", "Fvrier", "Mars", "Avril", "Mai", "Juin", "Juillet", "Aot", "Septembre", "Octobre", "Novembre", "Dcembre"); $labelJour = array("Lu.","Ma.","Me.","Je.","Ve.","Sa.","Di.");

// Dtermine le nombre de jours dans le mois // en tenant compte des annes bissextiles $nbJours=mcal_days_in_month($mois, mcal_is_leap_year($annee)); echo "<table>\n"; echo "<tr><td colspan=\"4\">$labelMois[$mois]</td>"; echo "<td colspan=\"3\" align=\"right\">$annee</td></tr>\n"; echo "<tr>"; for ($i = 0; $i < 7; $i++) { echo "<td>$labelJour[$i]</td>"; } echo "</tr>\n"; echo "<tr>"; $premierJour = mcal_day_of_week($annee, $mois, 1);

8. La gestion des dates et des calendriers 457

Chapitre 8

La gestion des dates et des calendriers

// convertir 0=Dimanche...6=Samedi // en 0=Lundi...6=Dimanche $premierJour = ($premierJour + 6) % 7; // Sauter autant de colonne que ncessaire pour atteindre // le premier jour de la semaine for ($i = 0; $i < $premierJour; $i++) { echo "<td></td>"; } // Puis passer en revue tous les jours du mois for ($i = 0; $i < $nbJours; $i++) { if (($i + $premierJour) % 7 == 0) { // Retour la ligne chaque Lundi echo "</tr>\n<tr>"; } $cssClass = "date"; echo "<td align=\"right\" class=\"$cssClass\">"; echo ($i+1); echo "</td>"; } echo "</tr>\n"; echo "</table>\n"; } } ?>

Ce script pourra tre appel de la faon suivante (ici, pour afficher les deux types de calendrier) :

Listing 8.10 : mcal_01.php


<?php include("mcal_01_inc.php"); ?> <html> <head> <style> .moisPair { background-color: #DDDDFF; } .moisImpair { background-color: #9999FF; } .date { background-color: #DDDDFF; } </style> </head> <body>

8. La gestion des dates et des calendriers 458

Les gestionnaires dvnements

<h2>Bibliothque MCAL</h2> <?php $dateCourante = getdate(); MCAL_Agenda::afficheAnnee($dateCourante["year"]); MCAL_Agenda::afficheMois($dateCourante["mon"], $dateCourante["year"]); ?> </body> </html>

Les fonctions daccs aux agendas


Comme le veut la logique, pour accder un agenda, il faut dabord se connecter. Il existe ce propos trois fonctions : mcal_open(), mcal_popen(), et mcal_reopen().

mcal_open()
Ouvre un calendrier. Syntaxe $calendrier $utilisateur $motDePasse $options retour resource mcal_open(string $calendrier, string $utilisateur, string $motDePasse[, int $options]) Identifiant du calendrier que vous souhaitez ouvrir. Chane de la forme {serveur/protocole}<proprietaire>calendrier. Nom de lutilisateur. Mot de passe de lutilisateur. Manifestement inutilis. Retourne un identifiant de connexion, ou FALSE en cas dchec.

Cette fonction se dcline galement en mcal_popen() (mais la persistance de la connexion nest pas dmontre) et mcal_reopen() (dont le fonctionnement ne semble pas tout fait satisfaisant). Il nest dailleurs pas assur que leur dveloppement soit tout fait finalis. Dans le cas dune connexion un calendrier via le protocole mstore, le serveur est ncessairement local. La chane didentification du serveur sera donc de la forme {/mstore}<proprietaire>calendrier. Il est noter quun utilisateur peut se connecter lagenda dune autre personne pour accder ses informations publiques. Do lutilit possible du champ propritaire. Toutefois, si ce paramtre nest pas prcis, cest le calendrier de lutilisateur qui est considr. Nous ajouterons donc notre classe MCAL_Agenda la mthode suivante :

8. La gestion des dates et des calendriers

Listing 8.11 : mcal_02_inc.php (extrait)


<?php // Extrait de la Classe MCAL

459

Chapitre 8

La gestion des dates et des calendriers

class MCAL_Agenda { /** * Se connecte lagenda * et retourne lidentifiant associ */ function connect() { $mcal = mcal_open("{/mstore}biblephp","biblephp","pwd") or die("La connexion lagenda a chou"); return $mcal; } (...) } ?>

Une fois toutes les oprations effectues, il sera possible de librer les ressources en fermant la connexion au calendrier par mcal_close().

mcal_close()
Ferme la connexion au calendrier. Syntaxe $idConnexion $options retour boolean mcal_close(resource $idConnexion [, int $options]) Identifiant de connexion tel que retourn par mcal_open(). Rle indtermin. Retourne FALSE en cas dchec, TRUE sinon.

Lecture des vnements


8. La gestion des dates et des calendriers
Une des premires oprations que vous serez amen faire sera probablement de rcuprer la liste des vnements que vous avez nots dans lagenda sur une priode donne. Pour cela, vous devrez faire appel la fonction mcal_list_events().

mcal_list_events()
Retourne la liste des vnements intervenant entre deux dates. Syntaxe array mcal_list_events(resource $idConnexion, int $anneeDebut, int $moisDebut, int $jourDebut, int $anneeFin, int $moisFin, int $jourFin)

460

Les gestionnaires dvnements

$idConnexion $anneeDebut $moisDebut $jourDebut $anneeFin $moisFin $jourFin retour

Identifiant de connexion tel que retourn par mcal_open(). Anne de la date de dbut de recherche. Mois de la date de dbut de recherche. Jour de la date de dbut de recherche. Anne de la date de fin de recherche. Mois de la date de fin de recherche. Jour de la date de fin de recherche. Tableau index ayant pour valeurs des entiers correspondant des identifiants dvnements.

Cela nous permet dj de crer une fonction (ou plus exactement une mthode) entranant laffichage dun calendrier avec, en surbrillance, les jours auxquels des vnements sont associs. Voici donc la mthode daffichage dun calendrier enrichi par cette nouvelle fonctionnalit :

Listing 8.12 : mcal_02_inc.php (extrait)


<?php // Extrait de la classe MCAL_Agenda class MCAL_Agenda { // (...) /** * Affiche une anne sous forme de calendrier * et montre les dates associes un vnement */ function afficheAnnee($annee, $mcal="") { $labelMois = array(1 => "Janv.", "Fvr.", "Mars", "Avril", "Mai", "Juin", "Juil.", "Aot", "Sept.", "Oct.", "Nov.", "Dc."); $labelJour = array("Di.","Lu.","Ma.","Me.","Je.","Ve.","Sa."); echo "<table cellspacing=\"10\">\n"; echo "<tr><td colspan=\"12\" align=\"center\">$annee</td></tr>\n"; // Affiche les enttes de colonnes (les mois) echo "<tr>"; for ($mois = 1; $mois <= 12; $mois++) { echo "<td>".$labelMois[$mois]."</td>"; } echo "</tr>\n"; // Complte chaque mois echo "<tr>";

8. La gestion des dates et des calendriers 461

Chapitre 8

La gestion des dates et des calendriers

for ($mois = 1; $mois <= 12; $mois++) { // Donne une couleur de fond diffrente pour les mois // pairs et les mois impairs if (($mois % 2) == 0) { $cssClass = "moisPair"; } else { $cssClass = "moisImpair"; } echo "<td class=\"$cssClass\">\n"; echo "<table cellspacing=\"0\" cellpadding=\"0\">"; // Dtermine le nombre de jours dans le mois // en tenant compte des annes bissextiles $nbJour = mcal_days_in_month($mois, mcal_is_leap_year($annee)); for ($jour = 1; $jour <= $nbJour; $jour++) { echo "<tr>"; echo "<td align=\"left\">"; // Determine de quel jour il sagit // pour lafficher en toutes lettres echo $labelJour[mcal_day_of_week($annee,$mois,$jour)]."</td>"; // A-t-on un vnement li cette date ? $avecEvenement = FALSE; if ($mcal != "") { $evenements = mcal_list_events($mcal, $annee, $mois, $jour, $annee, $mois, $jour); if (count($evenements) >0 ) $avecEvenement = TRUE; }

8. La gestion des dates et des calendriers

if ($avecEvenement) { $cssClass = "dateEvenement"; } else { $cssClass = "date"; } echo "<td align=\"right\" class=\"$cssClass\">"; echo "$jour</td>"; echo "</tr>"; } // Ajoute des blancs en bas de tableau si ncessaire for ($jour = $nbJour + 1; $jour <= 31; $jour++) { echo "<tr><td>&nbsp;</td><td>&nbsp;</td></tr>"; } echo "</table>\n"; echo "</td>"; } echo "</tr>";

462

Les gestionnaires dvnements

echo "</table>\n"; } // (...) } ?>

qui pourra tre appel par :

Listing 8.13 : mcal_02.php


<?php include("mcal_02_inc.php"); ?> <html> <head> <style> .moisPair { background-color: #DDDDFF; } .moisImpair { background-color: #9999FF; } .date { background-color: #DDDDFF; } .dateEvenement { background-color: #FF0000; } </style> </head> <body> <h2>Bibliothque MCAL</h2> <?php $mcal = MCAL_Agenda::connect();

8. La gestion des dates et des calendriers

$dateCourante = getdate(); MCAL_Agenda::afficheAnnee($dateCourante["year"], $mcal); MCAL_Agenda::afficheMois($dateCourante["mon"], $dateCourante["year"], $mcal); ?> </body> </html>

Le fichier mcal_02.php nest rien dautre que mcal_01.php auquel nous avons ajout un style afin de prciser la couleur des dates associes un vnement et une connexion lagenda.

463

Chapitre 8

La gestion des dates et des calendriers

Voici un exemple de rsultat obtenu (dans les cas dun vnement mensuel sur toute lanne et dun vnement hebdomadaire sur les derniers mois).

Figure 8.5 : Calendrier annuel avec des vnements

8. La gestion des dates et des calendriers

Attention aux vnements rcurrents Nous aurions pu (comme nous lavons vu dans des exemples proposs sur Internet) viter un appel la fonction mcal_list_event() pour chaque jour, et se contenter de lappliquer lensemble de la priode considre. Le problme est que, dans ce cas, pour les vnements rcurrents, nous naurions pu calculer leurs diffrentes dates dapparition (la fonction mcal_list_event() ne retournant quune seule fois lidentifiant de lvnement, quel que soit son nombre dapparitions sur la priode donne). Cette mthode nest donc srieusement envisageable que dans le cas dun agenda ne contenant que des vnements ponctuels.
Comme vous le constatez, la fonction mcal_list_event() ne retourne quune liste didentifiants, mais pas le descriptif des vnements. Pour cela, vous devez faire appel (pour chaque identifiant) la fonction mcal_fetch_event().

464

Les gestionnaires dvnements

mcal_fetch_event()
Retourne les proprits dun vnement. Syntaxe $idConnexion $idEvenement $options retour object mcal_fetch_event(resource $idConnexion, int $idEvenement [, int $options]) Identifiant de connexion tel que retourn par mcal_open(). Identifiant de lvnement. Manifestement inutilis. Objet vnement.

Les proprits dun vnement sont donc retournes sous la forme dun objet. Cet objet possde les attributs publics suivants:
j j j j j j j j j
id (int) : identifiant de lvnement ; public (boolean) : TRUE si lvnement est public, FALSE sil est priv ; title (string) : nom de lvnement ; category (string) : chane de caractres libre destine indiquer la catgorie de lvnement ; description (string) : description de lvnement ; attrlist (array) : tableau associatif des attributs personnaliss (attribut => valeur) ; start (objet date et heure) : date de dbut (de la premire occurrence) de lvnement ; end (objet date et heure) : date de fin (de la premire occurrence) de lvnement ; recur_type (int) : type de frquence pouvant avoir une des valeurs MCAL_RECUR_NONE (ponctuelle), MCAL_RECUR_DAILY (frquence exprime en jours), MCAL_RECUR_WEEKLY (frquence exprime en semaines), MCAL_RECUR_MONTHLY_MDAY (frquence exprime en mois), MCAL_RECUR_MONTHLY_WDAY (frquence exprime en mois, base sur le jour de la semaine), MCAL_RECUR_YEARLY (frquence exprime en annes). recur_interval (int) : frquence 1 (jour/semaine/mois/anne) sur recur_interval (ex . : un jour sur deux si recur_type = MCAL_RECUR_DAILY et recur_interval = 2) ;

j j

8. La gestion des dates et des calendriers

recur_data (int) : jours de la semaine pendant lesquels lvnement a lieu (si recur_type = MCAL_RECUR_WEEKLY). Cette valeur est la somme des valeurs suivantes : 1 = dimanche, 2 = lundi, 4 = mardi, 8 = mercredi, 16 = jeudi, 32 = vendredi, 64 = samedi). recur_enddate (objet date et heure) : date laquelle lvnement rcurrent sarrte ; alarm (int) : dlai (en minutes) prcdant lvnement pour lequel il faut dclencher une alarme.

j j

Lobjet date et heure, quant lui, possde les attributs publics suivants :
j j
year (int) : anne ; month (int) : mois ;

465

Chapitre 8

La gestion des dates et des calendriers

j j j j j

mday (int) : jour ; hour (int) : heure ; min (int) : minutes ; sec (min) : secondes ; alarm (min) : ce paramtre nest toutefois pas utilis.

Nous pouvons donc ajouter une mthode affichant (brut de fonderie) les proprits dun vnement.

Listing 8.14 : mcal_03_inc.php (extrait)


<?php // Extrait de la Classe MCAL_Agenda class MCAL_Agenda { // (...) function afficheEvenement($idEvenement, $mcal) { $evenement = mcal_fetch_event($mcal, $idEvenement); echo "<table>"; echo "<td colspan=\"2\" class=\"titreEvenement\">"; echo $evenement->title." (".$evenement->id."/"; if ($evenement->public) { echo "Publique"; } else { echo "Priv"; } echo ")</td></tr>\n"; echo "<tr><td>Catgorie</td><td>".$evenement->category."</td></tr>"; echo "<tr><td>Description</td>"; echo "<td>".$evenement->description."</td></tr>"; echo "<tr><td>Attributs Personnaliss</td>"; echo "<td>"; foreach ($evenement->attrlist as $nom => $valeur) { echo "$nom = $valeur<br />"; } echo "</td></tr>"; echo "<tr><td>Alarme</td>"; echo "<td>".$evenement->alarm." minutes avant</td></tr>"; $dateDebut = $evenement->start; echo "<tr><td>Dbut</td>"; echo "<td>".$dateDebut->mday."/".$dateDebut->month."/"; echo $dateDebut->year." ".$dateDebut->hour.":".$dateDebut->min; echo ":".$dateDebut->sec.; echo " (Alarme : ".$dateDebut->alarm.")</td></tr>";

8. La gestion des dates et des calendriers 466

Les gestionnaires dvnements

$dateFin = $evenement->end; echo "<tr><td>Fin</td><td>".$dateFin->mday."/".$dateFin->month."/"; echo $dateFin->year." ".$dateFin->hour.":".$dateFin->min; echo ":".$dateFin->sec." (Alarme : ".$dateFin->alarm.")</td></tr>"; echo "<tr><td>Frquence</td>"; echo "<td>"; switch ($evenement->recur_type) { case 0 : echo "Ponctuel"; break; case 1 : if ($evenement->recur_interval == 1) { echo "Quotidien"; } else { echo "1 jour sur ".$evenement->recur_interval; } break; case 2 : if ($evenement->recur_interval == 1) { echo "Hebdomadaire"; } else { echo "1 semaine sur ".$evenement->recur_interval; } echo "<br />Les "; if (($evenement->recur_data & 1)>0) echo "Dimanche "; if (($evenement->recur_data & 2)>0) echo "Lundi "; if (($evenement->recur_data & 4)>0) echo "Mardi "; if (($evenement->recur_data & 8)>0) echo "Mercredi "; if (($evenement->recur_data & 16)>0) echo "Jeudi "; if (($evenement->recur_data & 32)>0) echo "Vendredi "; if (($evenement->recur_data & 64)>0) echo "Samedi "; break; case 3 : if ($evenement->recur_interval == 1) { echo "Mensuel"; } else { echo "1 mois sur ".$evenement->recur_interval; } break; case 4 : echo "Tous les N-ime jour (Dim, Lun...) du mois."; if ($evenement->recur_interval == 1) { echo "Mensuel"; } else { echo "1 mois sur ".$evenement->recur_interval; } break; case 5 : if ($evenement->recur_interval == 1) { echo "Annuel"; } else { echo "1 an sur ".$evenement->recur_interval; } break; default : echo "????"; break;

8. La gestion des dates et des calendriers 467

Chapitre 8

La gestion des dates et des calendriers

} echo "</td></tr>"; $dateFinRecur = $evenement->recur_enddate; echo "<tr><td>Jusquau</td>"; echo "<td>".$dateFinRecur->mday."/".$dateFinRecur->month."/"; echo $dateFinRecur->year." "; echo $dateFinRecur->hour.":".$dateFinRecur->min; echo ":".$dateFinRecur->sec; echo " (Alarme : ".$dateFinRecur->alarm.")</td></tr>"; echo "</table>"; } } ?> Figure 8.6 : Fiche vnement

Il est galement possible de connatre la date du prochain vnement par rapport une date donne.

mcal_next_recurrence()
Retourne la date de lvnement suivant la date donne. Syntaxe

8. La gestion des dates et des calendriers

object mcal_next_recurrence(resource $idConnexion, int $weekstart, array $dateDebut) Identifiant de connexion tel que retourn par mcal_open(). Vraiment pas clair, le rle de cet argument ! Il ne semble avoir aucune influence sur le rsultat Tableau associatif contenant la date de dbut de recherche avec les cls : "year" pour lanne. "month" pour le mois. "mday" pour le jour. "hour" pour lheure. "min" pour les minutes. "sec" pour les secondes. Objet date.

$idConnexion $weekstart $dateDebut

retour

468

Les gestionnaires dvnements

Dnition des donnes des vnements


Linsertion de nouveaux vnements dans lagenda dbute par linitialisation des donnes de lvnement en cours de description par un appel mcal_event_init().

mcal_event_init()
Initialise une nouvelle description dvnement. Syntaxe $idConnexion retour boolean mcal_event_init(resource $idConnexion) Identifiant de connexion tel que retourn par mcal_open(). TRUE.

Il est ensuite possible de dfinir, pour lvnement en cours :


j j j j j j

Sa visibilit (publique ou prive) ; Son titre ; Sa description ; Sa catgorie ; Ses paramtres personnaliss ; Sa date.

mcal_event_set_class()
Fixe la visibilit (publique ou prive) de lvnement. Par dfaut, un vnement est priv. Syntaxe $idConnexion $visibilite retour boolean mcal_event_set_class(resource $idConnexion, boolean $visibilite) Identifiant de connexion tel que retourn par mcal_open().

8. La gestion des dates et des calendriers

Visibilit de lvnement (TRUE = publique, FALSE = prive). TRUE.

mcal_event_set_title()
Associe un nom lvnement. Syntaxe boolean mcal_event_set_title(resource $idConnexion, string $nom)

469

Chapitre 8

La gestion des dates et des calendriers

$idConnexion $nom retour

Identifiant de connexion tel que retourn par mcal_open(). Intitul de lvnement. TRUE.

mcal_event_set_description()
Associe un commentaire lvnement. Syntaxe $idConnexion $description retour boolean mcal_event_set_description(resource $idConnexion, string $description) Identifiant de connexion tel que retourn par mcal_open(). Descriptif de lvnement. TRUE.

mcal_event_set_category()
Associe une catgorie lvnement. Syntaxe $idConnexion $category retour boolean mcal_event_set_category(resource $idConnexion, string $category) Identifiant de connexion tel que retourn par mcal_open(). Catgorie de lvnement (il ny a pas de valeurs prdfinies : vous de les crer). TRUE.

8. La gestion des dates et des calendriers

mcal_event_add_attribute()
Associe lvnement un attribut personnalis. Syntaxe $idConnexion $attribut $valeur boolean mcal_event_add_attribute(resource $mcal, string $attribut, string $valeur) Identifiant de connexion tel que retourn par mcal_open(). Nom de lattribut personnalis. Valeur associe lattribut personnalis.

470

Les gestionnaires dvnements

Dnition des dates dapparition des vnements


Les dates des vnements sappuient sur plusieurs lments. En effet, les vnements ntant pas toujours ponctuels, prciser des dates de dbut et de fin se rvle souvent insuffisant. Vous serez donc probablement amen devoir prciser une frquence dapparition de lvnement. Un vnement pourra, en effet, avoir lieu un jour sur N, une semaine sur N, un mois sur N (en sappuyant soit sur le numro du jour dans le mois, soit sur le nom du jour de la semaine et le numro de la semaine dans le mois) ou bien encore un an sur N.

mcal_event_set_start()
Prcise la date de dbut (de la premire occurrence) de lvnement. Syntaxe boolean mcal_event_set_start(resource $idConnexion, int $annee, int $mois [, int $jour [, int $heure [, int $minute [, int $seconde]]]]) Identifiant de connexion tel que retourn par mcal_open(). Anne de dbut de lvnement. Mois de dbut de lvnement. Jour de dbut de lvnement. Heure de dbut de lvnement. Minutes de la date de dbut de lvnement. Secondes de la date de dbut de lvnement. TRUE.

$idConnexion $annee $mois $jour $heure $minute $seconde retour

mcal_event_set_end()
Prcise la date de fin (de la premire occurrence) de lvnement. Syntaxe boolean mcal_event_set_end(resource $idConnexion, int $annee, int $mois [, int $jour [, int $heure [, int $minute [, int $seconde]]]]) Identifiant de connexion tel que retourn par mcal_open(). Anne de dbut de lvnement. Mois de dbut de lvnement. Jour de dbut de lvnement. Heure de dbut de lvnement. Minutes de la date de fin de lvnement. Secondes de la date de fin de lvnement. TRUE.

8. La gestion des dates et des calendriers

$idConnexion $annee $mois $jour $heure $minute $seconde retour

471

Chapitre 8

La gestion des dates et des calendriers

mcal_event_set_recur_daily()
Prcise la frquence de lvnement sur la base des jours. Syntaxe $idConnexion $annee $mois $jour $frequence retour boolean mcal_event_set_recur_daily(resource $idConnexion, int $annee, int $mois, int $jour, int $frequence) Identifiant de connexion tel que retourn par mcal_open(). Anne de la date de fin de rcurrence de lvnement. Mois de la date de fin de rcurrence de lvnement. Jour de la date de fin de rcurrence de lvnement. Lvnement a lieu un jour sur $frequence. (Si $frequence = 0, lvnement est ponctuel.) TRUE.

mcal_event_set_recur_weekly()
Prcise la frquence de lvnement sur la base des semaines. Syntaxe boolean mcal_event_set_recur_weekly(resource $idConnexion, int $annee, int $mois, int $jour, int $frequence, int $joursSemaine) Identifiant de connexion tel que retourn par mcal_open(). Anne de la date de fin de rcurrence de lvnement. Mois de la date de fin de rcurrence de lvnement. Jour de la date de fin de rcurrence de lvnement. Lvnement a lieu une semaine sur $frequence. Indique quels jours de la semaine lvnement a lieu. Cette valeur est laddition des valeurs suivantes : 1 = dimanche, 2 = lundi, 4 = mardi, 8 = mercredi, 16 = jeudi, 32 = vendredi, 64 = samedi. TRUE.

$idConnexion $annee $mois $jour $frequence $joursSemaine

8. La gestion des dates et des calendriers

retour

mcal_event_set_recur_monthly_mday()
Prcise la frquence de lvnement sur la base des mois. Syntaxe boolean mcal_event_set_recur_monthly_mday(resource $idConnexion, int $annee, int $mois, int $jour, int $frequence)

472

Les gestionnaires dvnements

$idConnexion $annee $mois $jour $frequence retour

Identifiant de connexion tel que retourn par mcal_open(). Anne de la date de fin de rcurrence de lvnement. Mois de la date de fin de rcurrence de lvnement. Jour de la date de fin de rcurrence de lvnement. Lvnement a lieu un mois sur $frequence ( la mme date que le jour de dbut de la premire occurrence). TRUE.

Semaines incompltes Le comportement de cette fonction peut surprendre dans certains cas (mme sil reste assez logique). Si vous prenez lanne 2003, qui commence par un mercredi, et que vous souhaitez indiquer que, tout au long de lanne, vous aurez une runion le premier lundi du mois, vous prenez comme date de dbut de lvnement le lundi 6 janvier (premier lundi du mois de janvier, mais lundi de la seconde semaine du mois) : vous pointerez donc chaque mois sur le lundi de la seconde semaine du mois.

mcal_event_set_recur_monthly_wday()
Prcise la frquence de lvnement sur la base des mois (au mme jour de la mme semaine chaque mois). Syntaxe $idConnexion $annee $mois $jour $frequence retour boolean mcal_event_set_recur_monthly_wday(resource $idConnexion, int $annee, int $mois, int $jour, int $frequence) Identifiant de connexion tel que retourn par mcal_open(). Anne de la date de fin de rcurrence de lvnement. Mois de la date de fin de rcurrence de lvnement. Jour de la date de fin de rcurrence de lvnement. Lvnement a lieu un mois sur $frequence (le mme jour de la mme semaine que la date de dbut de la premire occurrence). TRUE.

8. La gestion des dates et des calendriers

mcal_event_set_recur_yearly()
Prcise la frquence de lvnement sur la base des annes. Syntaxe boolean mcal_event_set_recur_yearly(resource $idConnexion, int $annee, int $mois, int $jour, int $frequence)

473

Chapitre 8

La gestion des dates et des calendriers

$idConnexion $annee $mois $jour $frequence retour

Identifiant de connexion tel que retourn par mcal_open(). Anne de la date de fin de rcurrence de lvnement. Mois de la date de fin de rcurrence de lvnement. Jour de la date de fin de rcurrence de lvnement. Lvnement a lieu un an sur $frequence. TRUE.

Dclenchement de lalarme

mcal_event_set_alarm()
Prpare une alarme pour lvnement. Syntaxe $idConnexion $delaisRappel retour boolean mcal_event_set_alarm(resource $idConnexion, int $delaisRappel) Identifiant de connexion tel que retourn par mcal_open(). Indique, en minutes, combien de temps avant lchance lalarme doit se dclencher. TRUE.

Synthse des proprits dun vnement


Nous vous proposons de regrouper toutes ces proprits dans un objet "fait maison". Lintrt en est peut-tre limit, mais, comme il sagit dun objet, vous pouvez toujours lenrichir votre guise. Il permet toutefois de dfinir les proprits par des noms dattributs en franais (pour les non anglophones) et, surtout, de distinguer la dfinition de lobjet (assignation des valeurs des attributs) des "appels" aux calendriers (avec passage du paramtre $idConnexion). Cette dernire opration est ici ralise par une unique mthode prepare($idConnexion).

8. La gestion des dates et des calendriers

Listing 8.15 : mcal_evenement_inc.php (extrait)


<?php // Extrait de MCAL_Evenement class MCAL_Evenement { var var var var var var $visibilite; $titre, $description, $categorie; $dateDebut, $heureDebut; $dateFin, $heureFin; $frequenceType; $frequence;

474

Les gestionnaires dvnements

var $frequenceDateFin; var $frequenceJours; var $alarme; // Les attributs personnaliss var $monAttribut1, $monAttribut2; // Libre vous de construire // les mthodes setXX() et getXX() qui vont bien

// Stocke tous les attributs de lobjet // dans lvnement courant // (avant sauvegarde) function prepare($mcal) { mcal_event_init($mcal); if (isset($this->visibilite)) mcal_event_set_class($mcal, $this->visibilite); if (isset($this->titre)) mcal_event_set_title($mcal, $this->titre); if (isset($this->description)) mcal_event_set_description($mcal, $this->description); if (isset($this->categorie)) { mcal_event_set_category($mcal, $this->categorie); } if (isset($this->dateDebut)) { list($annee, $mois, $jour) = explode("-", $this->dateDebut); if (isset($this->heureDebut)) { list($heure, $minutes, $secondes) = explode(":", $this->heureDebut); } mcal_event_set_start($mcal, $annee, $mois, $jour, $heure, $minutes, $secondes); } if (isset($this->dateFin)) { list($annee, $mois, $jour) = explode("-", $this->dateFin); if (isset($this->heureFin)) { list($heure, $minutes, $secondes) = explode(":", $this->heureFin); } mcal_event_set_end($mcal,

8. La gestion des dates et des calendriers 475

Chapitre 8

La gestion des dates et des calendriers

$annee, $mois, $jour, $heure, $minutes, $secondes); } if (isset($this->frequenceType) && isset($this->frequenceDateFin) && isset($this->frequence)) { if (isset($this->frequenceDateFin)) { list($annee, $mois, $jour) = explode("-", $this->frequenceDateFin); } switch ($this->frequenceType) { case MCAL_RECUR_DAILY : mcal_event_set_recur_daily($mcal, $annee, $mois, $jour, $this->frequence); break; case MCAL_RECUR_WEEKLY : mcal_event_set_recur_weekly($mcal, $annee, $mois, $jour, $this->frequence, $this->frequenceJours); break; case MCAL_RECUR_MONTHLY_MDAY : mcal_event_set_recur_monthly_mday($mcal, $annee, $mois, $jour, $this->frequence); break; case MCAL_RECUR_MONTHLY_WDAY : mcal_event_set_recur_monthly_wday($mcal, $annee, $mois, $jour, $this->frequence); break; case MCAL_RECUR_YEARLY : mcal_event_set_recur_yearly($mcal, $annee, $mois, $jour, $this->frequence); break; default: // vnement ponctuel break; } } if (isset($this->alarme)) { mcal_event_set_alarm($mcal, $this->alarme); } if (isset($this->monAttribut1)) { mcal_event_add_attribute($mcal, "monAttribut1",$this->monAttribut1); }

8. La gestion des dates et des calendriers 476

Les gestionnaires dvnements

if (isset($this->monAttribut2)) { mcal_event_add_attribute($mcal, "monAttribut2",$this->monAttribut2); } } // (...) }

noter que, dans notre cas, nous avons un objet qui pourra contenir deux attributs personnaliss, que nous appellerons respectivement monAttribut1 et monAttribut2. Nous verrons un exemple dutilisation de cet objet un peu plus loin dans ce chapitre.

Consultation de lvnement en cours


Il est possible tout moment de consulter le contenu de lvnement en cours grce mcal_fetch_current_stream_event(). Ceci peut tre utile pour le dbogage, afin de vrifier ce que nous nous apprtons sauvegarder.

mcal_fetch_current_stream_event()
Retourne les proprits de lobjet en cours. Syntaxe $idConnexion retour object mcal_fetch_current_stream_event(resource $idConnexion) Identifiant de connexion tel que retourn par mcal_open(). Objet vnement.

cette fin, nous avons ajout une mthode lobjet MCAL_Evenement voqu prcdemment.

Listing 8.16 : mcal_evenement_inc.php (extrait)


<?php // Extrait de MCAL_Evenement class MCAL_Evenement { // (...) function toHTMLStringCurrentEvent($mcal) { $even = mcal_fetch_current_stream_event($mcal); $txt $txt $txt $txt $txt = .= .= .= .= ""; "Id = ".$even->id."<br />"; "Titre = ".$even->title."<br />"; "Visibilit = ".$even->public."<br />"; "Categorie = ".$even->category."<br />";

8. La gestion des dates et des calendriers 477

Chapitre 8

La gestion des dates et des calendriers

$txt .= "Description = ".$even->description."<br />"; $attrlist = $even->attrlist; $txt .= "monAttribut1 = ".$attrlist["monAttribut1"]."<br />"; $txt .= "monAttribut2 = ".$attrlist["monAttribut2"]."<br />"; $date = $txt .= $txt .= $txt .= $txt .= $date = $txt .= $txt .= $txt .= $txt .= $even->start; "debut = "; $date->year."-".$date->month."-".$date->mday; " ".$date->hour.":".$date->min.":".$date->sec; "<br />"; $even->end; "debut = "; $date->year."-".$date->month."-".$date->mday; " ".$date->hour.":".$date->min.":".$date->sec; "<br />";

$txt .= "frequenceType = ".$even->recur_type."<br />"; $txt .= "frequence = ".$even->recur_interval."<br />"; $txt .= "frequenceJours = ".$even->recur_data."<br />"; $date = $txt .= $txt .= $txt .= $even->recur_enddate; "frequenceDateFin = "; $date->year."-".$date->month."-".$date->mday; "<br />";

$txt.="Alarme = ".$even->alarm."<br />"; return $txt; } }

Sauvegarde des vnements


Enfin, pour sauvegarder lvnement, nous disposons de la fonction mcal_store_event().

8. La gestion des dates et des calendriers

mcal_store_event()
Enregistre lvnement en cours. ( lissue de cet appel, ltat de lvnement courant est indtermin. Il convient donc de faire un appel mcal_event_init().) Syntaxe $idConnexion retour int mcal_store_event(resource $idConnexion) Identifiant de connexion tel que retourn par mcal_open(). Identifiant de lvnement ainsi ajout, ou FALSE en cas dchec.

478

Les gestionnaires dvnements

mcal_append_event() Depuis la version 4.0, est apparue la fonction mcal_append_event(), qui semble avoir le mme comportement que mcal_store_event() (mme si la documentation PHP indique que lune sert modifier un vnement, tandis que lautre sert lajouter lagenda).
Ceci nous permet denrichir notre objet MCAL_Evenement avec une mthode sauve().

Listing 8.17 : mcal_evenement_inc.php (extrait)


<?php // Extrait de MCAL_Evenement class MCAL_Evenement { // (...) // Sauve lvnement function sauve($mcal) { $this->prepare($mcal); $id=mcal_store_event($mcal); if ($id !== FALSE) { $this->id=$id; } return $id; } }

Remarquez, quici, nous en profitons pour stocker lidentifiant de lvnement dans lobjet MCAL_Evenement. Maintenant, comme nous ne voulons pas avoir crit cette classe pour rien, nous allons lutiliser afin denregistrer un vnement dans lagenda. Mais, pour cela, un formulaire de saisie tant plus que pratique, nous allons ajouter cette classe une mthode permettant dafficher un formulaire adapt.

8. La gestion des dates et des calendriers

Listing 8.18 : mcal_evenement_inc.php (extrait)


<?php // extrait de MCAL_Evenement class MCAL_Evenement { // (...) /**

479

Chapitre 8

La gestion des dates et des calendriers

* Affiche un formulaire de saisie dvnement * * @param action string page appeler lors de lenvoi des donnes */ function afficheFormulaire($action="mcal_evenement_sauve.php") { echo "<form action=\"$action\" method=\"post\">\n"; echo "<table border=\"0\" cellspacing=\"0\" cellpadding=\"2\">\n"; echo "<tr class=\"champsdescription\"><td><b>Titre</b></td>"; echo "<td><input type=\"texte\" name=\"titre\"/></td>"; echo "<td><select name=\"visibilite\">"; echo "<option value=\"0\">Priv</option>"; echo "<option value=\"1\">Publique</option>"; echo "</select></td></tr>\n"; echo "<tr class=\"champsdescription\"><td><b>Catgorie</b></td>"; echo "<td colspan=\"2\"><select name=\"categorie\">"; echo "<option value=\"boulot\">Boulot</option>"; echo "<option value=\"loisirs\">Loisirs</option>"; echo "<option value=\"divers\">Divers</option>"; echo "</select></td>"; echo "</tr>\n"; echo "<tr class=\"champsdescription\"><td><b>Description</b></td>"; echo "<td colspan=\"2\"><textarea name=\"description\">"; echo "</textarea></td>"; echo "</tr>\n"; echo "<tr class=\"champsdescription\"><td><b>Salle</b>(*)</td>"; echo "<td colspan=\"2\"><input type=\"text\" name=\"salle\"></td>"; echo "</tr>\n"; echo "<tr class=\"champsdate\"><td><b>Date Dbut</b></td>"; echo "<td><input type=\"text\" name=\"dateDebut\" /></td>"; echo "<td>(AAAA-MM-JJ)</td>"; echo "</tr>\n"; echo "<tr class=\"champsdate\"><td><b>Heure Dbut</b></td>"; echo "<td><input type=\"text\" name=\"heureDebut\" /></td>"; echo "<td>(HH:MM:SS)</td>"; echo "</tr>\n"; echo "<tr class=\"champsdate\"><td><b>Date Fin</b></td>"; echo "<td><input type=\"text\" name=\"dateFin\" /></td>"; echo "<td>(AAAA-MM-JJ)</td>"; echo "</tr>\n"; echo "<tr class=\"champsdate\"><td><b>Heure Fin</b></td>"; echo "<td><input type=\"text\" name=\"heureFin\" /></td>"; echo "<td>(HH:MM:SS)</td>"; echo "</tr>\n"; echo "<tr class=\"champsfrequence\">"; echo "<td><b>Frquence</b></td>"; echo "<td>1 <select name=\"frequenceType\">"; echo "<option value=\"0\">(Evnement ponctuel)</option>"; echo "<option value=\"1\">Jour</option>"; echo "<option value=\"2\">Semaine</option>"; echo "<option value=\"3\">Mois (mme date)</option>"; echo "<option value=\"4\">Mois (mme jour,semaine)</option>";

8. La gestion des dates et des calendriers 480

Les gestionnaires dvnements

echo "<option value=\"5\">An</option>"; echo "</select></td>\n"; echo "<td>sur <input type=\"text\" name=\"frequence\"". " size=\"3\"></td>"; echo "</tr>\n"; echo "<tr class=\"champsfrequence\">"; echo "<td><b>Jours de la semaine</b><br />(si hebdomadaire)</td>"; echo "<td colspan=\"2\"><table><tr>"; echo "<td><input type=\"checkbox\" name=\"dimanche\" />Dimanche</td>"; echo "<td><input type=\"checkbox\" name=\"lundi\" />Lundi</td>"; echo "<td><input type=\"checkbox\" name=\"mardi\" />Mardi</td>"; echo "<td><input type=\"checkbox\" name=\"mercredi\" />Mercredi</td>"; echo "</tr><tr>"; echo "<td><input type=\"checkbox\" name=\"jeudi\" />Jeudi</td>"; echo "<td><input type=\"checkbox\" name=\"vendredi\" />Vendredi</td>"; echo "<td><input type=\"checkbox\" name=\"samedi\" />Samedi</td>"; echo "</tr></table></td></tr>\n"; echo "<tr class=\"champsfrequence\">"; echo "<td><b>Jusquau</b></td>"; echo "<td><input type=\"text\" name=\"frequenceDateFin\" /></td>"; echo "<td>(AAAA-MM-JJ)</td></tr>\n"; echo "<tr class=\"champsalarme\"><td><b>Prevenez moi</b></td>"; echo "<td colspan=\"2\">"; echo "<select name=\"alarme\">"; echo "<option value=\"0\">(pas)</option>"; echo "<option value=\"5\" selected=\"selected\">5 min.</option>"; echo "<option value=\"10\">10 min.</option>"; echo "<option value=\"15\">1/4 h.</option>"; echo "<option value=\"30\">1/2 h.</option>"; echo "<option value=\"60\">1 h.</option>"; echo "</select>"; echo " avant</td></tr>"; echo "<tr><td colspan=\"3\">"; echo "(*) Exemple dattribut personnalis</td></tr>\n"; echo "<tr><td colspan=\"3\" align=\"center\">"; echo "<input type=\"submit\" value=\"Ajouter\" />"; echo "</td></tr>"; echo "</table>\n"; echo "</form>"; } // (...) }

8. La gestion des dates et des calendriers

Ce formulaire aura lallure suivante (certes, il manque de fioritures, mais cest efficace) (voir fig. 8.7) : Lors de la validation du formulaire, la page mcal_evenement_sauve.php sera appele. Celle-ci a donc pour mission de copier les paramtres issus de la mthode POST dans un objet MCAL_Evenement et dappeler tout bonnement la mthode sauve() aprs avoir ouvert une connexion sur lagenda.

481

Chapitre 8

La gestion des dates et des calendriers

Figure 8.7 : Formulaire de saisie dvnement

Listing 8.19 : mcal_evenement_sauve.php


<?php include("mcal_03_inc.php"); include("mcal_evenement_inc.php"); // Connexion lagenda $mcal = MCAL_Agenda::connect();

// Instanciation dun objet MCAL_Evenement // (objet construit par nos soins) $evenement = new MCAL_Evenement(); // Copie des donnes issues du formulaire // dans la structure de lobjet $evenement->visibilite $evenement->titre $evenement->categorie $evenement->description $evenement->monAttribut1 $evenement->dateDebut $evenement->heureDebut $evenement->dateFin $evenement->heureFin = = = = $_POST["visibilite"]; stripslashes($_POST["titre"]); $_POST["categorie"]; stripslashes($_POST["description"]);

8. La gestion des dates et des calendriers

= $_POST["salle"]; = $_POST["dateDebut"]; = $_POST["heureDebut"]; = $_POST["dateFin"]; = $_POST["heureFin"];

$evenement->frequenceType = $_POST["frequenceType"]; $evenement->frequence = $_POST["frequence"]; if ($evenement->frequenceType == 2) {

482

Les gestionnaires dvnements

+= 64; } $evenement->frequenceDateFin = $_POST["frequenceDateFin"]; $evenement->alarme = $_POST["alarme"];

$evenement->frequenceJours = 0; if ($_POST["dimanche"] == "on") $evenement->frequenceJours if ($_POST["lundi"] == "on") $evenement->frequenceJours if ($_POST["mardi"] == "on") $evenement->frequenceJours if ($_POST["mercredi"] == "on") $evenement->frequenceJours if ($_POST["jeudi"] == "on") $evenement->frequenceJours if ($_POST["vendredi"] == "on") $evenement->frequenceJours if ($_POST["samedi"] == "on") $evenement->frequenceJours

+= 1; += 2; += 4; += 8; += 16; += 32;

$id = $evenement->sauve($mcal); ?> <html> <body> <h1>Enregistrement dun vnement</h1> <?php if ($d !== FALSE) { echo "Votre nouvel vnement a t enregistr (avec lidentifiant". " $id)"; } else { echo "La tentative denregistrement de lvnement chou"; } echo $evenement->toHTMLString(); ?> </body> </html>

8. La gestion des dates et des calendriers

Utilisation de stripSlashes() Comme les paramtres titre et description sont des chanes de caractres librement saisies par lutilisateur, ils peuvent contenir (entre autres) des apostrophes. Or, par dfaut, PHP est configur avec loption magic_quotes_gpc = on, ce qui fait que les valeurs passes par les mthodes POST, et GET ou par cookies voient leurs apostrophes prcdes dun anti-slash (comme le fait la fonction addSlashes()). Il faut les supprimer, car, bien que fort utiles dans le cas dun ajout dans une base de donnes, ils sont gnants lorsque les valeurs sont simplement passes en paramtre dune fonction (ici les fonctions mcal).

483

Chapitre 8

La gestion des dates et des calendriers

Oprations sur les vnements enregistrs


Une fois lvnement enregistr, il est tout de mme possible de supprimer facilement lalarme qui lui est associe par un appel la fonction mcal_snooze().

mcal_snooze()
Supprime lalarme associe un vnement. Syntaxe $idConnexion $idEvenement retour boolean mcal_snooze(resource $idConnexion, int $idEvenement) Identifiant de connexion tel que retourn par mcal_open(). Identifiant de lvnement. TRUE.

La bibliothque propose une fonction qui est cense retourner la liste des vnements ayant une alarme programme la date donne. Mais il est difficile den tirer quelque chose. En voici tout de mme la syntaxe (corrige par rapport celle propose par la documentation PHP) :
array mcal_list_alarms(resource $idConnexion[, int $annee [, int $mois [, int $jour [, int $heure [, int $minutes [, int $secondes]]]]]])

Et, bien videmment, il est possible de supprimer un vnement de lagenda par un appel mcal_delete_event().

mcal_delete_event()
Supprime un vnement. Syntaxe $idConnexion boolean mcal_delete_event(resource $idConnexion, resource $idEvenement) Identifiant de connexion tel que retourn par mcal_open(). Identifiant de lvnement supprimer. TRUE (mme si lvnement nexiste pas).

8. La gestion des dates et des calendriers

$idEvenement retour

Divers
La bibliothque MCAL prsente des fonctions destines la manipulation des agendas (dans leur ensemble). Il sagit des fonctions mcal_create_calendar(), mcal_rename_calendar(), mcal_delete_calendar(), mais celles-ci ne semblent pas avoir t vritablement implmentes et se contentent de retourner TRUE.

484

Chapitre 9

La gestion des chiers et des rpertoires


9.1 9.2 9.3 Le systme de chiers POSIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487 Accder au systme de chiers du serveur . . . . . . . . . . . . . . . . . . . . . . . . 490 Les streams ou les ux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593

Le systme de fichiers POSIX

a manipulation et le traitement des donnes ncessitent, voire imposent, de pouvoir stocker celles-ci une fois le travail et les diffrentes oprations effectus. Mme si, souvent, lutilisation dune base de donnes est plus efficace, le stockage sur le disque reste une solution simple mettre en uvre, et parfois mme la seule solution pertinente. Dans ce chapitre, nous allons voir comment le langage PHP peut permettre de lister, lire et crire des fichiers. Tout au long de ce chapitre, nous allons mettre en place diffrentes fonctions qui nous permettront, au final, de dvelopper un explorateur de fichiers simple et sympa (attention toutefois : il nest pas laisser entre toutes les mains). Dans une deuxime partie, nous allons voir comment il est possible daccder au systme de fichier, rseau, socket laide dune mthode introduite avec PHP 4.3 et disponible galement sur PHP 5 : Les streams ou flux.

9. La gestion des fichiers et des rpertoires

9.1.

Le systme de chiers POSIX

Mme si vous tes un adepte des produits Microsoft, il est probable que votre application sera hberge sur une plateforme de type UNIX/Linux. Cest en effet le systme dexploitation adopt par la majorit des hbergeurs quils soient ou non gratuits. Nous vous offrons donc, ici, un petit cours de rattrapage en faisant un point sur les spcificits du systme de fichiers de ces systmes dexploitation (ceci est valable pour tous les systmes de fichiers la norme POSIX que sont Linux et tous les UNIX modernes). Mme si, petit petit, Windows tente (pniblement) de rattraper son retard en termes de scurit, avec UNIX/Linux, les droits des utilisateurs ne sont dj pas un vain mot. Ainsi, lutilisateur devra ncessairement sidentifier pour se connecter au systme, ce qui constitue la base de la scurit de la machine. UNIX tant, ds son origine, un systme multi-utilisateur, il a t conu de sorte que les fichiers ne soient accessibles qu certains utilisateurs et certains groupes dutilisateurs. Seul ladministrateur, appel le plus souvent "root", possde tous les droits sur tous les fichiers du systme (sil existait des virus dans un environnement UNIX/Linux, il faudrait encore quils accdent au compte "root" pour causer des dommages irrparables ; de mme, un utilisateur protgeant ses fichiers vis--vis des autres utilisateurs ne pourrait tre contamin). Chaque utilisateur peut appartenir un ou plusieurs groupes que lon dfinira librement (ex. : groupe des chercheurs, des invits, des utilisateurs du service web, etc). Chaque fichier est la proprit dun utilisateur et dun groupe dutilisateurs. Ainsi, si vous listez le contenu dun rpertoire dun systme UNIX/Linux (si vous faites appel aux services dun hbergeur, vous pouvez, par exemple, vous connecter sous votre compte FTP, et taper la commande ls), vous observerez une srie de lignes ayant lallure suivante :
rwxrwr 1 laurent user 985540 Mai 4 09:16 Monfichier

Chaque ligne est associe un fichier ou un rpertoire dont le nom est prcis dans la dernire colonne (ici : Monfichier).

On ne rigole pas avec la casse... UNIX respecte la casse. Faites donc bien attention au respect des majuscules et minuscules des noms de fichiers et rpertoires. Vous pouvez trs bien avoir un fichier nomm toto.txt qui coexiste, dans le mme rpertoire, avec un fichier toto.TXT.

487

Chapitre 9

La gestion des fichiers et des rpertoires

Les troisime et quatrime colonnes nous indiquent que le propritaire du fichier est "laurent" et que le groupe auquel appartient le fichier est "user".

9. La gestion des fichiers et des rpertoires

Mais attention, ce nest pas parce que le fichier appartient "laurent" et au groupe "user" que Laurent et les membres du groupe "user" ont tous les droits, ni non plus que tous les autres utilisateurs nont aucun droit sur ce fichier. Les permissions sont dfinies ici par les proprits -rwxrw-r-- quil faut dcomposer en un caractre suivi de trois blocs de trois caractres. Nous reviendrons plus tard sur ce premier caractre. Le premier bloc de trois caractres prcise les droits de lutilisateur, le bloc suivant ceux des membres du groupe et enfin le dernier bloc de trois caractres indique les droits des autres utilisateurs. Chaque bloc se dcompose ainsi : 1. Un premier caractre pouvant prendre la valeur "r" pour indiquer que le fichier est accessible en lecture (pour lutilisateur, les membres du groupe ou les autres, selon les cas) ou "-" sinon. Dans le cas dun rpertoire, ceci indique que lon peut lister le contenu du rpertoire. Un second caractre pouvant prendre la valeur "w" pour indiquer que le fichier est accessible en criture (pour lutilisateur, les membres du groupe ou les autres, selon les cas), ce qui inclut la possibilit deffacer le fichier ou "-" sinon. Dans le cas dun rpertoire, ceci indique que lon peut modifier les fichiers contenus dans le rpertoire ( condition que les droits individuels des fichiers le permettent). Un troisime caractre pouvant prendre la valeur "x" pour indiquer que le fichier peut tre excut (par lutilisateur, les membres du groupe ou les autres, selon les cas) condition, toutefois, que ce soit un "excutable" ou "-" sinon. Dans le cas dun rpertoire, ceci indique que lon peut se dplacer dans le rpertoire.

2.

3.

Dans notre exemple, nous pouvons donc dire que le fichier est accessible en lecture, criture et excution pour lutilisateur. Le groupe possde les permissions en lecture et criture, mais ne peut pas excuter le fichier. Enfin, les autres utilisateurs ne sont autoriss qu la lecture. Les droits ne sont gnralement pas spcifis sous forme alphabtique, mais sous la forme dun nombre exprim en octal (base 8) et compos de trois chiffres (prcds dun 0 pour indiquer PHP quil sagit dun nombre en octal et non en dcimal). Chaque chiffre reprsente les droits dune catgorie (propritaire, groupe et autres). Pour chaque catgorie, il faut faire la somme des valeurs de chaque droit en considrant que r=4, w=2 et x=1. Imaginons, pour prendre un exemple, un fichier possdant les droits rwx pour lutilisateur, rx pour le groupe et r pour toutes les autres personnes.

Tableau 9.1 : Les droits en octal donnent pour le cas prsent : 0754
Propritaire Read(r) = 4 Write(w) = 2 Execute(x) = 1 Total Oui Oui Oui 4+2+1=7 Groupe Oui Non Oui 4+0+1=5 Autres Oui Non Non 4+0+0=4

Retenez bien cette leon, nous nous en resservirons un peu plus tard.

488

Le systme de fichiers POSIX

Revenons maintenant au premier caractre de la chane indiquant les droits du fichier. Il prcise le type du "fichier". Ici, "" indique que cest un fichier classique, mais cela aurait pu tre un rpertoire reprsent par la lettre "d", un priphrique dfini par "b" ou "c", ou un encore un lien symbolique associ la lettre "l". Vous savez tous ce quest un fichier ou un rpertoire (mme si certains ont russi imposer leur terminologie et parlent de dossier). Afin de ne pas nous tendre davantage sur les spcificits Linux/UNIX, nous ne parlerons pas des priphriques. Mais, afin de mieux comprendre certaines fonctions proposes par PHP, il est bon de vous prsenter ce quest un lien. Sous Linux/UNIX, il est possible de crer un "fichier" (une entre dans un rpertoire) qui sera en fait un lien, dit lien symbolique, vers un "vrai" fichier. Sous Windows, vous connaissez un ersatz du lien symbolique appel "raccourci". Double-cliquer sur un raccourci Windows revient double-cliquer sur le fichier point. En revanche, si vous souhaitez accder au contenu du raccourci, vous naccderez qu un fichier descripteur et non au contenu du fichier point. Sous Linux/UNIX, que vous accdiez au lien symbolique ou directement au fichier, le rsultat est le mme. Il existe une variante du lien symbolique appel lien physique, mais la nuance est subtile. Alors que le lien symbolique est un renvoi vers le fichier, le lien physique est une copie du descripteur de fichier. De ce fait, contrairement au lien physique, si vous supprimez le fichier "original", le lien symbolique nest plus valide. Dans les lignes retournes par la commande ls (via FTP ou ls l en accs direct sur le systme), le chiffre suivant correspond au nombre de liens physiques vers le fichier. Dans notre exemple, 1 signifie que le fichier ne possde aucun lien mis part lui-mme. Le nombre qui suit le groupe dappartenance du fichier est le poids (la taille) en octets. Ensuite, on retrouve la date de la dernire modification du fichier.

9. La gestion des fichiers et des rpertoires

Point et point-point sont dans un rpertoire... Pour chaque rpertoire vous noterez deux fichiers portant des noms particuliers : il sagit de "." et "..". Point est, en fait, une reprsentation du rpertoire courant, et point-point une reprsentation du rpertoire suprieur. Cest un point ;-) connatre lorsque vous souhaitez en lister le contenu.

Les chiers textes, les chiers binaires


Les fichiers peuvent tre rangs en deux catgories : les fichiers textes et les fichiers binaires. Dans le premier cas, ce sont des fichiers qui ne contiennent que des lignes de texte ; ce peut tre un document quelconque, un listing de programme ou des donnes textes. Le fichier binaire est destin contenir des donnes brutes qui ne peuvent pas tre sectionnes en lignes. Ce sont, en rgle gnrale, des fichiers de type image ou des donnes complexes comme des fichiers de traitement de texte ou de tableur. Sous un systme de type UNIX, la diffrence entre les fichiers textes et binaires concerne les traitements de fin de fichier et de fin de lignes. Alors quun fichier texte est spar en lignes termines par un "\n" et que la fin du fichier est identifie par un "\0", la fin dun fichier de type binaire est donne par le systme dexploitation lui-mme. Cest sa taille en octets qui indique que le fichier a t entirement lu et, donc, que le pointeur de lecture est arriv la fin du fichier. Il est, de ce fait, inutile de spcifier le mode binaire dans vos fonctions douverture de fichier.

489

Chapitre 9

La gestion des fichiers et des rpertoires

UNIX, conforme la norme POSIX, ne fait aucune diffrence entre un fichier binaire et un fichier texte.

9. La gestion des fichiers et des rpertoires

En revanche, lorsque vous manipulez un fichier avec Windows, il est ncessaire de prciser si le fichier ouvrir est de type texte ou binaire. Par dfaut, il sera considr comme tant de type texte.

Fins de lignes
Attention galement aux fins de lignes sous Windows. Toutes les lignes sont spares par le couple de caractres \r\n, qui indique de passer la ligne suivante. Lorsque vous passez un fichier dun systme un autre, nhsitez pas effectuer une conversion du fichier texte laide de la commande UNIX dos2unix ou depuis votre diteur sil en possde loption (cest le cas dUltraEdit par exemple). Ce dtail, qui peut paratre insignifiant, peut se rvler source de problmes dans bien des cas.

9.2.

Accder au systme de chiers du serveur

Lire et crire le contenu dun chier


La mthodologie pour traiter un fichier est la suivante :
j j j

Ouverture du fichier ; Opration sur le fichier (lecture, criture, lecture et criture) ; Fermeture du fichier.

Ouvrir et fermer un chier


Louverture dun fichier se fait laide de linstruction fopen(). Linstruction retourne un descripteur de fichier qui servira par la suite lors des oprations dentre et de sortie. Il est ncessaire de donner la fonction le mode douverture (lecture, criture, lecture et criture, etc.) du fichier. Notez que cette fonction permet aussi douvrir des "fichiers" distants en donnant une URL la place du chemin du fichier. Notez que vous ne pouvez pas utiliser les ouvertures de fichiers distance si vous avez compil PHP avec loption --disable-url-fopen-wrapper pour PHP 4.0.3, ou initialis le paramtre allow_url_fopen off dans le fichier php.ini pour les versions suprieures de PHP.

fopen()
Ouverture dun fichier ou dune URL. Syntaxe resource fopen(string $nomFichier, string $mode [, int $cheminInclude [, resource $contexte]])

490

Accder au systme de fichiers du serveur

$nomFichier $mode

Chemin du fichier, URL (HTTP ou FTP) du fichier ou encore entre/sortie standard.

9. La gestion des fichiers et des rpertoires

Dfinit le mode douverture du fichier : "r" pour la lecture seule (le fichier doit exister). "r+" pour une lecture et une criture (le fichier doit exister). "w" pour une criture avec crasement des donnes. "w+" pour un mode en lecture et criture avec crasement des donnes (si le fichier nexiste pas, il sera cr). "a" pour louverture en ajout de donnes. "a+" pour louverture du fichier en mode lecture et criture par ajout (si le fichier nexiste pas, il sera cr). Sous Windows, vous pouvez accoler lun des arguments suivants : "t" (valeur par dfaut) signalant que le fichier est un fichier texte. "b" qui dsigne un fichier binaire. TRUE si le fichier doit tre recherch dans les rpertoires prciss dans include_path., FALSE sinon. La valeur par dfaut est FALSE. Paramtre optionnel, utilisable depuis les versions 4.3 de PHP, spcifiant la ressource de contexte cre par stream_context_create() utiliser. Voir le sous-chapitre sur les flux pour plus de renseignements sur les contextes de flux. Retourne un pointeur sur le fichier, ou FALSE en cas derreur.

$cheminInclude $contexte

retour

include_path La variable include_path est dfinie dans le php.ini et spcifie PHP une liste de dossiers o les fonctions comme include() ou require() vont chercher les fichiers.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur le fichier php.ini.
Le nom du fichier peut tre indiqu sous diffrentes formes :
j j

Un chemin de fichier ; fopen() tentera alors daccder ce fichier dans le mode demand. Une URL du style http://www.toto.com et, dans ce cas, une connexion HTTP est ouverte sur le serveur. Lidentifiant retourn pointe sur le document. Notez que vous ne pouvez ouvrir ces fichiers quen lecture seule. Vous pouvez galement accder des fichiers sur un serveur demandant une autorisation daccs. Pour cela, vous devez passer, dans lURL, lidentifiant de lutilisateur ainsi que son mot de passe de la faon suivante : http://utilisateur:motdepasse@domaine.com. Une adresse FTP. Une connexion FTP est cre avec le serveur. Vous pouvez ouvrir les fichiers en lecture ou en criture. Les doubles modes lecture et criture (mode full duplex) ne sont pas supports. Pour lauthentification, utilisez la syntaxe identique une

491

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

authentification HTTP : ftp://utilisateur:motdepasse@ftp.domaine.com. Notez que le serveur distant doit supporter le mode passif ; dans le cas contraire la connexion ne pourra seffectuer.
j

Une entre/sortie standard du style php://. Ce peut-tre php://stdin pour lentre standard, php://stdout pour la sortie standard ou php://stderr pour la sortie derreur.

Les actions effectuer sur le fichier sont dfinir ds son ouverture. Cest le mode du fichier qui indique la fonction fopen() pour quelle opration le fichier est ouvert.
<?php $fp = fopen("/home/laurent/data.txt", "a"); // Ouverture du fichier data.txt en ajout de donnes $fp = fopen("http://www.linux.org/", "r"); // Ouverture de lURL distante http://www.linux.org $fp = fopen("http://utilisateur:motdepasse@localhost/", "r"); // Ouverture dune URL demandant une authentification $fp = fopen("ftp://utilisateur:motdepasse@ftp.tuxfamily.org/", "w"); // Ouverture dune connexion FTP avec lutilisateur et le mot de passe dfinie ?>

La partie du nom de fichier du genre http://, ftp://, php:// fait rfrence un gestionnaire de flux (les streams). Il en existe dautres. Nous verrons en particulier celui charg de la gestion des fichiers compresss et nous verrons galement quil est possible de dfinir ses propres gestionnaires.

Pour plus dinformations, reportez-vous plus loin au chapitre Les steams ou les flux

Droits de proprit... Noubliez pas quUNIX gre les droits de lecture et dcriture. Si vous utilisez FTP pour uploader un fichier sous votre compte utilisateur (avec les droits qui lui sont propres), le serveur HTTP naura pas forcment les permissions pour y accder (en lecture ou en criture). Vous devrez alors modifier les droits via votre accs FTP et la commande chmod. Par exemple, pour donner tous les droits :
chmod 777 monfichier

Le chemin des fichiers sous Windows Sous Windows, le caractre habituellement utilis pour sparer les noms des rpertoires est lanti-slash ; assurez-vous bien de doubler ces anti-slashes.
<?php $fp = fopen("c:\\Rep1\\Rep2\\data.txt", "a"); ?>

492

Accder au systme de fichiers du serveur

Fichiers HTTP
Pour les fichiers accds via HTTP, len-tte retourn par le serveur ne fait pas partie des donnes accessibles laide de lidentifiant de fichier. Il est toutefois possible dy accder via la variable globale $http_response_header (attention, cette variable est bien en minuscules et non en majuscules). Celle-ci contient alors un tableau index o chaque entre est une ligne de len-tte. partir de PHP 4.3, vous devez utiliser la fonction file_get_wrapper_data()() pour rcuprer cette information.

9. La gestion des fichiers et des rpertoires

le_get_wrapper_data()
Retourne len-tte HTTP dun fichier ouvert ( partir de PHP 4.3). Syntaxe $fp retour array file_get_wrapper_data(resource $fp) Pointeur du fichier tel que retourn par fopen(). Tableau index o chaque entre est une ligne de len-tte.

Fichiers temporaires
En supposant que vous ayez plusieurs fichiers manipuler la fois, il est probable que vous soyez amen utiliser des fichiers temporaires. Vous pouvez bien entendu crer ces fichiers avec la fonction fopen() et les supprimer une fois que la manipulation a t effectue avec linstruction unlink(), mais le langage PHP possde une fonction adquate pour grer ces fichiers. La commande tmpfile() ouvre un fichier sous un nom unique et retourne un pointeur. Le fichier est automatiquement dtruit lorsque la ressource est libre avec linstruction fclose().

tmple()
Crer un fichier temporaire en mode criture seule et retourne un identifiant unique permettant dcrire dans ce fichier. Syntaxe retour resource tmpfile(void) Retourne un pointeur de fichier.

<?php $fpT = tmpfile(); // Traitements divers fclose($fpT); ?>

493

Chapitre 9

La gestion des fichiers et des rpertoires

Fermeture des chiers


9. La gestion des fichiers et des rpertoires
La fermeture des fichiers ainsi ouverts se fait laide de la fonction fclose(). La fonction a pour objectif de librer les ressources utilises. Attention, si vous oubliez de fermer vos fichiers, vous risquez de perdre des donnes.

fclose()
Ferme un fichier pralablement ouvert. Syntaxe $fp retour boolean fclose(resource $fp) Pointeur du fichier tel que retourn par fopen(), tmpfile() ou fsockopen(). TRUE en cas de russite, FALSE sinon.

Si le pointeur de fichier nest pas valide, la fonction renvoie une erreur.


<?php $fp = fopen("monfichier.txt", "a"); // Traitements divers if (fclose($fp)) { echo "Le fichier monfichier.txt a t correctement ferm !"; } else { echo "Le fichier monfichier.txt na pas t ferm !"; } ?>

fsockopen() est une fonction douverture dune socket de connexion. Rendez-vous dans le chapitre "La gestion des protocoles" pour plus dinformations sur le sujet.

crire dans un chier


Pour crire dans un fichier, vous disposez de la fonction fwrite().

fwrite()
criture dune chane de caractres dans un fichier. Syntaxe $fp $chaine int fwrite(resource $fp, string $chaine [, int $longueur]) Identifiant de fichier tel que retourn par fopen(), popen(), tmpfile() ou fsockopen(). Chane de caractres crire dans le fichier.

494

Accder au systme de fichiers du serveur

$longueur retour

Paramtre optionnel indiquant combien de caractres doivent tre crits. Sil est omis, la chane complte est crite dans le fichier.

9. La gestion des fichiers et des rpertoires

Nombre de caractres qui ont t crits dans le fichier. En cas derreur, linstruction retourne FALSE.

La fonction fwrite() dispose dun alias appel fputs(). Les deux fonctions sont donc utilises de la mme faon.

criture binaire Notez bien que la fonction fwrite() nexcepte quune chane de caractres comme paramtre. Si vous souhaitez crire des donnes binaires, vous devrez convertir au pralable la valeur de chaque octet en son quivalent ASCII. Ainsi, fwrite($fp, 255); stockera la chane de caractres "255" et non un octet ayant la valeur 255 (comme on pourrait sy attendre). Pour ajouter au fichier loctet ayant la valeur 255, il faut utiliser lappel suivant : fwrite($fp, chr(255));.
Les quelques fonctions vues jusque-l nous permettent dcrire un petit programme qui pourrait constituer la base dun systme de discussion. En effet, ce script crit, dans un fichier texte, des messages envoys laide dun formulaire HTML. Le fichier rsultant possde une ligne par message et contient la date du message, le pseudo de lutilisateur, et le message lui-mme, les lments tant spars par une tabulation. Nous pourrons donc, par la suite, afficher la liste des derniers messages qui ont t crits dans le fichier texte.

Listing 9.1 : fwrite.php


<?php // Vrifie que les donnes sont bien postes if ($_POST["message"] && $_POST["pseudo"]) { // Ouverture du fichier en criture (mode ajout) $fp = fopen("message.txt", "a+"); // Rcupration de lheure $heure = date(H:m:s); // Ecriture de lheure et dune tabulation fwrite($fp, $heure."\t"); // Ecriture du pseudo et dune tabulation /* On utilise linstruction htmlEntities afin de convertir les caractres spciaux dans leur version HTML */ fwrite($fp, htmlEntities($_POST["pseudo"])."\t"); // Ecriture du message fwrite($fp, htmlEntities($_POST["message"])."\n"); // On ferme le fichier. fclose($fp);

495

Chapitre 9

La gestion des fichiers et des rpertoires

} ?>

9. La gestion des fichiers et des rpertoires

<html> <title>Ecrire des messages dans un fichier</title> </head> <body> <table border="0" width="100%"> <tr> <form method="post"> <td width="600"> pseudo: <input type="text" name="pseudo" value="<?php htmlEntities($_GET["pseudo"]); ?>" size="20" maxlength="20"> message: <input type="text" name="message" size="40" maxlength="255"> <input type="submit" name="envoyer" VALUE="&gt;&gt;"> </td> </form> <td>&nbsp;</td> </tr> </body> </html>

Le fichier rsultant prsente alors cette forme :


15:07:48<tab>Laurent<tab>Cest bon, je suis enfin en vacances ! 15:07:50<tab>Damien<tab>Non mais tu r&ecirc;ves... tu as un chapitre &agrave; rendre ! 15:07:49<tab>Pem<tab>Hi hi hi... :) 15:07:48<tab>Laurent<tab>Groupf... Je vais devoir y passer la nuit l&agrave; ! 15:07:49<tab>Thomas<tab>Tu devrais faire comme moi. 15:07:00<tab>Thomas<tab>Des jours que je ne dors plus ! 15:07:10<tab>Thomas<tab>Mon secret ? La caf&eacute;ine !

Il est temps de passer la lecture du contenu dun fichier.

Lire des informations dans un chier


La lecture des donnes contenues dans un fichier peut se faire octet par octet, bloc de N octets par bloc de N octets, ligne par ligne ou encore dun bloc. Ceci est assur par les diffrentes fonctions que sont fread(), fgets(), fgetss(), fgetc() et deux instructions particulires que sont file() et readfile().

Lecture octet par octet


Tout comme le langage C, PHP possde la fonction fgetc() qui retourne le caractre se trouvant la position courante du pointeur de fichier. Notez quen langage C ce nest pas le caractre qui est retourn, mais son code ASCII.

496

Accder au systme de fichiers du serveur

fgetc()
Retourne le caractre se trouvant la position courante du pointeur de lecture. Syntaxe $fp retour string fgetc(resource $fp) Identifiant de fichier tel que retourn par fopen(), popen()ou fsockopen(). Le caractre se trouvant la position courante, ou FALSE si cest la fin du fichier.

9. La gestion des fichiers et des rpertoires

Lecture N octets par N octets


fread() a pour objectif de lire des donnes dans un fichier, la lecture se faisant paquet doctets

par paquet doctets (ce qui est habituellement utilis pour les fichiers binaires ou pour ceux formats sur la base de chanes de caractres de longueur constante).

fread()
Lecture des donnes contenues dans un fichier. Syntaxe $fp $nbOctet retour string fread(resource $fp, int $nbOctet) Identifiant de fichier tel que retourn par fopen(), popen()ou fsockopen(). Nombre doctets qui doivent tre lus. Chane contenant les donnes lues, ou FALSE si cest la fin du fichier.

Pour lire le contenu du fichier prcdemment gnr, nous pourrions donc envisager dcrire le script suivant :

Listing 9.2 : fread.php


<?php // Reprenons notre fichier message.txt. $fp = fopen("message.txt","r"); // Lecture du fichier jusqu la fin de celui-ci. while ($lecture = fread($fp, 70)) { // Affichage des 70 caractres lus puis // retour la ligne. echo $lecture."<br />"; } fclose($fp); ?>

497

Chapitre 9

La gestion des fichiers et des rpertoires

Ce qui donnerait :

9. La gestion des fichiers et des rpertoires

22:06:38 Laurent Cest bon, je suis enfin en vacances ! 22:07:10 Damie n Non mais tu rves... tu as un chapitre rendre ! 22:07 :26 Pem Hi hi hi... :) 22:08:01 Laurent Groupf... Je vais devoir y pas ser la nuit l ! 22:08:30 Thomas Tu devrais faire comme moi. 22 :08:30 Thomas Des jours que je ne dors plus ! 22:08:39 Thomas Mon secr et ? La cafine !

Certes, tout le contenu y est (en HTML, les tabulations apparaissent comme une simple espace). Mais pour la mise en forme... ce nest pas a ! En fait, plutt que de lire le fichier 70 caractres par 70 caractres, il aurait t prfrable de le lire ligne par ligne. Mais fread() ne tient pas compte des retours la ligne. Nous vous rassurons tout de suite, nous allons trouver une solution !

Lire en une fois Il est possible de lire un fichier texte en une seule fois simplement en passant en argument de taille la taille du fichier texte. Vous devrez alors utiliser linstruction fileSize() qui nous retourne la taille du fichier en octets (cette fonction est dcrite plus loin dans ce chapitre).
<?php // Ouverture du fichier message.txt. $fp = fopen("message.txt","r"); // Rcupration de la taille du fichier en octets. $taille = fileSize("message.txt"); // Lecture de la totalit du fichier. $lecture = fread($fp, $taille); // Affichage du fichier. echo $lecture; fclose($fp); ?>

Lecture ligne par ligne


Comme vous lattendiez, vous pouvez galement lire le fichier ligne par ligne. La fonction fgets() permet de retourner la ligne courante (o se trouve le pointeur). La lecture de la ligne se termine lorsque le caractre retour chariot \n est trouv, lorsque le nombre de caractres maximum est lu, ou lorsque la fin du fichier a t dtecte.

fgets()
Lecture de la ligne courante du fichier. Syntaxe string fgets(resource $fp, int $nbOctet)

498

Accder au systme de fichiers du serveur

$fp $nbOctet retour

Identifiant de fichier tel que retourn par fopen(), popen()ou fsockopen().

9. La gestion des fichiers et des rpertoires

Nombre doctets qui doivent tre lus. Chane contenant les donnes lues de la ligne courante, ou FALSE si le pointeur est en fin de fichier.

La lecture du fichier peut alors se faire comme suit :

Listing 9.3 : fgets.php


<?php // Ouverture du fichier $fp = fopen("message.txt","r"); // Lecture de chaques ligne // jusqu la fin du fichier while ($lecture = fgets($fp,255)) { // Affichage de la ligne echo $lecture; echo "<br />"; } // Fermeture du fichier fclose($fp); ?>

Dans ce cas, le rsultat obtenu est bien celui escompt. Lire un fichier ligne par ligne permet ventuellement de manipuler ces lignes avant de les afficher.

Des chiers formats


Un fichier est, le plus souvent, cens contenir une srie de donnes selon un format particulier choisi par le dveloppeur. Cela peut tre une srie de valeurs spares par des tabulations comme pour notre exemple du systme de discussion. Si le format du fichier a t bien pens, alors son analyse, et donc la rcupration des donnes quil contient, se trouve grandement simplifie par lutilisation de linstruction fscanf(). Cette fonction lit les caractres en provenance dun fichier que vous aurez pralablement ouvert, et les traitent en fonction dun schma que vous aurez spcifi.

fscanf()
Rcupre les donnes dune ligne dun fichier en fonction dun format spcifi. Syntaxe mixed fscanf(resource $fp, string $format [, string &$variable1 [, ...]])

499

Chapitre 9

La gestion des fichiers et des rpertoires

$fp

Identifiant sur un fichier ouvert laide de linstruction fopen(). Format de la chane de caractres et des donnes rcuprer. Variables dans lesquelles les valeurs seront copies. Selon les cas : Le nombre de donnes qui ont t lues si des variables ont t passes en paramtre. Un tableau index contenant les diffrentes valeurs si les paramtres ont t omis. Lorsque le pointeur de lecture arrive la fin du fichier, la fonction retourne FALSE.

9. La gestion des fichiers et des rpertoires

$format $variable1, ... retour

Le format de la chane est identique au format quutilise la fonction sscanf(). Rendez-vous au chapitre "La manipulation des chanes de caractres" pour plus de dtails sur les formats.
Ainsi, il est ais de rcuprer nos donnes depuis le fichier messages.txt et dafficher les diffrents messages, ainsi que la date et le pseudo de lutilisateur ayant post ce message. Ensuite, il ne reste plus qu afficher cela dans une page HTML.

Listing 9.4 : fscanf.php


<?php // fichier "fwrite.php" // Ecrire des messages dans un fichier texte // Vrifie que les donnes sont bien postes if($_POST["message"] && $_POST["pseudo"]) { // Ouverture du fichier en criture $fp = fopen("message.txt", "a+"); // Rcupration de lheure $heure = date(H:m:s); // Ecriture de lheure fwrite($fp, $heure."\t"); // Ecriture du pseudo /* On utilise linstruction htmlEntities afin de convertir les caractres spciaux dans leur entit HTML */ fwrite($fp, htmlEntities($_POST["pseudo"])."\t"); // Ecriture du message fwrite($fp, htmlEntities($_POST["message"])."\n"); // On ferme le fichier. fclose($fp); } ?>

500

Accder au systme de fichiers du serveur

<html> <title>Ecrire des messages dans un fichier</title> </head> <body> <table border="0" width="100%"> <?php // Affiche les messages $fp = fopen("message.txt","r"); while($donnee = fscanf($fp, "%s\t". "%s\t". "%[^\t]\n", $heure, $pseudo, $message)) { echo "<tr>"; echo " <td><font color=#0000ff>"; echo $heure; echo " </font></td>"; echo " <td><b>"; echo $pseudo; echo " </b></td>"; echo " <td>"; echo $message; echo " </td>"; echo "</tr>"; } fclose($fp); ?> </table> <hr /> <table border="0" width="100%"> <tr> <form method="post"> <td width="600"> pseudo: <input type="text" name="pseudo" value="<?php htmlEntities($_POST["pseudo"]);?>" size="20" maxlength="20"> message: <input type="text" name="message" size="40" maxlength="255"> <input type="submit" name="envoyer" VALUE="&gt;&gt;"> </td> </form> <td>&nbsp;</td> </tr> </body> </html>

9. La gestion des fichiers et des rpertoires 501

Les espaces qui ne passent pas... Dans le cas o vous devez rcuprer une donne comportant une espace, il est indispensable de ne pas utiliser le formatage des donnes avec "%s". Vous devez en

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

revanche utiliser les expressions rgulires afin de prciser quels caractres peut contenir la chane ou, plus simplement, prciser quels caractres ne peut contenir la chane (ici, la tabulation qui a t choisie comme dlimiteur).

Pour plus dinformations sur les expressions rgulires, reportez-vous au chapitre "La manipulation des chanes de caractres"

Lecture dun bloc


Le langage PHP possde une fonction permettant deffectuer cette opration sans avoir grer louverture et la fermeture des fichiers. Linstruction file() retourne en effet le contenu dun fichier dans un tableau, chaque entre tant une ligne du fichier.

le()
Retourne le contenu dun fichier dans un tableau. Syntaxe $nomFichier $cheminInclude $contexte array file(string $nomFichier [, int $cheminInclude [, resource $contexte]]) Nom du fichier lire. Cette fonction peut aussi lire les fichiers distants. TRUE si le fichier doit tre recherch dans les rpertoires prciss dans include_path., FALSE sinon. La valeur par dfaut est FALSE. Paramtre optionnel, utilisable depuis les versions 4.3 de PHP, spcifiant la ressource de contexte cre par stream_context_create() utiliser. Voir le sous-chapitre sur les flux pour plus de renseignements sur les contextes de flux. Tableau index contenant chaque ligne du fichier, ou FALSE si une erreur est survenue.

retour

Listing 9.5 : file.php


<?php $buffer = file("message.txt"); for ($i=0;$i<count($buffer);$i++) { echo "<font color=#cc0000>message ".($i+1)."</font>:"; echo $buffer[$i]; echo "<br />"; } ?>

Si vous souhaitez simplement afficher le contenu du fichier sur la sortie, il existe une fonction plus pratique ; readfile() permet en effet ce type dopration.

502

Accder au systme de fichiers du serveur

readle()
Retourne, sur la sortie standard, le contenu du fichier pass en paramtre. Syntaxe $nomFichier $cheminInclude $contexte int readfile(string $nomFichier [, int $cheminInclude [, resource $contexte]]). Nom du fichier lire. Cette fonction peut aussi lire les fichiers distants. TRUE si le fichier doit tre recherch dans les rpertoires prciss dans include_path., FALSE sinon. La valeur par dfaut est FALSE. Paramtre optionnel, utilisable depuis les versions 4.3 de PHP, spcifiant la ressource de contexte cre par stream_context_create() utiliser. Voir le sous-chapitre sur les flux pour plus de renseignements sur les contextes de flux. Retourne le nombre doctets qui ont t lus, ou FALSE en cas derreur.

9. La gestion des fichiers et des rpertoires

retour

Listing 9.6 : readfile_01.php


<?php $taille = readfile("http://www.mozilla.org"); echo "<hr />"; echo "Taille de la page = ".$taille." octets"; ?>

Cette fonction est galement pratique (associe un en-tte appropri) pour forcer le tlchargement de fichiers, y compris sil sagit de fichiers habituellement interprts par le navigateurs (.txt, .html, etc.).

Listing 9.7 : readfile_02.php


<?php header("Content-type: application/octet-stream"); header("Content-disposition: attachment; filename=\"message.txt\"); readfile("message.txt"); ?>

Le premier en-tte permet de "forcer" le type du document en un type thoriquement non interprt par le navigateur du client (sauf si ce dernier la configur de manire inadquate), ce qui aura pour effet de proposer la sauvegarde du fichier sur le disque. Le second en-tte permet de suggrer un nom de sauvegarde pour le fichier. Et, enfin, lappel readfile() envoie les donnes au client. De la mme faon, il est possible de rediriger un fichier sur la sortie standard partir de la position courante du pointeur de lecture. fpassthru(), tout comme readfile(), est utilis pour envoyer au client le contenu dun fichier. Attention, fpassthru() ferme automatiquement le fichier (vous ne pouvez plus utiliser lidentifiant de fichier).

503

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

fpassthru()
Retourne sur la sortie standard le contenu dun fichier partir de la position courante du pointeur de lecture. Syntaxe $fp retour int fpassthru(resource $fp) Identifiant de fichier tel que retourn par fopen(), popen() et fsockopen(). Nombre doctets renvoys sur la sortie standard.

Listing 9.8 : fpassthru.php


<?php // Ouverture du fichier en mode lecture $fp = fopen("message.txt","r"); // Dplacement de la position courante de 20 octets. fseek($fp, 20, SEEK_SET); echo "<b>Affiche le fichier partir du 20me caractre.</b>"; echo "<br />"; fpassthru($fp); echo "<hr />"; // reouverture ncessaire du fichier en mode lecture $fp = fopen("message.txt","r"); // Dplacement de la position courante de 100 octets. fseek($fp, 100, SEEK_SET); echo "<b>Affiche le fichier partir du 100me caractre.</b>"; echo "<br />"; fpassthru($fp); ?>

Depuis PHP4.3, linstruction file_get_contents() a fait son apparition. Pratique cette fonction permet de rcuprer le contenu dun fichier directement dans une variable chane.

le_get_contents()
Retourne le contenu dun fichier dans une chane de caractres. Cette fonction est plus rapide utiliser quune lecture en utilisant fread() ou fgets(). Syntaxe : $nomFichier $cheminInclude string file_get_contents(string $nomFichier [, bool $cheminInclude [, ressource $contexte]]) Nom du fichier lire. Cette fonction peut aussi lire les fichiers distants. TRUE si le fichier doit tre recherch dans les rpertoires prciss dans include_path., FALSE sinon. La valeur par dfaut est FALSE.

504

Accder au systme de fichiers du serveur

$contexte

Paramtre optionnel spcifiant la ressource de contexte cre par stream_context_create() utiliser. Voir le sous-chapitre sur les flux pour plus de renseignement sur les contextes de flux. Retourne dans une chane de caractres le contenu du fichier spcifi en argument. Si la lecture a rencontr un problme, la fonction retourne FALSE.

9. La gestion des fichiers et des rpertoires

retour

Voici une alternative lexemple vu avec readfile():


<?php $contenu = file_get_contents("http://www.mozilla.org"); echo $contenu ; ?>

Lecture et ltrage HTML


Le langage PHP possde une instruction permettant de lire une page HTML et de la retourner sans les diffrentes balises. Il sagit de fgetss(), qui est similaire la fonction fgets() si ce nest que les donnes retournes ne possdent plus aucune balise HTML, hormis celles que le dveloppeur aura demand de conserver.

fgetss()
Lecture de la ligne courante du fichier sans les balises HTML le composant. Syntaxe $fp $nbOctet $tagsAutorise retour string fgetss(resource $fp, $nbOctet [, string $tagsAutorise]) Identifiant sur un fichier ouvert laide de linstruction fopen(), fsockopen() ou popen(). Nombre doctets qui doivent tre lus. Les balises qui ne doivent pas tre supprimes ; vous pouvez en spcifier plusieurs en les sparant par le caractre "|". Ex. : "<br>|<b>|<center>". Chane contenant les donnes lues de la ligne courante sans les balises HTML. Retourne FALSE si le pointeur se trouve la fin du fichier.

Listing 9.9 : fgetss.php


<?php $fp = fopen("http://www.gnu.org/home.fr.html","r"); while ($ligne=fgetss($fp, 255, "<br>|<center>")) { echo $ligne; } fclose($fp); ?>

505

Chapitre 9

La gestion des fichiers et des rpertoires

Les balises sur plusieurs lignes Le fait que linstruction fgetss() ne retourne quune ligne la fois fait quil est impossible de supprimer les balises de deux lignes et plus. Avant toute chose, il est donc important de vrifier que le code HTML de votre fichier ne possde pas de balises sur plusieurs lignes. Si vous ntes pas lauteur de la page que vous voulez traiter, commencez par mettre tout le code HTML sur une ligne unique, comme le fait le code ci-dessous.
<?php $buffer = file("http://www.gnu.org/home.fr.html"); $fichier = join("",$buffer); echo strip_tags($fichier,"<br>|<center>"); ?>

9. La gestion des fichiers et des rpertoires

La page retourne est ici compltement vide de balises HTML, lexception des balises <br> et <center> que nous avions choisi de conserver.

Figure 9.1 : Le site original

506

Accder au systme de fichiers du serveur

9. La gestion des fichiers et des rpertoires

Figure 9.2 : Le site aprs suppression des balises HTML

Lecture des chiers CSV


Un fichier CSV (pour Comma Separated Value, valeurs spares par des virgules) est un format utilis par un grand nombre de tableurs et de bases de donnes pour limportation et lexportation des donnes. Ce format est constitu de lignes comportant diffrentes valeurs spares par un dlimiteur ( lorigine une virgule, mais gnralement un point-virgule pour les versions franaises). Chacune des lignes du fichier reprsente alors une ligne dun tableau, et chacune des valeurs, une donne dun champ de ce tableau. Voici un exemple de fichier CSV :
Laurent;GUEDON;http://www.tild.com;Socit de dveloppement Pierre-Emmanuel;MULLER;http://pem.levillage.org;Journalisme Thomas;HEUTE;http://www.toutestfacile.com;Le site pour apprendre Damien;HEUTE;http://www.ootoogo.com;Le portail du Tourisme et des Loisirs

Limportation dans un tableau de type Excel ou Gnumeric donne un tableau de la forme ci-dessous (voir fig. 9.3) : Linstruction fgetcsv() permet de lire aisment ce type de fichier. Nous allons nous en servir pour rcuprer notre fichier de messages (il suffira dindiquer que le dlimiteur nest pas une virgule mais une tabulation).

507

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

Figure 9.3 : Un tableau Excel aprs importation des donnes du fichier CSV

fgetcsv()
Lit une ligne dun fichier et retourne un tableau contenant les diffrents champs CSV. Syntaxe $fp $nbOctet $delimiteur retour array fgetcsv(resource $fp, int $nbOctet [, string $delimiteur]) Identifiant sur un fichier ouvert laide de linstruction fopen(), fsockopen() ou popen(). Nombre doctets qui doivent tre lus au maximum. Caractre dlimitant chacune des donnes (par dfaut, le dlimiteur est la virgule). Retourne un tableau contenant les diffrentes donnes dune ligne du fichier CSV. Lorsque la fin du fichier est atteinte, la fonction retourne FALSE.

Et voil ! Cette fonction est particulirement bien adapte notre systme de discussion.

Listing 9.10 : chat.php


<?php // Vrifie que les donnes sont bien postes if($_POST["message"] && $_POST["pseudo"]) { // Ouverture du fichier en criture (mode ajout) $fp = fopen("message.txt", "a+"); // Rcupration de lheure $heure = date(H:m:s); // Ecriture de lheure et dune tabulation fwrite($fp, $heure."\t"); // Ecriture du pseudo et dune tabulation /* On utilise linstruction htmlEntities afin de convertir les caractres spciaux dans leur entit HTML */ fwrite($fp, htmlEntities($_POST["pseudo"])."\t"); // Ecriture du message fwrite($fp, htmlEntities($_POST["message"])."\n"); // On ferme le fichier.

508

Accder au systme de fichiers du serveur

fclose($fp); } ?> <html> <title>Ecrire des messages dans un fichier</title> </head> <body> <table border="0" width="100%"> <?php // Affiche les messages $fp = fopen("message.txt","r"); while($donnee = fgetcsv($fp, 255, "\t")) { echo "<tr>"; echo " <td><font color=#0000ff>"; echo $donnee[0]; echo " </font></td>"; echo " <td><b>"; echo $donnee[1]; echo " </b></td>"; echo " <td>"; echo $donnee[2]; echo " </td>"; echo "</tr>"; } fclose($fp); ?> </table> <hr /> <table border="0" width="100%"> <tr> <form method="post"> <td width="600"> pseudo: <input type="text" name="pseudo" value="<?php htmlEntities($_POST["pseudo"]);?>" size="20" maxlength="20"> message: <input type="text" name="message" size="40" maxlength="255"> <input type="submit" name="envoyer" VALUE="&gt;&gt;"> </td> </form> <td>&nbsp;</td> </tr> </body> </html>

509

9. La gestion des fichiers et des rpertoires

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

Figure 9.4 : Voici le systme de discussion quil ne vous reste plus qu perfectionner

Lecture des chiers .ini


Linstallation dun logiciel ou dune application ncessite la cration dun certain nombre de paramtres dpendant de lutilisateur ou de lenvironnement. Il est courant de stocker ces informations dans un fichier du type monFichier.ini. Le fichier de configuration php.ini est un bon exemple de ce genre de configuration. Celui-ci contient alors, sous un format bien spcifique, diffrentes donnes, regroupes par section, qui peuvent tre exploites par la suite. Le fichier se prsente de la faon suivante :
; Quelques lignes de commentaires. ; Le parseur ne les prendra pas en compte. [section1] utilisateur = 3 administrateur = 1 ;rien = rien [section2] titre = Mon application url = http://www.tild.com [section3] fichier = parse_ini_file.php chemin = /home/e-smith/files/ibays/kangouroo/html/bible/fichier droit = 755

Le langage PHP possde une fonction permettant de traiter les fichiers de ce type et den extraire les lments qui le composent. Linstruction parse_ini_file() retourne les diffrentes donnes dans un tableau associatif. Vous pouvez rcuprer un tableau sur deux niveaux comportant, dans le premier niveau, les diffrentes sections et, dans le second, les attributs et leurs valeurs.

510

Accder au systme de fichiers du serveur

parse_ini_le()
Retourne les diffrents lments composant un fichier du type .ini et forme un tableau associatif. Syntaxe $nomFichier $traiteSection retour array parse_ini_file(string $nomFichier [, boolean $traiteSection]) Nom du fichier lire. Cette fonction peut aussi lire les fichiers distants en donnant une URL en paramtre. TRUE si vous souhaitez que les donnes de chaque section soient regroupes dans des tableaux, FALSE (par dfaut) sinon. Selon les cas : Un tableau associatif ayant pour cls les noms des sections et pour valeur un tableau associatif ayant lui-mme pour cl le nom du paramtre et pour valeur la valeur associe si $traiteSection=TRUE. Un tableau associatif ayant pour cls les noms des paramtres (toutes sections confondues) et pour valeur la valeur associe si $traiteSection=FALSE.

9. La gestion des fichiers et des rpertoires

Listing 9.11 : parse_ini_file.php


<html> <head> <title>Lecture dun fichier CSV</title> </head> <body> <table border="1" cellpadding="1" cellspacing="0"> <tr> <td colspan="2"> <?php echo "Affichage des donnes sans les diffrentes sections."; echo " </td>"; echo "</tr>"; $tableauIni = parse_ini_file("emma.ini"); while (list($key, $val) = each($tableauIni)) { echo "<tr>"; echo " <td>"; echo "$key"; echo " </td>"; echo " <td>"; echo "$val"; echo " </td>"; echo "</tr>"; } ?> </table> <br /> <table border="1" cellpadding="1" cellspacing="0"> <tr>

511

Chapitre 9

La gestion des fichiers et des rpertoires

<td colspan="2"> <? echo "Affichage des donnes avec les diffrentes sections."; echo "<br />"; echo " </td>"; echo "</tr>"; $tableauIni = parse_ini_file("emma.ini", TRUE); while (list($section, $tableauPar) = each($tableauIni)) { echo "<tr>"; echo " <td colspan=2>"; echo " <b>".$section."</b>"; echo " </td>"; echo "</tr>"; while (list($key, $val) = each($tableauPar)) { echo "<tr>"; echo " <td>"; echo " $key"; echo " </td>"; echo " <td>"; echo " $val"; echo " </td>"; echo "</tr>"; } } ?> </table> </body> </html> Figure 9.5 : Le rsultat de traitement du fichier emma.ini

9. La gestion des fichiers et des rpertoires 512

Accder au systme de fichiers du serveur

Positionner le pointeur de lecture/criture


Lorsque lon dsire lire les donnes contenues dans un fichier, elles sont dans un premier temps copies dans un espace mmoire (buffer). On dit que le mode de lecture est "bufferis". Une fois le fichier ouvert, un pointeur de lecture se place automatiquement au dbut de ce fichier, chacun des appels une instruction de lecture faisant avancer ce pointeur. Lavance de ce pointeur peut tre contrle par trois fonctions qui sont feof(), fseek() ou rewind(). La premire instruction permet de dterminer si la fin du fichier ouvert est atteinte. La seconde instruction repositionne le pointeur de lecture (ou dcriture) une position spcifique. Quant la dernire fonction, elle renvoie le pointeur au dbut du fichier.

9. La gestion des fichiers et des rpertoires

feof()
Dtermine si la fin du fichier est atteinte. Syntaxe $fp retour boolean feof(resource $fp) Identifiant sur un fichier ouvert laide dune instruction fopen(), tmpfile(), fsockopen() ou popen(). Retourne TRUE si le pointeur est la fin du fichier, FALSE dans le cas contraire.

<?php $fp = fopen("data.txt", "r"); // Traitements divers if (feof($fp)) { echo "Fin du fichier.<br />"; } fclose($fp); ?>

Vous pouvez connatre la position courante du pointeur laide la fonction ftell().

ftell()
Retourne la position courante du fichier. Syntaxe $fp retour int ftell(resource $fp) Identifiant sur un fichier ouvert laide dune instruction fopen(), tmpfile(), fsockopen() ou popen(). Retourne la position courante du pointeur de lecture/criture.

<?php $fp = fopen("data.txt", "r");

513

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

echo "Position courante : ".ftell($fp); fclose($fp); ?>

fseek()
Dplace le pointeur de lecture/criture dun fichier une position spcifique. Syntaxe $fp $offset $origine int fseek(resource $fp, int $offset [, $origine]) Identifiant sur un fichier ouvert laide dune instruction fopen(), tmpfile(), fsockopen() ou popen(). Nombre indiquant le dplacement en octets (positif ou ngatif) par rapport lorigine slectionne. Indique partir de quel endroit doit tre compt le dplacement. Au choix : SEEK_SET ( = 0) partir du dbut du fichier. SEEK_CUR ( = 1) partir de la position courante du pointeur (valeur par dfaut). SEEK_END ( = 2) partir de la fin du fichier. retour 0 en cas de succs, et 1 en cas derreur..

Il est noter quun dplacement positif partir de la fin du fichier nentrane pas derreur. En effet, dplacer un pointeur au-del de EOF est possible.

Listing 9.12 : fseek.php


<?php echo "taille : ".filesize("message.txt"); // Affiche la taille du fichier en octets echo "<br />"; $fp = fopen("message.txt","r"); fseek($fp, 20, SEEK_SET); echo "Position par rapport au dbut du fichier (0+20) : "; echo ftell($fp)."<br />"; fseek($fp, 20, SEEK_CUR); echo "Position par rapport la position courante (20+20) : "; echo ftell($fp)."<br />"; fseek($fp, 20, SEEK_END); echo "Position par rapport la fin du fichier (Fin+20 ): "; echo ftell($fp)."<br />"; fclose($fp); ?>

514

Accder au systme de fichiers du serveur

pourrait retourner un rsultat du genre :


taille : Position Position Position 190 par rapport au dbut du fichier (0+20) : 20 par rapport la position courante (20+20) : 40 par rapport la fin du fichier (Fin+20 ): 210

9. La gestion des fichiers et des rpertoires

Le pointeur de lecture/criture Si vous ouvrez le fichier laide de linstruction fopen() avec le mode "a" ou "a+" (ouverture pour ajout de donnes), le pointeur est systmatiquement plac la fin du fichier.

rewind()
Repositionne le pointeur de lecture/criture au dbut du fichier. Syntaxe $fp retour boolean rewind(resource $fp) Identifiant sur un fichier ouvert laide dune instruction fopen(), tmpfile(), fsockopen() ou popen(). TRUE si lopration sest droule sans problme, et FALSE si le pointeur na pas pu tre repositionn.

<?php $fp = fopen("message.txt", "r"); // Traitements divers if (rewind($fp)) { echo "Le pointeur du fichier a t repositionn au dbut"; echo "<br />"; } fclose($fp); ?>

Tronquer un chier
Une fonction particulire permet de tronquer les fichiers qui ont t ouverts en mode criture. Le langage PHP permet de rcuprer une partie des informations contenues dans un fichier et de les rcrire en supprimant le reste des donnes. Linstruction ftruncate() ne fonctionne que dans le cas o le fichier a t ouvert en criture, cest--dire les modes criture seule (w, a), lecture et criture (w+, a+).

515

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

ftruncate()
Tronque un fichier (i.e. ne conserve que les premiers octets du fichier). Syntaxe $fp $taille retour int ftruncate(resource $fp, int $taille) Identifiant sur un fichier ouvert laide dune instruction fopen(), tmpfile(), fsockopen() ou popen(). Nouvelle taille du fichier. 1 (mais pas strictement TRUE) si le fichier a bien t tronqu, 0 (mais pas strictement FALSE) sinon.

Imaginons le contenu dun fichier dedicace.txt.


Je ddicace ce livre tous mes amis Et plus particulirement Myriam si adorable. A Amiel pour son soutien et ses comptences. A Damien pour savoir botter le cul quand il le faut. A Thomas pour son calme faire passer un bouddha pour un rocker sous ecsta.

Ce fichier est bien trop long et nous ne voulons conserver que les deux premires lignes. La principale difficult consiste donc dterminer la nouvelle taille que nous souhaitons donner ce fichier. Pour cela, il suffit de lire les deux premires lignes, et de dterminer quelle est la position atteinte par le pointeur de fichier (grce ftell()). Cette position correspondra la taille voulue.

Listing 9.13 : ftruncate.php


<?php // Ouvre un fichier texte en mode lecture et criture if ($fp = fopen("dedicace.txt", "r+")) { // Lecture des deux premires lignes fgets($fp, 255); fgets($fp, 255); // On tronque une taille gale // la position courante du pointeur de // lecture ftruncate($fp, ftell($fp)); // Fermeture du fichier fclose($fp); // Affichage du fichier une fois tronqu readfile("dedicace.txt"); } else { echo "Impossible douvrir le fichier ddicace."; } ?>

516

Accder au systme de fichiers du serveur

Ce qui donnera le rsultat suivant :


Je ddicace ce livre tous mes amis Et plus particulirement Myriam si adorable.

9. La gestion des fichiers et des rpertoires

Gestion de lespace tampon


Lcriture dans un fichier est effectue en deux temps. Les donnes sont dabord copies vers un buffer (espace mmoire) et sont ensuite crites sur le fichier ouvert. Ce systme de bufferisation permet de gagner du temps, car les appels systme se font plus rares. Imaginons que lon dsire crire dans un fichier 20 lignes de 200 caractres. Il faudra alors normalement 20 appels systme pour crire la totalit des donnes dans le fichier. Lutilisation du buffer permet dcrire une seule fois les 4 000 (20*200) caractres, cest--dire que le programme ne fait appel quune fois au systme dexploitation, et ne sollicite quune fois le disque dur pour crire dans le fichier. Le langage PHP possde, par dfaut, un buffer de 8 Ko, mais il est possible de lui fixer une autre taille avec linstruction set_file_buffer(). Il peut tre particulirement intressant daugmenter cette valeur si votre script doit traiter des fichiers de trs grande taille. Depuis PHP 4.3, linstruction stream_set_write_buffer() remplace cette fonction. set_file_buffer() demeure un alias pour des raisons de retro-compatibilits.

stream_set_write_buffer()
Fixe la taille du buffer. Syntaxe $fp $taille retour int stream_set_write_buffer(ressource $fp, int $taille) Identifiant sur un fichier ouvert laide dune instruction fopen(), tmpfile(), fsockopen() ou popen(). Nouvelle taille du buffer. 0 si linstruction se droule convenablement, EOF dans le cas contraire.

Du fait de la prsence de ce systme de cache, les donnes crites dans un fichier ne sont pas toujours disponibles immdiatement (pour les scripts cherchant en lire le contenu). Les donnes ne seront effectivement accessibles quune fois le buffer vid (ce qui intervient automatiquement ds quil est plein ou manuellement lorsque vous appelez la fonction fflush()). Notez galement que le buffer est automatiquement vid lors de lappel fclose(). A contrario, si vous quittez lexcution de votre programme sans faire appel fclose(), vous courez le risque de perdre les donnes restant dans le cache.

fflush()
crit et vide le buffer dun fichier. Syntaxe boolean fflush (resource $fp)

517

Chapitre 9

La gestion des fichiers et des rpertoires

$fp

Identifiant sur un fichier ouvert laide dune instruction fopen(), tmpfile(), fsockopen() ou popen(). Retourne TRUE si le buffer a t vid dans le fichier, ou FALSE dans le cas contraire.

9. La gestion des fichiers et des rpertoires

retour

Listing 9.14 : fflush.php


<?php $fp = fopen("twiki.txt", "w"); if ($fp) { // Les donnes seront crites tous les 500 octets set_file_buffer($fp, 500); // Cette phrase fait moins de 500 octets // elle nest donc pas immdiatement crite fputs($fp, "Bidibidibidi comme dirait Twiki."); // Mais qu cela ne tienne. Nous allons forcer lcriture fflush($fp); // Cette phrase attendra fclose() pour tre crite fputs($fp, "Glop Glop comme dirait Pifou."); fclose($fp); } ?>

Lister le contenu dun dossier


Nous avons vu que, pour visualiser le contenu dun fichier, il suffit de louvrir et dobtenir ainsi un pointeur vers ce fichier. Louverture dun rpertoire est similaire celle dun fichier. Vous crez, laide de la fonction openDir(), un identifiant, qui vous permet par la suite de lire ce dossier la faon dun fichier.

openDir()
Ouvre le rpertoire dsign et retourne un pointeur dessus. Syntaxe $chemin retour resource openDir(string $chemin) Chemin du dossier ouvrir. Pointeur sur le dossier ouvert.

Ne pas oublier de fermer le dossier laide de linstruction closeDir().

518

Accder au systme de fichiers du serveur

closeDir()
Fermer un dossier pralablement ouvert avec la fonction openDir(). Syntaxe $repertoire void closeDir(resource $repertoire) Pointeur sur un dossier ouvert avec linstruction openDir().

9. La gestion des fichiers et des rpertoires

<?php // Ouverture du dossier parent "/monrepertoire" $repertoire = openDir("/monrepertoire"); // Placer les diffrents traitements effectuer // ... // Fermeture du dossier closeDir($repertoire); ?>

Une fois un pointeur obtenu sur le rpertoire, il suffit, pour lister le contenu dun dossier, de faire appel la fonction readDir(). Le pointeur de lecture se place au dbut du rpertoire et chacun des appels la fonction readDir() le fait avancer sur lentre suivante, savoir le nom du fichier ou rpertoire suivant. De proche en proche, il est ainsi possible de lire la totalit du contenu dun dossier.

readDir()
Lecture des entres dans un dossier. Syntaxe $repertoire retour string readDir(resource $repertoire) Pointeur sur un dossier ouvert avec linstruction openDir(). Retourne le nom du fichier dsign par le pointeur de lecture.

Ainsi, pour afficher le contenu dun rpertoire, nous pouvons utiliser la fonction suivante :

Listing 9.15 : readdir.php


<?php // La fonction dexploration function explorer($chemin) { $repertoire = openDir($chemin); while ($fichier = readDir($repertoire)) { // Inutile dafficher les entres . et .. if (($fichier != ".")&&($fichier != "..")) { // noublions pas dajouter // le chemin au nom du fichier echo $chemin."/".$fichier<br />"; } }

519

Chapitre 9

La gestion des fichiers et des rpertoires

// Cest fini. On ferme ! closeDir($repertoire);

9. La gestion des fichiers et des rpertoires

} // Dfinition du chemin explorer $cheminRep = "."; // Lappel la fonction explorer($cheminRep); ?>

qui pourrait donner :


./fichier0.php ./fichier1.php ./fichier2.php ./repertoire

Nous pouvons, de plus, imaginer que tous les sous-rpertoires soient lists, permettant ainsi davoir la liste complte des fichiers contenus dans le dossier courant. Pour cela, nous allons utiliser les proprits de rcursivit du langage PHP. Nous devrons en outre tre capables de distinguer les rpertoires des fichiers. Pour cela, nous devrons faire appel la fonction is_dir() qui indique sil sagit dun rpertoire. Et, enfin, afin de distinguer le parcours du rpertoire du traitement du contenu, nous retournerons un tableau contenant les noms des fichiers.

Listing 9.16 : readdir_recursif.php


<?php // La fonction dexploration function explorer($chemin, $recursif=FALSE) { $listeFichier = array(); $repertoire = openDir($chemin); while ($fichier = readDir($repertoire)) { // Inutile de tenir compte des entres . et .. if (($fichier != ".")&&($fichier != "..")) { // Est-ce que $file est un rpertoire ? // Pour le savoir il suffit dappeler is_dir // mais attention noublions pas dajouter // le chemin au nom du fichier if (is_dir($chemin."/".$fichier)&&($recursif)) { // oui ? alors explorons-le // et ajoutons le rsultat la liste de fichiers $listeFichier = array_merge($listeFichier, explorer($chemin."/".$fichier, $recursif)); } else { // sinon, cest un fichier et on lajoute // la liste des fichiers $listeFichier[] = $chemin."/".$fichier; }

520

Accder au systme de fichiers du serveur

} } // Cest fini. On ferme ! closeDir($repertoire); // et on retourne le rsultat return $listeFichier; } // Dfinition du chemin explorer $cheminRep = "../."; // Lappel la fonction $fichiers = explorer($cheminRep, TRUE); // Affichage ( titre dmonstratif) for ($i=0; $i<count($fichiers); $i++) echo $fichiers[$i]."<br />"; ?>

9. La gestion des fichiers et des rpertoires

Ce script aisment rutilisable retournera donc quelque chose comme :


./fichier0.php ./fichier1.php ./fichier2.php ./repertoire/fichier0.php ./repertoire/fichier1.php ./repertoire/fichier2.php ./repertoire/fichier3.php ./repertoire/fichier4.php

Dans certains cas, comme la galerie dimages (un grand classique), il faut filtrer les noms des fichiers (gnralement daprs leur extension). Nous allons donc perfectionner encore notre fonction pour prciser une expression rgulire laquelle doit rpondre le nom du fichier. Une fois la liste des fichiers rcupre, il suffira dafficher les images.

Listing 9.17 : readdir_filtre.php


<?php // La fonction dexploration // $chemin : Rpertoire explorer // $recursif : TRUE si lexploration doit tre rcursive // $filtre : Expression rgulire de filtrage des fichiers function explorer($chemin, $recursif=FALSE, $filtre=NULL) { $listeFichier = array(); $repertoire = openDir($chemin); while ($fichier = readDir($repertoire)) { // Inutile de tenir compte des entres . et .. if (($fichier != ".")&&($fichier != "..")) { // Est-ce que $file est un rpertoire ? // Pour le savoir il suffit dappeler is_dir // mais attention noublions pas dajouter

521

Chapitre 9

La gestion des fichiers et des rpertoires

// le chemin au nom du fichier if (is_dir($chemin."/".$fichier)&&($recursif)) { // oui ? alors explorons-le // et ajoutons le rsultat la liste de fichiers $listeFichier = array_merge($listeFichier, explorer($chemin."/".$fichier, $recursif, $filtre)); } else { // sinon, cest un fichier et sil rpond // aux critres de lexpression rgulire // on lajoute a la liste des fichiers if (is_null($filtre)||eregi($filtre, $fichier)) { $listeFichier[] = $chemin."/".$fichier; } } } } // Cest fini. On ferme ! closeDir($repertoire); // et on retourne le rsultat return $listeFichier; } // Dfinition du chemin explorer $cheminRep = "../."; // Lappel la fonction $fichiers = explorer($cheminRep, TRUE, ".gif|.jpg|.png"); // Affichage ( titre dmonstratif) echo "<html><body>"; echo "<table width=100% border=0>"; for ($i=0; $i<count($fichiers); $i++) { // 5 images par ligne if ($i%5 == 0) echo "<tr></td>"; else echo "<td>"; echo "<img src=".$fichiers[$i]."><br />"; if (($i+1)%5 == 0) echo "</td></tr>\n"; else echo "</td>"; } echo "</table>"; echo "</body></html>"; ?>

9. La gestion des fichiers et des rpertoires 522

Accder au systme de fichiers du serveur

9. La gestion des fichiers et des rpertoires

Figure 9.6 : Notre galerie dimages

Lordre des fichiers Vous pouvez observer que la liste des fichiers nest pas donne dans lordre alphabtique. Si vous voulez ordonner cette liste, il vous suffit dappliquer la fonction sort() au tableau.
Dans les exemples prcdents, nous avons opt pour une solution retournant la liste des fichiers dans un tableau. Cette mthode peut ncessiter beaucoup de mmoire si la liste est longue. Une autre solution aurait pu consister ajouter la fonction un paramtre permettant de prciser le nom dune fonction appeler ds quun nouveau fichier est rencontr.

Pointeur de lecture du rpertoire


Lors de la lecture du contenu du dossier, vous pouvez dplacer le pointeur la premire entre laide de linstruction rewindDir().

523

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

rewindDir()
Dplace le pointeur de lecture du dossier la premire entre. Syntaxe $repertoire void rewindDir(resource $repertoire) Pointeur sur un dossier ouvert avec linstruction opendir().

<?php $repertoire = openDir("./"); while ($fichier = readDir($repertoire)) { echo $fichier."<br />"; } // Affichage de la liste des fichiers du dossier. while ($fichier = readDir($repertoire)) { echo $fichier."<br />"; } // Le programme naffiche rien. // On dplace le pointeur sur la premire entre rewindDir($repertoire); while ($fichier = readDir($repertoire)) { echo $fichier."<br />"; } // Affichage de la liste des fichiers du dossier. closeDir($repertoire); ?>

Rechercher un chier dans un rpertoire


Depuis la version 4.3 du langage PHP il est possible deffectuer directement des recherches de fichier laide de la fonction glob(). Ainsi, la fonction openDir() peut tre avantageusement remplace par glob() lorsquil est ncessaire de lister le contenu dun rpertoire en utilisant un filtre (masque).

glob()
Retourne les fichiers vrifiant un masque. Syntaxe : $masque $param array glob(string $masque [, int $param]) Masque permettant de filtrer les fichiers retourner. Option affectant le rsultat : GLOB_MARK : Ajoute un slash (caractre /) la fin de chaque rpertoire. GLOB_NOSORT : Indique de ne pas utiliser lordre alphabtique pour retourner les rsultats.

524

Accder au systme de fichiers du serveur

GLOB_NOCHECK : Retourne le masque si aucun fichier ne correspond au masque $masque. GLOB_NOESCAPE : Enlve les anti-slash devant les mta-caractres comme lespace. GLOB_BRACE : utilise la formulation {a, b, c} pour rechercher dans le masque les chanes a, b ou c. GLOB_ONLYDIR : Ne retrourne que les rpertoires. retour Retourne un tableau contenant la liste des rsultats. En cas derreur, la fonction retourne FALSE.

9. La gestion des fichiers et des rpertoires

<?php /* Rpertoire contenant les fichiers emma.txt, damien.txt, laurent.txt, thomas.txt, pem.txt et les rpertoire bible et php. */ print_r(glob("p*")); print_r(glob("p*", GLOB_MARK)); print_r(glob("p*", GLOB_NOSORT)); print_r(glob("*nux", GLOB_NOCHECK)); print_r(glob("{la,da,th}*.txt", GLOB_BRACE)); print_r(glob("*", GLOB_ONLYDIR)); ?> Array ( [0] [1] ) Array ( [0] [1] ) Array ( [0] [1] ) Array ( [0] ) Array ( [0] [1]

=> pem.txt => php

=> pem.txt => php/

=> php => pem.txt

=> *nux

=> laurent.txt => damien.txt

525

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

[2] => thomas.txt ) Array ( [0] => bible [1] => php )

Manipulation de chiers et rpertoires


Maintenant que nous avons une liste de fichiers, nous pouvons nous intresser la manipulation de ces fichiers. Le langage PHP possde une liste de fonctions qui vont nous permettre de copier, renommer, supprimer ou mme crer des liens symboliques sur les fichiers. Dans un premier temps, intressons-nous la copie de fichier. Linstruction copy() permet votre programme daccder au systme de fichier, et de copier le fichier dsign vers le dossier et sous le nom que vous aurez dcid.

copy()
Copie un fichier. Syntaxe $source $destination retour boolean copy(string $source, string $destination) Chemin vers le fichier source copier. Chemin de destination du fichier. Retourne TRUE si le fichier a bien t copi, FALSE sinon.

<?php copy("emma.jpg", "../emma.jpg"); // Cet exemple copie le fichier emma.jpg // vers le dossier en dessous ?>

Le langage PHP possde deux instructions link() et symlink() qui permettent respectivement de crer un lien dur ou un lien symbolique sur un fichier.

link() (non disponible sous Windows)


Crer un lien dur sur un fichier. Syntaxe boolean link(string $nomFichier, string $nomLien)

526

Accder au systme de fichiers du serveur

$nomFichier $nomLien retour

Le nom du fichier sur lequel le lien doit tre cr. Le nom du lien crer. TRUE si le lien a bien t cr, FALSE dans le cas contraire (avec un message de type "warning" sous Windows).

9. La gestion des fichiers et des rpertoires

<?php if (link("/home/laurent/emma.png","/home/damien/emma.png") { echo "Le lien a bien t cr."; } else { echo "Le lien na pas t cr."; } ?>

symLink() (non disponible sous Windows)


Crer un lien symbolique sur un fichier. Syntaxe $nomFichier $nomLienSymb retour boolean symLink(string $nomFichier, string $nomLienSymb) Le nom du fichier sur lequel le lien doit tre cr. Le nom du lien symbolique crer. TRUE si la fonction na pas rencontr de problme, FALSE sinon (avec un message de type "warning" sous Windows).

<?php if (symlink("/home/laurent/emma.png","/home/damien/emma.png") { echo "Le lien symbolique a bien t cr."; } else { echo "Le lien symbolique na pas t cr."; } ?>

Les programmes exploitant les fonctions de manipulation de fichiers doivent souvent utiliser des fichiers temporaires. Il est en effet souvent intressant de crer des fichiers tampons afin de stocker les donnes temporairement. La fonction tempNam() permet cette manipulation en crant, sur un rpertoire, un fichier possdant un nom unique.

tempNam()
Crer un fichier temporaire dans un rpertoire fourni en paramtre. Syntaxe $dossier string tempNam(string $dossier, string $prefixe) Dossier o doit tre cr le fichier temporaire. Si le nom du dossier est mis NULL, le fichier sera cr dans le rpertoire temporaire du systme

527

Chapitre 9

La gestion des fichiers et des rpertoires

(dpend de la configuration mais, gnralement, /tmp sous Linux et C:\windows\temp\ sous Windows).

9. La gestion des fichiers et des rpertoires

$prefixe

Prfixe du nom de fichier crer (permet de distinguer plus simplement les fichiers temporaires des autres). Si vous ne souhaitez pas en prciser, mettez cette valeur NULL. Le nom du fichier qui a t cr. Si une erreur est survenue, FALSE sera renvoy.

retour

<?php $nomTemporaire = tempNam(NULL, "php_"); echo "Le fichier ".$nomTemporaire." vient dtre cr."; ?>

La manipulation de fichiers suppose aussi la possibilit de supprimer. Linstruction unlink() efface dfinitivement un fichier (ou un lien) du disque.

unlink()
Destruction dun fichier ou dun lien sur un fichier (pour les rpertoires voir rmdir()). Syntaxe $nomFichier retour boolean unlink(string $nomFichier) Nom et chemin daccs du fichier supprimer. TRUE si le fichier a bien t supprim, FALSE dans le cas contraire.

<?php if (unlink("/home/laurent/emma.jpg") { echo "Le fichier a t effac"; } else { echo "Le fichier na pas t dtruit."; } ?>

Nous avons vu comment copier un fichier et le supprimer ; ces deux instructions que sont copy() et unlink() seraient amplement suffisantes pour nous permettre de dplacer un fichier dun endroit un autre si le langage PHP ne possdait pas linstruction rename(). Ainsi, en une seule commande, il est possible de dplacer le fichier et (ou) de le renommer.

rename()
Renomme et (ou) dplace un fichier ou un rpertoire. Syntaxe boolean rename(string $ancienNom, string $nouveauNom)

528

Accder au systme de fichiers du serveur

$ancienNom $nouveauNom retour

Ancien nom ou ancien chemin du fichier. Nouveau nom ou nouvel emplacement du fichier. Si le changement de nom sest bien droul, linstruction retourne TRUE, FALSE sinon.

9. La gestion des fichiers et des rpertoires

<?php if (rename("/home/laurent/emma.png", "/home/thomas/emma.png")) { echo "Le fichier a t dplac avec succs."; } else { echo "Impossible de dplacer le fichier."; } ?>

rmDir()
Supprime un rpertoire la condition que celui-ci soit vide. Syntaxe $nomDossier retour boolean rmDir(string $nomDossier) Chemin daccs du dossier supprimer. Retourne TRUE si le dossier a bien t supprim, FALSE sinon.

<?php if (rmdir("/home/laurent/emma") { echo "Le dossier a t effac"; } else { echo "Le dossier na pas t dtruit."; } ?>

Le langage PHP permet, bien videmment, de crer des dossiers. Pour cela, vous disposez de linstruction mkDir(). Vous pourrez alors prciser les droits sur le rpertoire ainsi cr. Bien entendu, le mode ne concerne que le systme UNIX et non les plateformes Windows.

mkDir()
Cre un dossier et lui affecte un mode. Syntaxe $nomDossier $mode retour boolean mkDir(string $nomDossier [, int $mode]) Nom du dossier crer. Droits rclams pour le dossier crer (inoprant sous Windows). Retourne TRUE si le dossier a bien t cr ; linverse, notamment si le dossier existe dj, linstruction renvoie FALSE.

529

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

<?php if (mkDir("nouveaurepertoire",0755) { echo "Le dossier a t cr."; } else { echo "Le dossier na pas t cr."; } ?>

Il est probable que le dossier que vous crerez ne possdera pas exactement les droits que vous aurez spcifis. En effet, chaque utilisateur (y compris le compte sous lequel tourne le serveur web) possde dans son environnement un paramtre appel umask. Ce paramtre dfinit les droits daccs qui sont, par dfaut, retirs lors de la cration des fichiers et rpertoires. Concernant les fichiers, les droits demands par dfaut sont 0666. Ainsi, un utilisateur qui possde un umask en 0000 crera par dfaut des fichiers ayant les droits 0666 (0666 - 0000 en octal), alors quun utilisateur avec un umask en 0022, crera des fichiers ayant les droits 0644 (0666 - 0022 en octal). Le principe est le mme pour les rpertoires. Si vous spcifiez des droits 0777, alors lumask sera appliqu. Sil est 0022, les droits effectifs du rpertoire seront 0755 (0777 - 0022 en octal). Si vous voulez crer des dossiers dans un mode particulier, vous serez peut-tre amen utiliser la fonction umask() qui permet de modifier lumask pendant la dure de lexcution du script (si PHP est compil en module ou, au-del, sil est excut en CGI).

Pour plus dinformations sur la compilation de PHP, reportez-vous au chapitre "Prise en main".

umask() (inoprant sous Windows)


Change (ou retourne) la valeur de lumask. Syntaxe $nouvMask retour int umask([int $nouvMask]) Nouvel umask. Retourne la valeur prcdente de lumask (0 sous Windows).

<?php // Modification de lumask $ancienUmask = umask(0022); if (mkdir("/home/laurent/emma",0777) { echo "Le dossier possde le mode 755."; } else { echo "Le dossier na pas t cr."; } // rinitailisation de lumask dans sa valeur initiale. umask($ancienUmask); ?>

530

Accder au systme de fichiers du serveur

Modication des permissions


Lorsque vous dsirez installer un logiciel, il est probable que, dans les notes dinstallation, lon vous demande de modifier les permissions de certains rpertoires et fichiers en 777 ; cela pour la raison suivante : gnralement, vous placez les fichiers sur le serveur laide dun client FTP. Ceux-ci appartiennent alors au compte et au groupe utiliss lors de laccs FTP. Les permissions sont donc limites lutilisateur du compte FTP. De ce fait, le serveur HTTP (qui tourne en gnral sous un autre utilisateur, qui peut tre, par exemple, apache ou nobody) na pas les droits daccs sur ces fichiers. Le serveur ne peut alors pas crire dans les rpertoires ou les fichiers. La solution de facilit est donc de modifier les permissions sur les fichiers que le serveur est cens retoucher en donnant les droits en lecture, criture et excution tous (0777). Cela est aussi valable dans le sens inverse. Le serveur web peut crer des fichiers que lutilisateur ne peut ensuite modifier, car il ne possde pas les droits dcriture sur ledit fichier. Le langage PHP permet la modification des propritaires des fichiers et des rpertoires, ainsi que la gestion de leurs droits. Il sagit tout simplement des quivalents des commandes chmod, chown et chgrp disponibles sous Linux. Attention, la modification des droits sur les fichiers suppose que le serveur HTTP possde les permissions ncessaires cette modification. En rgle gnrale, lutilisateur qui effectue les changements est lutilisateur propritaire des fichiers ou fait partie du groupe propritaire.

9. La gestion des fichiers et des rpertoires

chmod() (inoprant sous Windows)


Modifie les permissions de lecture, dcriture et dexcution dun fichier. Syntaxe $nomFichier $mode retour boolean chmod(string $nomFichier, int $mode) Chemin daccs au fichier modifier. Indique en octal le nouveau mode (ex. : 0755). TRUE si le changement de mode se droule sans problme (et sous Windows), FALSE sinon.

Il est, l aussi, conseill de placer un zro devant le mode afin de prciser que celui-ci est donn en octal et non en dcimal.
<?php if (chmod("emma.txt", 0755)) { echo "Le changement de permission est un succs."; } else { echo "Echec dans le changement de permission."; } ?>

531

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

chown() (inoprant sous Windows)


Change le propritaire du fichier. Syntaxe $nomFichier $utilisateur retour boolean chown(string $nomFichier, mixed $utilisateur) Nom du fichier modifier. Lutilisateur qui lon veut donner les droits. Peut tre prcis soit par son UID (identifiant dutilisateur) soit par son login (nom dutilisateur). TRUE si la modification a bien t effectue (ou sous Windows), FALSE dans le cas contraire.

<?php if (chown("fichier.txt", "damien")) { echo "Le changement dutilisateur est un succs."; } else { echo "Echec dans le changement dutilisateur."; } ?>

chgrp() (inoprant sous Windows)


Change le groupe propritaire du fichier. Syntaxe $nomFichier $groupe retour boolean chgrp(string $nomFichier, mixed $groupe) Nom du fichier modifier. Le groupe qui lon veut donner les droits. Peut tre prcis soit par son GID (identifiant de groupe) soit par son nom. TRUE si la modification du groupe a t effectue avec succs, FALSE dans le cas contraire (et sous Windows).

<?php if (chgrp("fichier.txt", "invite")) { echo "Le changement de groupe est un succs."; } else { echo "Echec dans le changement du groupe."; } ?>

Upload de chiers
Le terme upload dsigne laction de transfrer, vers un serveur distant, un fichier qui se situe en local (sur le poste du client). Lupload de fichiers laide dun formulaire HTML nest possible que depuis la version 1.1 de la norme HTTP. Le navigateur peut, laide dune mthode POST,

532

Accder au systme de fichiers du serveur

expdier un fichier sur le serveur dans un rpertoire temporaire, quil soit dun format texte ou binaire. Le code HTML permettant cette action est de la forme :

9. La gestion des fichiers et des rpertoires

Listing 9.18 : upload_form.html


<html> <head> <title>Upload de fichiers</title> </head> <body> <form action="upload.php" enctype="multipart/form-data" method="post"> <input type="hidden" name="MAX_FILE_SIZE" value="1024" /> Uploader le fichier : <input name="fichier" type="file" /><br /> <input type="submit" value="Go &gt;&gt;"> </form> </body> </html>

Ce formulaire contient deux balises particulirement importantes :


j

La balise <form> avec lattribut enctype="multipart/formdata" indique au navigateur la faon dont les donnes seront envoyes (donc ici, sous forme de donnes brutes), alors que la valeur par dfaut est application/xwwwformurlencoded. Lenvoi de fichiers ne peut se faire quavec la mthode POST, do la prsence de lattribut method="post". La balise <input> avec lattribut type="file". Cette balise se traduit par la prsence, sur le formulaire, dun bouton permettant la slection du fichier (sur le poste client).

Il est galement conseill de spcifier une balise supplmentaire contenant un champ cach qui prcise la taille maximale (en octets) des fichiers transfrer. <input type="hidden" name="MAX_FILE_SIZE" value="1024" /> (ici, pour des fichiers de 1 Ko au maximum).

Il y a toujours un risque de casse Prenez garde : le nom du champ MAX_FILE_SIZE doit obligatoirement tre en majuscules.
Lorsquun tel formulaire est "soumis", le client envoie plusieurs lignes supplmentaires dans len-tte HTTP. Habituellement, pour des donnes classiques, cest--dire qui ne sont pas des upload de fichier, le navigateur ajoute une ligne ContentDisposition: formdata; name="leNomDuChamp" suivie dun retour chariot et de la valeur du champ. Pour chaque champ de type fichier, le navigateur ajoute une ligne den-tte ContentDisposition: formdata; name="leNomDuChamp"; filename="monFichier.gif" suivie dun retour chariot, dune ligne dcrivant le contenu du fichier ContentType: image/gif et, nouveau, dun retour chariot et, enfin, du contenu du fichier envoyer sur le serveur. Au final, le fichier est rceptionn dans un rpertoire temporaire du serveur. Notez que le nom du fichier dans ce rpertoire est indpendant du nom du fichier que lutilisateur a transmis. En

533

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

effet, le fichier porte lui-mme un nom temporaire. Il vous faudra alors renommer et dplacer le fichier dans un lieu sr ( moins que vous ne souhaitiez seulement le consulter, et non pas le conserver).

Taille maximale du fichier Lajout du champ cach MAX_FILE_SIZE nest en rien une garantie que des fichiers de plus petite taille puissent tre envoys sur le serveur. En effet, la taille des fichiers uploads est limite par diffrents autres paramtres. La limite peut tre impose par PHP via loption upload_max_filesize (par dfaut 2 Mo) du fichier php.ini et, ventuellement, par le serveur web lui-mme. De plus, il faut noter que la prsence du champ MAX_FILE_SIZE dans le formulaire que vous mettez disposition ninterdit en rien un utilisateur dutiliser son propre formulaire (sans se fixer de limitation dans la taille du fichier upload). Il est donc ncessaire de ne pas trop sappuyer sur ce paramtre HTML, et de toujours vrifier dans votre programme que le fichier en question ne dpasse pas la taille autorise.
Le script PHP appel par le formulaire (ici upload.php) dispose alors de plusieurs entres dans la variable globale $_FILES de type tableau associatif (anciennement $HTTP_POST_FILES ou $_POST). Ce tableau contient une cl portant le nom spcifi dans la balise <input type="file"> (ici $_FILES["fichier"]). ce moment-l, la valeur associe est un tableau, lui aussi associatif, contenant les cls prsentes dans le tableau suivant :

Tableau 9.2 : Les diffrentes "cls" de la variable denvironnement $_FILES dans le cas o "fichier" est le nom du champ "file" du formulaire
$_FILES $_FILES["fichier"]["tmp_name"] $_FILES["fichier"]["name"] $_FILES["fichier"]["size"] $_FILES["fichier"]["type"] Description Contient le nom temporaire (sur le serveur) du fichier qui a t transmis par le formulaire. Contient le nom du fichier tel quil existe sur le disque du client. Contient la taille en octets du fichier transmis. Contient le type MIME du fichier.

register_global Comme cela a t voqu de nombreuses reprises concernant dautres variables externes, si votre fichier php.ini prcise register_global=on, alors $_FILES["fichier"] est directement accessible via la variable $fichier. Il est cependant fortement dconseill de positionner register_global on (comme prcis dans le chapitre sur les variables externes).
Le langage PHP permet ensuite, laide de quelques fonctions, de manipuler ce fichier trs simplement.

534

Accder au systme de fichiers du serveur

La premire tape peut consister en un appel la fonction is_uploaded_file(). Lobjectif est alors double. Il sagit de vrifier si lupload du fichier sest bien droul (prsence effective dun fichier portant le nom indiqu), mais galement de vrifier si le fichier pass en paramtre est bien un fichier qui a t tlcharg. Cette dernire vrification est trs importante. Il est en effet imaginable quun hacker puisse tromper le script, en lui faisant croire quun fichier a t upload dans un rpertoire donn sous un nom correspondant un fichier vital de votre systme. Les traitements oprs par le script seffectueraient alors non pas sur un fichier transfr lambda, mais sur ce fichier systme. Le risque est vident si vous avez opt pour une configuration avec register_globals=on (ce qui tait la configuration par dfaut avant PHP 4.2.0) et que les paramtres GET sont rendus globaux aprs les paramtres POST (ce qui nest pas la configuration par dfaut). Dans ce cas, il suffirait dappeler le script de la faon suivante : upload.php?fichier[tmp_name]=/etc/passwd pour lui faire croire que le fichier tlcharg sappelle /etc/passwd. Mme si le cas voqu ici nest pas trs raliste, dans la mesure o il rsulte dune modification aberrante du fichier de configuration, il nest pas exclure que dautre moyens dobtenir ce rsultat sont envisageables. Prudence tant mre de sret, vous savez ce quil vous reste faire

9. La gestion des fichiers et des rpertoires

is_uploaded_le()
Indique si le fichier est un fichier tlcharg via un formulaire HTTP de type POST. Syntaxe $nomFichier retour boolean is_uploaded_file(string $nomFichier) Chemin complet vers le fichier. TRUE si le fichier est un fichier tlcharg par formulaire, FALSE dans le cas contraire.

Pour mettre en vidence lutilisation de la fonction is_uploaded_file() et le contenu du tableau $_FILE, nous utiliserons un script contenant un formulaire et qui sappellera lui-mme afin de donner les informations sur le fichier upload.

Listing 9.19 : is_uploaded_file.php


<?php // Vrifions que le tableau $_POST existe avant de lutiliser if ($_POST){ // Vrifions que le formulaire a t valid if ($_POST["envoyer"]) { if (is_uploaded_file($_FILES["fichier"]["tmp_name"])) { echo "Le fichier ".$_FILES["fichier"]["name"]. " a bien t tlcharg.<br />"; echo "Il fait ".$_FILES["fichier"]["size"]." et est de type ". $_FILES["fichier"]["type"]."<br />"; } else { echo "Le fichier ".$_FILES["fichier"]["name"]. " na pas t tlcharg<br />".

535

Chapitre 9

La gestion des fichiers et des rpertoires

"Peut-tre dpassait-il la limite des 1Ko<br />". "A moins que vous nayez essay de truander";

9. La gestion des fichiers et des rpertoires

} } } ?> <html> <head> <title>is_uploaded_file</title> </head> <body> <form enctype="multipart/form-data" method="post"> <input type="hidden" name="MAX_FILE_SIZE" value="1024"> Tlcharger le fichier : <input name="fichier" type="file"> <input name="envoyer" type="submit" value="Envoyer"> </form> </body> </html>

Une fois cette vrification effectue, il ne reste plus qu dplacer ce fichier vers le dossier de travail, afin de ne pas le laisser sur le rpertoire temporaire o il serait dtruit plus ou moins long terme. Pour dplacer un fichier, il existe deux mthodes. Soit vous dplacez le fichier de faon classique laide de linstruction move(), soit vous dplacez le fichier laide de la fonction move_uploaded_file(). Dans ce dernier cas, vous navez pas besoin dutiliser is_uploaded_file(). En effet, move_uploaded_file() se charge de vrifier si la source est bien un fichier tlcharg laide dun formulaire.

move_uploaded_le()
Dplace un fichier tlcharg depuis le rpertoire temporaire vers un dossier de destination. Syntaxe $nomFichier $destination retour boolean move_uploaded_file(string $nomFichier, string $destination) Nom temporaire du fichier dplacer. Fichier de destination. TRUE si le fichier est bien un fichier upload et a bien t dplac, FALSE sil y a une erreur quelconque.

Il est alors possible dcrire le script suivant, charg de copier le fichier upload dans le rpertoire dexcution du script, et de lister le contenu de ce mme rpertoire. Ce script pourra tre appel par le formulaire upload_form.html prsent au dbut de ce chapitre.

536

Accder au systme de fichiers du serveur

Listing 9.20 : upload.php


<?php // Dplacement du fichier du rpertoire temporaire // vers le rpertoire courant do est excut le script. if (move_uploaded_file($_FILES["fichier"]["tmp_name"], "./".$ _FILES["fichier"]["name"])) { // Le fichier est dplac // Affichage de la liste des fichiers du rpertoire $repertoire = opendir("./"); while ($fichier = readdir($repertoire)) { echo $fichier."<br />"; } closedir($repertoire); } ?>

9. La gestion des fichiers et des rpertoires

La difficult que nous avons occulte ici est celle qui consiste donner un nom unique au fichier. En effet, stocker le fichier sous le nom quil porte sur le poste client (comme cela est le cas dans lexemple prcdent) nest gnralement pas satisfaisant. Si deux utilisateurs "uploadent" un fichier emma.jpg et que ce fichier est copi dans le mme rpertoire, alors le fichier du premier sera cras par celui du second. Mais la stratgie mettre en place dpend fortement du rsultat que vous souhaitez obtenir. Il est envisageable de stocker le fichier sous le nom initial sil est copi dans un rpertoire propre chaque utilisateur. Il est galement possible de copier le fichier sous un nom incluant lidentifiant (unique) de lutilisateur (si ce dernier doit sidentifier pour accder au site). Mais il est aussi possible duploader plusieurs fichiers partir dun unique formulaire. Il suffira, dans ce cas, de donner un nom distinct pour chaque champ de type file, ou bien de leur donner un nom de tableau (i.e. un nom termin par []).

Listing 9.21 : uploadmulti_form.html


<html> <head> <title>Upload de plusieurs fichiers</title> </head> <body> <form action="uploadmulti.php" enctype="multipart/form-data" method="post"> Uploader les fichiers suivants : <br /> Fichier 0 : <input name="fichier[]" type="file" /><br /> Fichier 1 : <input name="fichier[]" type="file" /><br /> Fichier 2 : <input name="fichier[]" type="file" /><br /> <input name="envoyer" type="submit" value="Envoyer"> </form> </body> </html>

537

Chapitre 9

La gestion des fichiers et des rpertoires

Dans ce cas, chaque lment du tableau associatif variable $_FILE["fichier"] est un tableau index. Il ne vous reste plus qu rcuprer les fichiers en utilisant la mthode suivante :

9. La gestion des fichiers et des rpertoires

Listing 9.22 : uploadmulti.php


<?php // Dplacement des fichiers du rpertoire temporaire // vers le rpertoire courant do est excut le script. for ($i=0; $i<count($_FILES["fichier"]["tmp_name"]); $i++) { move_uploaded_file($_FILES["fichier"]["tmp_name"][$i], "./".$_FILES["fichier"]["name"][$i]); } // Affichage de la liste des fichiers du rpertoire $repertoire = openDir("."); while ($fichier = readDir($repertoire)) { echo $fichier."<br />"; } closeDir($repertoire); ?>

Encore plus de fonctions daccs au systme de chiers du serveur


Modication de lenvironnement
Bien souvent, lorsque vous dveloppez une application, le problme est de connatre le chemin du rpertoire o sexcute le programme. La commande getcwd() permet de rcuprer le chemin du rpertoire de travail.

getcwd()
Retourne le chemin du rpertoire de travail. Syntaxe retour string getcwd(void) Chemin du rpertoire de travail o est excut le script.

<?php echo "Le dossier de travail est : ".getcwd(); echo "<br />"; echo "Le script est : ".$_SERVER["SCRIPT_FILENAME"]; ?>

538

Accder au systme de fichiers du serveur

Et, puisque lon peut rcuprer le rpertoire de travail, il peut tre tout aussi intressant de prciser ce rpertoire au cours de lexcution du programme. La commande chdir() permet de spcifier le dossier de travail pendant la dure de lexcution du script.

9. La gestion des fichiers et des rpertoires

chdir()
Modification du dossier de travail. Syntaxe $repertoire retour boolean chdir(string $repertoire) Nouveau rpertoire de travail. TRUE en cas de succs, FALSE sinon.

<?php if (chdir("/home/laurent/emma")) { echo "Changement de rpertoire effectu avec succs."; }else{ echo "Problme lors du changement de rpertoire.<br />"; echo "Veillez vrifier les droits daccs au dossier."; } ?>

Mme si lutilisation de ces fonctions nest pas ncessaire pour parvenir ce rsultat, nous pouvons les utiliser pour commencer constituer notre explorateur de fichiers, qui sappuiera sur la fonction explorer() dveloppe lors de la prsentation de la fonction readDir().

Listing 9.23 : gestionnaire_fichiers_01_inc.php (sans la fonction explorer)


<?php function listRepertoire() { // Rcupration du chemin courant $repCourant = getcwd(); $fichiers = explorer("."); // Nous ajouterons ".." (qui a t filtr par la fonction) if ($repCourant != "/") $fichiers = merge(array(".."), $fichiers); ?> <table border="1" width="100%"> <tr> <td><font color="#cc0000"> <?php echo $repCourant; ?> </font> </td> </tr> </table> <table border="0" width="100%"> for ($i=0; $i<count($fichiers); $i++)

539

Chapitre 9

La gestion des fichiers et des rpertoires

{ <tr> <td> <?php // Le fichier est-il un rpertoire ? if (is_dir($fichiers[$i])) { /* Le fichier est un rpertoire On affiche alors un lien qui va nous permettre de visualiser le contenu de ce dossier */ ?> <a href="?repertoire=<?php echo $repCourant."/".$fichiers[$i];?>"> <?php echo $fichiers[$i];?> </a> <?php }else{ /* Le fichier nest pas un rpertoire On affiche simplement le nom du fichier */ echo $fichiers[$i]; } ?> </td> </tr> <?php } ?> echo "</table>"; }

9. La gestion des fichiers et des rpertoires

Le programme principal sera alors (pour linstant) :

Listing 9.24 : gestionnaire_fichier_01.php


<?php include("gestionnaire_fichier_01_inc.php"); // Vrifie si "repertoire" est pass en paramtre. if ($_GET["repertoire"]) { if (!@chdir($_GET["repertoire"])) { echo "Le changement de repertoire a chou."; } } listeRepertoire(".");

540

Accder au systme de fichiers du serveur

Figure 9.7 : Gestionnaire de fichiers (version 1)

9. La gestion des fichiers et des rpertoires

Scurit du systme Maintenant que lutilisateur peut se dplacer simplement dans la liste des rpertoires, il est important de rendre inaccessibles certains dossiers contenant des informations que vous ne voulez pas rendre publiques. Modifier les droits daccs du serveur web sur les rpertoires en question permet dinterdire le changement de dossier de travail. Exemple : rwxrw utilisateur apache

Statistiques sur les chiers


Chemin daccs aux chiers
Avant douvrir un fichier, il est utile, voire ncessaire, de connatre certaines informations concernant son chemin daccs, son nom, etc. Le langage PHP possde quelques instructions pouvant tre trs pratiques pour rcuprer ces informations. Il est simple de rcuprer le nom dun fichier (sans le chemin) laide de linstruction basename().

basename()
Extrait dune chane de caractres la partie correspondant au nom du fichier. Syntaxe $cheminFichier $suffixe retour string basename(string $cheminFichier [, string $suffixe]) Chemin dun fichier (qui na pas besoin dexister). Ce paramtre optionnel indique sil faut supprimer le suffixe. Retourne le nom du fichier.

541

Chapitre 9

La gestion des fichiers et des rpertoires

<?php $image= "/home/laurent/emma.png"; // Affichage de emma.png echo basename($image); echo "<br />"; // Affichage de emma echo basename($image, "png"); ?> emma.png emma

9. La gestion des fichiers et des rpertoires

Pour aller dans le mme sens que basename(), on va maintenant tudier linstruction dirname() qui retourne le chemin du rpertoire contenant un fichier.

dirname()
Extrait dune chane de caractres la partie correspondant au chemin. Syntaxe $cheminFichier retour string dirname(string $cheminFichier) Chemin dun fichier (qui na pas besoin dexister). Retourne le chemin du dossier contenant le fichier.

<?php $image= "/home/laurent/emma.png"; // Affichage de /home/laurent echo basename($image); ?> /home/laurent

Une fonction permet galement de rcuprer toutes ces informations en une seule fois. Linstruction pathInfo() retourne un tableau contenant les diffrents renseignements sur un chemin de fichier.

pathInfo()
Extrait dune chane de caractres les parties correspondant au chemin, au nom du fichier (extension incluse) et lextension. Syntaxe $cheminFichier retour array pathInfo(string $cheminFichier) Chemin dun fichier (qui na pas besoin dexister). Tableau associatif contenant les cls : "dirname" associe au nom du rpertoire. "basename" associe au nom du fichier. "extension" associe lextension du fichier.

542

Accder au systme de fichiers du serveur

<?php $infoChemin = pathInfo("/home/laurent/emma.png"); while (list ($key, $val) = each ($infoChemin)) { echo "$key = $val<br />"; } ?> dirname = /home/laurent basename = emma.png extension = png

9. La gestion des fichiers et des rpertoires

Grce la fonction realPath(), il est possible dobtenir le chemin absolu dun fichier partir de son chemin relatif.

realPath()
Retourne le chemin absolu dun fichier. Syntaxe $cheminFichier retour string realPath(string $cheminFichier) Chemin dun fichier. Chemin absolu du fichier.

<?php echo realpath("../../info.php"); echo "<br />"; echo realpath("bonzour.jpg"); ?> /home/e-smith/files/ibays/kangouroo/html/info.php /home/e-smith/files/ibays/kangouroo/html/bible/fichier/bonzour.jpg

Nature du chier
Une srie de fonctions vous permet de vrifier la nature du fichier ou du rpertoire, savoir : is_dir(), is_executable(), is_file(), is_link(), is_readable(), is_writable() (ou son alias is_writeable) et is_uploaded_file().

is_dir()
Indique si le fichier pass en paramtre est un rpertoire ou non. Syntaxe $nomFichier retour boolean is_dir(string $nomFichier) Chemin du fichier. TRUE si le fichier est un rpertoire, FALSE dans le cas contraire.

543

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

<?php if (is_dir("indetermine")) { echo "OUUIII, je suis un repertoire !"; }else{ echo "Ben non je suis autre chose, snif !"; } ?>

is_le()
Indique si le fichier est un fichier classique. Syntaxe $nomFichier retour boolean is_file(string $nomFichier) Chemin du fichier. TRUE si le fichier est un fichier classique, FALSE dans le cas contraire.

<?php if (is_file("indetermine")) { echo "Je suis bien un fichier !"; }else{ echo "Cest pas encore a, je ne suis pas un fichier."; } ?>

is_link() (inoprant sous Windows)


Indique si le fichier est un lien symbolique ou non. Syntaxe $nomFichier retour boolean is_link(string $nomFichier) Chemin du fichier. TRUE si le fichier est un lien symbolique, FALSE dans le cas.

<?php if (is_link("indetermine")) { echo "Cest a ! Je suis un lien symbolique."; }else{ echo "Ben, toujours pas :o(."; } ?>

Vous pouvez aussi remplacer ces prcdentes fonctions par une autre bien pratique : la fonction fileType() renvoie une chane de caractres indiquant le type du fichier.

544

Accder au systme de fichiers du serveur

leType()
Retourne une chane indiquant le type du fichier pass en paramtre. Syntaxe $nomFichier retour string filetype(string $nomFichier) Chemin du fichier. Retourne le type du fichier savoir : "fifo". "char". "dir" sil sagit dun rpertoire. "block". "link" sil sagit dun lien symbolique. "file" sil sagit dun vritable fichier. "unknown" dans le cas ou le type de "fichier" est inconnu.

9. La gestion des fichiers et des rpertoires

<?php echo filetype("monfichier.txt"); ?>

Droits sur les chiers


Diffrentes fonctions permettent galement de tester les droits sur les fichiers. Dans les cas suivants, les droits sont tests par rapport lutilisateur et au groupe excutant le script. Ce sera la plupart du temps lutilisateur du serveur HTTP (gnralement apache ou nobody, par exemple, dans le cas dun serveur Apache). Ces fonctions sont trs intressantes si vous voulez dvelopper une installation automatique dune de vos applications, la manire de SPIP par exemple (voir les annexes pour linstallation de SPIP). Votre installation devant crer ou retoucher un fichier de configuration, il peut tre utile de vrifier si celui-ci est accessible en criture par votre script. Si cest le cas, vous excutez linstallation, sinon vous envoyez des informations lutilisateur indiquant pas pas ce quil doit faire pour que le script puisse tre lanc.

is_readable()
Indique si le fichier est accessible en lecture. Syntaxe $nomFichier retour boolean is_readable(string $nomFichier) Chemin du fichier. TRUE si le fichier est accessible en lecture, FALSE dans le cas contraire.

<?php if (is_readable("monfichier.txt")) { echo "Je suis un livre ouvert."; }else{ echo "Vous ne regarderez pas en moi."; } ?>

545

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

is_writable()
Indique si le fichier est accessible en criture. Syntaxe $nomFichier retour boolean is_writable(string $nomFichier) Chemin du fichier. TRUE si le fichier est accessible en criture, FALSE dans le cas contraire.

<?php if (is_writable("monfichier.txt")) { echo "Vous pouvez me modifier sans problme."; }else{ echo "Ne me touchez pas !"; } ?>

Vous pouvez galement utiliser la fonction is_writeable() qui est un alias de is_writable().

is_executable()
Indique si le fichier est excutable ou non. Syntaxe $nomFichier retour boolean is_executable(string $nomFichier) Chemin du fichier. TRUE si le fichier est excutable, FALSE dans le cas contraire.

<?php if (is_executable("monfichier.txt")) { echo "Je marche avec vous."; }else{ echo "Vous pouvez toujours rver pour mexcuter !"; } ?>

Existence et taille des chiers


Le langage PHP possde une instruction simple pour vrifier lexistence ou non dun fichier. Il est souhaitable de tester si ce fichier est bien lendroit o il devrait tre avant de lui appliquer une ou plusieurs fonctions de statistiques ; cest ce que permet la fonction file_exists().

546

Accder au systme de fichiers du serveur

le_exists()
Permet de vrifier quun fichier existe bien. Syntaxe $nomFichier retour boolean file_exists(string $nomFichier) Chemin du fichier tester. TRUE si le fichier est bien prsent, FALSE sil nexiste pas ou si une erreur sest produite.

9. La gestion des fichiers et des rpertoires

<?php if (file_exists("emma.png")==TRUE) { echo "Le fichier emma.png est bien prsent sur le disque."; } else { echo "Le fichier emma.png nexiste pas."; } ?>

Pour continuer notre chemin et complter notre petit gestionnaire de fichiers en ligne, nous devons galement rcuprer la taille du fichier. La fonction qui va nous permettre de raliser cela est fileSize().

leSize()
Rcupre la taille du fichier pass en paramtre en octets. Syntaxe $nomFichier retour int fileSize(string $nomFichier) Chemin du fichier. Retourne la taille du fichier en octets.

Ceci nous permet de crer une nouvelle fonction charge de rcuprer la taille du fichier et de lafficher dans un format adapt (i.e. Ko, Mo, etc. selon les cas).

Listing 9.25 : gestionnaire_fichier_02_inc.php (extrait)


<?php function tailleFichier($fichier) { // calculs des taux de conversion entre Ko, // Mo et octet $Ko = pow(2, 10); $Mo = pow(2, 20); // recupre la taille du fichier en octets $taille = fileSize($fichier);

547

Chapitre 9

La gestion des fichiers et des rpertoires

// Pas de conversion if ($taille<$Ko){ $tailleDef = $taille; // Conversion en Ko } elseif ($taille>=$Ko && $taille<$Mo){ $tailleDef = round($taille/$Ko, 1)."k"; // Conversion en Mo } else { $tailleDef = round($taille/$Mo, 1)."M"; } return $tailleDef; } ?> Figure 9.8 : Gestionnaire de fichiers (version 2)

9. La gestion des fichiers et des rpertoires

Utilisateurs et groupes propritaires des chiers


Afin de rcuprer lidentifiant de lutilisateur et le groupe propritaire du fichier, nous utiliserons deux autres fonctions qui sont fileOwner() et fileGroup(). Ces fonctions renvoient les UID et GID correspondant au fichier.

leOwner() (inoprant sous Windows)


Retourne lidentifiant de lutilisateur (UID) propritaire du fichier. Syntaxe $nomFichier retour int fileOwner(string $nomFichier) Chemin du fichier. Identifiant de lutilisateur propritaire du fichier (0 sous Windows), FALSE en cas derreur.

548

Accder au systme de fichiers du serveur

leGroup() (inoprant sous Windows)


Retourne lidentifiant du groupe (GID) propritaire du fichier. Syntaxe $nomFichier retour int fileGroup(string $nomFichier) Chemin du fichier. Identifiant du groupe propritaire du fichier (0 sous Windows), FALSE en cas derreur.

9. La gestion des fichiers et des rpertoires

<?php function proprietaire($fichier) { $utilisateur = fileowner($fichier); $groupe = filegroup($fichier); return array("utilisateur"=>$utilisateur, "groupe"=>$groupe); } $tabPropietaire = proprietaire("fichier.txt"); echo "utilisateur = ".$tabPropietaire["utilisateur"]; echo "<br />"; echo "groupe = ".$tabPropietaire["groupe"]; ?> utilisateur = 101 groupe = 102

Il peut tre intressant dafficher lutilisateur et le groupe par leurs noms respectifs. Il faut, dans ce cas, utiliser les fonctions du module POSIX, savoir posix_getpwuid() et posix_getgrgid(). La premire fonction renvoie les informations sur lutilisateur possdant lUID pass en paramtre, et la seconde retourne les informations sur le groupe possdant le GID donn.

Vous pouvez vous reporter au chapitre "Les processus et les identifiants" pour plus dinformations sur posix_getpwuid() et posix_getgrgid().
Le script suivant retourne donc les noms du propritaire et du groupe du fichier, et sera intgr notre gestionnaire de fichiers.

Listing 9.26 : gestionnaire_fichier_03_inc.php (extrait)


<?php function proprietaire($fichier) { // recupre lUID du fichier $uid = fileowner($fichier); // Recupre les informations sur lUID $tabUtilisateur = posix_getpwuid($uid);

549

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

// recupre le GID du fichier $gid = filegroup($fichier); // Rcupre les informations sur le GID $tabGroup = posix_getgrgid($gid); // Renvoie les noms du groupe et de lutilisateur return array( "utilisateur"=>$tabUtilisateur["name"], "groupe"=>$tabGroup["name"] ); } ?>

Simplement appliqu un fichier de la faon suivante :


<?php $tabPropietaire = proprietaire("fichier.txt"); echo "utilisateur = ".$tabPropietaire["utilisateur"]; echo "<br />"; echo "groupe = ".$tabPropietaire["groupe"]; ?>

cela pourrait donner : utilisateur = admin groupe = www Utilis dans notre gestionnaire de fichiers, cela donne :
Figure 9.9 : Gestionnaire de fichiers (version 3)

Dates et heures chiers


Il peut tre intressant de rcuprer la date de la dernire modification du fichier. On utilisera alors la fonction filemtime() du langage PHP.

550

Accder au systme de fichiers du serveur

lemtime()
Retourne la date de la dernire modification du fichier. Syntaxe $nomFichier retour int filemtime(string $nomFichier) Chemin du fichier. Date de la dernire modification en secondes depuis epoch (1er janvier 1970).

9. La gestion des fichiers et des rpertoires

Voil une nouvelle fonction que nous pouvons ajouter notre gestionnaire de fichiers en lagrmentant dune mise en forme de la date au format mois/jour/heure/minutes.

Listing 9.27 : gestionnaire_fichier_04_inc.php (extrait)


<?php function modificationFichier($fichier) { // Rcupration de la dernire modification du fichier $modification = filemtime($fichier); // Retourne la date de modifications formate return strftime("%b %d %H:%M", $modification)."\n"; } ?> Figure 9.10 :

Gestionnaire de fichiers (extrait 4)

Pour modifier cette date, vous pouvez utiliser la fonction touch().

551

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

touch()
Spcifie une nouvelle date de modification pour un fichier (cre le fichier sil nexiste pas). Syntaxe $nomFichier $date retour boolean touch(string $nomFichier [, int $date]) Chemin du fichier dont vous souhaitez modifier la date de dernire modification. Nouvelle date de modification (en secondes depuis epoch). Par dfaut, il sagit de la date courante. TRUE en cas de succs, FALSE sinon.

<?php // Retourne la date de dernire modification du fichier echo filemtime("fichier.txt"); // Change la date dans la date courante touch("fichier.txt"); // Retourne la nouvelle date de modification echo filemtime("fichier.txt"); ?>

De la mme faon, il est possible daccder la date de dernier accs au fichier, ainsi qu la date du dernier accs linode (dernire fois que les droits, utilisateur, groupe, date de dernire modification, etc. du fichier ont t modifis). Les fonctions fileatime() et filectime() permettent au dveloppeur daccder ces diffrentes informations.

leatime()
Retourne la date et lheure du dernier accs au fichier. Syntaxe $nomFichier retour int fileatime(string $nomFichier) Chemin du fichier. Date du dernier accs au fichier (en secondes depuis epoch).

<?php function dateAcces($fichier) { // Rcupration de la dernire modification du fichier $modification = fileatime($fichier); // Retourne la date de modifications formate return strftime("%b %d %H:%M", $modification)."\n"; } echo "Dernier accs au fichier le ". dateAcces("fichier.txt"); ?>

552

Accder au systme de fichiers du serveur

lectime()
Retourne la date et lheure du dernier accs linode. Syntaxe $nomFichier retour int filectime(string $nomFichier) Chemin du fichier. Retourne la date du dernier accs linode (en secondes depuis epoch).

9. La gestion des fichiers et des rpertoires

<?php function dateAccesInode($fichier) { // Rcupration de la dernire modification du fichier $modification = filectime($fichier); // Retourne la date de modifications formate return strftime("%b %d %H:%M", $modification)."\n"; } echo "Dernier accs linode le ". dateAccesInode("fichier.txt"); ?>

Date de modification et daccs et liens symboliques Si vous utilisez lune des fonctions filectime(), fileatime() ou filemtime() sur un lien symbolique, vous aurez la date de modification du fichier sur laquelle pointe le lien. Pour rcuprer les informations sur le lien symbolique, vous devez utiliser la fonction lstat().

Inode
Comme nous lavons voqu prcdemment, linode (index node ou nud dindex) est une structure contenant les diffrentes informations lies un fichier (droits, propritaire, date de dernire modification, etc). chaque inode est associ un identifiant INumber qui est le numro dindex de linode. Le langage PHP possde une fonction qui permet de rcuprer ce numro dindex pour un fichier donn. Linstruction fileinode() permet en effet de retourner lINumber.

leInode() (inoprant sous Windows)


Retourne lINumber de linode dun fichier. Syntaxe $nomFichier retour int fileInode(string $nomFichier) Chemin du fichier. Inode du fichier (0 sous Windows).

553

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

<?php echo fileinode("emma.png"); ?>

La fonction qui fait tout


Pour rcuprer les diffrentes informations en une seule fois, le langage PHP possde une fonction trs utile. La fonction stat() permet, en effet, de retrouver tous les paramtres du fichier dans un tableau. Cette instruction utilise la structure des fichiers pour obtenir les informations ncessaires.

stat()
Retourne les informations propos dun fichier dans un tableau. Syntaxe $nomFichier retour array stat(string $nomFichier) Chemin du fichier analyser. Tableau la fois index et associatif contenant toutes les informations du fichier.

Le tableau retourn contient toutes les informations relatives un fichier ; ce tableau peut se dcomposer comme suit :

Tableau 9.3 : Le tableau retourn par la fonction stat()


Indice 0 1 2 3 4 5 6 7 8 Cl Dev Ino Mode Nlink Uid Gid Rdev size atime Description Numro didentifiant du systme de fichiers. INumber de linode reprsentant la structure du fichier. Les droits daccs sur le fichier (valeur en dcimal). Nombre de liens vers le fichier. Identifiant du propritaire du fichier. Identifiant du groupe propritaire du fichier. Identifiant du matriel (disque dur, CD-ROM, etc.) contenant le fichier (inode) (1 sous Windows). Taille du fichier en octets. Indique la date du dernier accs en secondes depuis epoch (sous UNIX, epoch correspond au 1er janvier 1970 0 heure 0 minute et 0 seconde, sous MacOS cest 1er janvier 1904 0 heure 0 minute et 0 seconde qui sert de rfrence). Date de la dernire modification du fichier depuis epoch. Date du dernier changement (modification de linode).

9 10

mtime ctime

554

Accder au systme de fichiers du serveur

Indice 11 12

Cl blksize blocks

Description Taille des blocs (en octets) de rfrence pour les entres/sorties du systme de fichier (1 sous Windows). Nombre de blocs allous pour le fichier (1 sous Windows).

9. La gestion des fichiers et des rpertoires

Lexemple suivant,
<?php function statistique($cheminFichier) { $tableau = stat($cheminFichier); while (list($key, $val) = each($tableau)) { echo "$key : $val<br>"; } } statistique("fichier.txt"); ?>

pourrait retourner :
0 : 834 1 : 131934 2 : 33264 3 : 1 4 : 101 5 : 102 6 : 0 7 : 23 8 : 1023545447 9 : 1023545460 10 : 1023545460 11 : 4096 12 : 8 dev : 834 ino : 131934 mode : 33264 nlink : 1 uid : 101 gid : 102 rdev : 0 size : 23 atime : 1023545447 mtime : 1023545460 ctime : 1023545460 blksize : 4096 blocks : 8

555

Chapitre 9

La gestion des fichiers et des rpertoires

Sil faut simplement rcuprer les droits correspondant un fichier, il suffit alors dcrire le programme suivant :

9. La gestion des fichiers et des rpertoires

<?php $tableau = stat("fichier.txt"); // recupre les permissions sur le fichier $droits = $tableau["mode"]; // Conversion en octale $octalPerm = decoct($droits); // Rcupration des 3 derniers caractres $normPerm = substr($octalPerm,-3); echo $normPerm; ?>

Retrouver le type du fichier Vous remarquerez que, dans lexemple prcdent, nous avons rcupr simplement les trois derniers caractres. En effet, seuls les derniers caractres correspondent aux permissions du fichier. Les autres indiquent le type du fichier. 0x1000 Port (Named pipe). 0x2000 Correspond un fichier de type caractre (imprimante, port srie, clavier, souris,..). 0x4000 Rpertoire. 0x6000 Reprsente un matriel disposant dun systme dentre/sortie (disques durs IDE, RAM, etc.). 0x8000 Fichier dit "normal". 0xA000 Lien symbolique. 0xC000 Socket.
Applique un lien symbolique, la fonction stat() retournera les informations concernant le fichier point. Si vous souhaitez obtenir les informations concernant le lien, vous devrez faire appel la fonction lstat(). Cette dernire est identique la fonction stat() et retourne un tableau identique.

lstat()
Retourne les informations propos dun lien symbolique (ou dun fichier). Syntaxe $nomFichier retour array lstat(string $nomFichier) Chemin du lien symbolique (ou fichier) analyser. Tableau contenant toutes les informations du fichier.

Vous pouvez sans doute tre amen rechercher le fichier point par le lien symbolique. Il est alors ncessaire dutiliser la fonction readLink().

556

Accder au systme de fichiers du serveur

readLink() (non disponible sous Windows)


Retourne le nom et le chemin du fichier cible du lien symbolique. Syntaxe $nomLienSymb retour string readLink(string $nomLienSymb) Lien symbolique analyser. Chemin du fichier point par le lien symbolique (FALSE accompagn du message de type "warning" sous Windows).

9. La gestion des fichiers et des rpertoires

<?php if (symlink("/home/laurent/emma.png", "/home/damien/emma.png") { echo "Le lien symbolique a bien t cr."; } else { echo "Le lien symbolique na pas t cr."; } echo readlink("/home/damien/emma.png"); ?> /home/laurent/emma.png

Si vous voulez simplement tester lexistence dun lien symbolique, vous pouvez utiliser la commande linkInfo(). En effet, la commande file_exists() retournera lexistence du fichier cible et non celle du lien. Remarquez que, si linstruction trouve le fichier cible, cest que le lien existe forcment. Mais il peut savrer que le fichier cible soit inexistant.

linkInfo() (non disponible sous Windows)


Retourne lidentifiant du matriel o est stock le lien symbolique. Syntaxe $nomLienSymb retour int linkInfo(string $nomLienSymb) Lien symbolique analyser. Identifiant du matriel (ou device, cest--dire le matriel o est stock le lien symbolique ; attention, device ne fait pas rfrence un disque dur, mais une partition) qui hberge le lien, ou FALSE si le lien nexiste pas, ou si une erreur se produit (avec un message de type "warning" sous Windows).

<?php if (@linkInfo("emma.png") != -1) { echo "Le lien symbolique existe bien."; } else { echo "Le lien symbolique nexiste pas."; } ?>

557

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

Il est aussi possible dutiliser fstat() afin dobtenir la liste des informations sur un fichier. La diffrence avec la fonction stat() tant que fstat() ne prend pas en paramtre le chemin dun fichier, mais un pointeur sur ce fichier.

fstat()
Retourne les informations propos dun fichier dans un tableau. Syntaxe $fp retour array fstat(string $fp) Pointeur sur le fichier analyser tel que retourn par fopen(). Tableau la fois index et associatif contenant toutes les informations du fichier (comme le propose la fonction stat()), ou FALSE si une erreur survient.

<? function statistique($cheminFichier) { $fp = fopen("$cheminFichier","r"); $tableau = fstat($fp); while (list($key, $val) = each($tableau)) { echo "$key : $val<br>"; } fclose($fp); } statistique("fichier.txt"); ?> 0 : 834 1 : 131934 2 : 33264 3 : 1 4 : 101 5 : 102 6 : 0 7 : 23 8 : 1023545447 9 : 1023545460 10 : 1023545460 11 : 4096 12 : 8 dev : 834 ino : 131934 mode : 33264 nlink : 1 uid : 101 gid : 102 rdev : 0 size : 23 atime : 1023545447

558

Accder au systme de fichiers du serveur

mtime : 1023545460 ctime : 1023545460 blksize : 4096 blocks : 8

9. La gestion des fichiers et des rpertoires

Les diffrentes fonctions de statistiques demandent beaucoup de ressources au systme. Cest pourquoi il existe un systme de cache qui permet de conserver, pendant la dure de lexcution du programme, les diffrentes valeurs relatives un fichier. En consquence, toutes les modifications apportes au fichier aprs un appel aux fonctions de type stat() ne seront pas visibles des appels ultrieurs ces mmes fonctions. Afin de renouveler le cache, vous devez faire appel la fonction clearStatCache(). Le cache nest valide que pendant la dure de lexcution du programme ; il nest donc pas ncessaire dappeler la fonction clearStatCache() avant chaque statistique sur les fichiers.

clearStatCache()
Rinitialise le cache des fonctions de statistiques. Syntaxe void clearStatCache(void)
<?php // Initialisation des droits en 770 chmod("fichier.txt", 0770); // Lecture des droits $tableau = stat("fichier.txt"); echo $tableau["mode"]."<br />"; // modification des droits sur le fichier en 777 chmod("fichier.txt", 0777); // Lecture des droits $tableau = stat("fichier.txt"); echo $tableau["mode"]."<br />"; // Rinitialisation du cache clearstatcache(); // Lecture des droits $tableau = stat("fichier.txt"); echo $tableau["mode"]."<br />"; ?> 33272 33272 33279

Nous pouvons observer, dans lexemple prcdent, que la modification des droits nentrane pas de modification dans laffichage des statistiques du fichier. Ce qui dmontre la ncessit de lappel la fonction clearStatCache(). Le cache est vid, et un nouvel appel la fonction stat() affiche les droits corrects du fichier.

559

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

Comme nous lavons annonc prcdemment, les fonctions de statistiques entranent une charge plus importante pour le systme. Ceci est dautant plus vrai lorsque vous utilisez les fonctions stat(), fstat() et lstat() qui retournent beaucoup dinformations. Certaines fonctions, plus lgres, peuvent les remplacer facilement si vous dsirez seulement rcuprer certaines informations sur le fichier. Pour rcuprer les permissions sur un fichier, il est plus judicieux dutiliser la fonction
filePerms() du langage PHP.

lePerms()
Retourne les permissions du fichier. Syntaxe $nomFichier retour int filePerms(string $nomFichier) Chemin du fichier. Droits daccs sur le fichier (sous forme dcimale) ou FALSE en cas derreur.

<?php $droits = fileperms("fichier.txt"); // Conversion en octale $octalPerm = decoct($droits); // Rcupration des 3 derniers caractres $normPerm = substr($octalPerm,-3); echo $normPerm; ?>

Nous pouvons amliorer notre gestionnaire de programmes pour quil affiche les droits des fichiers sous une forme classique pour un utilisateur Unixien.

Listing 9.28 : gestionnaire_fichiers_05_inc.php (extrait)


<?php function uPerm($perm) { switch ($perm) { case 0: $retPerm = break; case 1: $retPerm = break; case 2: $retPerm = break; case 3: $retPerm =

"---";

"--x";

"-w-";

"-wx";

560

Accder au systme de fichiers du serveur

break; case 4: $retPerm break; case 5: $retPerm break; case 6: $retPerm break; case 7: $retPerm break; } return $retPerm; }

= "r--";

9. La gestion des fichiers et des rpertoires

= "r-x";

= "rw-";

= "rwx";

function affichePermission($fichier) { // Rcupre le mode du fichier et conversion en octal $mode = fileperms($fichier); // Dtermine le type du fichier if(($mode & 0x1000) === 0x1000) $type = "p"; // Port elseif(($mode & 0x2000) === 0x2000) $type = "c"; // Matriel elseif(($mode & 0x4000) === 0x4000) $type = "d"; // Rpertoire elseif(($mode & 0x6000) === 0x6000) $type = "b"; // Matriel FIFO elseif(($mode & 0x8000) === 0x8000) $type = "-"; // Fichier normal elseif(($mode & 0xa000) === 0xa000) $type = "l"; // Lien symbolique elseif(($mode & 0xc000) === 0xc000) $type = "s"; // Socket else $type = "u"; // Unknown $mode = decoct($mode); $perTemp = substr($mode,-3); $permission["utilisateur"] = uPerm(substr($perTemp,0,1)); $permission["groupe"] = uPerm(substr($perTemp,1,1)); $permission["tous"] = uPerm(substr($perTemp,2,1)); return $type.$permission["utilisateur"]. $permission["groupe"].$permission["tous"]; } ?>

561

Chapitre 9

La gestion des fichiers et des rpertoires

Lexcution de ce programme affiche donc une rponse de la forme drwxrwxrwx.

9. La gestion des fichiers et des rpertoires

Figure 9.11 : Gestionnaire de programmes (version 5)

Informations sur le disque


Nous allons prsent complter ce petit gestionnaire de fichiers en affichant lespace disque disponible : lespace disque total. disk_free_space(), ou son alias diskfreespace(), retourne la place restante sur le serveur ; linstruction disk_total_space() renvoie la capacit totale du disque.

disk_free_space()
Retourne lespace disponible sur le disque contenant un rpertoire donn. Syntaxe $repertoire retour float disk_free_space(string $repertoire) Chemin du dossier o lespace est analyser. Espace disponible en octets, ou FALSE en cas derreur.

<?php // Espace disponible dans le rpertoire courant. echo disk_free_space("./"); echo "<br />"; // Espace disponible la racine. echo disk_free_space("/"); ?>

562

Accder au systme de fichiers du serveur

disk_total_space()
Retourne lespace total du disque contenant un rpertoire donn. Syntaxe $repertoire retour float disk_total_space(string $repertoire) Chemin du dossier o lespace est analyser. Espace total en octets, ou FALSE en cas derreur.

9. La gestion des fichiers et des rpertoires

<?php // Espace disque total dans le repertoire courant. echo disk_total_space("./"); echo "<br />"; // Espace disque total la racine. echo disk_total_space("/"); ?>

Il est prsent possible dajouter une fonction utilisateur notre gestionnaire de fichiers. Celle-ci va nous permettre dafficher lespace restant ainsi que lespace total dans le rpertoire courant.

Listing 9.29 : gestionnaire_fichier_06.php (extrait)


function espaceDisque($repCourant) { $Mo = pow(2, 20); // Retourne une chane de caractres indiquant // lespace disque disponible sur lespace disque // total. $chDisque = round(disk_free_space($repCourant)/$Mo, 1)."Mo"; $chDisque .= "&nbsp;/&nbsp;"; $chDisque .= round(disk_total_space($repCourant)/$Mo, 1)."Mo"; return $chDisque; } Figure 9.12 : Gestionnaire de fichiers (version 6)

563

Chapitre 9

La gestion des fichiers et des rpertoires

Exemple dapplication
9. La gestion des fichiers et des rpertoires
prsent, nous pouvons modifier notre gestionnaire de fichiers de faon permettre aux utilisateurs daccder la copie de fichiers, ainsi quaux autres fonctions : cration de liens, de liens symboliques, de rpertoires, suppression et dplacement de fichiers. Nous allons maintenant ajouter des boutons radio afin de permettre la slection dun des fichiers et dune srie de champs texte, ainsi que des boutons destins slectionner une opration effectuer en prcisant ventuellement un nom. Ce qui nous donne le script complet final suivant :

Listing 9.30 : gestionnaire_fichiers_07_inc.php


<?php // La fonction dexploration // $chemin : Rpertoire explorer // $recursif : TRUE si lexploration doit tre rcursive // $filtre : Expression rgulire de filtrage des fichiers function explorer($chemin, $recursif=FALSE, $filtre=NULL) { $listeFichier = array(); $repertoire = openDir($chemin); while ($fichier = readDir($repertoire)) { // Inutile de tenir compte des entres . et .. if (($fichier != ".")&&($fichier != "..")) { // Est-ce que $file est un rpertoire ? // Pour le savoir il suffit dappeler is_dir // mais attention noublions pas dajouter // le chemin au nom du fichier if (is_dir($chemin."/".$fichier)&&($recursif)) { // oui ? alors explorons-le // et ajoutons le rsultat la liste de fichiers $listeFichier = array_merge($listeFichier, explorer($chemin."/".$fichier, $recursif, $filtre)); } else { // sinon, cest un fichier et sil rpond // aux critres de lexpression rgulire // on lajoute a la liste des fichiers if (is_null($filtre)||eregi($filtre, $fichier)) { $listeFichier[] = $chemin."/".$fichier; } } } } // Cest fini. On ferme ! closeDir($repertoire); // et on retourne le rsultat tri sort($listeFichier); return $listeFichier; }

564

Accder au systme de fichiers du serveur

// Retourne la taille du fichier function tailleFichier($fichier) { // calculs des taux de conversion entre Ko, Mo et octet $Ko = pow(2, 10); $Mo = pow(2, 20); // recupre la taille du fichier en octets $taille = fileSize($fichier); // Pas de conversion if ($taille<$Ko){ $tailleDef = $taille; // Conversion en Ko } elseif ($taille>=$Ko && $taille<$Mo){ $tailleDef = round($taille/$Ko, 1)."k"; // Conversion en Mo } else { $tailleDef = round($taille/$Mo, 1)."M"; } return $tailleDef; } // Retourne le groupe et lutilisateur // propritaires du fichier function proprietaire($fichier) { // recupre lUID du fichier $uid = fileowner($fichier); // Recupre les informations sur lUID $tabUtilisateur = posix_getpwuid($uid); // recupre le GID du fichier $gid = filegroup($fichier); // Recupre les informations sur lGID $tabGroup = posix_getgrgid($gid); // Renvoie les noms du groupe et de lutilisateur return array( "utilisateur"=>$tabUtilisateur["name"], "groupe"=>$tabGroup["name"] ); } // Retourne la date de la dernire modification du fichier function modificationFichier($fichier) { // Rcupration de la dernire modification du fichier $modification = filemtime($fichier); // Retourne la date de modification formate

565

9. La gestion des fichiers et des rpertoires

Chapitre 9

La gestion des fichiers et des rpertoires

return strftime("%b %d %H:%M", $modification)."\n"; }

9. La gestion des fichiers et des rpertoires

// Retourne les permissions sous la forme "rwx" function uPerm($perm) { switch ($perm) { case 0: $retPerm = "---"; break; case 1: $retPerm = "--x"; break; case 2: $retPerm = "-w-"; break; case 3: $retPerm = "-wx"; break; case 4: $retPerm = "r--"; break; case 5: $retPerm = "r-x"; break; case 6: $retPerm = "rw-"; break; case 7: $retPerm = "rwx"; break; } return $retPerm; } // Retourne les permissions du fichier function affichePermission($fichier) { // Rcupre le mode du fichier et conversion en octal $mode = fileperms($fichier); // Dtermine le type du fichier if(($mode & 0x1000) === 0x1000) $type = "p"; // Port elseif(($mode & 0x2000) === 0x2000) $type = "c"; // Matriel elseif(($mode & 0x4000) === 0x4000) $type = "d"; // Rpertoire elseif(($mode & 0x6000) === 0x6000) $type = "b"; // Matriel FIFO elseif(($mode & 0x8000) === 0x8000)

566

Accder au systme de fichiers du serveur

$type = "-"; // Fichier normal elseif(($mode & 0xa000) === 0xA000) $type = "l"; // Lien symbolique elseif(($mode & 0xc000) === 0xC000) $type = "s"; // socket else $type = "u"; // Unknown $mode = decoct($mode); $perTemp = substr($mode,-3); $permission["utilisateur"] = uPerm(substr($perTemp,0,1)); $permission["groupe"] = uPerm(substr($perTemp,1,1)); $permission["tous"] = uPerm(substr($perTemp,2,1)); return $type.$permission["utilisateur"]. $permission["groupe"].$permission["tous"]; } // Retourne lespace disque libre et total function espaceDisque($repCourant) { $Mo = pow(2, 20); // Retourne une chaine de caractres indiquant lespace disque // disponible sur lespace disque total. $chDisque = round(disk_free_space($repCourant)/$Mo, 1)."Mo"; $chDisque .= "&nbsp;/&nbsp;"; $chDisque .= round(disk_total_space($repCourant)/$Mo, 1)."Mo"; return $chDisque; } // Liste et affiche le contenu du rpertoire courant function listRepertoire() { // Rcupration du chemin courant $repCourant = getcwd(); $fichiers = explorer("."); // Nous ajouterons ".." (qui a t filtr par la fonction) if ($repCourant != "/") $fichiers = array_merge(array("./.."), $fichiers); ?> <table border="1" width="100%"> <tr> <td><font color="#cc0000"> <?php echo $repCourant; ?> </font></td> <td> <?php echo espaceDisque($repCourant);?> </td> </tr>

567

9. La gestion des fichiers et des rpertoires

Chapitre 9

La gestion des fichiers et des rpertoires

</table> <table border="0" width="100%"> <form name=fliste> <?php // Formulaire de selection de fichier ?> <?php for ($i=0; $i<count($fichiers); $i++) { ?> <tr> <td> <input type="radio" name="selection" value="<?php echo $fichiers[$i];?>"> </td> <td> <?php echo affichePermission($fichiers[$i]);?> </td> <td> <?php $tabProprietaire = proprietaire($fichiers[$i]); echo $tabProprietaire["utilisateur"]."&nbsp;"; echo $tabProprietaire["groupe"]; ?> </td> <td> <?php echo tailleFichier($fichiers[$i]);?> </td> <td> <?php echo modificationFichier($fichiers[$i]);?> </td> <td> <?php /* Le fichier est-il un rpertoire ? */ if (is_dir($fichiers[$i])) { /* Le fichier est un rpertoire On affiche alors un lien qui va nous permettre de visualiser le contenu de ce dossier */ ?> <a href="?repertoire=<?php echo $repCourant."/".$fichiers[$i];?>"> <?php echo basename($fichiers[$i]);?> </a> <?php }else{ /* Le fichier nest pas un rpertoire On affiche simplement le nom du fichier */ echo basename($fichiers[$i]); } ?> </td>

9. La gestion des fichiers et des rpertoires 568

Accder au systme de fichiers du serveur

</tr> <?php } ?> </form> </table> <?php /* Affichage des diffrents formulaires HTML nous permettant de manipuler les fichiers et rpertoires. */ ?> <table border=0 width=100%> <?php /* Copie de fichier */?> <tr> <form method=post action=gestionnairefichier.php name=fcopie> <td> <b>Copie dun fichier</b>&nbsp;&nbsp; <input type=hidden name=repertoire value=<?php echo $repCourant;?>> <input type=hidden name=idFichier> nom du nouveau fichier <input type=text name=nomCopy> <input type=hidden value=copy name=operation> <input type=button value= Copier onclick= for (var i = 0; i < document.fliste.selection.length; i++) { if (document.fliste.selection[i].checked) { document.fcopie.idFichier.value = document.fliste.selection[i].value; break; } } document.fcopie.submit(); > </td> </form> </tr> <?php /* Cration dun lien */?> <tr> <form method=post action=gestionnairefichier.php name=flien> <td> <b>Cration dun lien sur un fichier</b>&nbsp;&nbsp; <input type=hidden name=repertoire value=<?php echo $repCourant; ?>> <input type=hidden name=idFichier> nom du lien <input type=text name=nomLien> <input type=hidden value=link name=operation> <input type=button value= Crer onclick= for (var i = 0; i < document.fliste.selection.length; i++) { if (document.fliste.selection[i].checked) {

569

9. La gestion des fichiers et des rpertoires

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

document.flien.idFichier.value = document.fliste.selection[i].value; break; } } document.flien.submit(); > </td> </form> </tr> <?php /* Cration dun lien symbolique */?> <tr> <form method=post name=flienSymb> <td> <b>Cration dun lien symbolique sur un fichier</b>&nbsp;&nbsp; <input type=hidden name=repertoire value=<?php echo $repCourant;?>> <input type=hidden name=idFichier> nom du lien symbolique <input type=text name=nomLienSymbolique> <input type=hidden value=symlink name=operation> <input type=button value= Crer onclick= for (var i = 0; i < document.fliste.selection.length; i++) { if (document.fliste.selection[i].checked) { document.flienSymb.idFichier.value = document.fliste.selection[i].value; break; } } document.flienSymb.submit(); > </td> </form> </tr> <?php /* Renommer un fichier */?> <tr> <form method=post name=frenom> <td> <b>Renommer un fichier</b>&nbsp;&nbsp; <input type=hidden name=repertoire value=<?php echo $repCourant;?>> <input type=hidden name=idFichier> nouveau nom du fichier <input type=text name=nomFichier> <input type=hidden value=rename name=operation> <input type=button value= Renommer onclick= for (var i = 0; i < document.fliste.selection.length; i++) { if (document.fliste.selection[i].checked) { document.frenom.idFichier.value = document.fliste.selection[i].value;

570

Accder au systme de fichiers du serveur

break; } } document.frenom.submit(); > </td> </form> </tr> <?php /* Crer un dossier */?> <tr> <form method=post name=fdossier> <td> <b>Crer un dossier</b>&nbsp;&nbsp; <input type=hidden name=repertoire value=<?php echo $repCourant;?>> nom du dossier <input type=text name=nomDossier> <input type=hidden value=mkdir name=operation> <input type=button value= Crer onclick=document.fdossier.submit();> </td> </form> </tr> <?php /* Suppression dun fichier */?> <tr><form method=post name=fsupprim> <td> <b>Supprimer un fichier</b>&nbsp;&nbsp; <input type=hidden name=repertoire value=<?php echo $repCourant;?>> <input type=hidden name=idFichier> <input type=hidden value=unlink name=operation> <input type=button value= Supprimer onclick= for (var i = 0; i < document.fliste.selection.length; i++) { if (document.fliste.selection[i].checked) { document.fsupprim.idFichier.value = document.fliste.selection[i].value; break; } } document.fsupprim.submit(); > </td> </form></tr> </table> <?php } ?>

571

9. La gestion des fichiers et des rpertoires

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

Quant au script principal, il ne devra plus se contenter de permettre la navigation dans les rpertoires, mais il devra galement prendre en charge les diffrentes actions proposes (suppression, renommage, cration de fichiers et de rpertoires).

Listing 9.31 : gestionnaire_fichier_07.php


<?php include ("gestionnaire_fichier_07_inc.php"); switch ($_POST["operation"]) { // Copie de fichier case "copy": if (@copy($_POST["repertoire"]."/".$_POST["idFichier"], $_POST["repertoire"]."/".$_POST["nomCopy"])) { $message = "La copie du fichier a t effectue."; } else { $message = "Erreur pendant la copie du fichier.<br>"; } break; // Cration dun lien case "link": if (@link($_POST["repertoire"]."/".$_POST["idFichier"], $_POST["repertoire"]."/".$_POST["nomLien"])) { $message = "La cration du lien a t effectue."; } else { $message = "Erreur pendant la cration du lien."; } break; // Supprimer un fichier case "unlink": if (is_dir($_POST["repertoire"]."/".$_POST["idFichier"])) { if (@rmdir($_POST["repertoire"]."/".$_POST["idFichier"])) { $message = "Le dossier a t supprim."; } else { echo $_POST["repertoire"]."/".$_POST["idFichier"]; $message = "Erreur, vrifiez que le dossier est vide". " avant de le supprimer."; } }else{ if (@unlink($_POST["repertoire"]."/".$_POST["idFichier"])) { $message = "Le fichier a t supprim."; } else { $message = "Erreur pendant la suppression du fichier."; }

572

Accder au systme de fichiers du serveur

} break;

9. La gestion des fichiers et des rpertoires

// Cration dun lien symbolique case "symlink": if (@symlink($_POST["repertoire"]."/".$_POST["idFichier"], $_POST["repertoire"]."/".$_POST["nomLienSymbolique"])) { $message = "Le fichier a t supprim."; } else { $message = "Erreur pendant la suppression du fichier."; } break; // Renommer un fichier case "rename": if (@rename($_POST["repertoire"]."/".$_POST["idFichier"], $_POST["repertoire"]."/".$_POST["nomFichier"])) { $message = "Le fichier a t renomm."; } else { $message = "Erreur, impossible de renommer le fichier."; } break; // Cration dun repertoire case "mkdir": umask(000); if (@mkdir($_POST["repertoire"]."/".$_POST["nomDossier"], 0760)) { $message = "Le repertoire a t cr."; } else { $message = "Erreur, impossible de crer le dossier."; } break; } // Vrifie si "repertoire" est pass en paramtre if ($_GET["repertoire"]) { if (!@chdir($_GET["repertoire"])) { $message = "Le changement de rpertoire a chou."; } } /* Dans le cas ou les donnes sont envoyes par une mthode GET */ if($_GET["repertoire"]) { if(!@chdir($_GET["repertoire"])) { $message = "Le changement de rpertoire a chou.";

573

Chapitre 9

La gestion des fichiers et des rpertoires

} } /* Dans le cas ou les donnes sont envoyes par une mthode POST */ elseif ($_POST["repertoire"]) { if(!@chdir($_POST["repertoire"])) { $message = "Le changement de rpertoire a chou."; } } listRepertoire(); ?>

9. La gestion des fichiers et des rpertoires

Figure 9.13 : Le gestionnaire de fichiers

Lecture sur un "pipe"


PHP offre la possibilit de lancer un processus depuis un script et de communiquer avec lui sur un canal de communication que lon appelle alors pipe (tuyau). Pour cela, il faut utiliser linstruction popen().

popen()
Lance un processus et ouvre un pipe de communication. Syntaxe resource popen(string $commande, string $mode)

574

Accder au systme de fichiers du serveur

$commande $mode retour

Commande excuter. Dfinit le mode douverture. Contrairement fopen(), ici le mode ne peut tre quen lecture seule r ou en criture seule w. Pointeur sur le processus cr, ou FALSE sil y a une erreur.

9. La gestion des fichiers et des rpertoires

<?php $pp = popen("more fichier.txt", "r"); ?>

Il nest pas possible de fermer le processus laide de linstruction fclose(). Le langage PHP met la disposition des dveloppeurs la fonction pclose() qui ferme et libre le processus cr par popen().

pclose()
Termine un processus et ferme le pipe associ. Syntaxe $pp retour boolean pclose(resource $pp) Pointeur du pipe tel que retourn par la fonction popen(). TRUE en cas de succs, FALSE sinon.

Voici un exemple (dans la srie "pourquoi faire simple quand on peut faire compliqu".) utilisant la commande more pour lire le contenu dun fichier.
<?php $pp = popen("more fichier.txt", "r"); while ($chaine = fgets($pp, 255)) { echo $chaine; } pclose($pp); ?>

Ce qui, dans notre cas, retourne (tout btement) :


:::::::::::::: fichier.txt :::::::::::::: voici le texte que jai placer dans fichier.txt Bon, a ne fait pas avancer le schmilblik

Compression
PHP propose diffrentes bibliothques lies la compression, mais la bibliothque Zlib est la seule fonctionner parfaitement (contrairement bzip2), comme elle est la seule permettre la fois la compression et la dcompression (contrairement zip).

575

Chapitre 9

La gestion des fichiers et des rpertoires

Compression Zlib
9. La gestion des fichiers et des rpertoires
Zlib est la bibliothque la base de Gzip (GNUZip), qui est lui-mme lutilitaire de compression le plus utilis sous UNIX. Toutes les distributions Linux fournissent cet utilitaire, ce qui est bien normal lorsquon sait quil est dvelopp par le Projet GNU de la Free Software Foundation (http://www.gnu.org). Rien dtonnant donc trouver, dans PHP, diverses commandes permettant dexploiter la librairie Zlib.

En ligne de commande, la compression est effectue avec la commande gzip nomArchive. Le fichier est alors remplac par un nouveau fichier possdant lextension .gz. Attention, car Gzip ne peut en aucun cas compresser plusieurs fichiers la fois. Si vous dsirez compresser une srie de fichiers, vous devez au pralable les archiver (avec la commande tar par exemple). La dcompression seffectue avec la commande gzip d nomArchive.gz. Si le fichier nest pas un fichier compress au format Gzip, alors la dcompression chouera et renverra une alerte. Le langage PHP sest donc interfac avec la bibliothque Zlib, ce qui permet deffectuer diverses oprations courantes de compression et de dcompression. Pour information, la Zlib utilise, entre autres, lalgorithme de Huffman pour compresser les donnes. Le principe de cet algorithme est de modifier lencodage des caractres en analysant la frquence de rptition de ces caractres. Lalgorithme les classe du plus au moins frquent. Lunit de traitement tant ramene au bit, chaque caractre possde alors un nouvel encodage sur un nombre de bits variable. Ainsi, le caractre le plus utilis possde une valeur sur un petit nombre de bits et le caractre le moins utilis est encod sur un nombre de bits plus grand. Une fois encode, une donne rptitive occupe moins de place que loriginal (il y a bien compression) tandis quune donne rare occupe plus de place (qui doit tre largement compense par la compression). Le tableau suivant permet de mieux comprendre ce principe. Imaginez un texte (autre que la Disparition de Georges Perec qui ne contient pas de "e") qui possderait 15 fois la lettre "w", 260 fois la lettre "e" et 510 fois la lettre "a". Habituellement, un caractre est cod sur 8 bits. Nous pouvons imaginer quavec la compression Zlib, le caractre "w" (peu reprsent) occupe 12 bits, le caractre "e" (bien reprsent) 6 bits et, enfin, le caractre "a" (trs prsent) 2 bits. Dans ce cas le texte ne fera pas (15+260+510)*8 = 6280 mais 15*12+260*6+510*2=2760, ce qui constitue bien une compression du texte. Cette technique dencodage est la base des compressions Jpeg, Tiff et aussi, donc, de la compression Zlib.

Installation
Sous Windows
Depuis PHP 4.3.0 vous navez rien faire pour disposer de ces fonctions. Si toutefois vous souhaitez utiliser une version antrieure alors vrifiez que vous avez activ lextension php_zlib.dll.

Sous Linux
Pour installer le module Zlib, vous devez, dans un premier temps, rcuprer les sources de la bibliothque disponible sur le site (en anglais) http://www.gzip.org/zlib/ (ou sur le CD-ROM fourni). Vous pouvez alors copier larchive dans un rpertoire quelconque (/usr/local/lib, par exemple) et commencer sa dcompression.

576

Accder au systme de fichiers du serveur

# gunzip zlib-1.1.4.tar.gz # tar xvf zlib-1.1.4.tar

9. La gestion des fichiers et des rpertoires

Vous utiliserez la mthode classique de compilation et dinstallation,


# # # # cd zlib-1.1.4 ./configure make make install

ce qui aura pour effet dajouter un fichier libz.a dans le rpertoire /usr/local/lib.

Distributions Linux Comme vous laurez remarqu, la procdure dinstallation dcrite ici fait elle-mme appel Gzip. Ceci ne devrait pas constituer un problme, puisque Gzip est gnralement install avec Linux. Sachez toutefois que larchive Gzip est disponible sous dautres formats de compression. De mme, il nest pas forcment ncessaire de recompiler cette bibliothque comme indiqu prcdemment, puisque les distributions Linux incluent gnralement des "paquetages" de Gzip pour le dveloppement (y sont inclus les en-ttes et la bibliothque compile). Ainsi, sous Mandrake 8.1 (par exemple), la procdure dinstallation peut tre remplace par :
# rpm -U zlib1-1.1.3-16.1mdk.i586.rpm # rpm -U zlib1-devel-1.1.3-16.1mdk.i586.rpm

Quoi quil en soit, vous devez ncessairement tre quip dune version suprieure ou gale 1.0.9.
Vous devez alors recompiler PHP avec loption --with-zlib=/usr/local.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur la compilation de PHP.

Vrication
Vrifiez que le module Zlib est bien install en appelant une page contenant <?php phpinfo(); ?>.

577

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

Figure 9.14 : Le phpinfo vous informe de linstallation du module zip.

Ouvrir et fermer un chier Gzip


Le module Zlib fonctionne peu prs comme les fonctions du systme de fichiers. Vous allez retrouver la plupart de ces fonctions. De plus, depuis la version 4.0.4 de PHP, il est possible douvrir un fichier compress au format gzip depuis un appel classique fopen(). Il suffit de faire prcder le chemin du fichier ouvrir par "compress.zlib://" (zlib: pour PHP<4.3.0), comme le montre lexemple ci-dessous.
<?php $fp = fopen("compress.zlib://monFichier.txt.gz","r"); fclose($fp); ?>

Louverture dun fichier compress avec Gzip se fait laide de linstruction gzopen(). Comme pour la fonction fopen(), le dveloppeur doit indiquer le mode douverture (criture seule, lecture seule ou lecture/criture), et peut galement prciser un niveau de compression ainsi quune stratgie de compression.

Rendez-vous au dbut de ce chapitre, la description de la fonction fopen(), pour connatre les diffrents modes possibles et leurs particularits.

gzopen()
Ouverture dun fichier compress au format gzip. Syntaxe $nomFichier $mode resource gzopen(string $nomFichier, string $mode [, boolean $cheminInclude]) Chemin du fichier. Dfinit le mode douverture du fichier : "r" pour la lecture seule. "r+" pour une lecture et une criture. "w" pour une criture avec crasement des donnes. "w+" pour un mode en lecture et criture avec crasement des donnes. "a" pour louverture en ajout de donnes. "a+" pour louverture du fichier en mode lecture et criture par ajout.

578

Accder au systme de fichiers du serveur

Vous pouvez ajouter le niveau de compression entre "0"(aucune compression) et "9"(compression maximale) ; par dfaut le niveau est de "6". Vous pouvez spcifier une stratgie : "f" pour des donnes filtres. "h" pour lutilisation de lalgorithme de Huffman uniquement. $cheminInclude retour TRUE si le fichier doit tre recherch dans les rpertoires prciss par include_path, FALSE (valeur par dfaut) sinon. Pointeur sur le fichier, ou FALSE en cas derreur.

9. La gestion des fichiers et des rpertoires

Ainsi le mode "a+b6h" dsigne une ouverture en lecture et criture par ajout dun fichier binaire avec un niveau de compression de 6 et lutilisation exclusive de lalgorithme de Huffman. De mme, le mode "wb9f" indique une ouverture en mode criture dun fichier binaire dun niveau de compression de 9 avec une stratgie filtre. La fermeture du fichier est effectue laide de la fonction gzclose().

gzclose()
Ferme un fichier pralablement ouvert avec linstruction gzopen(). Syntaxe $gzFichier retour boolean gzclose(resource $gzFichier) Pointeur vers le fichier tel que retourn par la fonction gzopen(). TRUE si le fichier a t ferm, FALSE dans le contraire.

<?php $gzFichier = gzopen("monfichier.txt.gz","w"); // Traitement gzclose($gzFichier); ?>

Le petit programme ci-dessous est quivalent lexemple prcdent :


<?php $gzFichier = fopen("zlib:monfichier.txt.gz","w"); // Traitement fclose($gzFichier); ?>

Ouverture des fichiers non compresss La fonction gzopen() peut galement ouvrir des fichiers non compresss. Dans ce cas, les lecture et criture se feront sans compression ni dcompression.

579

Chapitre 9

La gestion des fichiers et des rpertoires

crire dans un chier


9. La gestion des fichiers et des rpertoires
Linstruction gzwrite() permet dcrire une chane de caractres dans un fichier ouvert pralablement laide de linstruction gzopen(). Lappel gzwrite() crit donc une chane la position courante du pointeur.

gzwrite()
criture dune chane de caractres dans un fichier. Syntaxe $gzFichier $chaine $longueur retour int gzwrite(resource $gzFichier, string $chaine [, int $longueur]) Pointeur vers le fichier ouvert avec linstruction gzopen(). Chane de caractres crire dans le fichier. Paramtre optionnel indiquant combien de caractres doivent tre crits. Sil est omis, la chane complte est crite dans le fichier. Nombre de caractres qui ont t crits dans le fichier. En cas derreur, linstruction retourne FALSE.

Tout comme linstruction fwrite(), la fonction gzwrite() possde un alias appel gzputs().

Listing 9.32 : gzwrite.php


<?php $maChaine = "\"Je suis un phnomne, je suis un magicien\n". "Un tuyau parcouru dinformations majeures\n". "Mais ya pas que des douceurs qui passent lintrieur\"\n". "Noir Dsir, Son style\n"; $gzFichier = gzopen("monfichier.txt.gz","w"); gzwrite($gzFichier, $maChaine); gzclose($gzFichier); ?>

Vous pouvez observer quun nouveau fichier a fait son apparition dans le rpertoire courant. Dzippez-le avec la commande gzip d monfichier.txt.gz et observez que votre texte sy trouve bel et bien (ou affichez directement son contenu avec zcat monfichier.txt.gz). Vous pouvez utiliser WinZip ou tout autre outil de dcompression supportant le format gz disponible sous Windows.

Lire des informations dans un chier


Tout comme pour un fichier classique, la lecture des donnes contenues dans un fichier peut se faire octet par octet, bloc de N octets par bloc de N octets, ligne par ligne ou encore dun bloc. Ceci est assur par les diffrentes fonctions que sont gzread(), gzgets(), gzgetss(), gzgetc() et deux instructions particulires que sont gzfile() et readgzfile().

580

Accder au systme de fichiers du serveur

Lecture octet par octet


La fonction getc() possde son quivalence pour traiter les fichiers au format gzip. Cette instruction est gzgetc().

9. La gestion des fichiers et des rpertoires

gzgetc()
Retourne le caractre se trouvant la position courante du pointeur de lecture. Syntaxe $gzFichier retour string gzgetc(resource $gzFichier) Pointeur vers le fichier tel que retourn par gzopen(). Caractre la position courante du pointeur de lecture ; FALSE en cas derreur ou lorsque le pointeur de lecture se trouve la fin du fichier.

Lecture N octets par N octets


galement semblable la lecture dans un fichier texte ou binaire classique. La fonction gzread() permet la lecture par paquet doctets.

gzread()
Lecture des donnes dcompresses contenues dans un fichier au format gzip. La lecture seffectue par paquet doctets. Syntaxe $gzFichier $longueur string gzread(resource $gzFichier, int $longueur) Pointeur vers le fichier ouvert tel que retourn par gzopen(). Taille en octets des donnes lire. Cette taille est indique pour des donnes une fois dcompresses. La lecture se termine lorsque le fichier a t entirement lu, ou lorsque le nombre doctets spcifi a t retourn. La chane de caractres dcompresse ; FALSE en cas derreur ou lorsque le pointeur de lecture se trouve la fin du fichier.

retour

Lexemple qui suit :

Listing 9.33 : gzread.php


<?php $gzFichier = gzopen("monfichier.txt.gz","r"); // Affiche le contenu 50 caractres par 50 caractres while ($maChaine = gzread($gzFichier, 50)){ echo $maChaine."<br />"; } gzclose($gzFichier); ?>

581

Chapitre 9

La gestion des fichiers et des rpertoires

offrira donc le rsultat suivant :

9. La gestion des fichiers et des rpertoires

"Je suis un phnomne, je suis un magicien Un tuya u parcouru dinformations majeures Mais ya pas qu e des douceurs qui passent lintrieur" Noir Ds ir, Son style

Lecture ligne par ligne


Comme le montre lexemple prcdent, la fonction gzread() nest pas adapte la lecture ligne par ligne. Linstruction gzgets() permet de retourner, au contraire, une ligne entre chaque lecture.

gzgets()
Retourne une ligne dcompresse depuis le fichier au format gzip. Syntaxe $gzFichier $longueur string gzgets(resource $gzFichier, int $longueur) Pointeur sur un fichier tel que retourn par gzopen(). Taille maximale (en octets) des donnes lire. Cette taille est indique pour des donnes une fois dcompresses. La lecture se termine lorsque la fin de la ligne a t rencontre, ou lorsque le nombre doctets spcifi a t retourn. Une chane de caractres dcompresse ; FALSE en cas derreur ou lorsque le pointeur de lecture se trouve la fin du fichier.

retour

Listing 9.34 : gzgets.php


<?php $gzFichier = gzopen("monfichier.txt.gz","r"); // Affiche une ligne et un retour la ligne // entre chaque affichage while ($maChaine = gzgets($gzFichier, 255)){ echo $maChaine."<br />"; } gzclose($gzFichier); ?>

Cet exemple retournera bien le rsultat escompt, savoir :


"Je suis un phnomne, je suis un magicien Un tuyau parcouru dinformations majeures Mais ya pas que des douceurs qui passent lintrieur" Noir Dsir, Son style

582

Accder au systme de fichiers du serveur

Lecture dun bloc


Tout comme linstruction file(), vous pouvez retourner directement le fichier dcompress dans un tableau contenant chaque ligne. Pour cela nous utiliserons la fonction gzfile().

9. La gestion des fichiers et des rpertoires

gzle()
Retourne le fichier dcompress dans un tableau. Syntaxe $nomFichier $cheminInclude retour array gzfile(string $nomFichier [, boolean $cheminInclude]) Chemin du fichier. TRUE si le fichier doit tre recherch dans les rpertoires prciss dans include_path, FALSE (par dfaut) sinon. Tableau contenant chaque ligne du fichier dcompress, ou FALSE si une erreur est survenue.

Listing 9.35 : gzfile.php


<?php $gzTableau = gzfile("monfichier.txt.gz"); // Regroupe tous les lments du tableau // dans une chane de caractres $chaine = implode("<br />", $gzTableau); // Affiche la chane de caractres echo $chaine; ?>

Lexemple prcdent affiche simplement le contenu du fichier dcompress (puisque le tableau est immdiatement converti en une chane de caractres en insrant des retours la ligne entre chaque ligne). Plus simplement, le langage PHP possde la fonction readgzfile(). Cette instruction dcompresse et affiche le fichier.

readgzle()
Affiche le contenu dcompress du fichier. Syntaxe $nomFichier $cheminInclude retour int readgzfile(string $nomFichier [, boolean $cheminInclude]) Chemin du fichier. TRUE si le fichier doit tre recherch dans les rpertoires prciss dans include_path, FALSE (par dfaut) sinon. Nombre doctets dcompresss qui ont t lus, ou FALSE en cas derreur.

583

Chapitre 9

La gestion des fichiers et des rpertoires

Listing 9.36 : readgzfile.php

9. La gestion des fichiers et des rpertoires

<?php $nombreOctets = readgzfile("monfichier.txt.gz"); echo "<br />"; echo "Nombre doctets lu : ".$nombreOctets; ?> "Je suis un phnomne, je suis un magicien Un tuyau parcouru dinformations majeures Mais ya pas que des douceurs qui passent lintrieur" Noir Dsir, Son style Nombre doctets lu : 163

Dans ce cas, parce que HTML ninterprte pas les retours chariots \n tout le texte apparatra sur une ligne unique (dans la limite de la taille de la fentre). Lorsque le fichier a dj t ouvert, il est possible dafficher le reste dun fichier depuis la position courante du pointeur de lecture. Linstruction gzpassthru() est la version pour les fichiers compresss au format gzip, de linstruction fpassthru().

gzpassthru()
Retourne sur lcran le contenu du fichier depuis la position courante du pointeur de lecture. Syntaxe $gzFichier retour int gzpassthru(resource $gzFichier) Pointeur du fichier tel que retourn par gzopen(). Nombre doctets dcompresss qui ont t affichs, ou FALSE en cas derreur.

Listing 9.37 : gzpassthru.php


<?php $gzFichier = gzopen("monfichier.txt.gz","r"); // Affiche les 30 premiers caractres et un retour la ligne. echo gzread($gzFichier, 30); echo "<br /><br />"; // Affiche le reste du fichier dcompress sur lcran. $nbOctets = gzpassthru($gzFichier); echo "<br />"; echo "Nombre doctets affichs par gzpassthru() : ".$nbOctets; ?> "Je suis un phnomne, je suis un magicien Un tuyau parcouru dinformations majeures Mais ya pas que des douceurs qui passent lintrieur" Noir Dsir, Son style Nombre doctets affich par gzpassthru() : 133

584

Accder au systme de fichiers du serveur

Remarquez quil est inutile de fermer le fichier par linstruction gzclose(). En effet, comme pour la fonction fpassthru(), le fichier est automatiquement ferm.

9. La gestion des fichiers et des rpertoires

Lecture et ltrage HTML


Vous pouvez galement filtrer les fichiers HTML compresss. Pour ce faire, vous utiliserez linstruction gzgetss(). Cette fonction retourne le fichier ligne par ligne en enlevant les balises HTML, lexception de celles que vous aurez spcifies.

gzgetss()
Retourne une ligne dun fichier compress sans les balises HTML (sauf celles que lon souhaite conserver). Syntaxe $gzFichier $longueur string gzgetss(resource $gzFichier, int $longueur [, string $tagsAutorise]) Pointeur du fichier tel que retourn par gzopen(). Taille maximale (en octets) des donnes lire. Cette taille est indique pour des donnes une fois dcompresses. La lecture se termine lorsque le fichier a t entirement lu ou lorsque le nombre doctets spcifi a t retourn. Les balises qui ne doivent pas tre supprimes. Vous pouvez spcifier plusieurs tags en les sparant par le caractre "|". Ex. : "<br>|<b>|<center>". Chane contenant les donnes lues de la ligne courante sans les balises HTML ; FALSE en cas derreur ou si le pointeur se trouve la fin du fichier.

$tagsAutorise

retour

<?php $fp = gzopen("monFichier.html.gz","r"); while ($ligne = gzgetss($fp, 255, "<br>|<center>")) { echo $ligne; } gzclose($fp); ?>

Lexemple ci-dessus affiche le fichier HTML dcompress en enlevant toutes les balises sauf celles qui correspondent <br> et <center>.

Positionner le pointeur de lecture/criture


Tout comme pour la lecture et lcriture des donnes dans un fichier non compress, vous pouvez dplacer le pointeur de lecture/criture. Ce pointeur est positionn par rapport au fichier dcompress. Les quatre fonctions feof(), ftell(), fseek() ou rewind() ont donc leurs quivalents pour les fichiers au format gzip. Ces fonctions sont gzeof(), gztell(), gzseek(), gzrewind().

585

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

gzeof()
Teste la fin du fichier dcompress. Syntaxe $gzFichier retour boolean gzeof(resource $gzFichier) Pointeur du fichier tel que retourn par gzopen(). TRUE si le pointeur est la fin du fichier, ou FALSE dans le cas contraire.

Listing 9.38 : gzeof.php


<?php // Ouverture du fichier $gzFichier = gzopen("monfichier.txt.gz","r"); // Initialise la variable $i "0" $i = 0; // Lit le fichier octet par octet jusqu // la fin du fichier while (!gzeof($gzFichier)) { // Lit un caractre et dplace le pointeur // de lecture dun octet gzgetc($gzFichier); // Indente la variable $i $i++; } echo "Le fichier possde ".($i-1)." octets."; gzclose($gzFichier); ?>

retournera :
Le fichier possde 162 octets.

Cet exemple montre comment fonctionne la fonction gzeof() et na dautre valeur que pdagogique. La technique pour dplacer le pointeur de lecture/criture nest pas efficace. gzgetc()est utiliser uniquement pour lire un octet. Pour dplacer un pointeur, utilisez linstruction gzseek() dcrite plus loin. Pour connatre la position courante du pointeur de lecture/criture dans un fichier, vous pouvez utiliser linstruction gztell().

gztell()
Retourne la position dun pointeur de lecture dans le fichier dcompress. Syntaxe int gztell(resource $gzFichier)

586

Accder au systme de fichiers du serveur

$gzFichier retour

Pointeur du fichier tel que retourn par gzopen(). Position courante du pointeur de lecture, et FALSE si une erreur survient.

9. La gestion des fichiers et des rpertoires

Le dplacement du pointeur de lecture/criture est effectu avec linstruction gzseek(). Cette fonction fixe la position du pointeur par rapport au dbut du fichier. Notez que, contrairement linstruction fseek(), vous navez pas la possibilit de fixer une origine pour le dplacement.

gzseek()
Fixe une nouvelle position au pointeur de lecture/criture par rapport au dbut du fichier. Syntaxe $gzFichier $nbOctets int gzseek(resource $gzFichier, int $nbOctets) Pointeur du fichier tel que retourn par gzopen(). Nombre doctets dont le pointeur doit tre dplac par rapport au dbut du fichier. Notez que si vous dplacez le pointeur aprs la fin du fichier, cela ne renvoie pas derreur. Nouvelle position du pointeur, ou 1 en cas derreur.

retour

Linstruction gzrewind() permet de repositionner le pointeur de lecture/criture au dbut du fichier.

gzrewind()
Repositionne le pointeur au dbut du fichier. Syntaxe $gzFichier retour boolean gzrewind (resource $gzFichier) Pointeur du fichier tel que retourn par gzopen(). TRUE si le pointeur a bien t positionn au dbut du fichier, FALSE dans le cas contraire.

Listing 9.39 : gztell.php


<?php // Ouverture du fichier $gzFichier = gzopen("monfichier.txt.gz","r+"); // Dplace le pointeur de 8 caractres. gzseek($gzFichier, 8); // Affiche la position du pointeur. echo "Nouvelle position du pointeur de lecture/criture : "; echo gztell($gzFichier); echo "<br />";

587

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

// Dplace le pointeur de 50 caractres. gzseek($gzFichier, 50); // Affiche la position du pointeur. echo "Nouvelle position du pointeur de lecture/criture : "; echo gztell($gzFichier); echo "<br />"; // Rinitialise le pointeur au dbut du fichier. gzrewind($gzFichier); // Affiche la position du pointeur. echo "Nouvelle position du pointeur de lecture/criture : "; echo gztell($gzFichier); echo "<br />"; gzclose($gzFichier); ?>

ce qui affichera :
Nouvelle position du pointeur de lecture/criture : 8 Nouvelle position du pointeur de lecture/criture : 50 Nouvelle position du pointeur de lecture/criture : 0

Compression et dcompression dune chane de caractres


Le module Zlib permet galement de compresser directement une chane de caractres sans ncessairement passer par un fichier.

Avec gzcompress

gzcompress()
Compresse une chane de caractres en utilisant lalgorithme de la librairie zziplib. Mais attention, il est impossible dutiliser loutil Gzip pour dcompresser les fichiers ainsi crs. Utilisez gzencode() pour obtenir des archives compatibles. Syntaxe $chaine $facteur string gzcompress(string $chaine [, int $facteur]) Chane contenant les donnes compresser. Indique le niveau de compression entre 0 (pour une compression nulle) et 9 (pour une compression maximale). Plus le facteur de compression est important, plus il y a utilisation des ressources. Par dfaut, le facteur est de 6. Donnes compresses.

retour

Listing 9.40 : gzdeflate.php


<?php $maChaine = "\"Je suis un phnomne, je suis un magicien\n".

588

Accder au systme de fichiers du serveur

"Un tuyau parcouru dinformations majeures\n". "Mais ya pas que des douceurs qui passent lintrieur\"\n". "Noir Dsir, Son style\n"; $codeHTML = "<html><head><title>". "Test de compression avec compress". "</head></title><body>". nl2br($machaine); if (strpos($_SERVER["HTTP_ACCEPT_ENCODING"], "compress") !== FALSE) { $codeHTML .= "<br /><center><i>". "Cette page a t compresse par le serveur<br />". "et admirablement bien dcompresse par votre". " navigateur</i></center></body></html>"; header("Content-Encoding: compress"); echo gzcompress($codeHTML); } else { $codeHTML .= "<br /><center><i>". "Dsol, votre navigateur ne supporte pas ce type de compression". "<br /> Cette page na donc pas t transfre compresse". "</i></center></body></html>"; echo $codeHTML; } ?>

9. La gestion des fichiers et des rpertoires

Vous pouvez vous reporter lannexe "Les en-ttes HTTP" et la section "Mise en cache avant mission des donnes pour plus dinformations" sur lenvoi (automatique) de donnes compresses.
La dcompression pourra seffectuer avec :

gzuncompress()
Dcompresse des donnes compresses avec la fonction gzcompress(). Syntaxe $chaine $longueur retour string gzuncompress (string $chaine [, int $longueur]) Chane contenant les donnes compresses. Longueur maximale des donnes dcompresses. La fonction retourne FALSE si la taille de la chane de retour est plus importante. Retourne la chane dcompresse, ou FALSE si linstruction rencontre une erreur dans le traitement. Si la chane de retour est 256 fois suprieure $chaine, la fonction renverra FALSE.

589

Chapitre 9

La gestion des fichiers et des rpertoires

Avec gzdeate
9. La gestion des fichiers et des rpertoires
Un autre algorithme de compression peut tre utilis pour compresser les donnes. Deflate est un format de compression particulirement bien adapt aux chanes de caractres. Les spcifications de ce format peuvent tre trouves ladresse suivante : http://www.ietf.org/rfc/rfc1951.txt. Pour compresser une chane en utilisant ce format, vous utiliserez linstruction gzdeflate().

gzdeate()
Compresse une chane de caractres. Syntaxe $chaine $facteur string gzdeflate(string $chaine [, int $facteur]) Chane contenant les donnes compresser. Indique le niveau de compression entre 0 (pour une compression nulle) et 9 (pour une compression maximale). Plus le facteur de compression est important, plus le traitement est lent. Par dfaut, le facteur est de 6. Donnes compresses.

retour

Listing 9.41 : gzcompress.php


<?php $maChaine = "\"Je suis un phnomne, je suis un magicien\n". "Un tuyau parcouru dinformations majeures\n". "Mais ya pas que des douceurs qui passent lintrieur\"\n". "Noir Dsir, Son style\n"; $codeHTML = "<html><head><title>". "Test de compression avec deflate". "</head></title><body>". nl2br($machaine); if (strpos($_SERVER["HTTP_ACCEPT_ENCODING"], "deflate") !== FALSE) { $codeHTML .= "<br /><center><i>". "Cette page a t compresse par le serveur<br />". "et admirablement bien dcompresse par votre". " navigateur</i></center></body></html>"; header("Content-Encoding: deflate"); echo gzdeflate($codeHTML); } else { $codeHTML .= "<br /><center><i>". "Dsol, votre navigateur ne supporte pas ce type de compression". "<br /> Cette page na donc pas t transfre compresse". "</i></center></body></html>"; echo $codeHTML; } ?>

590

Accder au systme de fichiers du serveur

Une chane compresse avec gzdeflate() pourra tre restitue par :

9. La gestion des fichiers et des rpertoires

gzinate()
Dcompresse les donnes compresses avec la fonction gzdeflate(). Syntaxe $chaine $longueur retour string gzinflate(string $chaine [, int $longueur]) Chane contenant les donnes compresses. Longueur maximale des donnes dcompresses. La fonction retourne FALSE si la taille de la chane de retour est plus importante. Retourne la chane dcompresse, ou FALSE si linstruction rencontre une erreur dans le traitement. Si la chane de retour est 256 fois suprieure $chaine, la fonction renverra FALSE.

Avec gzencode
Pour compresser une chane dans un format compatible avec Gzip, vous devrez utiliser la fonction gzencode().

gzencode()
Compresse une chane en utilisant le mme format de compression que la commande gzip. Syntaxe $chaine $facteur string gzencode(string $chaine [, int $facteur [, int $modeEncodage]]) Chane contenant les donnes compresser. Indique le niveau de compression entre 0 (pour une compression nulle) et 9 (pour une compression maximale). Plus le facteur de compression est important, plus le traitement est lent. Par dfaut, le facteur est de 6. Au choix : FORCE_DEFLATE si la compression doit inclure les en-ttes de la Zlib. FORCE_GZIP (par dfaut) sinon. retour Donnes compresses.

$modeEncodage

Listing 9.42 : gzencode.php


<?php $maChaine = "\"Je suis un phnomne, je suis un magicien\n". "Un tuyau parcouru dinformations majeures\n". "Mais ya pas que des douceurs qui passent lintrieur\"\n". "Noir Dsir, Son style\n"; $codeHTML = "<html><head><title>".

591

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

"Test de compression avec gzip". "</head></title><body>". nl2br($machaine); if (strpos($_SERVER["HTTP_ACCEPT_ENCODING"], "gzip") !== FALSE) { $codeHTML .= "<br /><center><i>". "Cette page a t compresse par le serveur<br />". "et admirablement bien dcompresse par votre". " navigateur</i></center></body></html>"; header("Content-Encoding: gzip"); echo gzencode($codeHTML); } else { $codeHTML .= "<br /><center><i>". "Dsol, votre navigateur ne supporte pas ce type de compression". "<br /> Cette page na donc pas t transfre compresse". "</i></center></body></html>"; echo $codeHTML; } ?>

Un fichier est prsent sur le disque, dans le rpertoire courant. Vous pouvez visualiser son contenu (si vous avez accs la console de la machine) en utilisant soit directement zcat debian.txt.gz soit avec gzip d debian.txt.gz suivi de more debian.txt. Vous constatez alors que vous retrouvez bel et bien votre fichier original. Il nexiste toutefois pas de fonction permettant de dcompresser directement une telle chane de caractres ; vous devez donc lutiliser directement dans une commande rclamant une chane compresse ou la stocker dans un fichier pour une utilisation ultrieure (dcompression et lecture avec les fonctions dcrites tout au long de ce chapitre). Cependant, il est tout de mme possible de sen sortir grce la fonction gzinflate(), en prenant soin toutefois de supprimer les dix premiers caractres de la chane compresse.
$chaine = gzinflate(substr($chaineCompressee,10));

Checksum
Il est trs simple de calculer un checksum bas sur le md5 dun fichier grce la fonction md5_file().

md5_le()
Permet de calculer le md5 dun fichier (chane hexadcimale de 32 caractres). Syntaxe $nomFichier retour string md5_file(string $nomFichier) Fichier texte dont on veut calculer le md5. md5 du fichier.

592

Les streams ou les flux

9.3.

Les streams ou les ux


9. La gestion des fichiers et des rpertoires

Les streams ont t introduit avec la version 4.3 de PHP. Lide est de gnraliser ou plutt de sabsoudre de lobjet qui doit tre atteint (systme de fichier, fichiers compresss, sockets, connexions ftp ou http, etc). Ces fonctions se comportent donc comme une interface commune permettant daccder, via un protocole dfini, aux donnes qui doivent tre traites.

Installation
Il ny a aucune manipulation particulire effectuer pour utiliser les streams. En effet, ces fonctions sont directement utilisables depuis PHP 4.3 et suprieur.

Les gestionnaires disponibles


Les gestionnaires sont des pilotes permettant de lire un flux de donnes en utilisant un protocole donn. Sil est possible dajouter des gestionnaires laide de fonctions que lon verra dans la suite de ce chapitre, plusieurs sont disponibles ds linstallation de PHP. Il est possible de lister ces diffrents gestionnaires laide de la fonction
stream_get_wrappers().

stream_get_wrappers()
Permet de rcuprer, dans un tableau, la liste des gestionnaires disponibles. Syntaxe retour
<?php print_r(stream_get_wrappers()); ?>

array stream_get_wrappers(void) Tableau index comprenant la liste de tous les gestionnaires disponibles sur le systme.

Le programme ci-dessus donne le rsultat suivant : Array ( [0] => php [1] => file [2] => http [3] => ftp [4] => compress.zlib )

593

Chapitre 9

La gestion des fichiers et des rpertoires

Tableau 9.4 : Liste des divers protocoles supports

9. La gestion des fichiers et des rpertoires

Nom du gestionnaire php file http ftp compress.zlib

Description Permet lusage des entres/sorties. Par exemple php://output permet simplement de remplacer la fonction print() et affiche des donnes. Gestionnaire par dfaut lors de lutilisation des fonctions fopen(), fwrite(), etc. Ce protocole permet daccder au systme de fichiers. Gestionnaire permettant daccder aux donnes se trouvant sur un serveur web via le protocole http. Gestionnaire permettant daccder aux donnes disponibles sur un serveur FTP. Gestionnaire permettant daccder aux donnes compresses via la librairie zlib. Remplace donc les fonctions gzopen(), gzclose(), etc. en permettant lusage des fonctions de lecture de fichiers fopen(), fread(), etc.

Si le support SSL a t activ alors vous aurez galement le support des protocoles https et ftps.

Le gestionnaire le
Le gestionnaire file est optionnel. En effet, lorsquil nest pas spcifi, cest cest celui-ci qui est utilis par dfaut.
<?php $fp = fopen("file:///tmp/file.txt","w") or die("Impossible de crer le fichier."); fwrite($fp, "Exemple de cration dun fichier laide du gestionnaire file"); fclose($fp); readfile("file:///tmp/file.txt"); ?>

Lexemple prcdent cre un fichier dans le rpertoire /tmp (sous UNIX/Linux, indiquer C:\\chemin pour un systme Windows) et lit celui-ci ensuite pour lafficher lcran.

Le gestionnaire http://
La lecture des fichiers distance est utilisable simplement en indiquant lurl du fichier.
<?php $ptFlux = fopen("http://www.php.net", "r"); while ($ligne=fread($ptFlux, 8192)) { print($ligne); } fclose($ptFlux); ?>

Pour passer une authentification il faut indiquer lidentifiant et le mot de passe de la faon suivante :

594

Les streams ou les flux

<?php $ptFlux = fopen("http://identifiant:motdepasse@www.php.net", "r"); while ($ligne=fread($ptFlux, 8192)) { print($ligne); } fclose($ptFlux); ?>

9. La gestion des fichiers et des rpertoires

Le gestionnaire FTP
La lecture des fichiers en utilisant le protocole FTP se fait en indiquant lurl du fichier de la faon suivante :
<?php $fp = fopen("ftp://identifiant:motdepasse@ftp.ouvaton.org/html/test.txt","w") or die("Impossible de crer le fichier."); fwrite($fp, "Exemple de cration dun fichier laide du gestionnaire file"); fclose($fp); readfile("ftp://identifiant:motdepasse@ftp.ouvaton.org/html/test.txt"); ?>

Notez quil est donc possible daccdez en criture sur un serveur FTP ce qui peut-tre trs pratique pour crer des fichiers distance.

Le gestionnaire compress.zlib
Remplacer avantageusement lutilisation des fonctions gzread, gzopen, gzclose()en utilisant le wrapper compress.zlib. En spcifiant ce gestionnaire, cela permet lusage des fonctions daccs aux fichiers classiques : fopen(), fread(), fwrite(), fclose().
<?php // Cration du fichier compress gzip.filtre.txt $fp = fopen("compress.zlib://gzip.filtre.txt","w") or die("Impossible de crer le fichier."); fwrite($fp, "Michael Moore :\n"); fwrite($fp, "Fahrenheit 9/11 (2003)\n"); fwrite($fp, "Bowling for Columbine (2002)\n"); fwrite($fp, "Last party 2000 (2001)\n"); fwrite($fp, "Le Bon numro (Lucky numbers) (2000)\n"); fwrite($fp, "The Big One (1998)\n"); fwrite($fp, "Canadian bacon (1995)\n"); fwrite($fp, "Roger et moi (Roger and me) (1989)"); fclose($fp); // Affichage du fichier dcompress readfile("compress.zlib://gzip.filtre.txt"); ?>

595

Chapitre 9

La gestion des fichiers et des rpertoires

Ce qui affiche le rsultat suivant : Michael Moore : Fahrenheit 9/11 (2003) Bowling for Columbine (2002) Last party 2000 (2001) Le Bon numro (Lucky numbers) (2000) The Big One (1998) Canadian bacon (1995) Roger et moi (Roger and me) (1989)

9. La gestion des fichiers et des rpertoires

Le gestionnaire PHP
Voici divers exemple dutilisation du protocole PHP Dans un premier temps voici comment utiliser fopen() pour crire dans le buffer de sortie. Le rsultat est identique lappel dune fonction print().
<?php $ptFlux = fopen("php://output", "w"); fwrite($ptFlux, "Voici un premier message\n"); fwrite($ptFlux, "Voici un deuxime message"); fclose($ptFlux); ?>

Il est simple de rcuprer les donnes envoyes via un formulaire de type POST. Voici un exemple implmentant une mthode alternative la (classique) variable $_POST.
<form method="post"> <input type="text" name="a" value="" /> <br /> <input type="radio" name="b" value="0" id="i_b0" /> <label for="i_b0">0</label> <input type="radio" name="b" value="1" id="i_b1" /> <label for="i_b1">1</label> <br /> <input type="checkbox" name="c" value="coche" /> <br /> <input type="submit" name="d" value="envoyer" /> </form> <?php $request = file_get_contents("php://input"); echo $request; ?>

Le rsultat est une chane de caractres du type a=test&b=1&c=coche&d=envoyer

596

Les streams ou les flux

Les ltres
Le gestionnaire php:// offre des possibilits particulirement intressantes qui permettent deffectuer des traitements lmentaires aux donnes lues, au travers dun flux, au fur et mesure de leur disponibilit. Il sagit en quelque sorte de filtrer les donnes. Ce peut tre le seul recours pour une fonction comme readfile() et peux permettre dviter un traitement posteriori avec file_get_contents() ou file() La liste des filtres disponibles est donne par la fonction stream_get_filters().

9. La gestion des fichiers et des rpertoires

stream_get_lters()
Retourne la liste des filtres disponibles sous la forme dun tableau index. Syntaxe : retour array stream_get_filters(void) Tableau index contenant la liste des filtres disponibles.

Utilisez simplement ce script pour voir quels sont les filtres que vous pouvez utiliser.
<?php print_r(stream_get_filters()); ?>

Vous devriez observer un rsultat de ce type : Array ( [0] => convert.iconv.* [1] => string.rot13 [2] => string.toupper [3] => string.tolower [4] => string.strip_tags [5] => convert.* [6] => zlib.* )

Tableau 9.5 : Les filtres utilisables par dfaut avec le gestionnaire php://filter
Filtres convert.iconv.* string.rot13 Descriptions Change lencodage de la chane de caractres. Effectue un encodage ROT13 la chane de caractres. Lencodage ROT13 dcale les caractres de 13 dans lalphabet. Exemple : a devient n, b devient o, c devient p. Retourne la chane en majuscule. Retourne la chane en minuscule.

string.toupper string.tolower

597

Chapitre 9

La gestion des fichiers et des rpertoires

Filtres

Descriptions Filtre les tags de formatage HTML. Utilise les fonctions de la zlib pour compresser ou dcompresser les donnes la vole. convert.base64-encode permet dencoder en base64. convert.base64decode permet de dcoder une chane de caractres encode en base64. convert.quoted-printable-encode permet de convertir une chane dans le format quoted-printable. Le format quoted-printable est souvent utilis dans le corps des mail ou dans le posts de newsgroup. convert.quoted-printable-decode permet de dcoder une chane au format quoted-printable.

9. La gestion des fichiers et des rpertoires

string.strip_tags zlib.* convert.base64-*

convert.quoted-printable-*

Pour utiliser ces filtres vous devez suivre la syntaxe suivante:

php://lter/
Applique un filtre en lecture ou criture du fichier Syntaxe : $filtreLecture $filtreEcriture $ressource php://filter/[read=$filtreLecture|write=$filtreEcriture] /resource=$ressource Paramtre optionnel indiquant le filtre appliquer lors de la lecture. Paramtre optionnel indiquant le filtre appliquer lors de lcriture. Ressource du flux filtrer, cela peut-tre un simple nom de fichier ou une ressource sappuyant sur les protocoles http://, ftp://, compress.zlib://, etc..

Exemple dutilisation du gestionnaire php avec le paramtre filter.


<?php // Recupre la page daccueil de php.net // Renvoie le contenu dans la chane $contenu en appliquant // un filtre qui retourne tous les caractres en majuscule. $contenu = file_get_contents("php://filter/read=string.toupper/resource=http://php.net"); // Cration du fichier compress php.net.gz avec le contenu // rcupr prcdemment $fp = fopen("compress.zlib://php.net.gz","w") or die("Impossible de crer le fichier."); fwrite($fp, $contenu); fclose($fp); // Affichage du fichier dcompress avec application dun filtre // retournant tous les caracteres en majuscules

598

Les streams ou les flux

readfile("php://filter/read=string.tolower/resource=compress.zlib://php.net.gz"); ?>

9. La gestion des fichiers et des rpertoires

Il est possible dassocier un filtre un flux de faon ce que le filtre en question soit utilis pour chaque opration effectue sur ce flux. On peut utiliser pour cela les fonctions stream_filter_append() ou stream_filter_prepend(). Dans le premier cas, le filtre est rattach la suite des filtres dj attribus au flux. La seconde fonction permet de spcifier un filtre qui sera plac en tte de liste des filtres utiliser. Les filtres en haut de la liste tant utiliss en premier.

stream_lter_append()
Attribue un filtre un flux pass en paramtre. Il est plac en queue de liste des filtres dj attachs au flux. Syntaxe : $flux $filtre $comportement bool stream_filter_append(ressource $flux, string $filtre [, int $comportement[, mixed $parametre]]) Ressource vers la flux retourne par fopen() ou fsockopen(). Filtre utiliser. Dans le cas ou le flux a t ouvert en mode lecture et criture, ce paramtre permet de fixer si le filtre doit sappliquer en lecture, en criture ou dans les deux cas. STREAM_FILTER_READ : Appliquer le filtre uniquement en lecture. STREAM_FILTER_WRITE : Appliquer le filtre uniquement en criture. STREAM_FILTER_ALL : Appliquer le filtre dans tous les cas. Paramtres optionnels pouvant tre ncessaires lutilisation du filtre $filtre. Retourne TRUE si le filtre a bien t rattach au flux et FALSE dans le cas contraire.

$parametre retour

stream_lter_prepend()
Attribue un filtre un flux pass en paramtre. Il est plac en tte de la liste des filtres dj attachs au flux. Syntaxe : $flux $filtre $comportement bool stream_filter_prepend(ressource $flux, string $filtre [, int $comportement [, mixed $parametre]]) Ressource vers la flux retourne par fopen() ou fsockopen(). Filtre utiliser. Dans le cas ou le flux a t ouvert en mode lecture et criture, ce paramtre permet de fixer si le filtre doit sappliquer en lecture, en criture ou dans les deux cas.

599

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

STREAM_FILTER_READ : Appliquer le filtre uniquement en lecture. STREAM_FILTER_WRITE : Appliquer le filtre uniquement en criture. STREAM_FILTER_ALL : Appliquer le filtre dans tous les cas. $parametre retour Paramtres optionnels pouvant tre ncessaires lutilisation du filtre $filtre. Retourne TRUE si le filtre a bien t rattach au flux et FALSE dans le cas contraire.

<?php // Ouverture dun fichier en lecture et criture $fp = fopen("bible.txt", "w+"); // On attache le filtre ROT13 uniquement en criture stream_filter_append($fp, "string.rot13", STREAM_FILTER_WRITE); // On attache au flux, le filtre string.toupper stream_filter_append($fp, "string.toupper", STREAM_FILTER_WRITE); // On attache au flux, le filtre string.tolower en fin de liste // Par consquent le filtre string.toupper naura aucun effet stream_filter_append($fp, "string.tolower", STREAM_FILTER_WRITE); // Ecriture fwrite($fp, fwrite($fp, fwrite($fp, fwrite($fp, rewind($fp); // Lecture du fichier while ($ligne=fread($fp, 1024) ) { echo ($ligne); } fclose($fp); ?> de donnes dans le fichier "Damien HEUTE\n"); "Thomas HEUTE\n"); "Laurent GUEDON\n"); "Pierre-Emmanuel MULLER\n");

On obtient le rsultat suivant : qnzvra urhgr gubznf urhgr ynherag thrqba cvreer-rzznahry zhyyre Si on modifie le code en spcifiant le filtre string.tolower en dbut de liste comme ceci :
<?php // Ouverture dun fichier en lecture et criture $fp = fopen("bible.txt", "w+"); // On attache le filtre ROT13 uniquement en criture stream_filter_append($fp, "string.rot13", STREAM_FILTER_WRITE);

600

Les streams ou les flux

// On attache au flux, le filtre string.toupper stream_filter_append($fp, "string.toupper", STREAM_FILTER_WRITE); // On attache au flux, le filtre string.tolower en dbut de liste // Par consquent ce filtre naura aucun effet (cras par string.toupper) stream_filter_prepend($fp, "string.tolower", STREAM_FILTER_WRITE); // Ecriture fwrite($fp, fwrite($fp, fwrite($fp, fwrite($fp, rewind($fp); // Lecture du fichier while ($ligne=fread($fp, 1024) ) { echo ($ligne); } fclose($fp); ?> de donnes dans le fichier "Damien HEUTE\n"); "Thomas HEUTE\n"); "Laurent GUEDON\n"); "Pierre-Emmanuel MULLER\n");

9. La gestion des fichiers et des rpertoires

On obtient alors : QNZVRA URHGR GUBZNF URHGR YNHERAG THRQBA CVREER-RZZNAHRY ZHYYRE Modifions encore notre scripte en modifiant le comportement du filtre string.rot13 en STREAM_FILTER_ALL. Cette fois la lecture du scripte utilise le filtre ROT13, ainsi le rsultat de son excution est le suivant : DAMIEN HEUTE THOMAS HEUTE LAURENT GUEDON PIERRE-EMMANUEL MULLER

Contexte de ressource
Vous pouvez spcifier un contexte lors de lappel une ressource. Par exemple vous pouvez passer des paramtres une URL. Pour cela, il est possible denregistrer votre contexte laide de la fonction stream_context_create().

601

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

stream_context_create()
Enregistre un contexte de flux utilis ensuite lors de lappel aux fonctions file(), file_get_contents() ou fopen(). Syntaxe : $contexte retour ressource stream_context_create([array $contexte]) Tableau optionnel fournissant les contextes. De $tableau[gestionnaire][option] = valeur. la forme

Retourne une ressource a passer en paramtre des fonctions file(), file_get_contents() ou fopen().

Exemple illustrant lutilisation de stream_context_create() :


<?php $postdata = "auteur1=Laurent%20GUEDON&". "auteur2=Damien%20HEUTE&". "auteur3=Pierre%20Emmanuel%20MULLER&". "auteur4=Thomas%20HEUTE\n"; $header = "User-Agent: Bible Browser V0.3\n". "Referer:http://www.monsite.com\n". "Content-Length:".strlen($postdata)."\n". "Content-Type: application/x-www-form-urlencoded\n\n". $postdata; $contexte = array( http=>array ( method => POST, header => $header ) ); $fc = stream_context_create($contexte); $fp = fopen(http://localhost/bible/recup.php, r, false, $fc); fpassthru($fp); fclose($fp); ?>

Ce script appelle une page recup.php dcrite ci-dessous :


<?php echo "Les variables postes : \n"; print_r($_POST); echo "\n----\n"; echo "Provenance:".$_SERVER["HTTP_REFERER"]."\n"; echo "Type de contenu:".$_SERVER["CONTENT_TYPE"]; ?>

602

Les streams ou les flux

Lexcution du script donne le rsultat suivant : Les variables postes : Array ( [auteur1] => Laurent GUEDON [auteur2] => Damien HEUTE [auteur3] => Pierre Emmanuel MULLER [auteur4] => Thomas HEUTE )
---Provenance:http://www.monsite.com Type de contenu:application/x-www-form-urlencoded

9. La gestion des fichiers et des rpertoires

On peut imaginer facilement les multiples usages qui en dcoulent. Pour ne pas avoir spcifier la ressource de contexte dans les fonctions file(), file_get_contents() ou fopen() vous pouvez utiliser la fonction stream_context_get_default().

stream_context_get_default()
Spcifie les options de contexte par dfaut lors des appels aux fonctions file(), file_get_contents() ou fopen(). Syntaxe : $contexte retour ressource stream_context_get_default([array $contexte]) Tableau optionnel fournissant les contextes. De $tableau[gestionnaire][option] = valeur. la forme

Retourne une ressource pouvant tre passe en paramtre des fonctions file(), file_get_contents() ou fopen().

<?php $postdata = "auteur1=Laurent%20GUEDON&". "auteur2=Damien%20HEUTE&". "auteur3=Pierre%20Emmanuel%20MULLER&". "auteur4=Thomas%20HEUTE\n"; $header = "User-Agent: Bible Browser V0.3\n". "Referer:http://www.monsite.com\n". "Content-Length:".strlen($postdata)."\n". "Content-Type: application/x-www-form-urlencoded\n\n". $postdata;

$contexte = array( http=>array ( method => POST, header => $header

603

Chapitre 9

La gestion des fichiers et des rpertoires

) );

9. La gestion des fichiers et des rpertoires

$fc = stream_context_get_default($contexte); $fp = fopen(http://localhost/bible/recup.php, r); fpassthru($fp); fclose($fp); ?>

Le rsultat est identique lexemple prcdent : Les variables postes : Array ( [auteur1] => Laurent GUEDON [auteur2] => Damien HEUTE [auteur3] => Pierre Emmanuel MULLER [auteur4] => Thomas HEUTE )
---Provenance:http://www.monsite.com Type de contenu:application/x-www-form-urlencoded

Autre solution, utiliser la fonction stream_context_set_option().Cette fonction permet de fixer une option de contexte aprs lappel la fonction stream_context_create().

stream_context_set_option()
Fixe une option de contexte la ressource de flux passe en paramtre file(), file_get_contents() ou fopen(). Syntaxe : $contexte $gestionnaire $option $valeur retour bool stream_context_set_option(ressource $contexte, string $gestionnaire, string $option, mixed $valeur) Ressource du contexte cre stream_context_create(). Identifiant du gestionnaire affect. Option du gestionnaire modifie Nouvelle valeur de loption Retourne TRUE si lopration a t effectue avec succs et FALSE dans le cas contraire. laide de la fonction

<?php $postdata = "auteur1=Laurent%20GUEDON&". "auteur2=Damien%20HEUTE&".

604

Les streams ou les flux

"auteur3=Pierre%20Emmanuel%20MULLER&". "auteur4=Thomas%20HEUTE\n";

9. La gestion des fichiers et des rpertoires

$header = "User-Agent: Bible Browser V0.3\n". "Referer:http://www.monsite.com\n". "Content-Length:".strlen($postdata)."\n". "Content-Type: application/x-www-form-urlencoded\n\n". $postdata; $fc = stream_context_create(); stream_context_set_option($fc, http, method, POST); stream_context_set_option($fc, http, header, $header); $fp = fopen(http://localhost/bible/recup.php, r, false, $fc); fpassthru($fp); fclose($fp); ?>

On obtient la mme chose que prcdemment, cest dire : Les variables postes : Array ( [auteur1] => Laurent GUEDON [auteur2] => Damien HEUTE [auteur3] => Pierre Emmanuel MULLER [auteur4] => Thomas HEUTE )
---Provenance:http://www.monsite.com Type de contenu:application/x-www-form-urlencoded

A tout moment, nous pouvons rcuprer les informations de contexte, simplement en utilisant la fonction stream_context_get_options().

stream_context_get_options()
Retourne les options de contexte dans un tableau associatif. Syntaxe : $contexte retour array stream_context_get_options(ressource $contexte) Ressource du contexte cre stream_context_create(). laide de la fonction

Tableau associatif contenant les informations de contexte.

605

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

<?php $postdata = "auteur1=Laurent%20GUEDON&". "auteur2=Damien%20HEUTE&". "auteur3=Pierre%20Emmanuel%20MULLER&". "auteur4=Thomas%20HEUTE\n"; $header = "User-Agent: Bible Browser V0.3\n". "Referer:http://www.monsite.com\n". "Content-Length:".strlen($postdata)."\n". "Content-Type: application/x-www-form-urlencoded\n\n". $postdata; $fc = stream_context_create(); echo "Options de contexte \n"; print_r(stream_context_get_options($fc)); stream_context_set_option($fc, http, method, POST); stream_context_set_option($fc, http, header, $header); echo "\nOptions de contexte, une fois modifies \n"; print_r(stream_context_get_options($fc)); ?>

Voici le rsultat de ce script : Options de contexte Array ( )


Options de contexte, une fois modifies Array ( [http] => Array ( [method] => POST [header] => User-Agent: Bible Browser V0.3 Referer:http://www.monsite.com Content-Length:106 Content-Type: application/x-www-form-urlencoded auteur1=Laurent%20GUEDON&auteur2=Damien%20HEUTE&auteur3=Pierre%20Emmanuel%20 MULLER&auteur4=Thomas20HEUTE ) )

606

Les streams ou les flux

Travailler avec les ux


9. La gestion des fichiers et des rpertoires

Copier dune ressource une autre


La fonction stream_copy_to_stream() permet de copier le contenu point par une ressource de flux vers une autre ressource. Mme si les gestionnaires utiliss par les deux flux sont diffrents.

stream_copy_to_stream()
Copie les donnes dun flux vers un autre. Syntaxe : $source $destination $taille retour int stream_copy_to_stream(ressource $source, ressource $destination [, int $taille]) Ressource du flux source. Ressource du flux destination Taille en octet des donnes copier. Par dfaut toutes les donnes seront intgralement copies. Retourne le nombre doctet ayant t copi si lopration a t effectue avec succs et FALSE dans le cas contraire.

<?php $src = fopen(http://www.php.net, r); $dest = fopen(ftp://laurent:motdepasse@ftp.serveur.org/php.net.html, w); $nboct = stream_copy_to_stream($src, $dest); echo $nboct." octets ont t copis sur le serveur\n"; ?> 34775 octets ont t copis sur le serveur

Rcuprer le contenu dun ux


Rcuprer lensemble
On peut galement avoir besoin de rcuprer le contenu dun flux dans une chane. La fonction stream_get_contents() permet de rcuprer le reste dun contenu dun flux.

stream_get_contents()
Rcupre le reste du contenu dun flux dans une chane. Syntaxe : $flux string stream_get_contents(ressource $flux [, int $taille]) Ressource du flux que lon considre.

607

Chapitre 9

La gestion des fichiers et des rpertoires

$taille

Taille en octet des donnes rcuprer. Par dfaut toutes les donnes seront intgralement retournes. Chane de caractre.

9. La gestion des fichiers et des rpertoires

retour

Lexemple suivant retourne le fichier index du site Php.net comme le ferait la fonction readfile().
<?php $flux = fopen(http://www.php.net, r); $content = stream_get_contents($flux); echo $content; ?>

Rcuprer une ligne


On peut galement lire les lignes les unes la suite des autres. On utilise pour cela la fonction stream_get_line().

stream_get_line()
Rcupre une ligne de donne dans un flux. Syntaxe : $flux $taille string stream_get_line (ressource $flux, int $taille, string $fin) Ressource du flux que lon considre. Taille en octet de la ligne rcuprer. La lecture se termine lorsque $taille octets ont t lus ou lorsque la fin de la ligne fixe par le paramtre $fin a t rencontre. Chane de caractre reprsentant la fin dune ligne (exemple : \n). Chane de caractre.

$fin retour

Lexemple ci-dessous permet de rcuprer uniquement lentte HTML du document prsent en index du site PHP.NET.
<?php $flux = fopen(http://www.php.net, r); $ligne = stream_get_line($flux, 4048, "</head>"); echo $ligne; ?>

Informations sur une ressource


Une fois la ressource ouverte, il peut-tre intressant de rcuprer des informations sur celle-ci. La fonction stream_get_meta_data() permet de retrouver bon nombre dinformations sur la ressource de flux.

608

Les streams ou les flux

stream_get_meta_data()
Retourne les informations sur une ressource de flux. Syntaxe : $flux retour array stream_get_meta_data(ressource $flux) Ressource ouverte avec les fonctions fopen(), fsockopen() ou pfsockopen(). Retourne un tableau associatif comportant les diffrentes information sur le flux.

9. La gestion des fichiers et des rpertoires

<?php $fp = fopen(ftp://tild:passe@ftp.monserveur.org/php.net.html, r); print_r(stream_get_meta_data($fp)); fclose($fp); ?>

Lexemple prcdent retourne un rsultat du type : Array ( [wrapper_data] => [wrapper_type] => ftp [stream_type] => tcp_socket [mode] => r+ [unread_bytes] => 0 [seekable] => [uri] => ftp://tild:passe@ftp.monserveur.org/php.net.html [timed_out] => [blocked] => 1 [eof] => )

Ajouter des gestionnaires


Il serait dommage de se limiter ces quelques protocoles supports. Le langage PHP, dans sa grande souplesse, permet de crer de nouveaux gestionnaires. Ainsi on peut imaginer que, dsirant ouvrir un fichier dans un format que vous auriez convenu pralablement, vous puissiez indiquer votre gestionnaire aux fonctions de lecture et dcriture de fichiers. De la sorte, il vous est plus commode deffectuer les oprations lmentaires en utilisant simplement les fonctions classiques daccs aux fichiers. Nous allons implmenter ici un gestionnaire qui va nous permettre daccder une base de donnes. Pour cela il faut faire appel la fonction stream_wrapper_register() ou son alias stream_register_wrapper().

609

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

stream_wrapper_register()
Cette fonction permet denregistrer un nouveau protocole dfinit par une classe. Syntaxe : $protocole $classe retour bool stream_wrapper_register(string $protocole, string $classe) Nom du protocole dfinir. Nom de la classe utilise pour implmenter le protocole. Retourne TRUE si le protocole bien t enregistr et FALSE dans le cas contraire (Par exemple si le protocole est dj enregistr).

Avant dutiliser cette fonction, vous devez avoir implment une classe. Celle-ci comprend un certain nombre de mthodes quil vous faut prendre en compte.

Exemple PHP 5 Lexemple qui va suivre prend en compte les modifications de PHP5 pour la partie objet. Cela a pour consquence que des modifications doivent tre apportes pour adapter la classe une version antrieure (PHP 4.3).
Il faut dans un premier temps permettre louverture du flux et indiquer dans la classe les oprations qui doivent tre effectues la suite dun appel la fonction fopen(). Pour ce faire nous utiliserons la mthode stream_open().

(Classe Stream Personnalise)->stream_open()


Cette commande interprte lappel la fonction fopen() et analyse le chemin du flux qui doit tre trait ainsi que le mode douverture. Syntaxe : $chemin $mode bool stream_open(string $chemin, string $mode, int $options, string $cheminReel) Chemin vers le flux traiter. Il faut utiliser la fonction parse_url() pour analyser la chane de caractres. Mode douverture du flux voir la fonction fopen() pour la liste des modes disponibles. Au dveloppeur danalyser le mode pour grer les traitements utilisables. Fournit des options particulires pour permettre louverture de la ressource de flux : STREAM_USE_PATH : Indique que la ressource est rechercher dans le chemin courant ou laide de la configuration de linclude_path (voir le chapitre sur php.ini).

$option

610

Les streams ou les flux

STREAM_REPORT_ERRORS : Le dveloppeur de la classe est responsable de la lev des erreurs qui pourrait survenir (Voir la fonction trigger_error()). $cheminReel retour Chemin rel de la ressource. Retournez TRUE si lopration a t effectue avec succs et FALSE dans le cas contraire.

9. La gestion des fichiers et des rpertoires

Voici un exemple implmentant uniquement louverture pour examiner les donnes passes la fonction stream_open() lorsque lon excute fopen().
<?php class dbStream { function stream_open($chemin, $mode, $options=, &$cheminReel=) { echo $chemin; echo "\n"; echo $mode; return TRUE; } } stream_wrapper_register(ex1,dbStream) or die("Impossible denregistrer ce protocole !"); $flux = fopen("ex1://monchemin", "r"); ?>

Le rsultat est le suivant :


ex1://monchemin r

Pour implmenter la fermeture du flux, il faut mettre en place la mthode stream_close().

(Classe Stream Personnalise)->stream_close()


Mthode appele lors de lexcution de la fonction fclose(). Syntaxe : void stream_close(void) Nous allons maintenant mettre en place la connexion notre base de donnes. Pour lexemple nous allons crer une base de donnes laide du script SQL suivant :
CREATE DATABASE bible ; CREATE TABLE auteurs ( id INT NOT NULL AUTO_INCREMENT , nom VARCHAR( 255 ) NOT NULL , prenom VARCHAR( 255 ) NOT NULL , PRIMARY KEY ( id ) ) COMMENT = Table des auteurs de la Bible du PHP;

611

Chapitre 9

La gestion des fichiers et des rpertoires

La connexion notre table s effectuera en indiquant lurl suivante :

9. La gestion des fichiers et des rpertoires

mysql://dbUser:dbPasse@serveur/base dbUser tant un utilisateur autoris accder la base de donnes. dbPasse tant le mode de passe de lutilisateur. serveur indique ladresse du serveur de la base. base est le nom de la base de donnes utilise pour la connexion. table enfin, est le nom de la table ou se trouve nos donnes.

Voici comment implmenter la classe correspondante :


<?php class fluxMysql { private $db; private $rs; private $table; function stream_open($chemin, $mode, $options=, &$cheminReel=) { $url = parse_url($chemin); $this->db = mysql_connect($url[host], $url[user], $url[pass]); // On spare la base et la table list($base, $this->table) = split("\.", $url[path]); // On supprime le "/" devant le nom de la base $base = substr($base, 1-strlen($base)); mysql_select_db($base); // On excute la requte de slection de la table $this->rs = mysql_query(select * from .$this->table, $this->db); return TRUE; } function stream_close() { return mysql_close($this->db); } } stream_wrapper_register(mysql,fluxMysql) or die("Impossible denregistrer ce protocole !"); // Ouverture de la connexion $flux = fopen("mysql://root@localhost/bible.auteurs", "r"); // Terminer la connexion fclose($flux); ?>

Bien sur cette fonction naffiche rien pour le moment. Pour se faire vous devez mettre en place la mthode qui sera appele lors de lexcution dune fonction fread() ou fgets(). Pour se faire, vous devez implmenter stream_read() dans votre classe.

612

Les streams ou les flux

(Classe Stream Personnalise)->stream_read()


Mthode excut lors de lappel de la fonction fread() ou fgets(). Syntaxe : $nombre retour string stream_read(int $nombre) Nombre doctets qui doivent tre lu (en fonction du pointeur courant). Chane de caractre correspondant la position du pointeur courant et de taille correspondant au nombre, $nombre, de caractres lus. Si aucun caractre ne peut-tre retourn, la fonction retourne FALSE.

9. La gestion des fichiers et des rpertoires

Pour illustrer par un exemple la mise en place de cette mthode, nous allons ajouter deux enregistrements notre base de donnes laide du script SQL suivant :
INSERT INTO auteurs (nom , prenom ) VALUES (GUEDON, Laurent); INSERT INTO auteurs (nom , prenom ) VALUES (HEUTE, Thomas);

Maintenant, implmentons notre mthode de lecture.


function stream_read($nombre) { $this->position++; $chaineretour = ; $row = mysql_fetch_array($this->rs); for ($i=0; $i<mysql_num_fields($this->rs); $i++) { $chaineretour .= $row[mysql_field_name($this->rs, $i)]; // Format la chane retourne // Tabulation entre les champs // Retour la ligne lorsque tous // les champs ont t lus if($i+1==mysql_num_fields($this->rs)){ $chaineretour .= "\n"; } else { $chaineretour .= "\t"; } } return $chaineretour; }

Si vous essayez deffectuer une lecture ce niveau, vous verrez le message suivant apparatre :
Warning: fread() [function.fread]: fluxMysql::stream_eof is not implemented!

En effet, vous devez implmenter une mthode stream_eof() avant deffectuer nimporte quelle lecture sur votre flux.

613

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

(Classe Stream Personnalise)->stream_eof()


Mthode indiquant si le pointeur du flux se trouve la fin du fichier ou non. Utilis dans le cas de lexcution de la fonction feof(). Syntaxe : retour bool stream_eof(void) Retourne TRUE si le pointeur se trouve en fin de lecture de la ressource.

Pour notre exemple, nous implmenterons cette mthode comme ceci :


function stream_eof() { // Vrifie si toutes les entres ont t lues if($this->position < $this->num_rows) { // Si non, retourne FALSE return FALSE; } else { // Dans le cas contraire, renvoie TRUE return TRUE; } }

Sans oublier dajouter ceci au dbut de la classe


private $position = 0;

La lecture peut maintenant seffectuer de la faon suivante :


stream_wrapper_register(mysql,fluxMysql) or die("Impossible denregistrer ce protocole !"); // Ouverture de la connexion $flux = fopen("mysql://root@localhost/bible.auteurs", "r"); while($c = fread($flux, 2048)) { echo $c; } // Terminer la connexion fclose($flux);

On obtient le rsultat suivant :


1....GUEDON....Laurent 2....HEUTE.....Thomas

Un exemple sans octet Vous remarquerez quici, nous navons pas trait le second paramtre de la fonction fread(). Mais il est simple de dcouper le rsultat pour ne retourner quune partie de la chane en fonction du nombre doctets dsir.

614

Les streams ou les flux

Vous pouvez remarquer que la lecture seffectue simplement, le pointeur se dplaant dun enregistrement lautre chaque appel de la fonction fread().

9. La gestion des fichiers et des rpertoires

PHP 4.3 oui, PHP 5 non... Cet exemple bien que fonctionnel dans les versions 4.3 et suprieur ne fonctionne pas dans la version rcente de PHP5. Le bug a t report et cela devrait tre rtabli dans les prochaines versions de PHP 5.
Vous savez quil est simple de connatre la position du pointeur chaque moment. Vous utilisez ftell() en indiquant la ressource utilise et la fonction vous retourne la position actuelle du pointeur. Pour implmenter un quivalent pour votre gestionnaire, vous devez mettre en place une mthode nomme stream_tell() dans votre classe.

(Classe Stream Personnalise)->stream_tell()


Mthode appele lors de lexcution de la fonction ftell(). Vous devez retourner la position du pointeur. Syntaxe : retour int stream_tell(void) Vous devez renvoyer la position du pointeur de type entier.

Voici comment dans notre exemple, la mthode stream_tell() retourne la position actuelle du pointeur.
function stream_tell() { return $this->position; }

Puis ajouter ceci :


rewind($flux); echo ftell($flux)."\n";

Bug de jeunesse Cette fonctionnalit nest pas utilisable dans PHP pour le moment, en effet, lheure de la rdaction de cette ouvrage (version 5.0.2), ftell() nutilise pas le valeur retourne par de la mthode stream_tell(). Peut-tre pour la version de PHP 5.1...
Lorsque vous utilisez les fonctions de lecture vous pouvez facilement dplacer le pointeur laide de la fonction fseek(). L encore vous pouvez implmenter une mthode qui va vous permettre lusage de cette fonction. Il faut mettre en place la mthode stream_seek().

615

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

(Classe Stream Personnalise)->stream_seek()


Permet de modifier la position du pointeur du flux. Cette mthode est utilise lors de lappel la fonction fseek(). Vous devez implmenter la mthode stream_tell() auparavant. Syntaxe : $offset $origine retour bool stream_seek(int $offset, int $origine) Nouvelle position du pointeur depuis lorigine $origine. Point de dpart pour calculer la nouvelle position. Voir les paramtre utiliss par la fonction fseek(). La mthode doit retourner TRUE si le dplacement a bien t effectu et FALSE dans le cas contraire.

Placez cette mthode dans votre classe :


function stream_seek($offset, $origine=SEEK_SET) { switch($origine) { // Lorigine du dplacement est 0 case SEEK_SET: $dep = 0; break; // Lorigine du dplacement est la position // courante case SEEK_CUR: $dep = $this->position; break; // Lorigine du dplacement est la fin du // flux case SEEK_END: $dep = mysql_num_rows($this->rs); break; } // Dplacement $this->position = $offset+$dep; return mysql_data_seek($this->rs, $this->position); }

Ainsi que lappel la fonction fseek() dans votre programme :


echo "Dplacer le pointeur sur la seconde entre :"; fseek($flux, 1); echo fread($flux, 2048)."\n";

Maintenant observons de quelle manire nous pouvons utiliser fwrite() pour crire des donnes dans la table. Pour cela nous devons mettre en place la mthode stream_write().

616

Les streams ou les flux

(Classe Stream Personnalise)->stream_write()


Cette mthode est appele en rponse lexcution de la fonction fwrite(). Vous devez implmenter la mthode en fonction des donnes passes en argument. Syntaxe : $donnee retour int stream_write(string $donnee) Chane de caractre quil faut traiter dans la fonction. Vous devez retourner la longueur, en octet, des donnes qui ont t prise en compte par votre fonction.

9. La gestion des fichiers et des rpertoires

Voici pour notre exemple, comment nous pouvons ajouter un enregistrement. Il faut dans un premier temps implmenter la mthode :
function stream_write($donnee) { $data = explode ("\n", $donnee); $nboct = 0; // Formate la chane dinsertion des donnes // Celles-ci sont passes la fonction fwrite() // sous la forme : // champ1=donne 1\nchamp2=donne 2\netc... $formatstr1 = $formatstr2 = "("; for ($i=0; $i<count($data); $i++) { list($champ, $valeur) = explode ("=", $data[$i]); $formatstr1 .= $champ; $formatstr2 .= "".$valeur.""; $nboct = $nboct + strlen($valeur); // Ajoute une virgule le cas chant if(count($data) > $i+1) { $formatstr1 .= ", "; $formatstr2 .= ", "; } } $formatstr1 .= ")"; $formatstr2 .= ")"; if(mysql_query("INSERT INTO ".$this->table." ".$formatstr1. " VALUES ".$formatstr2, $this->db)) { // On execute de nouveau la requete afin de rcuprer le dernier // enregistrement mysql_free_result($this->rs); $this->rs = mysql_query(select * from .$this->table, $this->db); // On place le pointeur sur la dernire entre $this->stream_seek(0, SEEK_END); return $nboct; } else { return FALSE; } }

617

Chapitre 9

La gestion des fichiers et des rpertoires

Et ajoutons ce code la fin de notre script:


echo "Enregistrement dune nouvelle entre : "; echo fwrite($flux, "nom=HEUTE\nprenom=Damien"); echo " caractres ont t enregistr\n"; // On crit les entres pour vrifier que lcriture // bien t effectue rewind($flux); echo "Position actuelle du pointeur :".ftell($flux)."\n"; while($c = fread($flux, 2048)) { echo "\n"; echo "entre :"; echo $c; }

9. La gestion des fichiers et des rpertoires

Le rsultat est maintenant le suivant :


Position actuelle du pointeur :17 1 GUEDON Laurent Position actuelle du pointeur :32 2 HEUTE Thomas Position actuelle du pointeur :0 Dplacer le pointeur sur la seconde entre :2

HEUTE

Thomas

Enregistrement dune nouvelle entre : 11 caractres ont t enregistr Position actuelle du pointeur :0 entre :1 entre :2 entre :3 GUEDON HEUTE HEUTE Laurent Thomas Damien

Vous pouvez observer que nous ne prenons pas en compte le mode douverture de la ressource. En effet, alors que nous avions slectionn louverture en lecture seule, il est possible dcrire des donnes dans la table. En consquence, cest au dveloppeur quil incombe la responsabilit de vrifier les accs la ressource en fonction du mode douverture de celle-ci. Nous pouvons spcifier ceci directement dans la mthode correspondante sans oublier dassigner le mode la proprit $mode de notre objet. Nous dclarons dans un premier temps une nouvelle proprit :
private $mode;

Ensuite, il faut lui assigner une valeur lors de lappel la fonction fopen() :
function stream_open($chemin, $mode, $options=, &$cheminReel=) { $url = parse_url($chemin); $this->db = mysql_connect($url[host], $url[user], $url[pass]); // On spare la base et la table list($base, $this->table) = split("\.", $url[path]); // On supprime le "/" devant le nom de la base

618

Les streams ou les flux

$base = substr($base, 1-strlen($base)); mysql_select_db($base);

9. La gestion des fichiers et des rpertoires

// On excute la requte de slection de la table $this->rs = mysql_query(select * from .$this->table, $this->db); $this->mode = $mode; return TRUE; }

Enfin excuter le test correspondant dans la mthode fwrite() :


function stream_write($donnee) { if($this->mode == "r") return FALSE; $data = explode ("\n", $donnee); $nboct = 0; // Formate la chane dinsertion des donnes // Celles-ci sont passes la fonction fwrite() ....

Si vous excutez le script, vous observez qu prsent, le mode dcriture "r" empche la cration de nouvelles entres dans la table. Vous pouvez ajouter un contrle dans la mthode fread() pour galement empcher la lecture lorsque le mode douverture de la ressource est en criture seule ("Write Only"). La fonction fstat() peut, elle aussi, tre implmente. Mme sil est vident quelle ne peut pas forcement retourner toutes les donnes que lon peut trouver en effectuant un fstat() sur un systme de fichier UNIX. La procdure stream_stat() est utilise chaque appel de cette fonction.

(Classe Stream Personnalise)->stream_stat()


Doit retourner le tableau associatif avec les clefs suivantes : [dev], [ino], [mode], [nlink], [uid], [gid], [rdev], [size], [atime], [mtime], [ctime], [blksize], [blocks] Syntaxe : retour array stream_stat(void) Retourne un tableau associatif comportant une ou plusieurs valeurs.

Dans notre exemple, nous allons mettre en oeuvre la procdure pour permettre la fonction fstat() de renseigner la date de cration, la date de dernire modification ainsi que la taille de la table (en comptant les indexes ).
function rettimestamp($datStr) { if(ereg("([0-9]{4})-([0-9]{2})-([0-9]{2}) ". // Dates "([0-9]{2}):([0-9]{2}):([0-9]{2})", // Heures $datStr, $regmatch)) { return mktime($regmatch[4], $regmatch[5], $regmatch[6], $regmatch[2], $regmatch[3], $regmatch[1]); } else { return FALSE;

619

Chapitre 9

La gestion des fichiers et des rpertoires

} }

9. La gestion des fichiers et des rpertoires

function stream_stat() { $sqlinfo = mysql_query(SHOW TABLE STATUS); $rsTableInfo = mysql_fetch_array($sqlinfo); $tableinfo = array( "size" => $rsTableInfo["Index_length"] + $rsTableInfo["Data_length"], "mtime" => $this->rettimestamp($rsTableInfo["Update_time"]), "ctime" => $this->rettimestamp($rsTableInfo["Create_time"]) ); return $tableinfo; }

Il ne nous reste plus qu appeler notre fonction fstat() et observer le rsultat:

Listing 9.43 : stream_open.php


echo "Informations sur la table :\n"; $stat = fstat($flux); echo "- Taille:".round($stat["size"]/1000, 1)." Ko\n"; echo "- Dernire modification:".date(j/m/Y G:i:s, $stat["mtime"])."\n"; echo "- Date de cration:".date(j/m/Y G:i:s, $stat["ctime"])."\n"; Informations sur la table : - Taille:2.7 Ko - Dernire modification:24/09/2004 13:49:18 - Date de cration:15/09/2004 17:05:50

La fonction unlink() est utilise pour supprimer les liens vers une ressource. Depuis PHP 5.0, il est possible dimplmenter dans un gestionnaire une mthode pouvant grer cette fonction. Il faut pour cela dfinir la mthode unlink().

(Classe Stream Personnalise)->unlink()


Dcrire dans la mthode, la suppression de la ressource dfinie par son URL. Elle ne peut tre implmente quavec les versions 5 et suprieures du langage PHP. Syntaxe : $chemin retour bool unlink(string $chemin) URL de la ressource supprimer Doit retourner TRUE si la ressource a bien t supprime et FALSE dans le cas contraire.

Voici un exemple expliquant la suppression dune ressource de type table laide de la fonction unlink().

620

Les streams ou les flux

Listing 9.44 : stream_unlink.php


<?php class fluxMysql { function unlink($chemin) { $url = parse_url($chemin); $db = mysql_connect($url[host], $url[user], $url[pass]); // On spare la base et la table list($base, $table) = split("\.", $url[path]); // On supprime le "/" devant le nom de la base $base = substr($base, 1-strlen($base)); mysql_select_db($base); mysql_query(DROP TABLE .$table, $db); mysql_close($db); } } stream_wrapper_register(mysql,fluxMysql) or die("Impossible denregistrer ce protocole !"); // Connexion $db = mysql_connect("localhost", "root", ""); mysql_select_db("bible"); // Cration dune table mysql_query(CREATE TABLE unlink (. ch1 VARCHAR( 10 ) NOT NULL ,. ch2 VARCHAR( 10 ) NOT NULL ,. ch3 VARCHAR( 10 ) NOT NULL), $db); // Insertion des donnes mysql_query("INSERT INTO unlink VALUES(test1, test1, test1)"); mysql_query("INSERT INTO unlink VALUES(test2, test2, test2)"); mysql_query("INSERT INTO unlink VALUES(test3, test3, test3)"); // Lecture des entres dans la table $rs = mysql_query("SELECT * FROM unlink"); while ($row = mysql_fetch_row($rs)) { echo "Entre : \n"; echo "\t".$row[0]."\n"; echo "\t".$row[1]."\n"; echo "\t".$row[2]."\n\n"; } mysql_close($db); // Suppression de la table via la fonction unlink() unlink("mysql://root@localhost/bible.unlink"); //Vrification de la suppression de la table // Connexion $db = mysql_connect("localhost", "root", ""); mysql_select_db("bible"); // Lecture des entres dans la table

621

9. La gestion des fichiers et des rpertoires

Chapitre 9

La gestion des fichiers et des rpertoires

$rs = mysql_query("SELECT * FROM unlink") or die ("Impossible de rcuprer les entres dans cette table"); while ($row = mysql_fetch_row($rs)) { echo "Entre : "; echo "\t".$row[0]."\n"; echo "\t".$row[1]."\n"; echo "\t".$row[2]."\n\n"; } mysql_close($db); ?>

9. La gestion des fichiers et des rpertoires

Et voici le rsultat :
Entre : test1 test1 test1 Entre : test2 test2 test2 Entre : test3 test3 test3 Impossible de rcuprer les entres dans cette table

Tous comme les fichiers, vous pouvez tre amen renommer vos ressources. Dans le cas dune base, vous pouvez modifier le nom de celle-ci. La mthode rename() est appele chaque excution de la fonction du mme nom (Si vous spcifiez, bien sur, votre gestionnaire dans lURL).

(Classe Stream Personnalise)->rename()


Renomme ou modifie le chemin vers votre ressource. Mthode implmenter uniquement avec les versions 5 et suprieures du langage PHP. Syntaxe : $ancienneRess $nouvelleRess retour bool rename(string $ancienneRess, string $nouvelleRess) Chemin vers lancienne ressource disponible Nouvelle ressource Retournez TRUE si lopration a t excute avec succs et FALSE dans le cas contraire.

622

Les streams ou les flux

Voici, comme lhabitude, un exemple dutilisation :

9. La gestion des fichiers et des rpertoires

Listing 9.45 : stream_rename.php


<?php class fluxMysql { function rename($anChemin, $nvChemin) { $url1 = parse_url($anChemin); $url2 = parse_url($nvChemin); // On ne prends pas en compte ici lurl complte // du nouveau chemin et on suppose que la mme base de donnes // est utilise pour la modification $db = mysql_connect($url1[host], $url1[user], $url1[pass]); // On spare la base et la table list($base1, $table1) = split("\.", $url1[path]); list($base2, $table2) = split("\.", $url2[path]); // On supprime le "/" devant le nom de la base $base1 = substr($base1, 1-strlen($base1)); mysql_select_db($base1); mysql_query(ALTER TABLE .$table1. RENAME TO .$table2, $db); mysql_close($db); } } stream_wrapper_register(mysql,fluxMysql) or die("Impossible denregistrer ce protocole !"); // Connexion $db = mysql_connect("localhost", "root", ""); mysql_select_db("bible"); // Cration dune table mysql_query(CREATE TABLE nomnaze (. ch1 VARCHAR( 10 ) NOT NULL ,. ch2 VARCHAR( 10 ) NOT NULL ,. ch3 VARCHAR( 10 ) NOT NULL), $db); // Insertion des donnes mysql_query("INSERT INTO nomnaze VALUES(test1, test1, test1)"); mysql_query("INSERT INTO nomnaze VALUES(test2, test2, test2)"); mysql_query("INSERT INTO nomnaze VALUES(test3, test3, test3)"); // Lecture des entres dans la table $rs = mysql_query("SELECT * FROM nomnaze"); echo "Il y a ".mysql_num_rows($rs)." Entre(s) dans la table naze !\n"; mysql_close($db); // Renommons la table rename("mysql://root@localhost/bible.nomnaze", "mysql://root@localhost/bible.nomquitue" );

623

Chapitre 9

La gestion des fichiers et des rpertoires

//Vrification que la table porte bien le nouveau nom // Connexion en utilisant lancien nom $db = mysql_connect("localhost", "root", ""); mysql_select_db("bible"); // Lecture des entres dans la table en utilisant lancien nom if($rs = mysql_query("SELECT * FROM nomnaze")) { echo "Lancien nom est utilis !"; } elseif($rs = mysql_query("SELECT * FROM nomquitue")) { echo "Nous utilisons maintenant le nouveau nom de la table !\n"; while ($row = mysql_fetch_row($rs)) { echo "Entre : \n"; echo "\t".$row[0]."\n"; echo "\t".$row[1]."\n"; echo "\t".$row[2]."\n\n"; } } mysql_close($db); ?> Il y a 3 Entre(s) dans la table naze ! Nous utilisons maintenant le nouveau nom de la table ! Entre : test1 test1 test1 Entre : test2 test2 test2 Entre : test3 test3 test3

9. La gestion des fichiers et des rpertoires

Comme les pour fonctions prcdentes, la fonction mkdir() qui est utilise pour crer un rpertoire, peut-tre ici utilis pour effectuer une toute autre opration. Nous devons pour cela implmenter une nouvelle mthode dans notre classe. Celle-ci est tous simplement la mthode mkdir().

(Classe Stream Personnalise)->mkdir()


Mthode implmenter pour excuter les commandes raliser la suite de lappel la fonction mkdir(). Elle ne peut tre implmente quavec les versions 5 et suprieures du langage PHP. Syntaxe : function mkdir(string $chemin, int $mode, int $options)

624

Les streams ou les flux

$chemin $mode $options

URL possdant le filtre appliquer ainsi que les informations permettant de traiter la ressource.

9. La gestion des fichiers et des rpertoires

Le mode est utilis pour indiquer les droits sur le dossier crer. Peut-tre indiques les options suivantes : STREAM_REPORT_ERRORS : Indique si les erreurs doivent tre leves par le gestionnaire. STREAM_MKDIR_RECURSIVE : Indique sil faut permettre la rcursivit de la fonction mkdir(). Indiquez TRUE si les commandes ont t ralises avec succs et FALSE dans le cas contraire.

retour

Voici un exemple dimplmentation de la mthode mkdir().

Listing 9.46 : stream_mkdir.php


<?php class fluxMysql { function mkdir($chemin, $mode=0777, $options=0) { $url = parse_url($chemin); $db = mysql_connect($url[host], $url[user], $url[pass]); $base = substr($url[path], 1-strlen($url[path])); $retour = mysql_query(CREATE DATABASE .$base, $db); mysql_close($db); return $retour; } } stream_wrapper_register(mysql,fluxMysql) or die("Impossible denregistrer ce protocole !"); if (mkdir("mysql://root@localhost/dbrmdir")) { echo "La base a t cre avec succs !"; } else { echo "Impossible de crer la base de donnes !"; } ?> La base a t cre avec succs !

Vous pouvez vrifier que la base de donnes est bien en place laide de phpMyAdmin ou du client MySQL. Si vous essayez de crer une nouvelle fois la base de donnes, le script vous retournera :
Impossible de crer la base de donnes !

Cette base une fois cre, vous pouvez la supprimer en SQL ou implmenter la mthode rmdir() dans votre classe pour quelle effectue lopration.

625

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

(Classe Stream Personnalise)->rmdir()


Mthode utilise lexcution de la fonction rmdir(). Elle ne peut tre implmente quavec les versions 5 et suprieures du langage PHP. Syntaxe : $chemin $options retour bool rmdir(string $chemin, int $options) URL possdant le filtre appliquer ainsi que les informations permettant de supprimer la ressource. Indiquez STREAM_REPORT_ERRORS si vous dsirez relever les erreurs laide du gestionnaire. Indiquez TRUE si les commandes de suppression ont t ralises avec succs et FALSE dans le cas contraire.

Voici le code prcdent arrang pour permettre la suppression de la base que vous venez de crer.
<?php class fluxMysql { function mkdir($chemin, $mode=0777, $options=0) { $url = parse_url($chemin); $db = mysql_connect($url[host], $url[user], $url[pass]); $base = substr($url[path], 1-strlen($url[path])); $retour = mysql_query(CREATE DATABASE .$base, $db); mysql_close($db); return $retour; } function rmdir($chemin, $option) { $url = parse_url($chemin); $db = mysql_connect($url[host], $url[user], $url[pass]); $base = substr($url[path], 1-strlen($url[path])); $retour = mysql_query(DROP DATABASE .$base, $db); mysql_close($db); return $retour; } } stream_wrapper_register(mysql,fluxMysql) or die("Impossible denregistrer ce protocole !"); // Cration de la base de donnes if (mkdir("mysql://root@localhost/dbrmdir")) { echo "La base a t cre avec succs !\n"; } else { echo "Impossible de crer la base de donnes !\n"; }

626

Les streams ou les flux

// Suppression de la base de donnes if (rmdir("mysql://root@localhost/dbrmdir")) { echo "La base a t supprime avec succs !\n"; } else { echo "Impossible de supprimer la base de donnes !\n"; } ?> La base a t cre avec succs ! La base a t supprime avec succs !

9. La gestion des fichiers et des rpertoires

Voyons maintenant comment nous pourrions lister les tables contenues dans une base de donnes. Pour cela nous allons implmenter dans notre gestionnaire la mthode dir_opendir().

(Classe Stream Personnalise)->dir_opendir()


Mthode appele lors de lutilisation de la fonction opendir(). Syntaxe : $chemin $options retour bool dir_opendir(string $chemin, int $options) URL indiquant le chemin vers la ressource traiter. Indiquez STREAM_REPORT_ERRORS si vous dsirez relever les erreurs laide du gestionnaire. Indiquez TRUE si la ressource a t ouverte avec succs et FALSE dans le cas contraire.

Nous avons galement besoin de crer une mthode dir_readdir() qui sera appel lors de chaque excution de la fonction readdir().

(Classe Stream Personnalise)->dir_readdir()


Mthode retournant le nom du prochain "fichier" ouvert. Celle-ci est appel lexcution de la fonction readdir(). Cette mthode sutilise conjointement avec dir_opendir(). Syntaxe : retour string dir_readdir(void) Retourne une chane reprsentant le nom du prochain fichier.

Noublions pas quil est ncessaire (parfois) de librer la ressource utilise. La mthode
dir_closedir() est l pour a !

627

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

(Classe Stream Personnalise)->dir_closedir()


Mthode appele lors de lexcution de la fonction closedir(). Vous limplmenterez de faon librer la ressource ouverte par dir_opendir(). Syntaxe : retour bool dir_closedir(void) Indiquez TRUE en cas de succs et FALSE dans le cas contraire.

Implmentation de ces mthodes pour rcuprer les tables contenues dans une base de donnes.

Listing 9.47 : dir_opendir.php


<?php class fluxMysql { private $base; var $table; function dir_opendir($chemin, $option=0) { $url = parse_url($chemin); $this->base = mysql_connect($url[host], $url[user], $url[pass]); $base = substr($url[path], 1-strlen($url[path])); if($this->table = mysql_list_tables($base, $this->base)) { return TRUE; } else { return FALSE; } } function dir_readdir() { if ($row = mysql_fetch_row($this->table)) { return $row[0]; } else { return FALSE; } } function dir_closedir() { return mysql_close($this->base); } } stream_wrapper_register(mysql,fluxMysql) or die("Impossible denregistrer ce protocole !"); // Cration dune base de donnes pour lexemple // Connexion au serveur $db = mysql_connect("localhost", "root", ""); mysql_query(CREATE DATABASE dir_opendir, $db);

628

Les streams ou les flux

// Connexion cette base de donnes mysql_select_db("dir_opendir"); // Cration de 10 tables for ($i=0; $i<10; $i++) { mysql_query(CREATE TABLE ex.$i. (. ch1 VARCHAR( 10 ) NOT NULL ,. ch2 VARCHAR( 10 ) NOT NULL ,. ch3 VARCHAR( 10 ) NOT NULL), $db); } mysql_close($db); // Liste les tables de la base de donnes $flux = opendir("mysql://root@localhost/dir_opendir") or die("Impossible douvir la ressource !"); echo "Liste des tables : \n"; while($table = readdir($flux)) { echo "-> ".$table."\n"; } closedir($flux); // Suppression de la base $db = mysql_connect("localhost", "root", ""); mysql_query(DROP DATABASE dir_opendir, $db); mysql_close($db); ?>

9. La gestion des fichiers et des rpertoires

Le rsultat de lexcution de ce script :


Liste des tables : -> ex0 -> ex1 -> ex2 -> ex3 -> ex4 -> ex5 -> ex6 -> ex7 -> ex8 -> ex9

Enfin, il est possible de rinitialiser le pointeur du flux si vous implmenter la mthode dir_rewinddir().

629

Chapitre 9

La gestion des fichiers et des rpertoires

9. La gestion des fichiers et des rpertoires

(Classe Stream Personnalise)->dir_rewinddir()


Mthode appele lors de lexcution de la fonction rewinddir(). A vous dcrire les commandes permettant de rinitialiser le pointeur du flux sa position principale. Syntaxe : retour bool dir_rewinddir(void) Retournez la valeur TRUE en cas de succs et FALSE dans le cas contraire.

Voici la source finale de cet exemple :


<?php class fluxMysql { private $base; var $table; function dir_opendir($chemin, $option=0) { $url = parse_url($chemin); $this->base = mysql_connect($url[host], $url[user], $url[pass]); $base = substr($url[path], 1-strlen($url[path])); if($this->table = mysql_list_tables($base, $this->base)) { return TRUE; } else { return FALSE; } } function dir_readdir() { if ($row = mysql_fetch_row($this->table)) { return $row[0]; } else { return FALSE; } } function dir_closedir() { return mysql_close($this->base); } function dir_rewinddir() { return mysql_data_seek($this->table, 0); } } stream_wrapper_register(mysql,fluxMysql) or die("Impossible denregistrer ce protocole !");

// Cration dune base de donnes pour lexemple // Connexion au serveur

630

Les streams ou les flux

$db = mysql_connect("localhost", "root", ""); mysql_query(CREATE DATABASE dir_opendir, $db);

9. La gestion des fichiers et des rpertoires

// Connexion cette base de donnes mysql_select_db("dir_opendir"); // Cration de 10 tables for ($i=0; $i<10; $i++) { mysql_query(CREATE TABLE ex.$i. (. ch1 VARCHAR( 10 ) NOT NULL ,. ch2 VARCHAR( 10 ) NOT NULL ,. ch3 VARCHAR( 10 ) NOT NULL), $db); } mysql_close($db); // Liste les tables de la base de donnes $flux = opendir("mysql://root@localhost/dir_opendir") or die("Impossible douvir la ressource !"); echo "Liste des tables : \n"; while($table = readdir($flux)) { echo "-> ".$table."\n"; } // On reinitialise le pointeur la position 0 rewinddir($flux); // Et on recommence echo "\nListe des tables (encore !): \n"; while($table = readdir($flux)) { echo "-> ".$table."\n"; } closedir($flux); // Suppression de la base $db = mysql_connect("localhost", "root", ""); mysql_query(DROP DATABASE dir_opendir, $db); mysql_close($db); ?>

Avec le rsultat suivant :


Liste des tables : -> ex0 -> ex1 -> ex2 -> ex3 -> ex4 -> ex5 -> ex6 -> ex7

631

Chapitre 9

La gestion des fichiers et des rpertoires

-> ex8 -> ex9

9. La gestion des fichiers et des rpertoires

Liste des tables (encore !): -> ex0 -> ex1 -> ex2 -> ex3 -> ex4 -> ex5 -> ex6 -> ex7 -> ex8 ->.ex9

632

Chapitre 10

Lutilisation des bases de donnes


10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 10.10 10.11 10.12 10.13 10.14 Introduction aux bases de donnes . . . Introduction au langage SQL . . . . . . . Les relations entre tables . . . . . . . . . . Le langage SQL . . . . . . . . . . . . . . . . Accder une base de donnes via PHP Prsentation de lapplication dexemple Access (MS) . . . . . . . . . . . . . . . . . . DB2 (IBM) . . . . . . . . . . . . . . . . . . MySQL . . . . . . . . . . . . . . . . . . . . . ODBC . . . . . . . . . . . . . . . . . . . . . . Oracle . . . . . . . . . . . . . . . . . . . . . SQLite . . . . . . . . . . . . . . . . . . . . . . SQL Server (MS) . . . . . . . . . . . . . . . Les couches dabstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635 636 636 639 652 654 683 687 690 730 761 812 836 871

Introduction aux bases de donnes

i vous souhaitez stocker des informations et pouvoir, par la suite, les trier, les compter, les filtrer, alors vous serez certainement amen utiliser une base de donnes.

Les bases de donnes peuvent tre utilises pour grer un rpertoire tlphonique ; dans ce cas, vous y stockerez probablement des noms, prnoms, adresses et numros de tlphone et, la plupart du temps, vous filtrerez ces informations par nom. Elles peuvent galement tre utilises pour stocker les messages dun forum, qui pourront alors tre tris par date ou par fil de discussion. Comme vous le pressentez, il y a de nombreux domaines dapplications ayant recours aux bases de donnes. Le choix dune base de donnes nest pas simple, il peut vous tre dict par votre hbergeur, par votre suprieur, par le cot, par les performances, par votre "religion" informatique... PHP 5 simplifie grandement lutilisation de petites bases de donnes en intgrant SQLite qui ne ncessite aucune installation ni cration dutilisateurs. Avant de voir comment utiliser une base de donnes (avec PHP), dtaillons ce quest une base de donnes (nous ne nous intresserons ici quaux bases de donnes relationnelles).

10. Lutilisation des bases de donnes

10.1. Introduction aux bases de donnes


Une base de donnes peut tre assimile un ensemble de fichiers (dans lesquels sont stockes les informations). Ces derniers sont grs uniquement par un logiciel serveur (il nest absolument pas question que vous les manipuliez directement). Tout comme vos scripts PHP sont mis disposition du public par un serveur Internet, vos donnes sont mises disposition par un serveur de bases de donnes. Les utilisateurs, quant eux, devront utiliser un logiciel client pour manipuler ces donnes. Les diffrents diteurs de bases de donnes fournissent ainsi systmatiquement le client et le serveur de bases de donnes. En rgle gnrale, le client dune base de donnes ne sera capable de communiquer quavec le serveur pour lequel il a t conu. Comme nous le verrons par la suite, il existe toutefois des standards permettant de communiquer avec plusieurs types de serveurs de bases de donnes. Comme nous lavons dit, lutilisateur devra accder aux donnes en utilisant le logiciel client appropri. Or, si le logiciel diffre dun serveur de bases de donnes lautre, il existe des familles de bases de donnes qui utilisent plus ou moins le mme langage, savoir le langage SQL.

Interface graphique Il existe galement des clients ayant une interface graphique utilisable directement via votre navigateur. Pour MySQL, vous pourrez par exemple utiliser phpMyAdmin.

Reportez-vous lannexe "phpMyAdmin" pour plus de dtails.

635

Chapitre 10

Lutilisation des bases de donnes

10.2. Introduction au langage SQL


Le langage SQL (Structured Query Language = langage de requtes structures) est cens tre normalis (notamment avec les normes SQL92 et SQL99), mais la plupart des diteurs ladaptent leur sauce.

10. Lutilisation des bases de donnes

Ce langage sappuie sur une reprsentation des donnes sous forme de tables. Une table peut tre assimile un tableau. Chaque table est compose de champs (les colonnes du tableau) et denregistrements (les lignes du tableau). Dans le cas dun rpertoire tlphonique, chaque enregistrement reprsentera un individu, et il y aura un champ pour le nom, un champ pour le prnom, etc. Une base de donnes peut (et cest quasiment toujours le cas) contenir plusieurs tables lies les unes aux autres. Il est noter quun mme serveur de bases de donnes peut hberger plusieurs bases de donnes (autrement dit plusieurs ensembles de tables).

Le typage
Une des forces des bases de donnes SQL sur les fichiers est, entre autres, que les champs sont typs. Il nest donc pas question de tenter de mettre une chane de caractres l o un entier est attendu, ce qui assure une certaine cohrence dans les informations. En revanche, il faudra videmment bien rflchir au choix du type de donnes (ce qui ne constitue gnralement pas une grosse difficult). Cela peut avoir son importance, notamment lors doprations de tri. Ainsi, des nombres stocks dans un champ de type texte ne seront pas tris de la mme manire que sils sont dans un champ de type entier. En effet, la chane de caractres "10" est alphanumriquement plus petite (avant) que "2" (le premier caractre de "10" tant avant le premier caractre de "2"), alors que le nombre 2 est plus petit que le nombre 10. Le choix du type est galement important en terme doccupation du disque : un nombre stock sous forme dune chane de caractres prend ncessairement plus de place que sil est stock sous sa forme binaire. Inutile, de mme, de choisir un type sur 3 octets pour un nombre entier compris entre 0 et 255 (tenant donc sur un unique octet).

Les contraintes
Le langage SQL permet galement dimposer des contraintes (autres que le type) sur les donnes, ceci toujours afin dassurer la cohrence des informations. Il est, par exemple, ainsi possible dobliger ce quun champ soit renseign, ou bien ce que la valeur donne appartienne une liste prdfinie (ce dernier point nest toutefois pas vrai pour tous les serveurs de bases de donnes).

10.3. Les relations entre tables


Les rgles de conception dune base de donnes peuvent un peu drouter les nophytes, mais ce nest finalement pas aussi compliqu que cela parat (mme sil existe des mthodes bien savantes, la plus clbre concernant les bases de donnes tant Merise). En effet, il nest

636

Les relations entre tables

gnralement pas question davoir une base de donnes ne possdant quune seule table, dans laquelle on mettrait toutes les informations (comme dans un fourre-tout). Non. Gnralement, une base est constitue de plusieurs tables relies entre elles par un ou plusieurs champs identifiant de faon unique un enregistrement de la table. Explication. Imaginez que vous souhaitez constituer une base de donnes de films. Dans ce cas, vous serez amen indiquer le nom du film, le nom du ralisateur ainsi que la liste des acteurs. Mais, vous comprenez bien quil nest pas question davoir une table (comme la suivante) avec, pour chaque enregistrement, un triplet (film, ralisateur, acteur), sachant quil y a plusieurs acteurs par film et que nous serions obligs de rpter le nom du ralisateur.

10. Lutilisation des bases de donnes

Tableau 10.1 : Exemple de table dune base de donnes mal conue


Film Forrest Gump Forrest Gump Il faut sauver le soldat Ryan Il faut sauver le soldat Ryan Ralisateur Robert Zemeckis Robert Zemeckis Steven Spielberg Steven Spielberg Acteur Tom Hanks Robin Wright Penn Tom Hanks Edward Burns

Nous pourrions ventuellement envisager de crer une table avec plusieurs champs acteur (acteur1, acteur2, etc.). Bien que ce soit gnralement le premier rflexe des nophytes, cela est une trs mauvaise ide. Ne serait ce que parce que lon ne sait pas, a priori, combien il y a dacteurs (au maximum) par film. Non, comme nous lavons dj dit, il faut alors faire plusieurs tables. Dans notre cas, une premire approche (pas encore satisfaisante) peut consister avoir une table de couples film/ralisateur et une table de couples film/acteur. Mais, dans ce cas, nous serions nouveau oblig de dupliquer les noms des films et des acteurs (si ces noms sont saisis manuellement, les risques de fautes de frappes sont importants). La solution consiste crer une table film, une table ralisateur et une table acteur, ainsi que des tables de liaisons. Les valeurs de champs dupliques seront alors remplaces par des rfrences un champ dune table. Ce qui donne, dans notre cas :

Tableau 10.2 : Table Film


FilmId 1 2 Film Forrest Gump Il Faut Sauver le Soldat Ryan

Tableau 10.3 : Table Acteur


ActeurId 1 2 3 Acteur Tom Hanks Robin Wright Penn Edward Burns

637

Chapitre 10

Lutilisation des bases de donnes

Tableau 10.4 : Table de liaison Film-Acteur


FilmId 1 1 2 ActeurId 1 2 1 3

10. Lutilisation des bases de donnes

Tableau 10.5 : Table Ralisateur


RealisateurId 1 2 3 Realisateur Robert Zemeckis Steven Spielberg Nora Ephron

Tableau 10.6 : Table de liaison Film-Ralisateur


FilmId 1 2 3 RealisateurId 1 2 3

premire vue, cela est devenu plutt illisible et difficile manipuler. Dtrompez-vous ; les requtes SQL vous permettront daccder simplement aux donnes. La difficult que peut prsenter la saisie des donnes dans ces tables sera gnralement masque par une interface graphique. Mais, surtout, nous avons grandement gagn en libert. Il ny a dsormais plus de contraintes: Il est possible dindiquer autant de noms dacteurs et de ralisateurs que voulus par film. Aucun nom de film, dacteur ou de ralisateur nest dupliqu (il sera donc facile de les corriger si besoin). Et enfin, dtail qui a toute son importance, une base de donnes ainsi structure occupera beaucoup moins de place que les premires versions envisages. En effet, si lon considre une base de 65 535 films (ce qui est relativement peu pour une base de donnes) faisant intervenir au plus un total de 65 535 acteurs et ralisateurs, alors les identifiants de film, acteur et ralisateur pourront tre stocks sur 2 octets. Si lon compte un ralisateur et cinq acteurs prciss par film, et si lon suppose que les noms de film, dacteur et de ralisateur ncessitent en moyenne 25 caractres, alors :
j j j j

La taille de la table film est 65 535*(2+25) = 1 769 445 octets. La taille de la table acteur est 65 535*(2+25) = 1 769 445 octets La taille de la table de liaison film-acteur est 65 535*5*(2+2) = 1 310 700 octets. La taille de la table ralisateur est 65 535*(2+25) = 1 769 445 octets.

638

Le langage SQL

La taille de la table de liaison film-ralisateur est 65 535*(2+2) = 262 140 octets.

Soit un total de 6 881 175 octets = 6,56 Mo. Alors quavec la premire version propose, la base de donnes aurait eu une taille de 65 535*5*(25+25+25) = 24 575 625 octets = 23,4 Mo.

10. Lutilisation des bases de donnes

Cls primaires et compteurs


Lidentifiant unique dun enregistrement dans une table est appel la cl primaire. Cest assez souvent un champ numrique (comme voqu dans lexemple prcdent) portant comme nom "Id" ou se terminant par "Id" (ou encore "PK" comme "Primary Key"). La cl primaire peut toutefois tre un champ dun autre type, ou encore tre un ensemble de champs. Dans le cas dune cl primaire numrique du type de celle prsente dans lexemple prcdent, il est fort intressant de pouvoir dterminer quelle est la valeur suivante disponible. Pour cela, un certain nombre de serveurs de bases de donnes proposent un type particulier (ex. : SERIAL pour PostgreSQL) ou "modificateur" de type (ex. : AUTO_INCREMENT pour MySQL) que lon peut appeler "compteur" ou "type auto-incrment". Certains serveurs (ex. : Oracle) ne proposent pas ce type de facilit, mais il est alors possible dobtenir le mme effet avec une SEQUENCE et un TRIGGER.

Index
Pour les champs sur lesquels de nombreuses recherches sont effectues, il est gnralement recommand dassocier un index. Cette opration est bien souvent implicitement applique sur les cls primaires, mais vous pourrez tre amen vous poser la question de lintrt lutiliser pour un autre de vos champs. Nous ne nous tendrons pas sur ce sujet, mais sachez que ceci permet dacclrer grandement les recherches (mme si cela entrane un dlai supplmentaire lors de lajout de donnes, et rclame quelques ressources disque et mmoire supplmentaires).

10.4. Le langage SQL


Il nest pas dans notre intention de dcrire, ici, lensemble des commandes SQL (il faudrait y consacrer un livre complet). Mais voici, tout de mme, les principales ; celles qui, probablement, rpondront 90 % de vos besoins. Si vous souhaitez tester immdiatement ces commandes, vous devez au pralable consulter la documentation de votre base de donnes afin didentifier et de lancer le logiciel client. Une fois que vous avez accs au client de votre base de donnes, vous pouvez saisir ces commandes, en nomettant pas (gnralement) de les faire suivre dun point-virgule (indiquant ainsi au client, non pas que vous souhaitez aller la ligne, mais que vous avez fini de saisir votre requte). Il est noter que certaines de ces oprations ncessitent des droits (privilges) particuliers ; vous ne serez donc pas ncessairement autoris les raliser.

639

Chapitre 10

Lutilisation des bases de donnes

Cration/suppression dune base de donnes


La cration dune base de donnes nest pas toujours ralisable depuis le logiciel client de la base de donnes. Pour certaines bases, cette opration doit tre ralise partir dun excutable fourni avec le serveur.

10. Lutilisation des bases de donnes

CREATE DATABASE
Cre une base de donnes. Syntaxe nombase CREATE DATABASE nombase Nom de la base de donnes crer.

La suppression de la base de donnes (attention aux fausses manipulations) se fait via la commande :

DROP DATABASE
Supprime une base de donnes. Syntaxe nombase DROP DATABASE nombase Nom de la base de donnes supprimer.

Les types
Avant de passer la suite, il est ncessaire de vous prsenter les diffrents types supports par les bases de donnes. L encore, cela peut varier dun serveur lautre, mais cela reste, dans les grandes lignes, sensiblement identique (nous nous sommes bass principalement sur les types MySQL). Certains types peuvent avoir des noms diffrents selon les serveurs. De ce fait, de nombreux serveurs acceptent plusieurs noms pour dsigner un mme type.

Les types numriques


Tableau 10.7 : Les types numriques entiers signs
Type TINYINT SMALLINT INT2 MEDIUMINT Valeur min. -128 -32768 -8388608 Valeur max. 127 32767 8388607 Taille en octets 1 2 3

640

Le langage SQL

Type INT INT4 INTEGER BIGINT INT8

Valeur min. -2147483648

Valeur max. 2147483647

Taille en octets 4

-9223372036854775808

9223372036854775807

10. Lutilisation des bases de donnes

Il est galement possible dutiliser des types entiers non signs en compltant le nom du type par UNSIGNED. Cela permet datteindre une valeur maximale plus grande (lorsque les noms ngatifs ne sont pas utiliss).

Tableau 10.8 : Les types numriques entiers non signs


Type TINYINT UNSIGNED SMALLINT UNSIGNED INT2 UNSIGNED MEDIUMINT UNSIGNED INT UNSIGNED INT4 UNSIGNED INTEGER UNSIGNED BIGINT UNSIGNED INT8 UNSIGNED Valeur min. 0 0 0 0 Valeur max. 255 65535 16777215 2147483647 Taille en octets 1 2 3 4

18446744073709551615

Il est noter que rares sont les bases de donnes qui proposent un type boolen.

Tableau 10.9 : Les types numriques dcimaux


Type FLOAT FLOAT4 DOUBLE DOUBLE PRECISION REAL FLOAT8 DECIMAL NUMERIC tendue [-3.402823466E+38, -1.175494351E-38] U {0} U [1.175494351E-38, 3.402823466E+38] [-1.7976931348623157E+308, -2.2250738585072014E-308] U {0} U [2.2250738585072014E-308, 1.7976931348623157E+308] Taille en octets 4

641

Chapitre 10

Lutilisation des bases de donnes

Les types texte


Tableau 10.10 : Les types texte
Type CHAR Taille en octet 1 Dpend de X Variable Variable Variable Variable Variable Variable Chane de taille fixe de X caractres, ne pouvant dpasser 255 caractres. Chane de taille variable ne pouvant dpasser X caractres (X ne peut dpasser 255). Chane de caractres limite 255 caractres. Chane de caractres limite 65 535 caractres. Chane de caractres limite 16 777 215 caractres. Chane de caractres limite 4 294 967 295 caractres. Chane de caractres sans limite. Description

10. Lutilisation des bases de donnes

CHARACTER(X) CHAR(X) CHARACTER VARYING(X) VARCHAR(X) TINYBLOB TINYTEXT BLOB TEXT (MySQL) MEDIUMBLOB MEDIUMTEXT LONGBLOB LONGTEXT TEXT (PostgreSQL)

Les types date


Tableau 10.11 : Les types dates
Type DATE DATETIME TIMESTAMP (MySQL) TIMESTAMP TIME (MySQL) TIME (PostgreSQL) TIME WITH TIME ZONE (PostgresSQL) YEAR (MySQL) HH:MM:SS Format AAAA-MM-JJ AAAA-MM-JJ hh:mm:ss AAAAMMJJHHMMSS Prcision jour seconde seconde microseconde seconde microseconde microseconde anne 4 4 4 Taille en octets

642

Le langage SQL

Cration/suppression dune table


Il existe de nombreuses variantes, dune base de donnes lautre, au niveau des options (qui ne seront donc gnralement pas prcises ici), mais les requtes lmentaires restent les mmes.

10. Lutilisation des bases de donnes

CREATE TABLE
Cre une table. Syntaxe nomtable champs CREATE TABLE nomtable (champs) Nom de la table crer. Dfinition des champs de la table. (Voir ci-aprs)

Les champs de la table sont dfinis par une succession de squences "nomchamp type [attributs de champ]" spares par des virgules ventuellement suivies par les attributs de la table. Un exemple tout simple de cration de table permettant de stocker un identifiant de film, un nom et une date de sortie donne :
CREATE TABLE film (filmid INT2 UNSIGNED, film VARCHAR(64), datesortie DATE);

Les attributs des champs peuvent tre : NOT NULL NULL Pour indiquer que le champ ne peut pas tre non renseign (NULL). Pour prciser que le champ peut tre laiss non renseign (NULL), (attribut par dfaut).

DEFAULT valeurpardefaut Pour prciser une valeur par dfaut si le champ nest pas renseign (ou mis NULL). PRIMARY KEY AUTO_INCREMENT Pour indiquer quil sagit dune cl primaire. (Uniquement valable pour MySQL). Pour prciser que, par dfaut, ce champ doit prendre la valeur du dernier indice affect + 1. Ce champ doit tre une cl.

Si lon reprend notre exemple, il est vident que le nom du film ne doit pas tre laiss vide et que filmid est une cl primaire.
CREATE TABLE film (filmid INT2 UNSIGNED PRIMARY KEY, film VARCHAR(64) NOT NULL, datesortie DATE);

Comme nous lavons galement dit, il est souhaitable que le champ filmid soit auto-incrment ; la requte devrait tre, sous MySQL :
CREATE TABLE film (filmid INT2 UNSIGNED PRIMARY KEY AUTO_INCREMENT, film VARCHAR(64) NOT NULL, datesortie DATE);

643

Chapitre 10

Lutilisation des bases de donnes

Les attributs de la table peuvent tre : PRIMARY KEY (champ1, champ2, ...) Pour prciser une cl primaire sur plusieurs champs. INDEX [nomindex] (champ1, champ2, ...) Pour prciser une cl sur plusieurs champs. Un index sera alors cr, avec la possibilit de prciser son nom avec nomindex.

10. Lutilisation des bases de donnes

UNIQUE [INDEX] [nomindex] (champ1, champ2, ...)

Pour contraindre lunicit de lensemble (champ1, champ2, ..) dans la table.

Certaines bases utilisent le mot-cl KEY au lieu de INDEX (avec la mme syntaxe). Poursuivons notre exemple. Il nest pas question de prciser plusieurs fois quun acteur donn a jou dans un film donn. Donc, pour viter les doublons, la dfinition de la table de liaison film-acteur pourra tre :
CREATE TABLE film2acteur (filmid INT2 NOT NULL, acteurid INT2 NOT NULL, UNIQUE(filmid, acteurid));

Vous vous tes compltement tromp ? Vous ne voulez plus de cette table ? Pas de problme ! vous pouvez la supprimer avec linstruction :

DROP TABLE
Suppression dune table. Syntaxe nomtable DROP TABLE nomtable Nom de la table supprimer (il est possible den prciser plusieurs spars par une virgule).

Si, en revanche, vous souhaitez apporter une correction une table existante, vous pouvez faire appel :

ALTER TABLE
Modifie la structure dune table existante. Syntaxe nomtable modification ALTER nomtable modification Nom de la table modifier. Modification apporter la table (voir ci-aprs). (Il est possible dapporter plusieurs modifications en les sparant par une virgule).

644

Le langage SQL

Les modifications qui peuvent tre apportes sont :


j
ADD [COLUMN] champ : pour ajouter un champ (en utilisant la mme syntaxe que pour CREATE TABLE). Le mot-cl COLUMN na pas dimpact et est gnralement optionnel. Il

assure simplement la compatibilit avec les syntaxes dautres serveurs de bases de donnes.
j j j j
ADD PRIMARY KEY (champ1, champ2, ...) : pour prciser une cl primaire (cf. CREATE TABLE). ADD INDEX [nomindex] (champ1, champ2, ...) : pour ajouter un index (cf. CREATE TABLE). ADD UNIQUE [nomindex] (champ1, champ2, ...) : pour ajouter une contrainte

10. Lutilisation des bases de donnes

dunicit (cf. CREATE TABLE).


DROP [COLUMN] nomchamp : pour supprimer le champ "nomchamp". Le mot cl COLUMN na pas dimpact et est gnralement optionnel. Il assure simplement la compatibilit avec les syntaxes dautres serveurs de bases de donnes. DROP PRIMARY KEY : pour supprimer une dfinition de cl primaire. DROP INDEX nomindex : pour supprimer lindex "nomindex". RENAME [AS|TO] nomtable2 : pour renommer la table en "nomtable2".

j j j

Ainsi, si nous voulons galement prciser la dure du film (en minutes), et mettre, par dfaut, 0, il est possible de reprendre la table cre prcdemment pour faire :
ALTER TABLE film ADD duree INT2 DEFAULT 0

Ajouter des donnes


Nous allons maintenant pouvoir entrer dans le vif du sujet. Ajouter des donnes, cest trs simple. Pour cela, vous disposez de la commande :

INSERT
Ajoute un enregistrement dans une table. Syntaxe nomtable champ1, champ2, INSERT INTO nomtable [(champ1, champ2, ...)] VALUES (valeur1, valeur2, ...) Nom de la table dans laquelle insrer les donnes du nouvel enregistrement. Noms des champs que vous souhaitez prciser (les autres champs prendront leur valeur par dfaut). Si vous ne spcifiez pas de liste de noms de champs, alors vous devrez prciser toutes les valeurs et dans lordre des champs.

valeur1, valeur2, Valeurs des champs dans le mme ordre que prcis par les noms des champs. Les chanes de caractres et dates doivent tre spcifies entre apostrophes. Si la valeur contient une apostrophe, alors vous pouvez au

645

Chapitre 10

Lutilisation des bases de donnes

choix (et selon le serveur de bases de donnes) mettre deux apostrophes ou faire prcder lapostrophe dun anti-slash. Une variante consiste crire INSERT INTO nomtable SET champ1=valeur1, champ2=valeur2, .. Avec MySQL le mot-cl INTO est optionnel (mais ce nest pas une raison pour lomettre).

10. Lutilisation des bases de donnes

Si lon reprend une table cre par


CREATE TABLE film (filmid INT2 UNSIGNED PRIMARY KEY, film VARCHAR(64) NOT NULL)

il sera alors possible dajouter un enregistrement, soit avec la requte suivante :


INSERT INTO film VALUES (1, Forrest Gump);

soit en prcisant les noms de tous les champs :


INSERT INTO film (filmid, film) VALUES (1, Forrest Gump); INSERT INTO film (film, filmid) VALUES (Forrest Gump, 1);

soit, notamment pour profiter du champ auto-incrment, avec :


INSERT INTO film VALUES (NULL, Forrest Gump); INSERT INTO film (film) VALUES (Forrest Gump);

Si le nom du film contient une apostrophe, alors la requte aura lallure suivante :
INSERT INTO film (film) VALUES (La vie nest pas un long fleuve tranquille); INSERT INTO film (film) VALUES (La vie n\est pas un long fleuve tranquille);

Mettre jour des donnes


Il est bien videmment possible de modifier des donnes ; pour cela, vous disposez de la commande UPDATE.

UPDATE
Met jour un ensemble denregistrements. Syntaxe nomtable champX valeurX condition UPDATE nomtable SET champ1=valeur1[, champ2=valeur2] [WHERE condition] Nom de la table contenant les enregistrements modifier. Nom du champ dont on veut modifier la valeur. Nouvelle valeur pour le champ. Critres de slection des enregistrements devant tre modifis.

646

Le langage SQL

Si vous souhaitez apporter une modification sur lensemble de la table, vous pouvez lancer une requte du type :
UPDATE film SET film=Forrest Gump;

Dans ce cas, tous les films de la base porteront le mme nom (ce nest certainement pas ce que lon veut, mais la requte aurait t similaire si nous avions voulu rinitialiser un champ servant, par exemple, compter le nombre de clics sur un lien). Il existe de nombreux oprateurs et fonctions pouvant tre utiliss dans les expressions de conditions ou mme encore qui peuvent tre appliques aux valeurs retournes. Mme si nous vous en prsenterons quelques-uns au fil de ce chapitre, il vous est conseill de consulter la documentation de votre serveur de bases de donnes pour en avoir la liste exhaustive. La condition la plus rudimentaire est, bien videmment, lgalit. Ainsi, si vous avez fait une faute dorthographe dans le nom du film ayant lidentifiant 1, vous pourrez excuter la requte :
UPDATE film SET film=Forrest Gump WHERE filmid=1;

10. Lutilisation des bases de donnes

Mais il est galement possible, par exemple, de modifier les noms de tous les titres de films commenant par "F" (mme si, dans notre cas, cela na pas de sens), en utilisant linstruction LIKE et le joker % (quivalent du * dans la plupart des systmes dexploitation, qui remplace un nombre quelconque de caractres).
UPDATE film SET film=Forrest Gump WHERE film LIKE F%;

Le joker pour un caractre unique (quivalent du ? dans la plupart des systmes dexploitation) est lunderscore _. Notez toutefois quil est possible de complter la requte pour utiliser dautres caractres comme joker.

Supprimer des donnes


Si vous souhaitez supprimer une donne, faites appel linstruction DELETE.

DELETE
Supprime un ensemble denregistrements. Syntaxe nomtable condition DELETE FROM nomtable [WHERE condition] Nom de la table contenant les enregistrements supprimer. Critres de slection des enregistrements devant tre modifis.

Pour vider totalement la table film, vous naurez donc qu saisir la requte suivante :
DELETE FROM film;

Si vous souhaitez supprimer les enregistrements pour lesquels le nom du film nest pas renseign (cela ne peut pas arriver si vous avec cr la table avec le champ film dfini comme NOT NULL), vous devrez utiliser :

647

Chapitre 10

Lutilisation des bases de donnes

DELETE FROM film WHERE film IS NULL;

NULL est diffrent de la chane vide Attention, il ne faut pas confondre un champ non renseign (reprsent par NULL) avec une chane de caractres vide (reprsente par deux apostrophes conscutives). 10. Lutilisation des bases de donnes

Lire des donnes


Maintenant que nous avons vu comment ajouter des enregistrements, nous allons voir comment y accder en lecture. Pour cela nous disposons de linstruction SELECT, dont voici la syntaxe abrge :

SELECT
Retourne un ensemble denregistrements. Syntaxe DISTINCT ALL table1, table2 condition SELECT [DISTINCT|ALL] champ1, champ2, ... FROM table1, table2,... [WHERE condition] Pour ne retourner que des valeurs diffrentes (pas de doublons). Pour autoriser les doublons (valeur par dfaut). Liste des tables impliques dans la recherche. Condition que doivent remplir les enregistrements.

champ1, champ2,... Liste des champs retourner.

Pour avoir la liste de tous les noms des films connus de la base de donnes, vous naurez qu excuter la requte :
SELECT film FROM film;

Si vous souhaitez galement rcuprer lidentifiant du film vous utiliserez alors plutt :
SELECT filmid, film FROM film;

ce qui revient afficher tous les champs des films, et qui peut se faire de faon plus gnrique avec :
SELECT * FROM film;

Si, par contre, vous ne souhaitez que le nom du film ayant pour identifiant la valeur 1, la requte devient :
SELECT film FROM film WHERE filmid=1;

Et, pour avoir la liste des films commenant par "F" :

648

Le langage SQL

SELECT film FROM film WHERE film LIKE F%;

Tout en continuant de nous intresser cette syntaxe de base, nous allons lgrement compliquer laffaire afin de nous rapprocher dune requte classique. Nous avons, en effet, vu quil tait souvent prfrable de stocker les informations dans de multiples tables lies entre elles par des cls primaires. Mais nous ne savons pas encore comment mettre en oeuvre ces liens. Pour cela, il suffit dutiliser la requte SELECT sur plusieurs tables, et de prciser dans la clause WHERE la condition du lien. Concrtement si lon a deux tables, lune stockant des noms de villes et lautre des noms de magasins ainsi quun identifiant de ville (ville o se situe le magasin) crs avec les requtes suivantes :
CREATE TABLE tableville (villeid INT4 PRIMARY KEY, ville VARCHAR(128)); CREATE TABLE tablemagasin (magasin VARCHAR(128), villeid INT4);

10. Lutilisation des bases de donnes

la requte permettant de retourner les couples (magasin, ville) sera alors


SELECT tablemagasin.magasin, tableville.ville FROM tablemagasin, tableville WHERE tablemagasin.villeid=tableville.villeid;

Vous noterez au passage quil est possible de prciser quelle table appartient le champ prcis en utilisant la syntaxe "nomtable.nomchamp". Il nest cependant pas ncessaire de prciser le nom de la table sil ny a pas de confusion possible, ce qui est vrai ici pour les champs "magasin" et "ville" mais pas pour le champ "villeid". La requte peut donc galement scrire :
SELECT magasin, ville FROM tablemagasin, tableville WHERE tablemagasin.villeid=tableville.villeid;

Si lon reprend lexemple des films dans lesquels interviennent trois tables, et si nous nous intressons aux acteurs jouant dans ces films, cela donne :
SELECT film, acteur FROM film, acteur, film2acteur WHERE film.filmid=film2acteur.filmid AND film2acteur.acteurid;

Puisque vous semblez avoir compris, nous allons encore augmenter la difficult. Il existe des cas o des tables sont lies plusieurs fois une autre. Cest le cas notamment si vous souhaitez crer un dossier dans lequel sont stocks des noms dindividus, des lieux de naissance et des lieux de rsidence. L, la table contenant les noms de villes sera lie la table des individus aussi bien par linformation lieu de naissance que par le lieu de rsidence. Il faut alors faire intervenir deux fois le nom de la table ville, ce qui de prime abord donne "... FROM individu, ville, ville ...". Mais dans ce cas, il nous est impossible de distinguer les deux "instances" de la table ville. Pour pallier ce problme, il suffit de faire appel des alias selon la syntaxe "nomtable AS autrenom". Do la requte :
SELECT individu, villenaissance.ville, villeresidence.ville FROM individu, ville AS villenaissance, ville AS villeresidence WHERE individu.villenaissanceid=villenaissance.villeid AND individu.villeresidenceid=villeresidence.villeid;

Notez que les alias peuvent galement tre utiliss pour manipuler un nom de table plus court :

649

Chapitre 10

Lutilisation des bases de donnes

SELECT * FROM unnomdetabletroplong AS t, autretable WHERE t.id=autretable.id;

Maintenant que nous avons dj bien progress dans la connaissance de linstruction SELECT, voici dautres options permettant, entre autres, de trier les donnes.

10. Lutilisation des bases de donnes

SELECT
Retourne un ensemble denregistrements. Syntaxe SELECT [DISTINCT|ALL] listechamp FROM listetable [WHERE condition] [GROUP BY listechampgb] [ORDER BY obchamp1 [DESC|ASC], obchamp2...] Liste des champs retourner. Liste des tables impliques dans la recherche. Condition que doivent remplir les enregistrements. Demande le regroupement des enregistrements. Liste des champs selon lesquels les rsultats de la requte doivent tre groups. Demande le tri des enregistrements. Premier champ devant servir de champ de tri. Effectue un tri dcroissant. Effectue un tri croissant (ordre de tri par dfaut).

listechamp listetable condition GROUP BY listechampgb ORDER BY obchamp1 DESC ASC

Pour obtenir un rsultat tri selon un ou plusieurs champs, il faut donc faire appel linstruction ORDER BY. Ainsi,
SELECT film FROM film ORDER BY film;

retourne la liste complte des films tris par ordre alphabtique ;


SELECT film FROM film ORDER BY film DESC;

retourne la liste complte dans lordre alphabtique inverse (de Z A) ;


SELECT film, acteur FROM film, acteur, film2acteur WHERE film.filmid=film2acteur.filmid AND film2acteur.acteurid ORDER BY film, acteur;

retourne la liste complte dans lordre alphabtique des films et, pour chaque film, les acteurs sont classs par ordre alphabtique ;
SELECT film, acteur FROM film, acteur, film2acteur WHERE film.filmid=film2acteur.filmid AND film2acteur.acteurid ORDER BY film DESC, acteur;

650

Le langage SQL

retourne la liste complte dans lordre alphabtique inverse des films et, pour chaque film, les acteurs sont classs par ordre alphabtique. Comme nous lavons voqu prcdemment, il est possible dappliquer des fonctions aux champs retourns, mais il est galement possible de leur appliquer des fonctions dagrgation. Il sagit de fonctions soprant sur un ensemble denregistrements comme COUNT() pour compter le nombre denregistrements retourns, SUM() pour calculer la somme des valeurs dun champ, et bien dautres. Ainsi, il est possible de dterminer le nombre de films que contient la base de donnes avec
SELECT COUNT(*) FROM film;

10. Lutilisation des bases de donnes

Mais il est galement possible dobtenir le nombre dacteurs par film. Dans ce cas, il faut prciser que lon souhaite faire le calcul par film avec linstruction GROUP BY :
SELECT film, COUNT(acteur) FROM film, acteur, film2acteur WHERE film.filmid=film2acteur.filmid AND film2acteur.acteurid GROUP BY film;

Rcuprer des informations sur une base


Les instructions permettant de rcuprer des informations sur une base (telles que la liste de bases sur le serveur, le nom et la structure des tables) varient fortement dune base lautre.

MySQL

SHOW DATABASES
Retourne la liste des noms des bases sur le serveur de bases de donnes. Syntaxe LIKE nombase SHOW DATABASES [LIKE nombase] Retourne la liste des bases ayant un nom correspondant la chane nombase comportant des jokers % ou _.

SHOW TABLES
Retourne la liste des tables contenues dans la base. Syntaxe FROM nombase LIKE nomtable SHOW TABLES [FROM nombase] [LIKE nomtable] Retourne la liste des tables contenues dans la base nombase. Par dfaut, ce sont les tables de la base actuellement connecte qui sont retournes. Retourne la liste des tables ayant un nom correspondant la chane nomtable comportant des jokers % et _.

651

Chapitre 10

Lutilisation des bases de donnes

SHOW COLUMNS
Retourne la liste des champs contenus dans une table. Syntaxe SHOW COLUMNS FROM nomtable [FROM nombase] [LIKE nomchamp] Retourne la liste des champs de la table nomtable. Utilise la table nomtable de la base nombase. Par dfaut, cest la table de la base actuellement connecte qui est utilise. Retourne la liste des champs ayant un nom correspondant la chane nomchamp comportant des jokers % et _. nomtable FROM nombase LIKE nomchamp

10. Lutilisation des bases de donnes

Describe Il existe un quivalent SHOW COLUMNS FROM nomtable qui est DESCRIBE nomtable.

10.5. Accder une base de donnes via PHP


Introduction
Dans le cas de lutilisation dune base de donnes via PHP, le client (on parle dans ce cas dAPI) de la base de donnes est intgr (principalement via des bibliothques C) au serveur web. Chaque base de donnes ayant son propre client, les noms des fonctions PHP diffrent dune base de donnes lautre. Cest pourquoi nous allons, serveur de bases de donnes aprs serveur de bases de donnes, dcrire les fonctions qui leur sont propres. Nous vous invitons (aprs avoir fini la lecture de ce chapitre) aller directement aux chapitres correspondant aux bases que vous serez amen utiliser.

Principe gnral
Quoi quil en soit, le principe dutilisation dune base de donnes avec PHP reste le mme dune base lautre. La premire opration consiste se connecter la base de donnes. Cette opration se ralise en prcisant ladresse du serveur de la base de donnes (incluant ventuellement le port de communication), le nom de la base de donnes et, probablement, un nom dutilisateur et un mot de passe. Une fois connect, vous rcuprez un identifiant de session (une ressource) valable jusqu la dconnexion ou la fin dexcution du script en cours. Cet identifiant de session, qui, selon les cas, doit tre pass en paramtre des fonctions appeles ou est implicitement utilis, vous permet alors dexcuter des requtes SQL. Une fois la requte excute, vous rcuprez un identifiant de rsultat de requte (une ressource). Cet identifiant vous permet den lire le contenu (sil sagit dune requte de type SELECT), gnralement ligne par ligne. Une fois toutes ces oprations ralises, vous navez plus qu clore la connexion.

652

Accder une base de donnes via PHP

Connexion persistante
Comme vous venez de le dcouvrir, vous devrez ouvrir une connexion pour chaque script excut. Il nest pas question douvrir une connexion lors de lexcution dun script et de communiquer lidentifiant de connexion (ou mme lidentifiant de rsultat) au script suivant (afin, par exemple, de lire les rsultats de la requte lance par le premier script). Cela ne fonctionnerait pas du tout.

10. Lutilisation des bases de donnes

Mme si ceci nest pas une grosse contrainte en terme de programmation, cela peut le devenir en terme de performance. Si vous tes confront un serveur de bases de donnes ayant un dlai de connexion lev, vous serez vite pnalis. Pour pallier cet ventuel problme, PHP propose dtablir des connexions persistantes. Quest-ce quune connexion persistante ? Globalement, il sagit dune connexion ouvrant une session qui pourra tre utilise par dautres scripts que celui qui la initialise. Cependant, le comportement dune connexion persistante nest pas exactement celui auquel vous auriez pu penser de prime abord. En effet, si un utilisateur visite votre site dans lequel un script A ouvre une connexion persistante, il serait faux de penser que, ncessairement, lorsque lutilisateur visitera le script B, il utilisera le mme identifiant de session. Pour bien comprendre cela, il faut revenir sur le principe de fonctionnement dun serveur web (en tout cas, celui du serveur Apache). Un serveur web, ce nest ni plus ni moins quun ensemble de processus (par dfaut initialement dix sur un serveur Apache, le nombre pouvant augmenter suivant la demande) qui attendent quon leur demande une page. Ainsi, lorsquun utilisateur demande visualiser une page, cest le premier processus disponible qui soccupe de rpondre la demande de son client. Donc, si lutilisateur demande une page A, qui est en fait un script PHP ouvrant une connexion persistante, cest ce premier processus qui va ouvrir et tre dtenteur de la session. Lorsque ce mme utilisateur va demander une page B (un autre script PHP utilisant une connexion persistante), ce nest pas ncessairement le processus prcdent (peut-tre est-il occup avec un autre client) qui va rpondre la demande. Si ce nouveau processus na pas lui-mme dj eu loccasion douvrir une connexion persistante, il devra alors en ouvrir une. Dans le cas contraire, il naura pas besoin douvrir une nouvelle connexion, mais il proposera une session diffrente de celle qui avait t ouverte avec le processus prcdent. Ainsi donc, si la connexion est bien persistante au niveau des processus du serveur, elle nest pas pour autant vritablement maintenue tout au long du parcours dun visiteur, puisquelle passe dun visiteur lautre. Il est noter qu linverse des connexions classiques, les connexions persistantes ne peuvent tre closes.

Le danger des connexions non persistantes Les connexions non persistantes sont censes tre automatiquement closes la fin de lexcution dun script. Mais, visiblement, il ne faut pas trop compter l-dessus. Sans que nous puissions vritablement laffirmer, il semblerait que cela ne soit pas toujours vrai (un bug au niveau du systme charg de librer les ressources ?) ou bien, plutt, que cela ne soit pas immdiat. De la sorte, si, dans un script, vous omettez de clore une connexion, le nombre de sessions risque daugmenter dramatiquement jusqu ce que la base de donnes rejette toute connexion. Nous vous conseillons donc de

653

Chapitre 10

Lutilisation des bases de donnes

nutiliser que des connexions persistantes, au moins dans cette configuration ; alors le nombre de connexions reste limit par le nombre de processus du serveur web.

10. Lutilisation des bases de donnes

Couches dabstraction
Comme les fonctionnalits proposes dune base de donnes lautre sont assez similaires, des efforts sont faits pour crer des fonctions pouvant tre utilises par le plus grand nombre de serveurs de bases de donnes possible. On parle alors de couche dabstraction.

ODBC
mi-chemin entre les deux, nous trouvons les serveurs de bases de donnes qui utilisent un protocole unifi, en loccurrence ODBC. Pour lensemble de ces bases, vous pourrez utiliser les mmes fonctions (celles qui commencent par odbc).

10.6. Prsentation de lapplication dexemple


Pour lensemble des bases de donnes voques dans ce chapitre, la description des fonctions offertes par PHP sera complte par deux exemples. Le premier est un compteur de cliques. Cet exemple tant trs simple il sera dclin dans chaque chapitre. Le second, quant lui, est plus complet, il sagit en effet dune application de type bibliothque/filmothque/discothque/ photothque que nous appellerons "superthque". Dans ce cas, nous vous prsenterons ici le code commun et nous mettrons profit les possibilits offertes par la programmation oriente objet (que nous vous avons fait dcouvrir dans les premiers chapitres de ce livre) pour navoir par la suite qu rcrire que quelques classes ou mthodes afin de tenir compte de la spcificit de la base de donnes tudie. Ces exemples ont t choisis parce quils correspondent des besoins frquemment rencontrs dans la conception dun site web, et quils rpondent certaines problmatiques parfois souleves en dautres circonstances. Lintrt de ces scripts va donc au-del de la simple mise en uvre dune base de donnes. Notre "superthque" sera constitue dune collection darticles (livre, film, musique, etc.) regroups en albums. Cet exemple est trs intressant, car il offre des solutions de nombreux problmes :
j j j j j

Comment afficher N articles par page ? Comment modifier lordre daffichage des articles ? Comment filtrer les articles ? Comment crer et grer un formulaire de saisie ? Et bien dautres points encore

Ce sont ces mmes problmes que lon rencontre dans le cas de la cration dun forum, dun moteur de recherche, dun site de petites annonces, etc.

654

Prsentation de lapplication dexemple

Principe de fonctionnement dun moteur de recherche Puisque nous abordons ce sujet, cela vous intresse peut-tre de mieux connatre le principe de fonctionnement dun moteur de recherche. Il y a, en fait, deux parties distinctes : lune (appele spider) est charge de collecter les informations (telle une araigne sur la toile) et lautre (le moteur de recherche proprement dit) est charge de restituer les informations selon les mots-cls saisis par lutilisateur. Le principe du spider est relativement simple. Il sagit dun logiciel qui lit le contenu dune page web (quelconque), lanalyse (en extrait principalement le texte hors HTML), stocke dans une base de donnes lURL de la page et le texte associ, puis stocke lURL des pages proposes en lien pour pouvoir les analyser ultrieurement, et ainsi de suite. La base du moteur de recherche est celle que nous avons utilise ici. En pratique, les moteurs utilisent de savants algorithmes pour afficher les rsultats par ordre de pertinence (gnralement, sont considrs comme pertinents les sites vers lesquels pointent de nombreux autres sites).
Par dfaut, lapplication affichera la liste des articles et albums stocks dans la base de donnes. Pour des contraintes daffichage, seul le titre et le type de larticle seront affichs, de plus un maximum de 10 articles (valeur paramtrable) sera disponible par page. Par consquent, le cas chant un lien sera propos pour accder la page de rsultats suivante ou prcdente. Linformation dtaille dun article sera disponible par un lien affich cot du rsum de larticle dans la liste. Par commodit, nous proposerons dafficher la liste des articles tris par titre ou type, au choix soit dans lordre croissant soit dans lordre dcroissant. Nous offrirons galement la possibilit de filtrer les articles par titre et/ou par type. Bref, lapplication aura lallure suivante:

10. Lutilisation des bases de donnes

Figure 10.1 : SuperTheque

655

Chapitre 10

Lutilisation des bases de donnes

et offrira la possibilit de voir le dtail dun article

10. Lutilisation des bases de donnes

Figure 10.2 : SuperTheque

Il sera bien videmment possible dajouter un article lalbum slectionn ; pour cela lutilisateur aura la possibilit de saisir un titre (obligatoire) et un commentaire et devra slectionner le type de larticle comme le montre lcran suivant:

Figure 10.3 : SuperTheque

656

Prsentation de lapplication dexemple

Certes la prsentation est largement perfectible mais dans limmdiat ce sont les fonctionnalits qui nous intressent.

Le modle de donnes
Le modle de donnes se dduit naturellement de la prsentation qui vient dtre faite de lapplication. Lobjet principal est bien entendu larticle. Celui-ci porte au minimum un titre et ventuellement un commentaire et est dun type donn : livre, film, musique, photo, etc. Nous ajouterons un type particulier baptis "album" qui aura pour objet de rassembler une collection darticles. Par consquent, chaque article (y compris un album) appartiendra un album donn. Lobjet de base sera donc lobjet Article dont voici le code:

10. Lutilisation des bases de donnes

Listing 10.1 : Article_class.php


<?php /** * Article.php * Objet representant un objet quelconque de la collection. * Compatibilite: PHP 5 */ class Article { // Identifiant unique de larticle protected $id; // Titre de larticle protected $titre; // Identifiant du type de larticle protected $typeId; // Identifiant de lalbum auquel appartient larticle protected $albumId; // Commentaire sur larticle protected $commentaire; public function __construct($id=-1, $albumId=-1, $titre="", $typeId=-1) { $this->setId($id); $this->setTitre($titre); $this->setTypeId($typeId); $this->setAlbumId($albumId); } public function getId() { return $this->id; } public function setId($id) {

657

Chapitre 10

Lutilisation des bases de donnes

$this->id = $id; } public function getTitre() { return $this->titre; }

10. Lutilisation des bases de donnes

public function setTitre($titre) { $this->titre = $titre; } public function getAlbumId() { return $this->albumId; } public function setAlbumId($albumld) { $this->albumId = $albumId; } public function getTypeId() { return $this->typeId; } public function setTypeId($typeId) { $this->typeId = $typeId; } public function getCommentaire() { return $this->commentaire; } public function setCommentaire($commentaire) { $this->commentaire = $commentaire; } } ?>

Notre application nayant pas pour objectif dafficher lensemble des articles mais seulement ceux de lalbum slectionn et ventuellement uniquement les articles ayant un titre et/ou un type donn, nous utiliserons un filtre matrialis par lobjet Filtre suivant:

658

Prsentation de lapplication dexemple

Listing 10.2 : Filtre_class.php


<?php class Filtre { private $albumId=-1; private $titre; private $typeId=-1; public function setAlbumId($albumId) { $this->albumId = $albumId; } public function getAlbumId() { return $this->albumId; } public function setTitre($titre) { $this->titre = $titre; } public function getTitre() { return $this->titre; } public function setTypeId($typeId) { if ($typeId == "") $typeId = -1; $this->typeId = $typeId; } public function getTypeId() { return $this->typeId; } } ?>

10. Lutilisation des bases de donnes

De mme il nest pas question dafficher tous les articles rpondant aux critres prcdents dans une seule et mme page. Il faut donc en extraire une plage de rsultat. cet effet, nous utiliserons la classe Plage suivante:

Listing 10.3 : Plage_class.php


<?php class Plage

659

Chapitre 10

Lutilisation des bases de donnes

{ private $premierArticle; private $nbArticleMax; public function setPremierArticle($premierArticle) { $this->premierArticle = $premierArticle; } public function getPremierArticle() { return $this->premierArticle; } public function setNbArticleMax($nbArticleMax) { $this->nbArticleMax = $nbArticleMax; } public function getNbArticleMax() { return $this->nbArticleMax; } } ?>

10. Lutilisation des bases de donnes

Nous utiliserons galement un objet Tri afin de dfinir la manire dont doivent tre tris les articles lors de laffichage.

Listing 10.4 : Tri_class.php


<?php class Tri { private $champ; private $sens; // -1 Dcroissant, 0 sans, 1 Croissant public function setChamp($champ) { $this->champ = $champ; } public function getChamp() { return $this->champ; } public function setSens($sens) { $this->sens = $sens; }

660

Prsentation de lapplication dexemple

public function getSens() { return $this->sens; } } ?>

10. Lutilisation des bases de donnes

Schma de la base de donnes


En base de donnes, nous utiliserons les tables suivantes:

Tableau 10.12 : Articles


Champ id albumId titre typeId commentaire Type Entier auto-incrment Entier non null Chane de caractres Entier non null Chane de caractres pouvant tre null Commentaire Identifiant unique de larticle Identifiant de lalbum (article de type album) auquel appartient larticle Titre de larticle Identifiant du type de larticle (voir table types)

Tableau 10.13 : Types


Champ id type Type Entier auto incrment Chane de caractres Commentaire Identifiant unique du type Nom du type

Evitons les conflits Si vous souhaitez diffuser vos scripts, vous tes invit faire prcder les noms des tables dun prfixe librement configurable afin que lutilisateur puisse viter tout conflit (simplement en changeant le prfixe) entre les noms des tables de vos scripts et ceux dautres scripts dans le cas o ils devraient utiliser la mme base.

Le contrleur
Le cur de lapplication, son moteur, que lon appelle aussi le contrleur, doit permettre de grer les diffrentes interactions de lutilisateur. Une des premires oprations consiste lire le fichier de configuration

661

Chapitre 10

Lutilisation des bases de donnes

Listing 10.5 : index.php (extrait)


include_once("config/supertheque_cfg.php");

dont voici le maigre contenu

10. Lutilisation des bases de donnes

Listing 10.6 : supertheque_cfg.php


<?php $nbArticleMax = 10;

// Decommenter la ligne adequat //-----------------------------//$ressource = "MySQL"; $ressource = "SQLite"; //$ressource = "MSSQLServer"; //$ressource = "Demo"; ?>

Ce fichier permet de prciser combien darticles seront affichs par page et quelle base de donnes (ou dune manire gnrale quelle ressource) sera utilise. Avant de pouvoir commencer le contrleur doit connatre ltat courant de lapplication: savoir quel est larticle qui a t slectionn? quels sont les critres de filtrage qui ont t choisis? etc. Pour cela, et par soucis de simplicit, ces diffrents paramtres seront stocks et lus en session. Pour chacun de ces paramtres nous vrifions donc sil existe en session (via la fonction isset()) et sil nest pas disponible nous initialisons sa valeur avant de le stocker en session.

Listing 10.7 : index.php (extrait)


// Lecture des informations stockee en session // ou initialisation si necessaire //--------------------------------------------if (isset($_SESSION["filtre"])) { $filtre = $_SESSION["filtre"]; } else { $filtre = new Filtre(); $filtre->setAlbumId(0); $filtre->setTitre(""); $filtre->setTypeId(-1); $_SESSION["filtre"] = $filtre; } if (isset($_SESSION["plage"])) { $plage = $_SESSION["plage"]; } else { $plage = new Plage(); $plage->setPremierArticle(0); $plage->setNbArticleMax($nbArticleMax); $_SESSION["plage"] = $plage; }

662

Prsentation de lapplication dexemple

if (isset($_SESSION["tri"])) { $tri = $_SESSION["tri"]; } else { $tri = new Tri(); $tri->setChamp("titre"); $tri->setSens(1); $_SESSION["tri"] = $tri; }

10. Lutilisation des bases de donnes

Attention, car avant de pouvoir manipuler les variables de session, il faut faire appel session_start(). Plus encore, il est impratif de dclarer les classes utilises dans les variables de session avant cet appel session_start(). Nous insrerons donc avant le code prcdent, le code:

Listing 10.8 : index.php (extrait)


include_once("classes/Article_class.php"); include_once("classes/Filtre_class.php"); include_once("classes/Tri_class.php"); include_once("classes/Plage_class.php"); include_once("classes/SuperTheque_class.php"); include_once("config/supertheque_cfg.php"); include_once("classes/Ressource".$ressource."_class.php"); session_start();

Nous retrouvons ici, le fichier de configuration voqu prcdemment ainsi que deux nouveaux fichiers de classes que nous verrons plus loin. Notez que le chargement de la dernire classe dpend du paramtre de configuration $ressource.

Vous pouvez vous reporter aux sections "Les inclusions de fichiers" et "Les sessions" pour plus de dtails.
Le contrleur travaillera selon le principe que chaque action de lutilisateur est identifie par un paramtre mode. Ce paramtre pourra tre pass soit au travers de lURL appele avec un lien selon le modle <a href="?mode=modeselectionn">, soit au travers dun formulaire avec un champ cach <input type="hidden" name="mode" value="modeselectionn" />. La lecture de ce mode se fera donc ainsi:

Listing 10.9 : index.php (extrait)


if (isset($_POST["mode"])) { $mode = $_POST["mode"]; } else if (isset($_GET["mode"])) { $mode = $_GET["mode"]; } else { $mode = "visualisation"; }

663

Chapitre 10

Lutilisation des bases de donnes

Vous pouvez vous reporter la sections "Les variables" pour plus de dtails.

Nous avons identifi les actions suivantes:

10. Lutilisation des bases de donnes

j j j j j j j

article: afin de slectionner un article (ou album) tri: afin de trier les articles selon un champ (titre ou type) et un sens donn (croissant, dcroissant) suivants, prcdents: afin dafficher les N articles suivants ou prcdents filtre: afin de dfinir un nouveau filtre (bas sur un titre ou type) visualisation: il sagit du mode par dfaut ajout: afin de proposer un formulaire pour lajout dun article sauver: afin de sauvegarder les donnes soumises via le formulaire dajout dun article

Mode = article
Lorsque nous voudrons proposer lutilisateur de slectionner un article (ou album) donn, nous naurons qu insrer un lien du type <a href="?mode=article &articleId=<articleId>"> (ou utiliser un champ cach dans le cas dun formulaire en mode post). Le contrleur doit alors modifier les critres de filtrage pour prciser quel est le nouvel article (ou album) slectionn. Attention, il y a toutefois une subtilit: Si lutilisateur slectionne un album dans la cinquime page de la liste du contenu de lalbum pre, il faut prendre soin de ne pas slectionner la cinquime page de lalbum fils car celui-ci contient peut-tre moins de cinq pages. Il faut donc revenir la premire page de lalbum slectionn. Cest ce qui est fait ici.

Listing 10.10 : index.php (extrait)


if ($mode == "article") { //----------------------------------------// Quel article (ou album) devra etre affiche ? //----------------------------------------if (isset($_POST["articleId"])) { $articleId = $_POST["articleId"]; } else if (isset($_GET["articleId"])) { $articleId = $_GET["articleId"]; } else { $articleId = 0; } // Modification des parametres de filtrage $album = $supertheque->getArticle($articleId); $filtre->setAlbumId($articleId); $_SESSION["filtre"] = $filtre; // Si lon passe dun album a un autre

664

Prsentation de lapplication dexemple

// mieux vaut aller au premier article de lalbum if ($supertheque->isAlbum($album)) { $plage->setPremierArticle(0); $_SESSION["plage"] = $plage; } // Passage en mode visualisation (avec le nouveau filtre) header("Location: ?mode=visualisation"); die(); }

10. Lutilisation des bases de donnes

Mode = tri
Si lutilisateur clique sur un lien de la forme "?mode=tri&tri_champ=titre&tri_sens=1" alors laction dclencher consiste uniquement modifier les paramtres de tri (champ sur lequel sapplique le tri et sens du tri : -1 si dcroissant, 0 si non tri, 1 si croissant) stocks en session et retourner la page principale.

Listing 10.11 : index.php (extrait)


if ($mode == "tri") { // Modification des paramtres de tri $tri->setChamp($_GET["tri_champ"]); $tri->setSens($_GET["tri_sens"]); $_SESSION["tri"] = $tri; // Passage en mode visualisation (avec le nouveau tri) header("Location: ?mode=visualisation"); die(); }

Mode = suivants, Mode = precedents


Si lutilisateur clique sur un lien de la forme "?mode=suivants" ou "?mode=precedents" alors laction dclencher consiste uniquement modifier, en session, les paramtres dfinissant la plage darticles (en fait uniquement lindex du premier article puisque le nombre darticles afficher fait quant lui des paramtres de configuration du script) afficher et retourner la page principale.

Listing 10.12 : index.php (extrait)


if ($mode == "suivants") { // Modification de la plage de selection $plage->setPremierArticle($plage->getPremierArticle() + $nbArticleMax); $_SESSION["plage"] = $plage; // Passage en mode visualisation header("Location: ?mode=visualisation"); die(); } if ($mode == "precedents") {

665

Chapitre 10

Lutilisation des bases de donnes

// Modification de la plage de selection $plage->setPremierArticle($plage->getPremierArticle() $nbArticleMax); $_SESSION["plage"] = $plage; // Passage en mode visualisation header("Location: ?mode=visualisation"); die();

10. Lutilisation des bases de donnes

Mode = ltre
Si lutilisateur clique sur le bouton "filtrer" alors un formulaire est soumis avec lattribut cach "mode" positionn la valeur "filtre". Il convient alors de modifier les paramtres de filtrage puis retourner la page principale.

Listing 10.13 : index.php (extrait)


if ($mode == "filtre") { // Modification des parametres de filtrage $filtre->setTitre($_POST["filtre_titre"]); $filtre->setTypeId($_POST["filtre_typeId"]); $_SESSION["filtre"] = $filtre; // Passage en mode visualisation (avec le nouveau filtre) header("Location: ?mode=visualisation"); die(); }

Mode = visualisation
Par dfaut la page principale affiche la liste des articles correspondants aux critres de slection (le filtre), tris selon la rgle stocke en session et en limitant laffichage la plage darticles slectionns (elle aussi stocke en session). Pour cela lapplication doit accder la base de donnes ou dune manire gnrale une ressource quelconque (une zone mmoire, un fichier par exemple). Cette ressource devra nous permettre de: nous connecter via une mthode connexion(), nous dconnecter via une mthode deconnexion(), rcuprer la liste des articles via une mthode getArticles(), dterminer le nombre darticles rpondant aux critres de slection via une mthode getNbTotalArticles() (pour ventuellement proposer un lien "page suivante"), rcuprer la liste des types connus via une mthode getTypes() (pour la slection du filtre). Afin de dterminer si un article donn est ou non un album, cette ressource devra galement nous retourner lidentifiant du type "album" via une mthode getAlbumTypeId(). Et comme nous le verrons bientt, nous aurons besoin dune mthode permettant lajout dun article dans la base via la mthode addArticle(). En quelques mots, nous avons dress linterface de lobjet qui nous permettra daccder une ressource quelle quelle soit (Un fichier, une base de donnes MySQL, Oracle, etc.). Do lobjet RessourceInterface:

666

Prsentation de lapplication dexemple

Listing 10.14 : RessourceInterface_class.php


<?php /** * RessouceInterface_class.php */ interface RessourceInterface { /** * Retourne lidentifiant de connexion a la base de donnees */ public function connexion(); /** * Demande la deconnexion a la base de donnees */ public function deconnexion(); /** * Re-cree la structure de la base de donnees */ public function reset(); /** * Ajoute un article en base * avec les caracteristiques donnees en parametre. * REM: Nous aurions egalement pu (du ?) proposer * une interface avec comme parametre un objet Article */ public function addArticle($albumId, $titre, $typeId, $commentaire); /** * Retourne lobjet Article correspondant a larticle * identifie par articleId */ public function getArticle($articleId); /** * Retourne un tableau indexe des articles repondant * aux criteres de filtrage, trie et dont la plage nous interessant * a ete extraite */ public function getArticles(Filtre $filtre, Plage $plage, Tri $tri); /** * Retourne le nombre total darticles repondant * aux criteres de filtrage */ public function getNbTotalArticles(Filtre $filtre);

10. Lutilisation des bases de donnes 667

Chapitre 10

Lutilisation des bases de donnes

/** * Retourne le tableau associatif des types * ou la cle est lidentifiant du type * la valeur le nom du type */ public function getTypes();

10. Lutilisation des bases de donnes

/** * Retourne lidentifiant du type associ au type album */ public function getAlbumTypeId(); } ?>

En fait, nous nattaquerons pas la classe Ressource directement puisque nous passerons par une classe SuperTheque charge deffectuer des tests et traitements complmentaires (mme si en loccurrence, ici, nous aurions sans doute pu nous en passer).

Listing 10.15 : SuperTheque_class.php


<?php /** * SuperTheque_class.php * Objet permettant dacceder a la discoTheque, filmoTheque, etc. * a priori stockee dans une base de donnees. */ class SuperTheque { /** * Objet ressource utilise pour acceder aux articles. * Ce sera un objet pour recuperer les articles dans * une base de donnees mais cela pourrait tout aussi * bien etre un objet pour recuperer les articles dans * un fichier ou autres.. */ protected $ressource; public function __construct($ressource) { $this->ressource = $ressource; } public function reset() { $this->ressource->connexion(); $articles = $this->ressource->reset(); $this->ressource->deconnexion(); } public function addArticle($albumId, $titre, $typeId,

668

Prsentation de lapplication dexemple

$commentaire) { $this->ressource->connexion(); $articles = $this->ressource->addArticle($albumId, $titre, $typeId, $commentaire); $this->ressource->deconnexion(); } public { // // if } $this->ressource->connexion(); $articles = $this->ressource->getArticle($articleId); $this->ressource->deconnexion(); return $articles; } /** * Retourne les N articles du type selectionne * a partir du I-ieme, lorsquils sont classes * dans lordre precise * @param filtre Filtre de selection * @param plage Plage des enregistrements a retourner * @param tri Regle de tri */ public function getArticles(Filtre $filtre, Plage $plage, Tri $tri) { $this->ressource->connexion(); $articles = $this->ressource->getArticles($filtre, $plage, $tri); $this->ressource->deconnexion(); return $articles; } public function getNbTotalArticles(Filtre $filtre) { $this->ressource->connexion(); $articles = $this->ressource->getNbTotalArticles($filtre); $this->ressource->deconnexion(); return $articles; } public function getTypes() function getArticle($articleId) Larticle racine (0) nest pas un "vrai" article il ne doit pas tre rcupr en BD. (($articleId == "")||($articleId == 0)) { return new Article(0, -1, "", $this->getAlbumTypeId());

10. Lutilisation des bases de donnes 669

Chapitre 10

Lutilisation des bases de donnes

{ $this->ressource->connexion(); $types = $this->ressource->getTypes(); $this->ressource->deconnexion(); return $types; }

10. Lutilisation des bases de donnes

public function getAlbumTypeId() { return $this->ressource->getAlbumTypeId(); } public function isAlbum($article) { if ($article->getTypeId() == $this->getAlbumTypeId()) return TRUE; else return FALSE; } } ?>

Lobjet supertheque sera donc instanci comme suit:

Listing 10.16 : index.php (extrait)


$supertheque = new SuperTheque(new Ressource());

Pour prparer laffichage de la liste des articles dun album ou du dtail dun article nous devons dans un premier temps utiliser cet objet supertheque pour rcuprer les donnes relatives larticle (ou album) slectionn. Ce que nous stockerons dans une variable $article. Sil sagit dun album nous devons rcuprer lensemble des articles que nous stockerons dans un tableau $articles. Nous verrons, plus loin, quil est indispensable de connatre le nombre total darticles
$nbTotalArticles rpondant aux critres du filtre afin dafficher ou non un lien permettant

daccder la page suivante.

Listing 10.17 : index.php (extrait)


if ($mode == "visualisation") { // Visualiser larticle (ou album) specifie (ou celui par dfaut) $article = $supertheque->getArticle($filtre->getAlbumId()); if ($supertheque->isAlbum($article)) { $articles = $supertheque->getArticles($filtre, $plage, $tri); $nbTotalArticles = $supertheque->getNbTotalArticles($filtre); } }

670

Prsentation de lapplication dexemple

Voil, nous disposons de toutes les informations ncessaires laffichage des articles dun album ou du dtail dun article. Selon le cas nous passerons donc lune ou lautre des vues

Listing 10.18 : index.php (extrait)


if ($mode == "visualisation") { if ($supertheque->isAlbum($article)) { include_once("vues/SuperTheque_VueVisualisation_inc.php"); } else { include_once("vues/SuperTheque_VueDetail_inc.php"); } }

10. Lutilisation des bases de donnes

Nous sommes quasiment prts passer aux aspects relatifs au rendu visuel de notre application. Reste toutefois le cas de lajout dun article dans la base.

Mode = ajout
Lapplication proposera un lien permettant de passer du mode visualisation au mode ajout dans lequel laffichage des articles est remplac par laffichage dun formulaire permettant la saisie des donnes relatives au nouvel article. Ce mode se rsume (du point de vue du contrleur) donc :

Listing 10.19 : index.php (extrait)


if ($mode == "ajout") { include_once("vues/SuperTheque_VueAjout_inc.php"); }

Mode = sauver
Une fois les donnes du formulaire soumises, il faut les rcuprer et les valider. Nous aurons un champ cach prcisant quel album doit tre rattach le nouvel article. Le champ titre est obligatoire. A chaque erreur dtecte un tableau $erreurs sera aliment. Si aucune erreur na t dtecte alors il sera possible dajouter larticle dans la base, sinon la page contenant le formulaire sera affich de nouveau avec les messages derreur simplement en passant du mode sauver au mode ajout.

Listing 10.20 : index.php (extrait)


if ($mode == "sauver") { // Ajouter le nouvel article a lalbum $albumId $albumId = $_POST["albumId"]; // Verifions tout de mme que larticle $albumId est bien un album $album = $supertheque->getArticle($albumId); if (!$supertheque->isAlbum($album)) {

671

Chapitre 10

Lutilisation des bases de donnes

$erreurs[] = "Larticle s&eactue;l&eacute;ctionn&eacute; nest pas". " un album!"; } // Verifions que le champ titre a t slectionn $titre = $_POST["titre"]; if ((!isset($titre))||(strlen($titre)==0)) { $erreurs[] = "Le titre ne doit pas &ecirc;tre vide."; } $typeId = $_POST["typeId"]; if (count($erreurs)>0) { // Au moins une erreur a ete detectee alors on ne // sauvegarde plus, on revient a la page dajout. $mode = "ajout"; } else { $supertheque->addArticle($albumId, stripSlashes($_POST["titre"]), $_POST["typeId"], stripSlashes($_POST["commentaire"])); // Une fois sauvegarde on repasse en mode visualisation header("Location: ?mode=visualisation"); die(); } }

10. Lutilisation des bases de donnes

Ce bout de code amne une remarque trs importante lie lutilisation de stripSlashes().

Magic quotes
Par dfaut, PHP est configur avec loption magic_quotes active, ce qui signifie que les valeurs passes par formulaire sont traites pour ajouter un anti-slash devant les apostrophes. Il faut donc en tenir compte (afin de le supprimer), notamment, ici, lors de lappel la mthode dajout dun article pour les champs de type texte (titre et commentaire). La valeur passe la addArticle() nest donc pas $_POST["commentaire"], mais mthode stripSlashes($_POST["commentaire"]).

La totale
Voici donc limplmentation complte du contrleur:

Listing 10.21 : index.php


<?php include_once("classes/Article_class.php"); include_once("classes/Filtre_class.php"); include_once("classes/Tri_class.php"); include_once("classes/Plage_class.php"); include_once("classes/SuperTheque_class.php"); include_once("config/supertheque_cfg.php"); include_once("classes/Ressource".$ressource."_class.php");

672

Prsentation de lapplication dexemple

session_start(); $supertheque = new SuperTheque(new Ressource()); // Lecture des informations stockee en session // ou initialisation si necessaire //--------------------------------------------if (isset($_SESSION["filtre"])) { $filtre = $_SESSION["filtre"]; } else { $filtre = new Filtre(); $filtre->setAlbumId(0); $filtre->setTitre(""); $filtre->setTypeId(-1); $_SESSION["filtre"] = $filtre; } if (isset($_SESSION["plage"])) { $plage = $_SESSION["plage"]; } else { $plage = new Plage(); $plage->setPremierArticle(0); $plage->setNbArticleMax($nbArticleMax); $_SESSION["plage"] = $plage; } if (isset($_SESSION["tri"])) { $tri = $_SESSION["tri"]; } else { $tri = new Tri(); $tri->setChamp("titre"); $tri->setSens(1); $_SESSION["tri"] = $tri; }

10. Lutilisation des bases de donnes

//----------------------------------------// Que veux le visiteur ? //----------------------------------------if (isset($_POST["mode"])) { $mode = $_POST["mode"]; } else if (isset($_GET["mode"])) { $mode = $_GET["mode"]; } else { $mode = "visualisation"; } if ($mode == "article") { //----------------------------------------// Quel article (ou album) devra etre affiche ? //----------------------------------------if (isset($_POST["articleId"])) {

673

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

$articleId = $_POST["articleId"]; } else if (isset($_GET["articleId"])) { $articleId = $_GET["articleId"]; } else { $articleId = 0; } // Modification des parametres de filtrage $album = $supertheque->getArticle($articleId); $filtre->setAlbumId($articleId); $_SESSION["filtre"] = $filtre; // Si lon passe dun album a un autre // mieux vaut aller au premier article de lalbum if ($supertheque->isAlbum($album)) { $plage->setPremierArticle(0); $_SESSION["plage"] = $plage; } // Passage en mode visualisation (avec le nouveau filtre) header("Location: ?mode=visualisation"); die(); } if ($mode == "filtre") { // Modification des parametres de filtrage $filtre->setTitre($_POST["filtre_titre"]); $filtre->setTypeId($_POST["filtre_typeId"]); $_SESSION["filtre"] = $filtre; // Passage en mode visualisation (avec le nouveau filtre) header("Location: ?mode=visualisation"); die(); } if ($mode == "tri") { // Modification des parametres de tri $tri->setChamp($_GET["tri_champ"]); $tri->setSens($_GET["tri_sens"]); $_SESSION["tri"] = $tri; // Passage en mode visualisation (avec le nouveau tri) header("Location: ?mode=visualisation"); die(); } if ($mode == "suivants") { // Modification de la plage de selection $plage->setPremierArticle($plage->getPremierArticle() + $nbArticleMax); $_SESSION["plage"] = $plage; // Passage en mode visualisation header("Location: ?mode=visualisation"); die(); }

674

Prsentation de lapplication dexemple

if ($mode == "precedents") { // Modification de la plage de selection $plage->setPremierArticle($plage->getPremierArticle() $nbArticleMax); $_SESSION["plage"] = $plage; // Passage en mode visualisation header("Location: ?mode=visualisation"); die(); }

10. Lutilisation des bases de donnes

if ($mode == "sauver") { // Ajouter le nouvel article a lalbum $albumId $albumId = $_POST["albumId"]; // Verifions tout de mme que larticle $albumId est bien un album $album = $supertheque->getArticle($albumId); if (!$supertheque->isAlbum($album)) { $erreurs[] = "Larticle s&eactue;l&eacute;ctionn&eacute; nest pas". " un album!"; } // Verifions que le champ titre a t slectionn $titre = $_POST["titre"]; if ((!isset($titre))||(strlen($titre)==0)) { $erreurs[] = "Le titre ne doit pas &ecirc;tre vide."; } $typeId = $_POST["typeId"]; if (count($erreurs)>0) { // Au moins une erreur a ete detectee alors on ne // sauvegarde plus, on revient a la page dajout. $mode = "ajout"; } else { $supertheque->addArticle($albumId, stripSlashes($_POST["titre"]), $_POST["typeId"], stripSlashes($_POST["commentaire"])); // Une fois sauvegarde on repasse en mode visualisation header("Location: ?mode=visualisation"); die(); } } if ($mode == "visualisation") { // Visualiser larticle (ou album) specifie (ou celui par dfaut) $article = $supertheque->getArticle($filtre->getAlbumId()); if ($supertheque->isAlbum($article)) { // Sil sagit dun album voici ce que nous devons faire //---------------------// Creation du Filtre //----------------------

675

Chapitre 10

Lutilisation des bases de donnes

$articles = $supertheque->getArticles($filtre, $plage, $tri); $nbTotalArticles = $supertheque->getNbTotalArticles($filtre); } }

10. Lutilisation des bases de donnes

// Pour laffichage, nous aurons besoin de connaitre les noms // des differents types existants $types = $supertheque->getTypes(); //----------------// Affichage //----------------include_once("entete_inc.php"); if ($mode == "visualisation") { if ($supertheque->isAlbum($article)) { include_once("vues/SuperTheque_VueVisualisation_inc.php"); } else { include_once("vues/SuperTheque_VueDetail_inc.php"); } } else if ($mode == "ajout") { include_once("vues/SuperTheque_VueAjout_inc.php"); } include_once("pieddepage_inc.php"); ?>

Vous y retrouvez lensemble des lignes de code prcdent. Les seules lignes passes sous silence jusque l, sont celles permettant de rcuprer dans un tableau associatif $types les noms des diffrents types (darticle) disponibles.

Listing 10.22 : index.php (extrait)


// Pour laffichage, nous aurons besoin de connaitre les noms // des differents types existants $types = $supertheque->getTypes();

Et celles relatives la mise en page


include_once("entete_inc.php");

et
include_once("pieddepage_inc.php");

que nous aborderons ds le chapitre suivant.

676

Prsentation de lapplication dexemple

Les vues
Une fois le traitement opr (cest dire, une fois les donnes mises jour ou rcupres) il est possible de passer laffichage de la vue. Comme nous lavons vu, cette application dispose de trois crans diffrents :
j j j

Laffichage de la liste des articles (mode visualisation dun album) Laffichage des dtails dun article (mode visualisation dun article) La page dajout dun nouvel article.

10. Lutilisation des bases de donnes

Toutefois, toutes trois auront globalement la mme mise en page. Nous voulons dire par-l, quelles auront toutes le mme bandeau suprieur, le mme menu gauche et ou droit, et ventuellement un bandeau infrieur. Afin dviter de dupliquer du code, il suffit de crer un fichier que nous appellerons entete_inc.php dcrivant le bandeau suprieur et ventuellement le menu gauche et un autre dcrivant le menu droit et ventuellement le bandeau infrieur appel pieddepage_inc.php Le squelette du fichier den-tte est le suivant :

Listing 10.23 : entete_inc.php (squelette)


<html> <body> <table> <tr><td colspan="3"><!-- Entete proprement dit --></td></tr> <tr><td><!-- Menu Gauche--></td><td>

alors que le pied de page a lallure suivante :

Listing 10.24 : pieddepage_inc.php (squelette)


</td><td><!-- Menu droit --></td></tr> <tr><td colspan="3"><!-- Pied de page proprement dit --></td></tr> </body> </html>

Il ny a plus qu mettre la page principale entre ces deux fichiers. Cest ce que le contrleur ralise en effectuant les diffrents include relatifs la vue.

Vue liste des articles


Pour rappel, lissue du traitement du contrleur nous disposons des variables suivantes:
$article, qui contient les informations relatives larticle slectionn. $articles, qui contient la liste des articles (filtrs, tris et extraits) de lalbum slectionn $nbTotalArticles, qui contient le nombre total darticles rpondant aux critres de filtrage. $types, qui contient la liste des types disponibles.

677

Chapitre 10

Lutilisation des bases de donnes

mais aussi tout moment de $plage, $filtre et $tri. la base, ce quil nous faut cest afficher le contenu du tableau $articles ce qui se fait aisment via une boucle foreach($articles as $articleListe). Mais il faut galement:
j j

proposer les liens permettant de modifier lordre de tri intgrer un formulaire pour la saisie des critres de filtrage. Ce dernier ncessite laffiche dans une liste de slection des diffrents types disponibles do la boucle foreach($types as $cle=>$type). proposer des liens permettant daccder au dtail dun article (ou au contenu dun album) proposer si ncessaire des liens pour afficher la page prcdente et/ou la page suivante. La dcision se fera en fonction des valeurs de $tri>premierArticle() et
$nbTotalArticles

10. Lutilisation des bases de donnes

j j

j j

proposer si ncessaire un lien pour revenir lalbum pre (si nous ne sommes pas lalbum racine) proposer un lien pour ajouter un article

Listing 10.25 : SuperTheque_VueVisualisation_inc.php


<form action="" method="post"> <table width="100%"> <tr> <th> <a href="?mode=tri&tri_champ=titre&tri_sens=-1">-</a> Titre <a href="?mode=tri&tri_champ=titre&tri_sens=1">+</a> </th> <th> <a href="?mode=tri&tri_champ=typeId&tri_sens=-1">-</a> Type <a href="?mode=tri&tri_champ=typeId&tri_sens=1">+</a> </th> </tr> <tr> <td> <input type="hidden" name="mode" value="filtre" /> <input type="text" name="filtre_titre" /> </td> <td> <select name="filtre_typeId"> <option value="-1">Tous</option> <?php foreach($types as $typeId=>$type) { ?> <option value="<?php echo $typeId;?>"><?php echo $type;?></option> <?php } ?> </select>

678

Prsentation de lapplication dexemple

</td> <td> <input type="submit" value="Filtrer" /> </td> </tr> <tr> <td colspan="3"><hr /></td> </tr> <?php if (count($articles)>0) foreach($articles as $articleListe) { ?> <tr> <td> <?php echo htmlEntities($articleListe->getTitre()); ?> </td> <td> <?php echo $types[$articleListe->getTypeId()]; ?> </td> <td> <?php echo "<a href=\"?mode=article&articleId=".$articleListe->getId()."\">"; ?> [D&eacute;tails] </a> </td> </tr> <?php } // Fin du foreach ?> </table> </form> <hr /> <table width="100%"> <tr> <td width="33%" align="left"> <?php if ($plage->getPremierArticle() > 0) { ?> <a href="?mode=precedents">&lt;&lt;&lt; Articles pr&eacute;c&eacute;dents</a> <?php } ?> </td> <td width="34%" align="center"> <?php if ($filtre->getAlbumId() != 0) { // Inserer un lien pour remonter a lalbum "pere" ?>

10. Lutilisation des bases de donnes 679

Chapitre 10

Lutilisation des bases de donnes

<a href="?mode=article&articleId=<?php echo $article->getAlbumId(); ?>">[..]</a> <?php } ?> </td> <td align="right"> <?php if ($nbTotalArticles > $plage->getPremierArticle() + $plage->getNbArticleMax()) { <a href="?mode=suivants">Articles suivants &gt;&gt;&gt;</a> <?php }

10. Lutilisation des bases de donnes

?>

</td> </tr> </table> <br /> <center> <a href="?mode=ajout"> [Ajouter un article &agrave; cet album] </a> </center>

?>

Comme vous pouvez le constater, il y a trs peu de code PHP. Comme quoi, nous avons bien russi distinguer la partie traitement de la partie affichage.

Vue ajout dun nouvel article


Il sagit du fichier de vue le plus complexe. En effet, cette vue ne doit pas seulement proposer un formulaire de saisie puisquelle doit galement permettre dafficher dventuels messages derreurs dtectes lorsque ce formulaire est soumis et dans ce cas les valeurs prcdemment saisies doivent tre affiches de nouveau.

Listing 10.26 : SuperTheque_VueAjout_inc.php


<?php if (count($erreurs)>0) { echo "<ul>"; foreach($erreurs as $erreur) { echo "<li>$erreur</li>"; } echo "</ul>"; } ?> <form action="index.php" method="post"> <input type="hidden" name="mode" value="sauver" /> <input type="hidden" name="albumId" value="<?php echo $filtre->getAlbumId(); ?>" />

680

Prsentation de lapplication dexemple

<table> <tr> <td>Titre:</td> <td><input type="text" name="titre" value="<?php echo htmlEntities(stripSlashes($_POST["titre"])); ?>"/></td> </tr> <tr> <td>Type:</td> <td> <select name="typeId"> <?php foreach($types as $typeId=>$type) { ?> <option value="<?php echo $typeId;?>" <?php if ($_POST["typeId"]==$typeId) echo "selected=\"selected\"";?>><?php echo $type;?></option> <?php } ?> </select> </td> </tr> <tr> <td>Commentaire:</td> <td> <textarea name="commentaire" cols="40" rows="5"><?php echo htmlEntities(stripSlashes($_POST["commentaire"])); ?></textarea> </td> </tr> <tr> <td colspan="2"> <i>Vous pouvez &agrave; votre guise ajouter dautres informations</i> </td> </tr> <tr> <td colspan="2"> <input type="submit" value="Sauver" /> </td> </tr> </table> </form>

10. Lutilisation des bases de donnes

Dans le cas dune saisie invalide, il est important de restituer le formulaire lutilisateur dans ltat o il la laiss avant de valider sa saisie. Pour cela, nous devons prciser les valeurs par dfaut (valeurs prcdemment saisies) de chaque champ. Dans le cas dun champ texte, il suffit de prciser lattribut value. Ainsi nous ne nous contentons pas dun simple <input type="text" name="titre" /> mais nous prciserons <input type="text"
name="titre" value="<?php echo htmlEntities(stripSlashes ])); ?>"/> (la valeur ayant t soumise via la mthode post) ($_POST["titre"

681

Chapitre 10

Lutilisation des bases de donnes

Ceci amne dailleurs plusieurs remarques. Nous retrouvons la problmatique du "magic quotes" qui implique lutilisation de stripSlashes().

htmlEntities
10. Lutilisation des bases de donnes
Attention ! Lorsque vous spcifiez un attribut value, noubliez pas, dune part, de mettre la valeur entre guillemets (mais a, vous devriez dj en avoir lhabitude, sans quoi il est grand temps de sy mettre !) et, dautre part, de faire appel htmlEntities() afin, en particulier, de remplacer les guillemets par leurs quivalents HTML pour viter tout conflit avec les guillemets dlimiteurs de la chane.

Rappel des prcdentes valeurs


Dans le cas dune liste de slection, il faut prciser selected pour les champs slectionns (ce qui en XHTML se dclare par selected="selected") ; dans le cas des boutons radio, il faut prciser checked (ce qui en XHTML se dclare par checked="checked") ; et, enfin, pour les zones de texte, il faut prciser leur contenu entre les balises <textearea> et </textarea>.

Vue dtail dun article


Listing 10.27 : SuperTheque_VueDetail_inc.php
<table> <tr> <td width="10%" >Titre:</td> <td><b><?php echo htmlEntities($article->getTitre());?></b></td> </tr> <tr> <td>Type:</td> <td><?php echo $types[$article->getTypeId()];?></td> </tr> <tr> <td>Commentaire:</td> <td><?php echo nl2br(htmlEntities($article->getCommentaire()));?></td> </tr> <tr> <td colspan="2"> <i>Vous pouvez &agrave; votre guise compl&eacute;ter cette page pour afficher dautres informations (que vous aurez pris soin dajouter apr&egrave;s avoir compl&egrave;t&eacute; la page de saisie).</i> </td> </tr> </table> <br /> <center> <a href="?mode=article&articleId=<?php echo $article->getAlbumId();?>">Retour &agrave; la liste.</a> </center>

682

Access (MS)

Il ny a pas de relles nouveauts dans ce script, seule la ligne permettant laffichage du commentaire peut ncessiter quelques explications.

Retours la ligne
La zone de texte, dfinie dans le formulaire pour saisir un commentaire, nous permet de saisir un texte format avec des retours la ligne. Mais il faut garder lesprit que ceux-ci sont matrialiss par des \n. Ainsi, si une description contenant des retours la ligne est stocke en base de donnes puis restitue telle quelle (echo $commentaire) dans un document HTML, elle perdra sa mise en page. En effet, le caractre \n nest pas considr en HTML comme un retour la ligne, la balise HTML correspondante tant <br> (ou <br/> en XHTML). Il faut donc utiliser, avant affichage, la fonction nl2br(). Cest donc ce que nous utilisons ici.

10. Lutilisation des bases de donnes

10.7. Access (MS)


Bien que lon ne puisse pas considrer MS Access comme un vritable serveur de bases de donnes, cest certainement la base de donnes la plus connue du grand public.

Installation
Afin de pouvoir accder une base de donnes Access depuis PHP, vous devez imprativement tablir une liaison ODBC. Lopration savre extrmement simple : 1. Ouvrez le Panneau de configuration.

Figure 10.4 : Panneau de configuration

683

Chapitre 10

Lutilisation des bases de donnes

2.

Slectionnez Performances et maintenance.

10. Lutilisation des bases de donnes

Figure 10.5 : Performances et maintenance

3.

Slectionnez Outils dadministration.


Figure 10.6 : Outils dadministration

684

Access (MS)

4.

Voil, vous tes en passe de dcouvrir le panneau dadministration de "sources de donnes (ODBC)". Cliquez...
Figure 10.7 :

Administrateur de sources de donnes ODBC 10. Lutilisation des bases de donnes

5.

Slectionnez longlet Sources de donnes systme puis, sans faiblir, cliquez sur Ajouter.
Figure 10.8 : Crer une nouvelle source de donnes

6.

Nous voil au cur du sujet. Slectionnez le pilote correspondant votre type de base de donnes, en loccurrence Microsoft Access Driver, puis cliquez sur Terminer.
Figure 10.9 :

Installation ODBC pour Microsoft Access

685

Chapitre 10

Lutilisation des bases de donnes

7.

Vous pouvez maintenant saisir un nom pour ce lien ODBC (qui peut tre diffrent du nom du fichier Access) qui servira de rfrence pour les futures connexions via PHP ainsi quun commentaire. Cliquez ensuite sur le bouton Slectionner....
Figure 10.10 : Installation ODBC pour Microsoft Access (suite)

10. Lutilisation des bases de donnes

8.

Vous tes alors invit reprer le fichier de votre base de donnes dans larborescence de votre disque dur. Une fois que cela est fait, cest bon, vous navez plus qu cliquer sur OK.
Figure 10.11 : Voil, cest fait

9.

Et voil, longlet Sources de donnes systme sest enrichi dune nouvelle ligne.

Utilisation
videmment, les fonctions permettant daccder MS Access sont celles proposes pour les liaisons ODBC.

Vous tes donc invit vous reporter la section ODBC.

686

DB2 (IBM)

10.8. DB2 (IBM)


DB2 est la base de donnes professionnelle du gant de linformatique, IBM.

Installation
Le but de ce chapitre nest pas de faire de vous un administrateur de base de donnes DB2. Non. Nous nous contenterons de dcrire une installation standard, sans tenir compte des problmes doptimisation et de scurit. Le but tant que vous puissiez installer PHP et DB2 sur des machines de test pour vous familiariser avec cet environnement avant de passer un serveur de bases de donnes destin la production.

10. Lutilisation des bases de donnes

Pr-requis
Pour commencer, vous devez vous procurer le script dinstallation. Celui-ci est disponible sur le site dIBM (http://www.ibm.fr) ladresse http://www-5.ibm.com/fr/software/data/db2/index.html. Pour la version Linux, il sagit dun fichier db2pelnx.tar.

Installation du serveur de bases de donnes


Nous supposerons ici que le serveur de bases de donnes et le serveur web tournent sur la mme machine.

Sous Linux
La premire chose faire consiste dcompresser larchive dans un rpertoire quelconque (ex. : /tmp/db2),
# tar xvf db2pelnx.tar

puis lancer le script dinstallation :


# ./db2setup

Apparat alors le premier cran, proposant une liste dlments installer :


+-------------------------------- Install DB2 V7 ----------------------------+ | | | Select the products you are licensed to install. Your Proof of | | Entitlement and License Information booklet identify the products for | | which you are licensed. | | | | To see the preselected components or customize the selection, select | | Customize for the product. | | [*] DB2 Administration Client : Customize... : | | [*] DB2 UDB Personal Edition : Customize... : | | [*] DB2 Application Development Client : Customize... : | | | | To choose a language for the following components, select Customize for |

687

Chapitre 10

Lutilisation des bases de donnes

| the product. | | DB2 Product Messages [ Customize... ] | | DB2 Product Library [ Customize... ] | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | [ OK ] [ Cancel ] [ Help ] | +----------------------------------------------------------------------------+

10. Lutilisation des bases de donnes

1.

Slectionnez les trois modules, puis slectionner loption "customize" de "DB2 Application Development Client" et assurez vous de bien cocher loption "Create links for DB2 libraries". Lancez linstallation en slectionnant le bouton OK. Deux crans successifs apparaissent alors, vous invitant prciser les noms et paramtres des diffrents comptes DB2. Conservez les paramtres par dfaut et validez. Vous aurez alors, trois nouveaux comptes :
j j j
db2inst1 associ au groupe db2iadm1, avec pour rpertoire /home/db2inst1 et mot de passe ibmdb2 ; db2fenc1 associ au groupe db2fadm1, avec pour rpertoire /home/db2fenc1 et mot de passe ibmdb2 ; db2as associ au groupe db2asgrp, avec pour rpertoire /home/db2as et mot de passe ibmdb2.

2. 3.

Et voil, votre base de donnes a t installe sous /usr/IBMdb2/V7.1.

Dmarrage du serveur de bases de donnes


lissue de linstallation, le serveur de bases de donnes tourne. Sachez toutefois que, si vous avez lancer le serveur, cela se fait simplement partir du compte db2inst1 avec la commande
$ db2start

688

DB2 (IBM)

Test du serveur de bases de donnes


partir du compte db2inst1, vous pouvez aisment tester le bon fonctionnement du serveur de bases de donnes. En crant la base de donnes dexemple :
$ db2sampl

10. Lutilisation des bases de donnes

En vous y connectant et en testant une requte :


$ db2 connect to sample $ db2 "select * from staff where dept=20"

Vous devez alors avoir quatre lignes de rsultat. Vous pouvez alors vous dconnecter.
$ db2 connect reset

Cration dune base


Vous pouvez crer une base de donnes depuis le client db2.
$db2 create database <nom de la base>

Arrt du serveur de bases de donnes


Vous pouvez arrter le serveur de bases de donnes avec linstruction
$ db2stop

Installation du client de base de donnes sur le serveur web


Nous avons, ici, suppos que le serveur de bases de donnes tournait sur la mme machine que le serveur web. Nous pourrions donc nous attendre ce quil ny ait rien dautre de particulier faire. Malheureusement, nous avons pu constater (du moins dans le cas de figure qui nous intressait) un lger dysfonctionnement dans la procdure dinstallation. En effet, nous nous sommes retrouvs avec un lien symbolique /usr/local/lib/libbd2.so.3 pointant sur un fichier /usr/local/lib/ libbd2.so inexistant. Ce qui nous posait problme lors de la compilation dApache. Problme que nous avons simplement rsolu en crant un lien symbolique du fichier /usr/db2inst1/lib/ libdb2.so vers /usr/lib, comme suit :
# ln -s /usr/db2inst1/lib/libdb2.so /usr/lib

Conguration de PHP avec support DB2


Sous Linux
Pour accder une base de donnes DB2 depuis PHP, vous navez qu recompiler PHP avec loption withibmdb2=/usr/db2inst1/sqllib.

689

Chapitre 10

Lutilisation des bases de donnes

Vous pouvez vous reporter au chapitre "Installation" pour plus de dtails sur la faon de compiler PHP.

Vrication de linstallation
10. Lutilisation des bases de donnes
Vous pouvez maintenant tester un script ne contenant que le code <?php phpinfo(); ?> et vous devez apercevoir les lignes suivantes :

Figure 10.12 : phpinfo() pour DB2

Utilisation
Bien que nutilisant pas une liaison ODBC, les fonctions permettant daccder aux bases DB2 sont les mmes que celles proposes pour les liaisons ODBC.

Vous tes donc invit vous reporter la section ODBC.

10.9. MySQL
MySQL est probablement la base de donnes la plus connue des adeptes de PHP. Le fait quelle soit sous licence GPL, disponible sous diffrentes plateformes et, somme toute, assez complte et performante ny est certainement pas pour rien. Cest trs probablement dailleurs la base de donnes que votre hbergeur vous propose (sous un environnement Linux, afin dallier la performance la limitation des frais de licence et de maintenance).

MySQL 3.X La dernire version de production de MySQL est la version 4.0. Cest donc linstallation de cette dernire qui est dcrite ici. Toutefois, il est possible que votre 690

MySQL

hbergeur propose toujours la version 3 et donc que vous souhaitiez installer la mme version. Rassurez-vous, la procdure dinstallation est totalement identique.

Installation
Nous nous contenterons ici de dcrire une installation standard, sans prendre en compte les problmes doptimisation et de scurit. Le but tant que vous puissiez installer PHP et MySQL sur des machines de test pour vous familiariser avec cet environnement avant de passer un serveur de bases de donnes destin la production.

10. Lutilisation des bases de donnes

Pr-requis
Si vous tes sous Windows et avez install EasyPHP, vous naurez rien installer ou configurer, puisque tout est fait automatiquement (aussi bien pour ce qui concerne MySQL que pour ce qui concerne PHP). Avec EasyPHP 1.7, cest MySQL 4.0.15 qui est fourni. Dans les autres cas, pour commencer, vous devrez vous procurer larchive de MySQL, disponible sur le site officiel ladresse http://www.mysql.com/downloads/ (vous la trouverez galement sur le CD-ROM fourni).

Installation du serveur de bases de donnes


Sous Windows
Vous devriez maintenant avoir un paquetage avec un nom du genre :
mysql4.0.14bwin.zip.

Winzip Si vous navez pas Windows XP ou un utilitaire pour extraire les fichiers du paquetage, vous pouvez tlcharger la version de dmonstration de Winzip sur http://www.winzip.com.
Il faut ensuite extraire les fichiers du paquetage dans un rpertoire quelconque et excuter le fichier Setup.exe. Linstallation est trs simple et rapide :

691

Chapitre 10

Lutilisation des bases de donnes

Figure 10.13 : Rpertoire dinstallation

10. Lutilisation des bases de donnes

Nous choisirons une installation typique, qui nous conviendra pour ce que lon souhaite faire.
Figure 10.14 :

Installation typique

Linstallation cre automatiquement un fichier my.ini dans le rpertoire de Windows, qui servira pour utiliser MySQL en tant que service.

Installation Si vous installez MySQL dans un rpertoire autre que C:\MYSQL, ou si vous voulez installer MySQL en tant que service sur Windows 2000/NT/XP, il faudra crer un fichier appel C:\MY.CNF ou placer un fichier my.ini dans votre rpertoire Windows avec les lignes suivantes ( modifier selon votre configuration) :
[mysqld] basedir=C:/repertoireinstallation/ datadir=C:/repertoiredonnees/

Quoi quil en soit, une fois linstallation de MySQL termine, le rpertoire dinstallation contiendra des fichiers appels my-xxxxx.cnf quil est possible dutiliser 692

MySQL

pour refaire votre propre fichier C:\MY.CNF, les diffrents fichiers dpendent de la taille de votre base de donnes : de small pour les petites bases de donnes huge pour les trs grosses en passant par medium et large.

10. Lutilisation des bases de donnes

Sous Linux
Il existe plusieurs faons de faire. Mais les deux principales consistent soit utiliser les versions prcompiles de MySQL soit les compiler soit mme. Mais curieusement larborescence des fichiers obtenus diffrent lgrement entre les deux solutions.

Version prcompile
Une fois larchive correspondant votre environnement (ici, une architecture intel) installe sur votre disque dur (par exemple sous /usr/local), il vous faudra la dcompresser par la commande :
# tar zxvf mysql-standard-4.0.20-pc-linux-i686.tar.gz

Vous disposez alors de tous les fichiers MySQL sous /usr/local/mysql-standard-4.0 .20-pc-linux-i686.rpertoire que nous renommerons en /usr/local/mysql.
# cd /usr/local # mv mysql-standard-4.0.20-pc-linux-i686 mysql # cd mysql

Il vous faut, dsormais, initialiser lespace destin accueillir les bases de donnes.
# ./scripts/mysql_install_db

Assurez-vous de bien excuter le script depuis le rpertoire mysql. Cela se traduit par la cration de fichiers et de rpertoires sous /usr/local/mysql/data. Puisquil est prfrable de ne pas faire tourner le serveur MySQL sous le compte root, nous vous invitons maintenant crer un compte mysql.
# groupadd mysql # useradd -g mysql -s /bin/bash mysql

Vous pouvez maintenant modifier le propritaire des fichiers de base de donnes :


# chown -R mysql /usr/local/mysql/data

ainsi que le groupe auquel appartiennent les fichiers du serveur.


# chgrp -R mysql /usr/local/mysql

Copiez ensuite le fichier de configuration dans le repertoire /etc/.


# cp support-files/my-medium.cnf /etc/my.cnf

693

Chapitre 10

Lutilisation des bases de donnes

Compte sans mot de passe Dans ltat actuel, ce compte mysql ne possde pas de mot de passe ; vous ne pourrez y accder que depuis le compte root en tapant su mysql.

10. Lutilisation des bases de donnes

Version compiler
Pour cela vous devez rcuprer les sources du serveur MySQL (disponibles sur le CD-ROM) puis, une fois larchive installe sur votre disque dur, il vous faudra la dcompresser par la commande :
# tar zxvf mysql-4.0.20.tar.gz

Une fois les sources dcompresses, il est possible de les compiler par les commandes :
# # # # cd mysql-4.0.20 ./configure --prefix=/usr/local/mysql make make install

MySQL est a prsent install sous /usr/local/mysql.


# cd /usr/local/mysql

Il vous faut, dsormais, initialiser lespace destin accueillir les bases de donnes.
# ./bin/mysql_install_db

Cela se traduit par la cration de fichiers et de rpertoires sous /usr/local/mysql/var. Puisquil est prfrable de ne pas faire tourner le serveur MySQL sous le compte root, nous vous invitons donc crer un compte mysql.
# groupadd mysql # useradd -g mysql -s /bin/bash mysql

Vous pouvez maintenant modifier le propritaire des fichiers de base de donnes :


# chown -R mysql /usr/local/mysql/var

ainsi que le groupe auquel appartiennent les fichiers du serveur.


# chgrp -R mysql /usr/local/mysql

Copiez ensuite le fichier de configuration dans le rpertoire /etc/.


# cp share/mysql/my-medium.cnf /etc/my.cnf

Compte sans mot de passe Dans ltat actuel, ce compte mysql ne possde pas de mot de passe ; vous ne pourrez y accder que depuis le compte root en tapant su mysql.

694

MySQL

Dmarrage du serveur de bases de donnes


Sous Windows
Pour lancer le service, il faut excuter le fichier winmysqladmin.exe du rpertoire bin de MySQL. la premire excution, le programme vous demandera un nom dutilisateur et un mot de passe crer. Un feu vert devrait alors apparatre dans votre barre des tches, indiquant que le serveur MySQL est prt.

10. Lutilisation des bases de donnes

Sous Linux
Le dmon mysqld doit tre actif pour pouvoir utiliser la base de donnes MySQL.
# /usr/local/mysql/bin/mysqld_safe --user=mysql &

Avec MySQL 3.X vous devrez lancer la commande


# /usr/local/mysql/bin/safe_mysqld --user=mysql &

Cration dune base


Sous Windows
En utilisant le logiciel WinMYSQLAdmin et longlet Databases, il est possible de voir les bases de donnes existantes. Pour en crer une, il suffit de cliquer avec le bouton droit sur le nom de la machine, puis de slectionner Create Database. Une fentre souvre, demandant le nom de la nouvelle base de donnes.

Figure 10.15 : Ajouter une base de donnes

695

Chapitre 10

Lutilisation des bases de donnes

Une autre faon de faire consiste excuter la commande en ligne mysql puis de taper :
CREATE DATABASE maBase;

10. Lutilisation des bases de donnes

Figure 10.16 : Ajouter une base de donnes par la commande en ligne

Sous Linux
Une fois mysql lanc, il suffit dentrer la commande :
$ mysql CREATE DATABASE maBase;

Utiliser un autre utilisateur que lutilisateur courant Pour lancer mysql avec un autre nom dutilisateur que le nom courant, il faut passer loption u. Il est galement possible de passer le mot de passe en ligne de commande par loption p.

$ mysql u root p motdepasse

Test du serveur de bases de donnes


Il est possible de faire excuter quelques requtes SQL pour voir le fonctionnement du serveur. Il suffit de lancer mysql et de taper, par exemple, (cela suppose que vous ayez cr la base de donnes maBase auparavant) :
$ mysql USE maBase; CREATE Table maTable (id INTEGER, valeur VARCHAR(32)); INSERT INTO maTable (1, "toto"); INSERT INTO maTable (2, "titi"); SELECT * FROM maTable;

Voici une capture dcran sous Windows de cette srie de requtes :

696

MySQL

10. Lutilisation des bases de donnes

Figure 10.17 : Quelques requtes pour tester

Configuration par dfaut de MySQL Avec une installation par dfaut de MySQL, vous aurez tous les droits utilisateurs si la base de donnes tourne localement, et que vous utilisez pour nom dutilisateur "root" et pour mot de passe simplement une chane vide. Mais nhsitez surtout pas modifier cette configuration de base pour obliger lutilisation dun mot de passe. Cette opration peut se raliser en excutant la requte SQL suivante sur la base mysql :
UPDATE user SET password=PASSWORD(<mot de passe>) WHERE user=root

Conguration de PHP avec support MySQL


Les dernires versions de PHP intgraient par dfaut le support de MySQL dans le noyau. Ce nest plus vrai depuis PHP 5. Et bien quil ny avait, a priori, rien faire pour que cela fonctionne (hormis avoir un serveur MySQL disposition) avec les versions 4.2 et 4.3, il tait dj conseill de recompiler PHP avec lAPI de la version MySQL installe. Avec PHP 5 cela devient une ncessit. Pour cela, il suffit dajouter loption withmysql= /usr/local/mysql.

Vous pouvez vous reporter au chapitre "Installation" pour plus de dtails sur la compilation de PHP.

Conguration php.ini
Le fichier php.ini permet de dfinir les paramtres suivants
mysql.allow_persistent = On

Autorise ou interdit les connexions persistantes.


mysql.max_persistent = -1

697

Chapitre 10

Lutilisation des bases de donnes

Nombre maximum de connexions persistantes. -1 autorise un nombre illimit.


mysql.max_links = -1

Nombre maximum de connexions (persistantes ou non). -1 autorise un nombre illimit.


mysql.default_port =

10. Lutilisation des bases de donnes

Indique le port utiliser sil nest pas prcis lors de lappel mysql_connect() ou mysql_pconnect(). Si vous ne renseignez pas cette directive, mysql_connect utilisera le port indiqu par $MYSQL_TCP_PORT, sinon cest le port associ au service mysqltcp, indiqu dans /etc/services, qui sera utilis, ou, enfin, la valeur dfinie lors de la compilation par la constante MYSQL_PORT. Sous Windows, seul le port prcis par MYSQL_PORT est pris en compte.
mysql.default_socket =

Indique le nom de la socket par dfaut pour les connexions MySQL en local. Si vous ne renseignez pas cette directive, PHP utilisera la configuration MySQL par dfaut.
mysql.default_host =

Indique le nom (ou ladresse) du serveur mysql utiliser par dfaut sil nest pas prcis lors de lappel mysql_connect() ou mysql_pconnect(). Cette option nest pas prise en compte en mode scuris.
mysql.default_user =

Indique le nom dutilisateur donner par dfaut sil nest pas prcis lors de lappel mysql_connect() ou mysql_pconnect().Cette option nest pas prise en compte en mode scuris.
mysql.default_password =

Indique le mot de passe utiliser par dfaut sil nest pas prcis lors de lappel mysql_connect() ou mysql_pconnect(). Cette option nest pas prise en compte en mode scuris. Il est dconseill de stocker les mots de passe dans ce fichier. Nimporte quel utilisateur ayant accs votre PHP, ou ayant les droits de lecture, pourrait lancer la commande echo cfg_get_var("mysql.default_password"), et accder ainsi ce mot de passe.

Vrication
Vous pouvez maintenant tester un script ne contenant que le code <?php phpinfo(); ?>. Vous devez apercevoir les lignes suivantes :

698

MySQL

Figure 10.18 :

phpinfo()

10. Lutilisation des bases de donnes

Utilisation
Comme indiqu dans le chapitre dintroduction, lutilisation basique de la base de donnes sopre selon le schma suivant :
j j j

Connexion

grce

aux

fonctions

mysql_connect()

ou

mysql_pconnect()

et

mysql_select_db().

Soumission de la requte via la fonction mysql_query(). Dconnexion grce la fonction mysql_close() (dans le cas dune connexion non persistante).

Connexion
La connexion une base de donnes MySQL ncessite deux oprations. Il faut, dans un premier temps, se connecter au serveur de bases de donnes avec la fonction mysql_connect(); la slection de la base sopre dans un second temps avec mysql_select_db().

mysql_connect()
tablit une connexion (non persistante) avec le serveur de bases de donnes. Syntaxe resource mysql_connect([string $nomServeur [:$port] [:$cheminSocket] [, string $utilisateur [, string $motDePasse [, boolean $nouvelleCnx [, int $option]]]]]) Nom du serveur (par dfaut "localhost").

$nomServeur

699

Chapitre 10

Lutilisation des bases de donnes

$port $cheminSocket $utilisateur

Port sur lequel la connexion au serveur de bases de donnes seffectue (par dfaut 3306). Chemin vers le fichier socket (lorsque le serveur de bases de donnes tourne en local). Nom dutilisateur (sous Linux/UNIX ; par dfaut, le propritaire du serveur web, qui traditionnellement pour Apache est "nobody"). Mot de passe de lutilisateur (par dfaut, aucun mot de passe). Prcise si lon souhaite (TRUE) ou non (FALSE, valeur par dfaut) forcer la cration dune nouvelle connexion si une connexion similaire a dj t ouverte. Prcise une option de communication avec le serveur de base de donnes. Ce paramtre est disponible depuis la version 4.3.0 de PHP. Elle peut prendre lune des valeurs suivantes: MYSQL_CLIENT_COMPRESS, pour envoyer les donnes sous forme compresses. MYSQL_CLIENT_IGNORE_SPACE, pour autoriser les espaces aprs les noms de fonction (tous les noms de fonctions sont alors des mots rservs). MYSQL_CLIENT_INTERACTIVE, pour baser le time-out de dconnexion non pas sur la valeur de wait_timeout mais sur celle de interactive_timeout. MYSQL_CLIENT_SSL, (uniquement avec MySQL 4) pour utiliser le protocole SSL. Identifiant de connexion au serveur de bases de donnes, ou FALSE en cas dchec.

10. Lutilisation des bases de donnes

$motDePasse $nouvelleCnx

$option

retour

Lutilisation dune connexion persistante requiert, la place, lappel la fonction mysql_pconnect().

mysql_pconnect()
tablit une connexion persistante avec le serveur de bases de donnes. Si une connexion persistante est disponible, elle sera utilise ; sinon, une nouvelle connexion persistante sera cre. Syntaxe resource mysql_pconnect([string $nomServeur [:$port] [:$cheminSocket] [, string $utilisateur [, string $motDePasse [, int $option]]]) Nom du serveur (par dfaut "localhost"). Port sur lequel la connexion au serveur de bases de donnes seffectue (par dfaut 3306). Chemin vers le fichier socket (lorsque le serveur de bases de donnes tourne en local). Nom dutilisateur (sous Linux/UNIX ; par dfaut, le propritaire du serveur web, qui traditionnellement pour Apache est "nobody"). Mot de passe de lutilisateur (par dfaut, aucun mot de passe).

$nomServeur $port $cheminSocket $utilisateur $motDePasse

700

MySQL

$option

Prcise une option de communication avec le serveur de base de donnes. Ce paramtre est disponible depuis la version 4.3.0 de PHP. Elle peut prendre lune des valeurs suivantes: MYSQL_CLIENT_COMPRESS, pour envoyer les donnes sous forme compresses. MYSQL_CLIENT_IGNORE_SPACE, pour autoriser les espaces aprs les noms de fonction (tous les noms de fonctions sont alors des mots rservs). MYSQL_CLIENT_INTERACTIVE, pour baser le time-out de dconnexion non pas sur la valeur de wait_timeout mais sur celle de interactive_timeout. MYSQL_CLIENT_SSL, (uniquement avec MySQL 4) pour utiliser le protocole SSL. Identifiant de connexion au serveur de bases de donnes, ou FALSE en cas dchec.

10. Lutilisation des bases de donnes

retour

mysql_select_db
Slectionne une base de donnes. Syntaxe $baseDonnees $idConnexion boolean mysql_select_db(string $baseDonnees [, resource $idConnexion]) Nom de la base de donnes. Identifiant de connexion au serveur de bases de donnes tel que retourn par mysql_connect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. TRUE en cas de succs, FALSE sinon (ex. : base de donnes inexistante).

retour

Excution de la requte SQL


Pour excuter une requte SQL, il suffit de faire appel la fonction mysql_query().

mysql_query()
Excute une requte SQL. Syntaxe $requete $idConnexion resource mysql_query(string $requete [, resource $idConnexion]) Requte SQL. Identifiant de connexion une base de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Identifiant de requte SQL, ou FALSE en cas dchec.

retour

701

Chapitre 10

Lutilisation des bases de donnes

Dans le cas dune requte retournant un rsultat (typiquement une requte SELECT), il faudra galement analyser le rsultat. Mais nous verrons cela un peu plus loin.

Dconnexion
10. Lutilisation des bases de donnes
Pour vous dconnecter opration thoriquement facultative mais toutefois vivement conseille , vous disposez de la fonction mysql_close().

mysql_close
Met fin la connexion la base de donnes et libre les ressources associes. Syntaxe $idConnexion boolean mysql_close([resource $idConnexion]) Identifiant de connexion une base de donnes tel que retourn par mysql_connect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. TRUE si lopration a t effectue avec succs, NULL (mais pas strictement FALSE) en cas dchec.

retour

Premier exemple
Vrifiez les paramtres Prenez garde ! Avant dexcuter ce script, assurez-vous que les paramtres prdfinis ne risquent pas de conduire la suppression des donnes dune de vos bases qui, par concidence, existerait dj.
Comme cela est fortement conseill, nous avons, ici, isol les paramtres de connexion dans un fichier aisment reprable,

Listing 10.28 : parametres_bd_inc.php


<?php // Parametres de connexion la base // de donnes $serveur $port $utilisateur $motDePasse $base ?> = = = = "localhost"; ""; // doit commencer par : "root"; "";

= "maBase";

702

MySQL

et qui est utilis par le script principal.

Listing 10.29 : insert01.php


<?php // Paramtres du script require_once("parametres_bd_inc.php"); $table = "tableexemple"; // Inclusion du script contenant les fonctions require_once("insert01_bd_inc.php"); // Connexion la base de donnes $idConnexion = mysql_pconnect($serveur, $utilisateur, $motDePasse); if (!$idConnexion) { die("<b>Impossible de se connecter la base de donnes</b>"); } if (!mysql_select_db($base)) { die("<b>Impossible de se connecter la base de donnes</b>"); } // Appel de la fonction principale if (EX_initialiseBD($idConnexion, $table)) { echo "Voil, une nouvelle table avec quelques donnes, ". "vous pouvez le vrifier avec votre client de base ". " de donnes ou via les scripts suivants."; } else { echo "La cration ou lalimentation de la table choue."; } // Pas de dconnexion dans le cas dune connexion persistante // mysql_close($idConnexion); ?>

10. Lutilisation des bases de donnes

Ce script utilise les fonctions dfinies dans le fichier :

Listing 10.30 : insert01_bd_inc.php


<?php /** * Fonction charge de crer et dalimenter une table * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_initialiseBD($idConnexion, $table) { // Supprime la prcdente table

703

Chapitre 10

Lutilisation des bases de donnes

$requete = "DROP TABLE $table"; @mysql_query($requete, $idConnexion); // Cre la table $requete = "CREATE TABLE $table (filmId INTEGER ". " AUTO_INCREMENT PRIMARY KEY,". "film VARCHAR(64))"; if (!mysql_query($requete, $idConnexion)) return FALSE; // Ajoute quelques donnes $requete = "INSERT INTO $table (film) VALUES (Forrest Gump)"; if (!mysql_query($requete, $idConnexion)) return FALSE; $requete = "INSERT INTO $table (film) VALUES (Matrix)"; if (!mysql_query($requete, $idConnexion)) return FALSE; $requete = "INSERT INTO $table (film) VALUES (La cit de la peur)"; if (!mysql_query($requete, $idConnexion)) return FALSE; return TRUE; } ?>

10. Lutilisation des bases de donnes

Valeur du champ auto-incrment


Parfois, aprs avoir insr des donnes dans une table contenant un champ auto-incrment, vous aurez besoin de connatre la valeur qui a t donne ce champ. Pour cela, vous devrez appeler la fonction mysql_insert_id().

mysql_insert_id()
Retourne la valeur affecte au champ auto-incrment lors de la dernire requte INSERT. Syntaxe $idConnexion int mysql_insert_id([resource $idConnexion]) Identifiant de connexion une base de donnes tel que retourn par mysql_connect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. La valeur du champ.

retour

Lecture des enregistrements


Dans le cas dune requte retournant une liste de donnes, il convient de rcuprer lidentifiant de requte et de lutiliser pour lire, en boucle, ligne aprs ligne, chaque enregistrement. Il existe diverses fonctions, chacune permettant de rcuprer les champs des enregistrements sous diffrentes formes.

704

MySQL

Les informations peuvent ainsi tre retournes :


j j

Champ par champ ; Enregistrement par enregistrement (sous la forme dun tableau index, dun tableau associatif ou encore dun tableau la fois index et associatif).

Lecture champ par champ


Bien que cela prsente peu dintrt, sachez quil existe une fonction appele mysql_result() permettant daccder au rsultat champ par champ.

10. Lutilisation des bases de donnes

Lecture enregistrement par enregistrement


La forme la plus simple est celle retourne par la fonction mysql_fetch_row().

mysql_fetch_row()
Retourne un enregistrement, retourn par une requte SQL, sous la forme dun tableau index. Syntaxe $idResultat retour array mysql_fetch_row(resource $idResultat) Identifiant de requte tel que retourn par mysql_query(). Tableau index contenant autant dlments que de champs retourns par la requte ; FALSE sil ny a plus denregistrement lire, ou rien en cas didentifiant de requte non valide.

Listing 10.31 : select_eei_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requete $requete = "SELECT * FROM $table"; $idResultat = mysql_query($requete, $idConnexion); if (!$idResultat) return FALSE; // Boucle de lecture (et daffichage) des enregistrements while ($enreg = mysql_fetch_row($idResultat)) { echo "FilmId=".$enreg[0]." ". "Film =" .$enreg[1]."<br />";

705

Chapitre 10

Lutilisation des bases de donnes

} return TRUE; } ?>

10. Lutilisation des bases de donnes

Mais il est galement possible de retourner un enregistrement sous la forme dun tableau index et associatif avec, pour cls, les noms des champs.

mysql_fetch_array()
Retourne un enregistrement, retourn par une requte SQL, sous la forme dun tableau index et/ou associatif. Syntaxe $idResultat $mode array mysql_fetch_array(resource $idResultat [, int $mode]) Identifiant de requte tel que retourn par mysql_query(). Au choix lune des constantes suivantes : MYSQL_ASSOC, pour retourner un tableau associatif, o les cls sont les noms des champs (faites attention la casse). MYSQL_NUM, pour retourner un tableau index. MYSQL_BOTH (par dfaut), pour retourner un tableau la fois index et associatif, o les cls (en minuscules) sont les noms des champs. retour Tableau index et/ou associatif selon le mode choisi ; FALSE sil ny a plus denregistrement ou rien en cas derreur (si lidentifiant de requte nest pas valide).

Cest ce mode de lecture des donnes que nous privilgierons ; il est en effet fort pratique pour les champs dont on connat le nom (ce qui est le plus souvent le cas), et permet galement de faire rfrence des champs sans nom, comme par exemple un champ SUM(nomchamp). Notez toutefois quil est possible daffecter un nom (ex. : somme) ce genre de champ en indiquant SUM(nomchamp) AS somme. Lexemple prcdent gagnera ainsi en lisibilit et deviendra :

Listing 10.32 : select_eea_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) {

706

MySQL

// Requete $requete = "SELECT * FROM $table"; $idResultat = mysql_query($requete, $idConnexion); if (!$idResultat) return FALSE; // Boucle de lecture (et daffichage) des enregistrements while ($enreg = mysql_fetch_array($idResultat)) { echo "FilmId=".$enreg["filmId"]." ". "Film =" .$enreg["film"]."<br />"; } return TRUE; } ?>

10. Lutilisation des bases de donnes

mysql_fetch_assoc() Utiliser la fonction mysql_fetch_array() avec loption MYSQL_ASSOC revient appeler une fonction appele mysql_fetch_assoc().
Pour votre culture personnelle, sachez quil existe galement une fonction (dun intrt discutable) qui permet de retourner lenregistrement sous forme dun objet possdant des variables internes portant les mmes noms (en minuscules) que les champs. Cette fonction sappelle mysql_fetch_object() et possde la mme syntaxe que mysql_fetch_row(), si ce nest quelle retourne un objet et non un tableau. La boucle de lecture se transforme alors en :
<?php while ($enreg = mysql_fetch_object($idResultat)) { echo "FilmId = ".$enreg->filmid." Film = ".$enreg->film."<br />"; } ?>

Libration des ressources


Si, au cours dun script, vous faites appel de nombreuses requtes retournant de nombreux enregistrements, alors, nhsitez pas, une fois le rsultat de la requte exploit, librer les ressources associes avec la fonction mysql_free_result().

mysql_free_result()
Libre les ressources alloues pour un rsultat de requte. Syntaxe $idResultat retour boolean mysql_free_result(resource $idResultat) Identifiant de requte tel que retourn par mysql_query(). TRUE en cas de succs, FALSE sinon.

707

Chapitre 10

Lutilisation des bases de donnes

Nombre denregistrements
Nombre denregistrements retourns
Il existe trois faons de dterminer le nombre denregistrements retourns par une requte. Si vous souhaitez uniquement connatre le nombre denregistrements, mais ne souhaitez pas immdiatement lire ces enregistrements, alors il vous suffit de faire une requte COUNT() comme suit :

10. Lutilisation des bases de donnes

Listing 10.33 : count_bd_inc.php


<?php /** * Fonction affichant le nombre denregistrements * dans une table * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la tabme **/ function EX_compte($idConnexion, $table) { // Requte $requete = "SELECT COUNT(*) FROM $table"; $idResultat = mysql_query($requete, $idConnexion); // Lecture du rsultat if ($enreg = mysql_fetch_row($idResultat)) { echo "Il y a ".$enreg[0]." enregistrements dans la table.<br />"; return TRUE; } else { echo "Etes vous sr que la table $table existe ?<br />"; return FALSE; } } ?>

Si vous souhaitez connatre le nombre denregistrements, et que vous souhaitez lire les enregistrements sans pour autant avoir besoin au pralable den connatre le nombre, il suffit de compter combien denregistrements sont lus.

Listing 10.34 : count_select_db_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD

708

MySQL

* @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requete $requete = "SELECT * FROM $table"; $idResultat = mysql_query($requete, $idConnexion); if (!$idResultat) return FALSE; // Boucle de lecture (et de comptage) des enregistrements $nb = 0; while ($row = mysql_fetch_row($idResultat)) { // Vous pouvez manipuler $enreg votre guise //echo "FilmId=".$enreg[0]." ". // "Film =" .$enreg[1]."<br />"; $nb++; } echo "Il y a $nb enregistrements dans la table.<br />"; return TRUE; } ?>

10. Lutilisation des bases de donnes

Et, pour finir, ce que vous attendez tous : si vous souhaitez connatre le nombre denregistrements avant de les lire, vous pouvez faire appel la fonction mysql_num_rows().

mysql_num_rows()
Retourne le nombre denregistrements retourns par la requte SQL. Syntaxe $idRequete retour int mysql_num_rows(resource $idRequete) Identifiant de requte tel que retourn par mysql_query(). Nombre denregistrements, ou rien en cas didentifiant de requte non valide.

Listing 10.35 : count_num_rows_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) {

709

Chapitre 10

Lutilisation des bases de donnes

// Requete $requete = "SELECT * FROM $table"; $idResultat = mysql_query($requete, $idConnexion); if (!$idResultat) return FALSE; echo "Il y a ".mysql_num_rows($idResultat)." enregistrements ". "dans la table<br />";

10. Lutilisation des bases de donnes

return TRUE; } ?>

Sachant quune requte SELECT * est plus longue quune requte SELECT COUNT(*), privilgiez la premire mthode si vous navez que faire du contenu des enregistrements.

Nombre denregistrements modis


Pour connatre le nombre de lignes affectes par la requte prcdente (comme le nombre de rsultats aprs un SELECT, le nombre de lignes effaces aprs un DELETE ou le nombre de lignes modifies aprs un UPDATE), nous pouvons utiliser la fonction mysql_affected_rows().

mysql_affected_rows()
Permet de retrouver le nombre de lignes affectes par la requte immdiatement prcdente. Syntaxe $idConnexion int mysql_affected_rows([resource $idConnexion]) Identifiant de connexion une base de donnes tel que retourn par mysql_connect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis.

Bien que plus difficilement exploitable, sachez que depuis PHP 4.3, vous diposez galement de la fonction mysql_info().

mysql_info()
Retourne une chane de caractres prcisant le nombre denregistrements ajouts, modifis, etc. durant la dernire requte. Toutefois, ceci ne concerne quun nombre rduit de type de requtes (INSERT avec des valeurs issues dun SELECT, INSERT de plusieurs lignes, LOAD DATA INFILE, ALTER TABLE et UPDATE) en fait il sagit de celles susceptible de modifier plusieurs enregistrements la fois. Syntaxe : $idConnexion string mysql_info([ressource $idConnexion]) Identifiant de connexion une base de donnes tel que retourn par mysql_connect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis.

710

MySQL

retour

Chane de caractres semblable "Records: 2 Duplicates: 0 Warnings: 0" ou FALSE si la requte ne retourne pas dinfo.

Gestion des erreurs


Jusque-l, en cas derreur, nous nous sommes contents dafficher un message gnrique. Il est cependant possible de dterminer plus prcisment lorigine de lerreur. Cela est notamment possible en rcuprant un code derreur via la fonction mysql_errno().

10. Lutilisation des bases de donnes

mysql_errno()
Retourne le code derreur du dernier appel MySQL. Syntaxe $idConnexion int mysql_errno([resource $idConnexion]) Identifiant de connexion au serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Code derreur, ou tout simplement 0 si la dernire opration sest passe sans erreur.

retour

mysql_error()
Retourne le message derreur associ au dernier appel MySQL. Ce message dpend du serveur, mais aura toutes les chances dtre en anglais. Syntaxe $idConnexion string mysql_error([resource $idConnexion]) Identifiant de connexion au serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Message derreur, ou tout simplement une chane vide "" si la dernire opration sest passe sans erreur.

retour

Tableau 10.14 : Exemples de codes et messages derreur


Code 0 1049 1051 1054 Message Unknown database nombase Unknown table nomtable Description Pas derreur La base nombase nexiste pas La table nomtable nexiste pas

Unknown column nomchamp in field Le champ nomchamp prcis list dans la liste de champs nexiste pas

711

Chapitre 10

Lutilisation des bases de donnes

Code 1054 (et oui ! le mme code que prcdemment) 2005

Message Unknown column nomchamp in where clause Unknown MYSQL Server Host nomserveur (2)

Description Le champ nomchamp prcis dans la clause WHERE nexiste pas Le serveur MySQL nomserveur nexiste pas

10. Lutilisation des bases de donnes

Vous pourrez, par exemple, vous servir des codes derreur pour afficher vos propres messages derreur. Dans lexemple suivant, nous montrons comment traduire les messages derreur (cela ne sappliquera qu lchantillon de codes qui vient dtre prsent).

Listing 10.36 : mysql_err_inc.php


<?php // Retourne une version Franaise du message derreur // en se basant sur le code derreur et sur les informations // complmentaires que lon peut trouver dans le message // Anglais function mysql_error_fr() { // Les noms de tables et autres informations // sont entre apostrophes dans le message derreur // il est donc utile de le dcomposer $morceaux = explode("", mysql_error()); switch (mysql_errno()) { case 0 : // message vide return ""; case 1049 : // Unknown database nombase return "La base ".$morceaux[1]." nexiste pas"; case 1051 : // Unknown table nomtable return "La table ".$morceaux[1]." nexiste pas"; case 1054 : // Unknown column nomchamp in field list // Unknown column nomchamp in where clause switch ($morceaux[3]) { case field list : return "Le champ ".$morceaux[1]." prcis". " dans la liste des champs nexiste pas"; case where clause : return "Le champ ".$morceaux[1]." prcis". " dans la clause WHERE nexiste pas"; default : return mysql_error(); } case 2005 : // Unknown MYSQL Server Host nomserveur (2) return "Le serveur MySQL ".$morceaux[1]." nexiste pas";

712

MySQL

default : return mysql_error(); } } ?>

Et voici un script gnrant lensemble des erreurs ci-dessus, afin de bien mettre en vidence le bon fonctionnement de cette fonction personnalise :

10. Lutilisation des bases de donnes

Listing 10.37 : mysql_err01.php


<?php include_once("parametres_bd_inc.php"); include_once("mysql_err_inc.php"); $table = "tableerr"; @mysql_pconnect("erreur"); echo mysql_error_fr()."<br />"; mysql_pconnect($serveur.$port, $utilisateur, $motDePasse) or die("<b>Impossible de se connecter au serveur base de donnes.</b>"); @mysql_select_db("erreur"); echo mysql_error_fr()."<br />"; mysql_select_db($base) or die("<b>Grrr... Jaurais aim quelle existe cette base.</b>"); @mysql_query("DROP TABLE erreur"); echo mysql_error_fr()."<br />"; mysql_query("CREATE TABLE IF NOT EXISTS $table (id INT2)") or die("<b>Grrr... Jaurais aim que cette requte ne tombe". " pas en erreur.</b>"); @mysql_query("SELECT erreur FROM $table"); echo mysql_error_fr()."<br />"; @mysql_query("SELECT * FROM $table WHERE erreur=1"); echo mysql_error_fr()."<br />"; ?>

Ce script gnre alors une page contenant les messages :


Le La La Le Le serveur MySQL erreur nexiste pas base erreur nexiste pas table erreur nexiste pas champ erreur prcis dans la liste des champs nexiste pas champ erreur prcis dans la clause WHERE nexiste pas

713

Chapitre 10

Lutilisation des bases de donnes

Exemples dapplications
Compteur de clics
10. Lutilisation des bases de donnes
Une application courante dutilisation des bases de donnes, et simple mettre en uvre, consiste crer un compteur de clics. En effet, peut-tre souhaitez-vous proposer, sur votre site, un certain nombre de liens vers des sites Internet (annuaire web) ou vers des fichiers (bibliothques de scripts). Peut-tre que certains (ou la totalit) de ces liens sont proposs par un partenaire. Bref, tout cela vous incite savoir quelles sont les pages les plus frquemment consultes (pour connatre les centres dintrt des visiteurs) et combien de visiteurs vous avez redirigs vers votre sponsor. La mthode la plus classique consiste stocker en base de donnes lensemble des liens ainsi proposs, et remplacer les traditionnels liens de la forme http://www.domaine.com par un lien vers un script charg dincrmenter le compteur correspondant au site indiqu, et de rediriger le client vers le site grce la fonction header().

Vous pouvez vous reporter lannexe "Les en-ttes" pour plus de renseignements sur la redirection.
Pour notre exemple, nous utiliserons une table appele url contenant trois champs :
j j j

urlid, identifiant de lURL (champ auto-incrment) ; url, lURL proprement dite ; nbclic, le nombre de clics.

Le script de redirection (appel ici compteurclic_redirection.php) devra alors accepter un paramtre (urlid) et devra, partir de ce paramtre, dterminer quelle est la valeur du champ url, incrmenter nbclic pour cette URL, et rediriger vers url. Les appels ce script auront alors la forme http://localhost/compteurclic_redirection.php?urlid=3 (pour accder lURL ayant lidentifiant 3). supposer que lURL 3 corresponde au site http://www.sqlfacile.com cela signifie que le lien <a href="http://www.sqlfacile.com "> devra tre remplac par <a href="compteurclic_redirection.php?urlid=3> si lon souhaite en compter le nombre de clics. Concrtement, cette table pourra tre cre et alimente avec la fonction CC_initialiseBD() du script suivant :

Listing 10.38 : compteurclic_bd_inc.php (dbut)


<?php //-----------------------------------// Charge les paramtres de connexion // la base de donnes. //-----------------------------------require_once("parametres_bd_inc.php");

714

MySQL

/** * Fonction de connexion une base de donnes * sappuie sur les paramtres fournis * dans parametres_bd_inc.php. * * @return resource Identifiant de connexion */ function CC_connexion() { global $serveur, $base, $utilisateur, $motDePasse; $idConnexion = mysql_pconnect($serveur, $utilisateur, $motDePasse); if (!$idConnexion) return FALSE; mysql_select_db($base); return $idConnexion; } /** * Fonction de deconnexion. * (Ne fait rien sachant que la fonction * de connexion tablit une connexion persistante) */ function CC_deconnexion() { return TRUE; } /** * Fonction charg de crer et dalimenter * la table "compteur de clics" **/ function CC_initialiseBD($idConnexion, $table) { // Cration de la table $requete = "DROP TABLE $table"; @mysql_query($requete, $idConnexion); $requete = "CREATE TABLE $table (". "urlId INTEGER ". "AUTO_INCREMENT PRIMARY KEY,". "url VARCHAR(128) NOT NULL,". "nbclic INTEGER DEFAULT 0,". "UNIQUE(url))"; if (!mysql_query($requete, $idConnexion)) return FALSE; // Alimentation de la table $requete = "INSERT INTO $table (url)". " VALUES (http://www.php.net)"; if (!mysql_query($requete, $idConnexion)) return FALSE; $requete = "INSERT INTO $table (url)".

10. Lutilisation des bases de donnes 715

Chapitre 10

Lutilisation des bases de donnes

" VALUES (http://www.phpfacile.com)"; if (!mysql_query($requete, $idConnexion)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.sqlfacile.com)"; if (!mysql_query($requete, $idConnexion)) return FALSE;

10. Lutilisation des bases de donnes

$requete = "INSERT INTO $table (url)". " VALUES (http://www.xmlfacile.com)"; if (!mysql_query($requete, $idConnexion)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.ootoogo.com)"; if (!mysql_query($requete, $idConnexion)) return FALSE; return TRUE; } ?>

La lecture de la liste des liens disponibles en base de donnes pourra se faire via la fonction CC_recupereLiens() du script suivant :

Listing 10.39 : compteurclic_bd_inc.php (milieu)


<?php /** * Fonction retournant les informations de liens * sous forme dun tableau associatif possedants * les cls * - "lien" associ au tableau des liens hypertextes * - "nbclic" associ au tableau des nombres de clics **/ function CC_recupereLiens($idConnexion, $table) { // Nom du script charg du comptage et de la redirection $script = "compteurclic_redirection.php"; // Requte SELECT $requete = "SELECT * FROM $table"; $idResultat = mysql_query($requete, $idConnexion); // Rcupration des enregistrements les uns aprs les autres while ($enreg = mysql_fetch_array($idResultat)) { $liens["lien"][] = "<a href=\"$script?urlid=". $enreg["urlId"]."\">". $enreg["url"]."</a>"; $liens["nbclic"][] = $enreg["nbclic"]; } return $liens; }

716

MySQL

Laffichage des liens consiste uniquement mettre en page le contenu du tableau ainsi rcupr (voir la fonction du script compteurclic_html_inc.php). Comme cela a t prcis, le lien <a href="http://www.sqlfacile.com">http://www .sqlfacile.com</a> a t remplac par <a href="compteurclic_redirection .php?urlid=3">http://www.sqlfacile.com </a>. La redirection vers le site www.sqlfacile .com est donc la charge du script compteurclic_redirection.php.

10. Lutilisation des bases de donnes

Listing 10.40 : compteurclic_redirection.php


<?php // Paramtres du script require_once("compteurclic_bd_inc.php"); $table = "compteurclic"; // Connexion la base de donnes $idConnexion = @CC_connexion(); if (!$idConnexion) { die("<b>Impossible de se connecter la base de donnes</b>"); } // Rcupration de lurl et incrmentation du compteur // pour lurl dindentifiant pass en paramtre de ce script // par la mthode GET $url = @CC_recupereUrl($idConnexion, $_GET["urlid"]); // Deconnexion @CC_deconnexion(); // Cest lheure de la redirection if ($url) { header("Location: $url"); } else { echo "Dsol, nous ne pouvons vous proposer ce lien"; } ?>

Ce script appelle principalement la fonction CC_recupereUrl() suivante :

Listing 10.41 : compteurclic_bd_inc.php (fin)


<?php /** * Fonction rcuprant une url partir de son identifiant * et incrmentant le compteur de clics **/ function CC_recupereUrl($idConnexion, $urlid) { global $table; // Rcupre lurl

717

Chapitre 10

Lutilisation des bases de donnes

$requete = "SELECT * FROM $table WHERE urlid=$urlid"; $idResultat = mysql_query($requete, $idConnexion); if ($enreg = mysql_fetch_array($idResultat)) { $url = $enreg["url"]; // Incrmente le compteur $requete = "UPDATE $table SET nbclic=nbclic+1 WHERE urlid=$urlid"; mysql_query($requete, $idConnexion); } else { $url = FALSE; } return $url; } ?>

10. Lutilisation des bases de donnes

Utilisation du bouton retour Si, aprs avoir suivi un lien, vous revenez sur la page compteurclic.php en utilisant le bouton retour (back), le contenu de la page ne sera pas ractualis. Par consquent, le nombre de visites affich ne sera pas correct. Noubliez donc pas, dans ce cas, de rafrachir (bouton actualiser) la page.

SuperTheque
Lessentiel du code de lapplication a t prsent en introduction de ce chapitre. Il ne restait plus qu connatre les fonctions MySQL pour implmenter linterface RessourceInterface cest dsormais chose faite:

Listing 10.42 : RessourceMySQL_class.php


<?php include_once("RessourceInterface_class.php"); include_once(dirname(__FILE__)."/../config/mysql_cfg.php"); /** * RessourceMySQL_class.php * Classe dacces a une base de donnees MySQL * Cette classe doit implementer toutes les methodes de linterface * RessourceInterface. * Compatibilite: PHP 5 */ class Ressource implements RessourceInterface { var $idConnexion; public function connexion() { global $mysql_serveur, $mysql_utilisateur, $mysql_motDePasse;

718

MySQL

global $mysql_base; if (!isset($this->idConnexion)) { $idConnexion = mysql_pconnect($mysql_serveur, $mysql_utilisateur, $mysql_motDePasse); if (!$idConnexion) return FALSE; mysql_select_db($mysql_base); $this->idConnexion = $idConnexion; } return TRUE; } public function deconnexion() { // Rien a faire, il sagit dune connexion persistante } public function reset() { $requete = "DROP TABLE types"; $idResultat = mysql_query($requete, $this->idConnexion); // Pas de raison de retourner un erreur // si la suppression echoue (si la table nexiste pas) $requete = "CREATE TABLE types (". "id INTEGER AUTO_INCREMENT PRIMARY KEY,". "type VARCHAR(255))"; $idResultat = mysql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; $types = array("Album", "Film", "Livre", "Musique"); foreach ($types as $type) { $requete = "INSERT INTO types (type) VALUES ($type)"; $idResultat = mysql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; } $requete = "DROP TABLE articles"; $idResultat = @mysql_query($requete, $this->idConnexion); // Pas de raison de retourner un erreur // si la suppression echoue (si la table nexiste pas) $requete = "CREATE TABLE articles (". "id INTEGER AUTO_INCREMENT PRIMARY KEY,". "albumId INTEGER,". "titre VARCHAR(255),". "typeId INTEGER,". "commentaire VARCHAR(255))"; $idResultat = mysql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; }

10. Lutilisation des bases de donnes 719

Chapitre 10

Lutilisation des bases de donnes

public function addArticle($albumId, $titre, $typeId, $commentaire) { $requeteDebut = "INSERT INTO articles (albumId, titre, typeId"; $requeteFin = ") VALUES ($albumId,". "".mysql_escape_string($titre).",". "$typeId"; if ($commentaire != "") { $requeteDebut .= ",commentaire"; $requeteFin .= ",".mysql_escape_string($commentaire).""; } $requete = $requeteDebut . $requeteFin . ")"; $idResultat = mysql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; } public function getArticle($articleId) { $requete = "SELECT * FROM articles WHERE id=$articleId"; $idResultat = mysql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; $article = NULL; if ($enreg = mysql_fetch_array($idResultat)) { $article = $this->enreg2Article($enreg); } return $article; } public function getArticles(Filtre $filtre, Plage $plage, Tri $tri) { $requete = "SELECT * FROM articles"; if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". mysql_escape_string($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL. " AND typeId=".$filtre->getTypeId(); } if ($tri->getSens() == -1) { $triSQL = "ORDER BY ".$tri->getChamp()." DESC"; } else if ($tri->getSens() == 1) { $triSQL = "ORDER BY ".$tri->getChamp()." ASC";

10. Lutilisation des bases de donnes 720

MySQL

} $limiteSQL = "LIMIT ".$plage->getNbArticleMax(). " OFFSET ".$plage->getPremierArticle(); $requete = $requete." WHERE ".$conditionSQL." ". $triSQL." ".$limiteSQL; $idResultat = mysql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; $articles = NULL; while ($enreg = mysql_fetch_array($idResultat)) { $articles[] = $this->enreg2Article($enreg); } return $articles; } public function getNbTotalArticles(Filtre $filtre) { $requete = "SELECT COUNT(*) FROM articles"; if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". mysql_escape_string($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL. " AND typeId=".$filtre->getTypeId(); } $requete = $requete." WHERE ".$conditionSQL; $idResultat = mysql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; if ($enreg = mysql_fetch_array($idResultat)) { return $enreg[0]; } else return FALSE; } public function getTypes() { $requete = "SELECT * FROM types"; $idResultat = mysql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; $types = NULL; while ($enreg = mysql_fetch_array($idResultat)) { $types[$enreg["id"]] = $enreg["type"]; }

10. Lutilisation des bases de donnes 721

Chapitre 10

Lutilisation des bases de donnes

return $types; } public function getAlbumTypeId() { return 1; }

10. Lutilisation des bases de donnes

private function enreg2Article($enreg) { $article = new Article(); $article->setId($enreg["id"]); $article->setAlbumId($enreg["albumId"]); $article->setTitre($enreg["titre"]); $article->setTypeId($enreg["typeId"]); $article->setCommentaire($enreg["commentaire"]); return $article; } } ?>

Comme vous le constatez, la principale difficult nest pas tant au niveau des fonctions disponibles quau niveau de la construction des requtes SQL. La requte sera simple lorsquil ne sagit que de rcuprer un enregistrement identifi par la cl Id (comme cest le cas avec getArticle()) elle sera bien plus complexe sil sagit des rcuprer un ensemble denregistrements rpondant des critres prcis et tris (comme cest le cas avec getArticles()).

Requtes avec des apostrophes


Lors de la construction de la requte, il faut bien garder lesprit que lun des lments de la requte (typiquement un champ de type texte saisi par lutilisateur, comme ici le titre ou le commentaire) peut contenir une apostrophe qui pourrait tre confondu avec le dlimiteur de chane. Pensez donc bien faire un appel addSlashes() lorsque cela peut savrer ncessaire.

Affichage page par page


La meilleure faon avec MySQL pour nextraire quun sous-ensemble des enregistrements retourns par une requte SQL consiste utiliser linstruction LIMIT. LIMIT permet de prciser combien denregistrements doivent tre retourns et partir duquel commencer (sachant que le premier enregistrement porte lindex 0). Ainsi, SELECT * FROM nomtable LIMIT 0, 10; retourne les dix premiers enregistrements (de lindex 0 lindex 9) et SELECT * FROM nomtable LIMIT 10, 20; retourne les vingt suivants (de lindex 10 lindex 29).

722

MySQL

Tri
Modifier lordre daffichage des annonces nest pas non plus bien sorcier. Le tri peut seffectuer directement au niveau de la requte SQL, grce linstruction ORDER BY.

Moteur de recherche (ltre)


10. Lutilisation des bases de donnes
Pour filtrer, il suffit dutiliser linstruction WHERE. Dans notre cas, nous souhaitons autoriser lutilisation de jokers (comme %) afin, par exemple, de rechercher les titres commenant par une chane donne. Cest pourquoi, nous ne ferons pas un test de type titre=motcle mais titre LIKE motcle (o motcle pourrait avoir la valeur "La 7eme compagnie%").

En savoir plus...
sur une requte
Si vous souhaitez connatre le nombre de champs retourns par une requte, faites simplement appel mysql_num_fields().

mysql_num_elds()
Retourne le nombre de champs dun enregistrement. Syntaxe $idRequete retour int mysql_num_fields(resource $idRequete) Identifiant de requte tel que retourn par mysql_list_tables(). Nombre de champs retourns par une requte.

sur les champs dune table


Vous pouvez rcuprer la liste des champs contenus dans une base en lanant une requte avec mysql_list_fields(), et en lisant le rsultat avec mysql_field_name().

mysql_list_elds()
Retourne un identifiant sur une requte listant les champs disponibles dans la table. Syntaxe $nomBaseDonnees $nomTable resource mysql_list_fields(string $nomBaseDonnees, string $nomTable, [resource $idConnexion]) Nom de la base de donnes contenant la table dont on souhaite connatre les champs. Nom de la table dont on souhaite connatre les champs.

723

Chapitre 10

Lutilisation des bases de donnes

$idConnexion

Identifiant de connexion un serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Identifiant de la requte, ou FALSE en cas dchec (nom de base ou de table non valide).

retour

10. Lutilisation des bases de donnes

mysql_eld_name()
Retourne le nom des champs dans la table. Syntaxe $idRequete $index string mysql_field_name(resource $idRequete, int $index) Identifiant de requte tel que retourn par mysql_list_tables(). Index du champ dont on souhaite connatre le nom (le premier champ porte lindex 0). Le nombre total de champs peut tre obtenu en faisant appel mysql_num_fields(). Nom du champ, ou FALSE si lindex nest pas valide, ou rien si lidentifiant de rsultat nest pas valide.

retour

Cependant, les champs ont dautres informations nous livrer que leur nom. Pour cela, vous diposez des fonctions :

mysql_eld_type()
Retourne le type des champs de la table. Syntaxe $idRequete $index retour string mysql_field_type(resource $idRequete, int $index) Identifiant de requte tel que retourn par mysql_list_tables(). Index du champ dont on souhaite connatre le type. Le nombre total de champs peut tre obtenu en faisant appel mysql_num_fields(). Type du champ, ou FALSE en cas derreur.

mysql_eld_len()
Retourne la taille (en octets) des champs de la table. Syntaxe $idRequete $index string mysql_field_len(resource $idRequete, int $index) Identifiant de requte tel que retourn par mysql_list_tables(). Index du champ dont on souhaite connatre le type. Le nombre total de champs peut tre obtenu en faisant appel mysql_num_fields().

724

MySQL

retour

Taille en octets occupe par le champ, ou FALSE en cas derreur dindex ou rien en cas didentifiant de requte non valide.

mysql_eld_ags()
Retourne les attributs (NOT NULL, etc.) des champs de la table. Syntaxe $idRequete $index retour string mysql_field_flags(resource $idRequete, int $index) Identifiant de requte tel que retourn par mysql_list_tables(). Index du champ dont on souhaite connatre le type. Le nombre total de champs peut tre obtenu en faisant appel mysql_num_fields(). Chane de caractres contenant les attributs spars par des espaces (les blancs contenus dans les attributs sont remplacs par des underscores (ex : not_null) ; FALSE en cas derreur dindex ou rien en cas didentifiant de requte non valide.

10. Lutilisation des bases de donnes

sur les tables dune base


Le principe est exactement le mme pour rcuprer la liste des tables contenues dans une base.

mysql_list_tables()
Retourne un identifiant sur une requte listant les tables disponibles dans la base de donnes. Syntaxe $nomBaseDonnees $idConnexion resource mysql_list_tables(string $nomBaseDonnees, [resource $idConnexion]) Nom de la base de donnes dont on souhaite connatre les tables. Identifiant de connexion un serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Identifiant de la requte, ou FALSE en cas dchec (nom de base non valide).

retour

mysql_tablename()
Retourne le nom des tables dans la base. Syntaxe $idRequete string mysql_tablename(resource $idRequete, int $index) Identifiant de requte tel que retourn par mysql_list_tables().

725

Chapitre 10

Lutilisation des bases de donnes

$index retour

Index de la table dont on souhaite connatre le nom. Le nombre total de tables peut tre obtenu en faisant appel mysql_num_rows(). Nom de la table, ou FALSE en cas derreur dindex, ou rien en cas didentifiant de requte non valide.

10. Lutilisation des bases de donnes

sur les bases dun serveur

mysql_list_dbs()
Retourne un identifiant sur une requte listant les bases de donnes disponibles sur le serveur. Syntaxe $idConnexion resource mysql_list_dbs([resource $idConnexion]) Identifiant de connexion un serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Identifiant de la requte.

retour

mysql_db_name()
Retourne le nom des bases de donnes sur le serveur. Syntaxe $idRequete $index retour string mysql_db_name(resource $idRequete, int $index) Identifiant de requte tel que retourn par mysql_list_dbs(). Index de la base de donnes dont on souhaite connatre le nom. Le nombre total de bases peut tre obtenu en faisant appel mysql_num_rows(). Nom de la base de donnes, ou FALSE en cas derreur (ex. : index non valide), voire rien pour dautres cas derreur (ex. : identifiant de requte non valide).

Vous pourrez donc lister les champs de la premire table de la premire base de votre serveur avec le script suivant :

Listing 10.43 : mysql_13.php


<?php include_once("parametres_bd_inc.php"); mysql_pconnect($serveur.$port, $utilisateur, $motDePasse) or die("<b>Impossible de se connecter au serveur base de donnes.</b>"); $idListeBD = mysql_list_dbs();

726

MySQL

if ($nomBD = @mysql_db_name($idListeBD, 0)) { //$nomBD = "basemysql"; // Pour forcer un nom de base echo "Votre serveur contient au moins la base <b>$nomBD</b><br />"; $idListeTable = mysql_list_tables($nomBD); if ($nomTable = @mysql_tablename($idListeTable, 0)) { echo "Et elle continent au moins la table <b>$nomTable</b><br />"; echo "Dont les champs sont:<br />"; $idListeChamp = mysql_list_fields($nomBD, $nomTable); echo "Rows=".mysql_num_rows($idListeChamp)."<br />"; echo "Col=".mysql_num_fields($idListeChamp)."<br />"; $nb = 0; while ($nomChamp = @mysql_field_name($idListeChamp, $nb)) { $type = mysql_field_type($idListeChamp, $nb); $taille = mysql_field_len($idListeChamp, $nb); $attribut = mysql_field_flags($idListeChamp, $nb); echo "- <i>$nomChamp</i> de type <i>$type</i>"; echo " occupant <i>$taille</i> octets"; echo " avec les attributs <i>$attribut</i><br />"; $nb++; } } } else { die("Il semblerait que votre serveur ne contienne aucune base"); } ?>

10. Lutilisation des bases de donnes

sur la connexion courante


PHP 4.3 a apport son lot de nouvelles fonctions permettant notamment den savoir un peu plus sur la connexion courante: Est-elle encore active? Quel identifiant lui est associ?

mysql_ping()
Teste la connexion avec le serveur de base de donnes et tente de la rtablir si elle a t perdue (apr exemple sur dlai expir). Syntaxe : $idConnexion boolean mysql_ping([resource $idConnexion]) Identifiant de connexion un serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Sil ny a pas eu de prcdente tentative de connexion, cest la connexion locale qui est teste. TRUE si la connexion est toujours tablie, FALSE sinon.

retour

727

Chapitre 10

Lutilisation des bases de donnes

mysql_thread_id()
Retourne lidentifiant de la connexion (thread) sur le serveur de bases de donnes. Syntaxe : int mysql_thread_id([resource $idConnexion]) Identifiant de connexion un serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Identifiant de connexion sur le serveur de base de donnes. $idConnexion

10. Lutilisation des bases de donnes

retour

sur lensemble des connexions


Egalement apparues depuis la version 4.3 de PHP, les fonctions suivantes:

mysql_stat()
Retourne diverses informations (nombre de connexions ouvertes, nombre de requtes traites, nombre de tables ouvertes, etc.) sur le serveur de bases de donnes. Syntaxe : $idConnexion string mysql_stat([resource $idConnexion]) Identifiant de connexion un serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Chane de caractres contenant lensemble des informations disponibles, sous une forme semblable "Uptime: 22 Threads: 1 Questions: 9 Slow queries: 0 Opens: 7 Flush tables: 1 Open tables: 1 Queries per second avg: 0.409"

retour

mysql_list_processes()
Retourne un identifiant sur une requte listant les connexions sur le serveur de bases de donnes. Syntaxe : $idConnexion resource mysql_list_processes([resource $idConnexion]] Identifiant de connexion un serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Identifiant de la requte.

retour

728

MySQL

sur les numros de version


Les fonctions voques ici ne sont pas dune utilisation trs courante, mais elles pourront ventuellement vous servir si vous tes amen utiliser des instructions avances de la base de donnes MySQL (instructions implmentes dans des versions rcentes, par exemple).

10. Lutilisation des bases de donnes

mysql_get_client_info()
Retourne le numro de version de client MySQL intgr PHP. Syntaxe retour string mysql_get_client_info(void) Numro de version du client MySQL.

mysql_get_server_info()
Retourne le numro de version du serveur MySQL sur lequel nous sommes connects. Syntaxe $idConnexion string mysql_get_server_info([resource $idConnexion]) Identifiant de connexion un serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Numro de version du serveur.

retour

mysql_get_host_info()
Retourne le nom du serveur MySQL sur lequel nous sommes connects et le mode de connexion. Syntaxe $idConnexion string mysql_get_host_info([resource $idConnexion]) Identifiant de connexion un serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Nom et mode de connexion au serveur.

retour

mysql_get_proto_info()
Retourne le numro de version du protocole de connexion utilis.

729

Chapitre 10

Lutilisation des bases de donnes

Syntaxe $idConnexion

string mysql_get_proto_info([resource $idConnexion]) Identifiant de connexion un serveur de bases de donnes tel que retourn par mysql_connect() ou mysql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Numro de version du protocole

retour

10. Lutilisation des bases de donnes

Ainsi, le script suivant :

Listing 10.44 : mysql_14.php


<?php include_once("parametres_bd_inc.php"); mysql_pconnect($serveur.$port, $utilisateur, $motDePasse) or die("<b>Impossible de se connecter au serveur base de donnes.</b>"); echo "Cette version de PHP intgre la version <b>". mysql_get_client_info(); echo "</b> du client MySQL<br /><br />"; echo echo echo echo "Et nous sommes connects au serveur <b>".mysql_get_host_info(); "</b><br />"; "sur lequel tourne la version <b>".mysql_get_server_info()."</b>"; "<br /><br />";

?>

echo "Nous utilisons (sans le savoir) la version "; echo "<b>".mysql_get_proto_info()."</b> du protocole de connexion.";

retournera une page du genre (selon votre configuration) :


Cette version de PHP intgre la version 3.23.40 du client MySQL Et nous sommes connects au serveur Localhost via UNIX socket sur lequel tourne la version 3.2.3.40 Nous utilisons (sans le savoir) la version 10 du protocole de connexion.

10.10. ODBC
Que vous utilisiez vritablement une liaison ODBC, ou que vous utilisiez une base de donnes comme DB2 (dIBM), ce sont ces fonctions que vous utiliserez.

Installation
Si vous devez utiliser une base de donnes via une vritable liaison ODBC, vous devrez au pralable configurer un pont ODBC (si le cas de votre base de donnes nest pas trait dans ce manuel, vous pouvez, titre dexemple, consulter le cas de la base de donnes MS Access).

730

ODBC

Conguration php.ini
Le fichier php.ini permet de dfinir les paramtres suivants
odbc.allow_persistent = On

Autorise ou interdit les connexions persistantes.

10. Lutilisation des bases de donnes

odbc.check_persistent = On

Vrifie si la connexion est encore valide avant chaque rutilisation.


odbc.max_persistent = -1

Nombre maximum de connexions persistantes. -1 autorise un nombre illimit.


odbc.max_links = -1

Nombre maximum de connexions (persistantes ou non). -1 autorise un nombre illimit.


odbc.defaultlrl = 4096

Indique le nombre doctets qui doivent tre retourns dans le cas des champs longs. La valeur 0 permet de passer outre.
odbc.defaultbinmode = 1

Prcise comment passer les donnes binaires : 1 retourne les donnes telles quelles, 2 convertit les donnes en caractres.

Utilisation
Lutilisation basique de la base de donnes sopre selon le schma suivant.
j j j

Connexion grce la fonction odbc_connect() ou odbc_pconnect(); Soumission de la requte via la fonction odbc_exec(); Dconnexion grce la fonction odbc_close() (dans le cas dune connexion non persistante).

Connexion
La connexion la base de donnes sopre grce la fonction odbc_connect().

odbc_connect()
tablit une connexion (non persistante) avec le serveur de bases de donnes. Syntaxe resource odbc_connect(string $baseDonnees , string $utilisateur, string $motDePasse [, int $typeCurseur])

731

Chapitre 10

Lutilisation des bases de donnes

$baseDonnees $utilisateur $motDePasse $typeCurseur

Nom de la base de donnes (ou nom de la liaison ODBC). Nom de lutilisateur. Mot de passe de lutilisateur. Slectionne un des modes suivants : SQL_CUR_USE_IF_NEEDED (non support par DB2). SQL_CUR_USE_ODBC (non support par DB2). SQL_CUR_USE_DRIVER. SQL_CUR_DEFAULT (non support par DB2). Identifiant de connexion au serveur de bases de donnes, ou FALSE en cas dchec.

10. Lutilisation des bases de donnes

retour

Il est galement possible dutiliser une connexion persistante.

odbc_pconnect()
tablit une connexion persistante avec le serveur de bases de donnes. Syntaxe $baseDonnees $utilisateur $motDePasse $typeCurseur resource odbc_pconnect(string $baseDonnees , string $utilisateur, string $motDePasse [, int $typeCurseur]) Nom de la base de donnes (ou nom de la liaison ODBC). Nom de lutilisateur. Mot de passe de lutilisateur. Slectionne un des modes suivants : SQL_CUR_USE_IF_NEEDED (non support par DB2). SQL_CUR_USE_ODBC (non support par DB2). SQL_CUR_USE_DRIVER. SQL_CUR_DEFAULT (non support par DB2). Identifiant de connexion au serveur de bases de donnes, ou FALSE en cas dchec.

retour

Excution de la requte SQL


Lexcution dune requte SQL sopre par un simple appel odbc_exec().

odbc_exec()
Excute une requte SQL. Syntaxe $idConnexion resource odbc_exec(resource $idConnexion, string $requete) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect().

732

ODBC

$requete retour

Requte SQL. Identifiant de rsultat de requte SQL, ou FALSE en cas dchec (identifiant de base de donnes ou requte SQL non valide).

Notez galement lexistence de odbc_do() qui est un alias de odbc_exec(). Nous verrons par la suite quil est galement possible dutiliser des requtes prpares (contenant des paramtres qui pourront tre modifis juste avant que celles-ci ne soient excutes) et de dsactiver le mode auto commit (validation automatique) pour avoir accs aux oprations de commit (validation) et rollback (annulation). Dans le cas dune requte retournant un rsultat (typiquement une requte SELECT), il faudra galement analyser le rsultat, mais nous verrons cela un peu plus loin.

10. Lutilisation des bases de donnes

Dconnexion
Pour vous dconnecter opration thoriquement facultative mais toutefois vivement conseille , vous disposez de la fonction odbc_close().

odbc_close()
Met fin la connexion la base de donnes et libre les ressources associes. Syntaxe $idConnexion void odbc_close(resource $idConnexion) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect().

Il existe galement une fonction mettant fin toutes les connexions ouvertes durant lexcution du script.

odbc_close_all()
Ferme toutes les connexions et libre les ressources associes. Syntaxe void odbc_close_all(void)

Premier exemple
Nous voil donc mme de construire notre premier script utilisant une base de donnes.

733

Chapitre 10

Lutilisation des bases de donnes

Vrifiez les paramtres Prenez garde ! avant dexcuter ce script, assurez-vous que les paramtres prdfinis ne risquent pas de conduire la suppression des donnes dune de vos bases qui, par concidence, existerait dj. 10. Lutilisation des bases de donnes
Comme cela est fortement conseill, nous avons, ici, isol les paramtres de connexion dans un fichier aisment reprable.

Listing 10.45 : parametres_bd_inc.php (exemple avec MS Access)


<?php // Paramtres de connexion la base de donnes // Nhsitez pas les modifier selon vos besoins $typeServeur $base $utilisateur $motDePasse ?> = = = = "MSAccess"; // MSAccess, IBMDB2, ... "mabase"; ""; "";

Notre script principal sera donc :

Listing 10.46 : insert01.php


<?php // Paramtres du script require_once("parametres_bd_inc.php"); $table = "tableexemple"; // Inclusion du script contenant les fonctions require_once("insert01_bd_inc.php"); // Connexion la base de donnes $idConnexion = odbc_pconnect($base, $utilisateur, $motDePasse); if (!$idConnexion) { die("<b>Impossible de se connecter la base de donnes</b>"); } // Appel de la fonction principale if (EX_initialiseBD($idConnexion, $table)) { echo "Voil, une nouvelle table avec quelques donnes, ". "vous pouvez le vrifier avec votre client de base ". " de donnes ou via les scripts suivants."; } else { echo "La cration ou lalimentation de la table choue."; }

734

ODBC

// Pas de dconnexion dans le cas dune connexion persistante // odbc_close($idConnexion); ?>

et ncessitera :

10. Lutilisation des bases de donnes

Listing 10.47 : insert01_bd_inc.php


<?php /** * Fonction charge de crer et dalimenter une table * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_initialiseBD($idConnexion, $table) { // Supprime la prcdente table $requete = "DROP TABLE $table"; @odbc_exec($idConnexion, $requete); // Cre la table $requete = "CREATE TABLE $table (filmId INTEGER, film VARCHAR(64))"; if (!odbc_exec($idConnexion, $requete)) return FALSE; // Ajoute quelques donnes $requete = "INSERT INTO $table VALUES (1, Forrest Gump)"; if (!odbc_exec($idConnexion, $requete)) return FALSE; $requete = "INSERT INTO $table VALUES (2, Matrix)"; if (!odbc_exec($idConnexion, $requete)) return FALSE; $requete = "INSERT INTO $table VALUES (3, La cit de la peur)"; if (!odbc_exec($idConnexion, $requete)) return FALSE; return TRUE; } ?>

Champ auto-incrment Il aurait t prfrable de dfinir filmId comme tant un champ auto-incrment, plutt que de le fixer manuellement. Mais, comme nous le verrons dans un prochain exemple, la syntaxe varie dune base de donnes lautre.

735

Chapitre 10

Lutilisation des bases de donnes

Commit/rollback
Par dfaut, les requtes sont automatiquement valides (mode auto commit). Il est toutefois possible de modifier ce comportement par dfaut en utilisant odbc_autoCommit().

10. Lutilisation des bases de donnes

odbc_autoCommit()
Active, dsactive ou retourne le mode auto commit. Syntaxe $idConnexion $autoCommit mixed odbc_autoCommit(resource $idConnexion [, boolean $autoCommit]) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect(). Indiquer TRUE pour activer le mode auto commit, FALSE pour dsactiver le mode auto commit, ne pas renseigner pour rcuprer le mode actuel. En mode lecture, 1 (mais pas strictement TRUE) si le mode auto commit est activ, 0 (mais pas strictement FALSE) sinon.

retour

En mode slection, TRUE en cas de succs, FALSE sinon. Si vous avez opt pour un mode de validation non automatique, vous pourrez valider ou annuler vos transactions avec les fonctions suivantes :

odbc_commit()
Valide les transactions. Syntaxe $idConnexion retour boolean odbc_commit(resource $idConnexion) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect(). TRUE en cas de succs, ou rien (mais pas FALSE) sinon (cest essentiellement le cas pour un identifiant non valide).

odbc_rollback()
Annule les transactions. Syntaxe $idConnexion boolean odbc_rollback(resource $idConnexion) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect().

736

ODBC

retour

TRUE en cas de succs, ou rien (mais pas FALSE) sinon (cest essentiellement le cas pour un identifiant non valide).

Lecture des enregistrements


Dans le cas dune requte retournant une liste de donnes (typiquement un SELECT), il convient de rcuprer lidentifiant de requte et de lutiliser pour lire, en boucle, ligne aprs ligne, chaque enregistrement. Il existe diverses fonctions, chacune permettant de rcuprer les champs des enregistrements sous diffrentes formes. Les informations peuvent ainsi tre retournes :
j j

10. Lutilisation des bases de donnes

Champ par champ ; Enregistrement par enregistrement (sous la forme dun tableau index).

Lecture champ par champ


Pour une lecture champ par champ, vous pouvez passer dun enregistrement au suivant par lappel odbc_fetch_row(), et accder lun quelconque des champs par appel odbc_result().

odbc_fetch_row()
Passe lenregistrement suivant ou accde nimporte quel enregistrement. Syntaxe $idResultat boolean odbc_fetch_row(resource $idResultat [, int $idxEnregistrement]) Identifiant de rsultat tel que retourn par odbc_exec() ou odbc_execute().

$idxEnregistrement Index de lenregistrement lire (le premier enregistrement ayant lindex 1). Par dfaut, il sagit de lenregistrement suivant. retour TRUE en cas de succs, FALSE sinon (plus denregistrement lire).

odbc_result()
Retourne la valeur dun champ de lenregistrement courant. Syntaxe $idResultat $champ mixed odbc_result(resource $idResultat, mixed $champ) Identifiant de rsultat tel que retourn par odbc_exec() ou odbc_execute(). Au choix, soit le nom du champ (insensible la casse), soit lindex du champ dans la requte (le premier champ ayant lindex 1).

737

Chapitre 10

Lutilisation des bases de donnes

retour

La valeur du champ, ou FALSE en cas derreur, mais galement dans le cas o le champ est NULL ! En cas derreur, un message derreur est lev (voir odbc_error() et odbc_errormsg()), mais pas dans le cas dun champ NULL.

Listing 10.48 : select_cc_bd_inc.php

10. Lutilisation des bases de donnes

<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requete $requete = "SELECT * FROM $table"; $idResultat = odbc_exec($idConnexion, $requete); if (!$idResultat) return FALSE; // Boucle de lecture (et daffichage) des enregistrements while (odbc_fetch_row($idResultat)) { echo "FilmId=".odbc_result($idResultat, "filmid")." ". "Film =" .odbc_result($idResultat, "film")."<br />"; } return TRUE; } ?>

Diffrence entre odbc_fetch_row() et mysql_fetch_row() Notez que les fonctions odbc_fetch_row() et mysql_fetch_row() ne jouent pas exactement le mme rle. mysql_fetch_row() regroupe les rles de odbc_fetch_row() et odbc_result().

Lecture enregistrement par enregistrement


La fonction odbc_fetch_into() peut, dans certains cas, tre plus pratique, puisquelle retourne lensemble des champs de lenregistrement courant sous la forme dun tableau. Linconvnient de cette fonction, cest que lon ne peut accder aux champs que par des index (et pas par des noms).

738

ODBC

odbc_fetch_into()
Retourne lenregistrement courant sous la forme dun tableau index. Syntaxe $idResultat $enregistrement int odbc_fetch_into(resource $idResultat, array &$enregistrement [, int $idxEnregistrement]) Identifiant de rsultat tel que retourn par odbc_exec() ou odbc_execute(). Rfrence sur un tableau dans lequel seront copies les donnes de lenregistrement. Ce tableau est un tableau index dans lequel les valeurs apparaissent dans lordre des champs de la requte (le premier champ ayant lindex 0).

10. Lutilisation des bases de donnes

$idxEnregistrement Index de lenregistrement lire (le premier enregistrement ayant lindex 1). Par dfaut, il sagit de lenregistrement suivant. retour Le nombre de champs en cas de succs, FALSE sinon (plus denregistrement lire).

Listing 10.49 : select_eei_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requete $requete = "SELECT * FROM $table"; $idResultat = odbc_exec($idConnexion, $requete); if (!$idResultat) return FALSE; // Boucle de lecture (et daffichage) des enregistrements while (odbc_fetch_into($idResultat, $enreg)) { echo "FilmId=".$enreg[0]." ". "Film =" .$enreg[1]."<br />"; } return TRUE; } ?>

739

Chapitre 10

Lutilisation des bases de donnes

Libration des ressources


Si, au cours dun script, vous faites appel de nombreuses requtes retournant de nombreux enregistrements, alors, nhsitez pas, une fois le rsultat de la requte exploit, librer les ressources associes avec la fonction odbc_free_result().

10. Lutilisation des bases de donnes

odbc_free_result()
Libre les ressources alloues pour un rsultat de requte. Syntaxe $idResultat retour boolean odbc_free_result(resource $idResultat) Identifiant de requte tel que retourn par mysql_query(). TRUE en cas de succs, FALSE sinon.

Nombre denregistrements
Nombre denregistrements retourns
Il existe trois faons de dterminer le nombre denregistrements retourns par une requte. Si vous souhaitez uniquement connatre le nombre denregistrements, mais ne souhaitez pas immdiatement lire ces enregistrements, alors il vous suffit de faire une requte COUNT(), comme suit :

Listing 10.50 : count_bd_inc.php


<?php /** * Fonction affichant le nombre denregistrements * dans une table * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la tabme **/ function EX_compte($idConnexion, $table) { // Requte $requete = "SELECT COUNT(*) FROM $table"; $idResultat = odbc_exec($idConnexion, $requete); // Lecture du rsultat if (odbc_fetch_into($idResultat, $enreg)) { echo "Il y a ".$enreg[0]." enregistrements dans la table.<br />"; return TRUE; } else { echo "Etes vous sr que la table $table existe ?<br />";

740

ODBC

return FALSE; } } ?>

Si vous souhaitez connatre le nombre denregistrements, mais que vous souhaitez lire les enregistrements sans pour autant avoir besoin au pralable den connatre le nombre, il suffit de les compter au fur et mesure de leur lecture.

10. Lutilisation des bases de donnes

Listing 10.51 : count_select_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requete $requete = "SELECT * FROM $table"; $idResultat = odbc_exec($idConnexion, $requete); if (!$idResultat) return FALSE; // Boucle de lecture (et de comptage) des enregistrements $nb = 0; while (odbc_fetch_into($idResultat, $enreg)) { // Vous pouvez manipuler $enreg votre guise //echo "FilmId=".$enreg[0]." ". // "Film =" .$enreg[1]."<br />"; $nb++; } echo "Il y a $nb enregistrements dans la table.<br />"; return TRUE; } ?>

Et, pour finir, ce que vous attendez tous : si vous souhaitez connatre le nombre denregistrements avant de les lire, vous pouvez faire appel la fonction odbc_num_rows().

741

Chapitre 10

Lutilisation des bases de donnes

odbc_num_rows()
Retourne le nombre denregistrements retourns ou modifis par la requte SQL. Syntaxe int odbc_num_rows(resource $idResultat) Identifiant de rsultat tel que retourn par odbc_exec() (ne fonctionne pas avec odbc_execute()). Nombre denregistrements, ou rien (mais pas FALSE) en cas derreur. $idResultat retour

10. Lutilisation des bases de donnes

Listing 10.52 : count_num_rows_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requete $requete = "SELECT * FROM $table"; $idResultat = odbc_exec($idConnexion, $requete); if (!$idResultat) return FALSE; echo "Il y a ".odbc_num_rows($idResultat)." enregistrements ". "dans la table<br />"; return TRUE; } ?>

Sachant quune requte SELECT * est plus longue quune requte SELECT COUNT(*), privilgiez la premire mthode si vous navez que faire du contenu des enregistrements.

Nombre denregistrements modis


Pour dterminer le nombre denregistrements modifis, vous pouvez appeler la fonction odbc_num_rows() prsente prcdemment.

Mise prot des requtes prpares


Certains serveurs de bases de donnes permettent lanalyse, la compilation et le stockage des requtes avant utilisation. Ceci permet dexcuter une srie de requtes similaires, sans avoir

742

ODBC

renouveler chaque fois les oprations danalyse et de compilation (mais seulement en changeant certaines valeurs). Pour cela, il suffit de prparer une requte dans laquelle les lments variables sont remplacs par des points dinterrogation (ex. : INSERT INTO matable (film) VALUES (?)). Il suffira ensuite de prciser ces valeurs au moment de son excution. La prparation de la requte se fait via la fonction odbc_prepare().

10. Lutilisation des bases de donnes

odbc_prepare()
Prpare une requte SQL. Syntaxe $idConnexion $requete retour resource odbc_prepare(resource $idConnexion, string $requete) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect(). Requte SQL. Identifiant de requte en cas de succs (peut galement tre le cas pour des requtes SQL non valides), ou rien (et non FALSE) en cas dchec (identifiant de connexion non valide).

odbc_execute()
Excute une requte prpare. Syntaxe $idRequete $tableauValeurs retour boolean odbc_execute(resource $idRequete [, array $tableauValeurs]) Identifiant de requte prpare tel que retourn par odbc_prepare(). Tableau index contenant les diffrentes valeurs des lments variables de la requte prpare (le premier paramtre ayant lindex 0). TRUE en cas de succs, FALSE sinon.

DB2 dIBM Nous avons rencontr des problmes avec lutilisation des requtes prpares sous DB2. En effet, nous navons pu utiliser quune seule requte prpare par script (ce qui nous condamnait utiliser odbc_exec() pour les requtes suivantes).

743

Chapitre 10

Lutilisation des bases de donnes

Gestion des erreurs


Jusque-l, en cas derreur, nous nous sommes contents dafficher un message gnrique. Il est cependant possible de dterminer plus prcisment lorigine de lerreur. Cest possible notamment en rcuprant un code derreur via la fonction odbc_error().

10. Lutilisation des bases de donnes

odbc_error()
Retourne le dernier code derreur rencontr ou associ la connexion. Syntaxe $idConnexion retour string odbc_error([resource $idConnexion]) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect(). Si lidentifiant de connexion est prcis : dernier code derreur (sur 5 chiffres) rencontr, ou chane vide en cas de succs de la dernire opration. (Il a t constat que la chane nest pas toujours exactement vide, mais peut contenir un caractre de contrle). Si lidentifiant de connexion nest pas prcis : dernier code derreur (sur 5 chiffres), mme si la dernire opration sest effectue avec succs.

odbc_errormsg()
Retourne le dernier message derreur rencontr ou associ la connexion. Syntaxe $idConnexion retour string odbc_errormsg([resource $idConnexion]) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect(). Si lidentifiant de connexion est prcis : dernier message derreur rencontr, ou chane vide en cas de succs de la dernire opration. (Il a t constat que la chane nest pas toujours exactement vide, mais peut contenir un caractre de contrle). Si lidentifiant de connexion nest pas prcis : dernier message derreur, mme si la dernire opration sest effectue avec succs.

744

ODBC

Exemples dapplications
Compteur de clics
Une application courante dutilisation des bases de donnes et simple mettre en uvre consiste crer un compteur de clics.

10. Lutilisation des bases de donnes

En effet, peut-tre souhaitez-vous, sur votre site, proposer un certain nombre de liens vers des sites Internet (annuaire web) ou vers des fichiers (bibliothques de scripts). Peut-tre que certains (ou la totalit) de ces liens sont proposs par un partenaire. Bref, tout cela vous incite savoir quelles sont les pages les plus frquemment consultes (pour connatre les centres dintrt des visiteurs) et combien de visiteurs vous avez redirigs vers votre sponsor. La mthode la plus classique consiste stocker, en base de donnes, lensemble des liens ainsi proposs, et remplacer les traditionnels liens de la forme http://www.domaine.com par un lien vers un script charg dincrmenter le compteur correspondant au site indiqu, et de rediriger le client vers le site grce la fonction header().

Vous pouvez vous reporter lannexe "Les en-ttes" pour plus de renseignements sur la redirection.
Pour notre exemple, nous utiliserons une table appele url contenant trois champs :
j j j

urlid, identifiant de lURL (champ auto-incrment) ; url, lURL proprement dite ; nbclic, le nombre de clics.

Le script de redirection (appel ici compteurclic_redirection.php) devra alors accepter un paramtre (urlid) et devra, partir de ce paramtre, dterminer quelle est la valeur du champ url, incrmenter nbclic pour cette URL, et rediriger vers url. Les appels ce script auront alors la forme http://localhost/compteurclic-redirection.php?urlid=3 (pour accder lURL ayant lidentifiant 3). supposer que lURL 3 corresponde au site http://www.sqlfacile.com cela signifie que le lien <a href="http://www.sqlfacile.com"> devra tre remplac par <a href="compteurclic_redirection.php?urlid=3> si lon souhaite en compter le nombre de clics. Concrtement, cette table pourra tre cre et alimente avec la fonction CC_initialiseBD() du script suivant :

Listing 10.53 : compteurclic_bd_inc.php (dbut)


<?php //-----------------------------------// Charge les paramtres de connexion // la base de donnes. //-----------------------------------require_once("parametres_bd_inc.php");

745

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

/** * Fonction de connexion une base de donnes * sappuie sur les paramtres fournis * dans parametres_bd_inc.php. * * @return resource Identifiant de connexion */ function CC_connexion() { global $base, $utilisateur, $motDePasse; return @odbc_pconnect($base, $utilisateur, $motDePasse); } /** * Fonction de deconnexion. * (Ne fait rien sachant que la fonction * de connexion tablit une connexion persistante) */ function CC_deconnexion() { return TRUE; } /** * Fonction charg de crer et dalimenter * la table "compteur de clics" **/ function CC_initialiseBD($idConnexion, $table) { global $typeServeur; switch ($typeServeur) { case "MSAccess" : $compteur = "COUNTER"; $default = ""; break; case "IBMDB2" : $compteur = "INTEGER GENERATED BY DEFAULT AS IDENTITY"; $default = "DEFAULT 0"; break; default : $compteur = "INTEGER AUTO_INCREMENT"; $default = "DEFAULT 0"; } // Cration de la table $requete = "DROP TABLE $table"; @odbc_exec($idConnexion, $requete); $requete = "CREATE TABLE $table (urlId $compteur,". "url VARCHAR(128) NOT NULL,".

746

ODBC

"nbclic INTEGER $default,". "UNIQUE(url))"; if (!odbc_exec($idConnexion, $requete)) return FALSE; // Alimentation de la table $requete = "INSERT INTO $table (url)". " VALUES (http://www.php.net)"; if (!odbc_exec($idConnexion, $requete)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.phpfacile.com)"; if (!odbc_exec($idConnexion, $requete)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.sqlfacile.com)"; if (!odbc_exec($idConnexion, $requete)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.xmlfacile.com)"; if (!odbc_exec($idConnexion, $requete)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.ootoogo.com)"; if (!odbc_exec($idConnexion, $requete)) return FALSE; if ($typeServeur == "MSAccess") { // Un "patch" pour MSAccess qui ne supporte pas DEFAULT $requete = "UPDATE $table SET nbclic=0"; if (!odbc_exec($idConnexion, $requete)) return FALSE; } return TRUE; } ?>

10. Lutilisation des bases de donnes

Spcificit des bases de donnes Mme si les fonctions ODBC permettent daccder de nombreuses bases de donnes, il nen reste pas moins que le langage SQL support diffre de lune lautre. Cest ce que nous pouvons constater ici en ce qui concerne la cration dun champ auto-incrment ou les valeurs par dfaut. DEFAULT ntant pas support par MS Access 97, il convient de fixer manuellement les valeurs par dfaut.
La lecture de la liste des liens disponibles en base de donnes pourra se faire via la fonction CC_recupereLiens() du script suivant :

Listing 10.54 : compteurclic_bd_inc.php (milieu)


<?php /** * Fonction retournant les informations de liens

747

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

* sous forme dun tableau associatif possedants * les cls * - "lien" associ au tableau des liens hypertextes * - "nbclic" associ au tableau des nombres de clics **/ function CC_recupereLiens($idConnexion, $table) { // Nom du script charg du comptage et de la redirection $script = "compteurclic_redirection.php"; // Requte SELECT $requete = "SELECT * FROM $table"; $idResultat = odbc_exec($idConnexion, $requete); // Rcupration des enregistrements les uns aprs les autres while (odbc_fetch_row($idResultat)) { $liens["lien"][] = "<a href=\"$script?urlid=". odbc_result($idResultat, "urlid")."\">". odbc_result($idResultat, "url")."</a>"; $liens["nbclic"][] = odbc_result($idResultat, "nbclic"); } return $liens; } ?>

Laffichage des liens consiste uniquement mettre en page le contenu du tableau ainsi rcupr (voir la fonction du script compteurclic_html_inc.php). Comme cela a t prcis, le lien <a href="http://www.sqlfacile.com">http://www .sqlfacile.com</a> a t remplac par <a href="compteurclic_redirection .php?urlid=3">http://www.sqlfacile.com </a>. La redirection vers le site www.sqlfacile .com est donc la charge du script compteurclic_redirection.php.

Listing 10.55 : compteurclic_redirection.php


<?php // Paramtres du script require_once("compteurclic_bd_inc.php"); $table = "compteurclic"; // Connexion la base de donnes $idConnexion = @CC_connexion(); if (!$idConnexion) { die("<b>Impossible de se connecter la base de donnes</b>"); } // Rcupration de lurl et incrmentation du compteur // pour lurl dindentifiant pass en paramtre de ce script // par la mthode GET $url = @CC_recupereUrl($idConnexion, $_GET["urlid"]);

748

ODBC

// Deconnexion @CC_deconnexion(); // Cest lheure de la redirection if ($url) { header("Location: $url"); } else { echo "Dsol, nous ne pouvons vous proposer ce lien"; } ?>

10. Lutilisation des bases de donnes

Ce script appelle principalement la fonction CC_recupereUrl() suivante :

Listing 10.56 : compteurclic_bd_inc.php (fin)


<?php /** * Fonction rcuprant une url partir de son identifiant * et incrmentant le compteur de clics **/ function CC_recupereUrl($idConnexion, $urlid) { global $table; // Rcupre lurl $requete = "SELECT * FROM $table WHERE urlid=$urlid"; $idResultat = odbc_exec($idConnexion, $requete); if (odbc_fetch_row($idResultat)) { $url = odbc_result($idResultat, "url"); // Incrmente le compteur $requete = "UPDATE $table SET nbclic=nbclic+1". " WHERE urlid=$urlid"; odbc_exec($idConnexion, $requete); } else { $url = FALSE; } return $url; } ?>

Utilisation du bouton retour Si, aprs avoir suivi un lien, vous revenez sur la page compteurclic.php en utilisant le bouton retour (back), le contenu de la page ne sera pas ractualis. Par consquent, le nombre de visites affich ne sera pas correct. Noubliez donc pas, dans ce cas, de rafrachir (bouton actualiser) la page.

749

Chapitre 10

Lutilisation des bases de donnes

SuperTheque
Lessentiel du code de lapplication a t prsent en introduction de ce chapitre. Il ne restait plus qua connatre les fonctions SQLite pour implmenter linterface RessourceInterface cest dsormais chose faite:

10. Lutilisation des bases de donnes

Listing 10.57 : RessourceODBC_class.php


<?php include_once("RessourceInterface_class.php"); include_once(dirname(__FILE__)."/../config/odbc_cfg.php"); /** * RessourceODBC_class.php * Classe dacces a une base de donnees MS ACCESS ou IBM DB2 via ODBC * Cette classe doit implementer toutes les methodes de linterface * RessourceInterface. * Compatibilite: PHP 5 */ class Ressource implements RessourceInterface { var $idConnexion; public function connexion() { global $odbc_serveur, $odbc_utilisateur, $odbc_motDePasse; global $odbc_base; if (!isset($this->idConnexion)) { $idConnexion = odbc_pconnect($odbc_base, $odbc_utilisateur, $odbc_motDePasse); if (!$idConnexion) return FALSE; $this->idConnexion = $idConnexion; } return TRUE; } public function deconnexion() { // Rien a faire, il sagit dune connexion persistante } public function reset() { global $odbc_typeServeur; $requete = "DROP TABLE types"; $idResultat = @odbc_exec($this->idConnexion, $requete); switch ($odbc_typeServeur) { case "MSAccess" : $compteur = "COUNTER";

750

ODBC

break; case "IBMDB2" : $compteur = "INTEGER GENERATED BY DEFAULT AS IDENTITY"; break; default: $compteur = "INTEGER AUTO_INCREMENT"; }

10. Lutilisation des bases de donnes

$requete = "CREATE TABLE types (". "id $compteur,". "type VARCHAR(255))"; $idResultat = odbc_exec($this->idConnexion, $requete); if (!$idResultat) return FALSE; $types = array("Album", "Film", "Livre", "Musique"); foreach ($types as $type) { $requete = "INSERT INTO types (type) VALUES ($type)"; $idResultat = odbc_exec($this->idConnexion, $requete); if (!$idResultat) return FALSE; } $requete = "DROP TABLE articles"; $idResultat = @odbc_exec($this->idConnexion, $requete); $requete = "CREATE TABLE articles (". "id $compteur,". "albumId INTEGER,". "titre VARCHAR(255),". "typeId INTEGER,". "commentaire VARCHAR(255) NULL)"; $idResultat = odbc_exec($this->idConnexion, $requete); if (!$idResultat) return FALSE; } public function addArticle($albumId, $titre, $typeId, $commentaire) { $requeteDebut = "INSERT INTO articles (albumId, titre, typeId"; $requeteFin = ") VALUES ($albumId,". "".addSlashes($titre).",". "$typeId"; if ($commentaire != "") { $requeteDebut .= ",commentaire"; $requeteFin .= ",".addSlashes($commentaire).""; } $requete = $requeteDebut . $requeteFin . ")"; $idResultat = odbc_exec($this->idConnexion, $requete); if (!$idResultat) return FALSE; }

751

Chapitre 10

Lutilisation des bases de donnes

public function getArticle($articleId) { $requete = "SELECT * FROM articles WHERE id=$articleId"; $idResultat = odbc_exec($this->idConnexion, $requete); if (!$idResultat) return FALSE; $article = NULL; if ($enreg = odbc_fetch_array($idResultat)) { $article = $this->enreg2Article($enreg); } return $article; } public function getArticles(Filtre $filtre, Plage $plage, Tri $tri) { $requete = "SELECT * FROM articles"; if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". addSlashes($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL. " AND typeId=".$filtre->getTypeId(); } if ($tri->getSens() == -1) { $triSQL = "ORDER BY ".$tri->getChamp()." DESC"; } else if ($tri->getSens() == 1) { $triSQL = "ORDER BY ".$tri->getChamp()." ASC"; } $requete = $requete." WHERE ".$conditionSQL." ". $triSQL; $idResultat = odbc_exec($this->idConnexion, $requete); if (!$idResultat) return FALSE; $articles = NULL; // Nous devons sauter les premiers resultats if ($plage->getPremierArticle()>0) { odbc_fetch_row($idResultat, $plage->getPremierArticle()); } while (($enreg = odbc_fetch_array($idResultat)) &&(count($articles)<$plage->getNbArticleMax())) { $articles[] = $this->enreg2Article($enreg); } return $articles;

10. Lutilisation des bases de donnes 752

ODBC

} public function getNbTotalArticles(Filtre $filtre) { $requete = "SELECT COUNT(*) FROM articles"; if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". addSlashes($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL. " AND typeId=".$filtre->getTypeId(); } $requete = $requete." WHERE ".$conditionSQL; $idResultat = odbc_exec($this->idConnexion, $requete); if (!$idResultat) return FALSE; if (odbc_fetch_into($idResultat, &$enreg)) { return $enreg[0]; } else return FALSE; }

10. Lutilisation des bases de donnes

public function getTypes() { $requete = "SELECT * FROM types"; $idResultat = odbc_exec($this->idConnexion, $requete); if (!$idResultat) return FALSE; $types = NULL; while ($enreg = odbc_fetch_array($idResultat)) { $types[$enreg["id"]] = $enreg["type"]; } return $types; } public function getAlbumTypeId() { return 1; }

private function enreg2Article($enreg) { $article = new Article(); $article->setId($enreg["id"]); $article->setAlbumId($enreg["albumId"]); $article->setTitre($enreg["titre"]);

753

Chapitre 10

Lutilisation des bases de donnes

$article->setTypeId($enreg["typeId"]); $article->setCommentaire($enreg["commentaire"]); return $article; } } ?>

10. Lutilisation des bases de donnes

Comme vous le constatez, la principale difficult nest pas tant au niveau des fonctions disponibles quau niveau de la construction des requtes SQL. La requte sera simple lorsquil ne sagit que de rcuprer un enregistrement identifi par la cl Id (comme cest le cas avec getArticle()) elle sera bien plus complexe sil sagit des rcuprer un ensemble denregistrements rpondant des critres prcis et tris (comme cest le cas avec getArticles()).

Requtes avec des apostrophes


Lors de la construction de la requte, il faut bien garder lesprit que lun des lments de la requte (typiquement un champ de type texte saisi par lutilisateur, comme ici le titre ou le commentaire) peut contenir une apostrophe qui pourrait tre confondu avec le dlimiteur de chane. Pensez donc bien faire un appel addSlashes() lorsque cela peut savrer ncessaire.

Affichage page par page


Certaines bases de donnes permettent de ne retourner quun sous-ensemble des rsultats dune requtes SQL ; dautres permettent seulement de retourner les N premiers rsultats. En ce qui concerne MS Access et DB2, il semblerait quils ne permettent pas ce genre doptimisation. Nous sommes donc dans lobligation de demander tous les rsultats, et dignorer ceux qui ne nous intressent pas.

Tri
Modifier lordre daffichage des annonces nest pas non plus bien sorcier. Le tri peut seffectuer directement au niveau de la requte SQL, grce linstruction ORDER BY.

Moteur de recherche (ltre)


Pour filtrer, il suffit dutiliser linstruction WHERE. Dans notre cas, nous souhaitons autoriser lutilisation de jokers (comme %) afin, par exemple, de rechercher les titres commenant par une chane donne. Cest pourquoi, nous ne ferons pas un test de type titre=motcle mais titre LIKE motcle (o motcle pourrait avoir la valeur "La 7eme compagnie%").

En savoir plus...
Il y a bien plus apprendre dune base de donnes...

754

ODBC

sur le rsultat dune requte


Il vous est ainsi possible de connatre le nombre de champs retourns par une requte (et par consquent le nombre de champs dune table dans le cas dune requte SELECT * FROM <nom_table> sur une table non vide).

10. Lutilisation des bases de donnes

odbc_num_els()
Retourne le nombre de champs dans lenregistrement retourn par une requte SQL. Syntaxe $idResultat retour int odbc_num_fields(resource $idResultat) Identifiant de rsultat tel que retourn par odbc_exec() ou odbc_execute(). Nombre de champs, ou FALSE en cas derreur.

Mais aussi, le nom de ces champs :

odbc_eld_name()
Retourne le nom dun champ dsign par son indice dans le rsultat de requte. Syntaxe $idResultat $idxChamp retour string odbc_field_name(resource $idResultat, int $idxChamp) Identifiant de rsultat tel que retourn par odbc_exec() ou odbc_execute(). Index du champ (le premier champ porte lindex 1). Nom du champ, ou FALSE en cas derreur.

Ou, linverse, leur index :

odbc_eld_num()
Retourne lindex du champ dsign par son nom dans le rsultat de requte. Syntaxe $idResultat $champ retour int odbc_field_num(resource $idResultat, string $champ) Identifiant de rsultat tel que retourn par odbc_exec() ou odbc_execute(). Nom du champ. Index du champ (le premier champ porte lindex 1), ou FALSE en cas derreur.

755

Chapitre 10

Lutilisation des bases de donnes

Cependant, les champs ont dautres informations nous livrer que leur nom et leur index. Pour cela, vous disposez des fonctions :

10. Lutilisation des bases de donnes

odbc_eld_type()
Retourne le type du champ dsign par son index dans le rsultat de requte. Syntaxe $idResultat $idxChamp retour int odbc_field_type(resource $idResultat, int $idxChamp) Identifiant de rsultat tel que retourn par odbc_exec() ou odbc_execute(). Index du champ (le premier champ porte lindex 1). Type du champ, ou FALSE en cas derreur.

odbc_eld_len()
Retourne la longueur du champ dsign par son index dans le rsultat de requte. Syntaxe $idResultat $idxChamp retour int odbc_field_len(resource $idResultat, int $idxChamp) Identifiant de rsultat tel que retourn par odbc_exec() ou odbc_execute(). Index du champ (le premier champ porte lindex 1). Longueur du champ, ou FALSE en cas derreur.

Cette fonction possde un alias baptis odbc_field_precision()

odbc_eld_scale()
Retourne lchelle (?) du champ dsign par son index dans le rsultat de requte (0 souvent, 6 pour un TIMESTAMP DB2). Syntaxe $idResultat $idxChamp retour int odbc_field_scale(resource $idResultat, int $idxChamp) Identifiant de rsultat tel que retourn par odbc_exec() ou odbc_execute(). Index du champ (le premier champ porte lindex 1). Echelle (?) du champ, ou FALSE en cas derreur.

756

ODBC

... sur les champs dune table


Il nest cependant pas ncessaire de passer par une requte pour rcuprer des informations sur une table. Vous disposez ainsi de :

10. Lutilisation des bases de donnes

odbc_columns()
Retourne un pointeur sur la liste des champs des tables dune base. Syntaxe $idConnexion retour resource odbc_columns(resource $idConnexion) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect(). Identifiant de requte ( analyser, par exemple, avec les fonctions odbc_fetch*()). Les champs sont alors : TABLE_CAT. TABLE_SCHEM. TABLE_NAME, le nom de la table. COLUMN_NAME, le nom du champ. DATA_TYPE, le code du type du champ (voir tableau). TYPE_NAME, le type du champ en toutes lettres. COLUMN_SIZE, taille du champ (en octets). BUFFER_LENGTH. DECIMAL_DIGITS. NUM_PREC_RADIX. NULLABLE, 1 si le champ peut prendre la valeur NULL. REMARKS, commentaire associ au champ. COLUMN_DEF. SQL_DATA_TYPE, le code SQL du type du champ. SQL_DATETIME_SUB. CHAR_OCTET_LENGTH. ORDINAL_POSITION. IS_NULLABLE, YES si le champ peut prendre la valeur NULL, NO sinon. ORDINAL.

Tableau 10.15 : Les types ODBC rencontrs


Identifiant de Type -400 -99 -98 -11 -7 -6 -5 GUID BIT BYTE BIGINT Access 97 (MS) DB2 (IBM) DATALINK CLOB BLOB

757

Chapitre 10

Lutilisation des bases de donnes

Identifiant de Type -4 -3 -2 -1 1 2 3 4 5 6 7 8 9 10 11 12

Access 97 (MS) LONGBINARY VARBINARY BINARY LONGCHAR CHAR CURRENCY

DB2 (IBM) LONG VARCHAR FOR BIT DATA VARCHAR () FOR BIT DATA CHARacter() FOR BIT DATA LONG VARCHAR CHARacter NUMeric DECimal

10. Lutilisation des bases de donnes

INTEGER COUNTER SMALLINT

INTeger SMALLINT FLOAT

REAL DOUBLE

REAL FLOAT DATE TIME

DATETIME VARCHAR

TIMESTAMP VARCHAR

... sur les tables dune base


De mme, vous pouvez aisment rcuprer la liste des tables.

odbc_tables()
Retourne un pointeur sur la liste des tables dune base. Syntaxe $idConnexion retour resource odbc_tables(resource $idConnexion) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect(). Identifiant de requte ( analyser, par exemple, avec les fonctions odbc_fetch*()). Les champs sont alors : TABLE_CAT. TABLE_SCHEM. TABLE_NAME, le nom de la table. TABLE_TYPE, type de la table TABLE, SYSTEM TABLE, VIEW, etc. REMARKS, commentaire associ la table.

758

ODBC

... sur les procdures stockes dune base


De mme, vous pouvez aisment rcuprer la liste des procdures stockes.

odbc_procedures()
Retourne un pointeur sur la liste des procdures stockes dune base. Syntaxe $idConnexion retour resource odbc_procedures(resource $idConnexion) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect(). Identifiant de requte ( analyser, par exemple, avec les fonctions odbc_fetch*()). Les champs sont alors : PROCEDURE_CAT. PROCEDURE_SCHEM. PROCEDURE_NAME, le nom de la procdure stocke. NUM_INPUT_PARAMS, le nombre de paramtres dentre. NUM_OUTPUT_PARAMS, le nombre de paramtres de sortie. REMARKS, commentaire associ la procdure stocke. PROCEDURE_TYPE, le type de la procdure stocke.

10. Lutilisation des bases de donnes

Tout comme les informations plus prcises :

odbc_procedurecolumns()
Retourne un pointeur sur la liste des paramtres des procdures stockes dune base. Syntaxe $idConnexion retour resource odbc_procedurecolumns(resource $idConnexion) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect(). Identifiant de requte ( analyser, par exemple, avec les fonctions odbc_fetch*()). Les champs sont alors : PROCEDURE_CAT. PROCEDURE_SCHEM. PROCEDURE_NAME, le nom de la procdure stocke. COLUMN_NAME, le nom du paramtre. COLUMN_TYPE. DATA_TYPE, lidentifiant du type du paramtre (voir tableau). TYPE_NAME, le type du paramtre en toutes lettres. COLUMN_SIZE, taille du paramtre (en octets). BUFFER_LENGTH. DECIMAL_DIGITS. NUM_PREC_RADIX. NULLABLE, 1 si le champ peut prendre la valeur NULL.

759

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

REMARKS, commentaire associ au paramtre. COLUMN_DEF. SQL_DATA_TYPE, lidentifiant SQL du type du paramtre. SQL_DATATYPE_SUB. CHAR_OCTET_LENGTH. ORDINAL_POSITION, position du paramtre dans lappel de la procdure. IS_NULLABLE, YES si le paramtre peut prendre la valeur NULL.

... sur le serveur


Il vous est possible daccder la liste des types supports par le serveur de bases de donnes en appelant la fonction odbc_getTypeInfo().

odbc_getTypeInfo()
Lance une requte interrogeant la base de donnes sur la liste des types SQL supports. Syntaxe $idConnexion $idType retour resource odbc_getTypeInfo(resource $idConnexion [, int $idType]) Identifiant de connexion une base de donnes tel que retourn par odbc_connect()ou odbc_pconnect(). Identifiant de type sur lequel limiter la recherche (par dfaut, ou si $idType vaut 0, la liste complte est retourne). Identifiant de rsultat de requte contenant les champs : TYPE_NAME, type en toutes lettres. DATA_TYPE, identifiant (numrique) du type. COLUMN_SIZE. LITERAL_PREFIX. LITERAL_SUFFIX. CREATE_PARAMS. NULLABLE. CASE_SENSITIVE. SEARCHABLE. UNSIGNED_ATTRIBUTE. FIXED_PREC_SCALE. AUTO_UNIQUE_VALUE. SQL_DATA_TYPE. SQL_DATETIME_SUB. NUM_PREC_RADIX. INTERVAL_PRECISION.

760

Oracle

10.11. Oracle
Oracle est certainement la base de donnes la plus utilise dans le monde professionnel ; il tait donc important de dcrire, ici, comment accder une telle base via PHP.

Installation
Le but de ce chapitre nest pas de faire de vous un administrateur de base de donnes Oracle. Non. Nous nous contenterons de dcrire une installation standard, sans prendre en compte les problmes doptimisation et de scurit. Le but tant que vous puissiez installer PHP et Oracle sur des machines de test pour vous familiariser avec cet environnement avant de passer un serveur de bases de donnes destin la production (et peut-tre configur par un expert Oracle). De plus nous installerons le serveur Oracle sur la mme machine que le serveur Web. Pour nos tests, nous avons install Oracle 10g sous un environnement Debian Sarge. Dans tous les cas, vous tes vivement invits consulter la documentation officielle Oracle pour mener bien linstallation de la base de donnes sur votre systme.

10. Lutilisation des bases de donnes

Pr-requis
Pour commencer, vous devez vous procurer le CD-ROM dinstallation dOracle ou en tlcharger une version ladresse http://otn.oracle.com/software/content.html. Pour Linux, la version 10.1.0.2 tlcharge se prsente sous la forme dun fichier ship.db.cpio.gz. Attention, linstallation dOracle est trs exigeante. Il vous faudra 512 Mo de RAM (en fait nous lavons mene bien avec peu moins) ainsi qu1 Go de swap.

En manque de swap ? Si vous ne disposez pas suffisamment de swap vous pouvez aisment en crer ( condition de disposer de suffisamment despace disque). Pour cela enchaner les commandes suivantes (vous pouvez la rpter pour crer plusieurs fichiers).
dd if=/dev/zero of=fichierswap bs=1k count=<taille en doctets du fichier de swap> chmod 600 fichierswap mkswap fichierswap swapon fichierswap

Prparation linstallation du serveur de base de donnes


Vous tes invit crer, depuis le compte root, sur le serveur Oracle, un nouveau compte utilisateur oracle associ au groupe principal oinstall (groupe des fichiers installs par oracle) et au groupe dba (groupe des administrateurs oracle).
# groupadd oinstall

761

Chapitre 10

Lutilisation des bases de donnes

# groupadd dba # useradd -g oinstall G dba -s /bin/bash -d /home/oracle oracle

Pour vous viter des soucis, vous pouvez crer ds maintenant le rpertoire destin hberger la partie logicielle dOracle et celui pour les donnes.

10. Lutilisation des bases de donnes

# # # #

mkdir mkdir chown chmod

p p R R

/usr/local/oracle10g /data/oradata oracle:oinstall /usr/local/oracle10g 775 /usr/local/oracle10g /data/oradata

Il est maintenant temps de se logger en tant quutilisateur oracle :


# su - oracle

et de modifier lenvironnement de ce compte utilisateur. Pour cela, modifiez le fichier ~oracle/ .bashrc en ajoutant les lignes suivantes :
export ORACLE_BASE=/usr/local/oracle10g export ORACLE_HOME=$ORACLE_BASE/product/10.1.0/db_1 export ORACLE_SID=mabase unset LANG export PATH=$ORACLE_HOME/bin:$PATH
ORACLE_BASE est le rpertoire o sera install la partie logicielle dOracle incluant les scripts dinstallation. Le moteur de la base de donne tant quant lui sous ORACLE_HOME. ORACLE_SID est le nom de la base de donnes que lon souhaite utiliser par dfaut.

Pour hriter de ces modifications, tapez maintenant la commande :


$ source ~/.bashrc

Il est temps maintenant de dcompresser larchive prcdemment tlcharge (par exemple, sous /usr/local/src/database/oracle10g).
$ cd /usr/local/src/database/oracle10g $ gunzip ship.db.cpio.gz $ cpio idmv < ship.db.cpio

Vous voil dsormais avec un rpertoire /usr/local/src/database/oracle10g/Disk1 contenant, entre autres, un fichier runInstaller.

Installation depuis un CD-ROM Dans le cas dune installation par CD-ROM, vous navez pas dcompresser darchives, mais vous devez "monter" le CD. Cette opration se ralise gnralement (mais cela dpend de lenvironnement) par lopration (depuis le compte root) :
# mount /mnt/cdrom

Ds lors, les oprations suivantes faisant rfrence /usr/local/src/database/ oracle10g/Disk1 doivent tre comprises comme faisant rfrence /mnt/cdrom.

762

Oracle

Avant de lancer le script dinstallation, assurez-vous que le compte oracle a le droit douvrir une fentre X. Pour cela, pas la peine de faire de sentiments : ouvrez une nouvelle fentre (xterm) en tant que lutilisateur initial de la session, et tapez la commande :
# xhost +

Vous pouvez alors tenter de lancer le script dinstallation.

10. Lutilisation des bases de donnes

$ export DISPLAY=:0.0 $ cd /tmp/Disk1 $ ./runInstaller

Ceci affiche la fentre suivante :

Figure 10.19 : Bienvenue

Comment ? Cela ne fonctionne pas ? Mouais... Il fallait sy attendre. Ce nest sans doute pas bien grave ; consultez simplement la remarque qui suit. Si, en revanche, cela a fonctionn, vous avez de la chance (!), et vous pouvez passer la suite.

Distribution non supporte Il se peut que lexcution de la commande prcdente conduise au message derreur suivant: Checking operating system version: must be redhat-2.1, UnitedLinux-1.0 or redhat-3 Failed <<<< Ceci est juste d au fait quOracle 10g ne supporte officiellement que les trois distributions cites dans le message, ce qui ne signifie toutefois pas quil ne fonctionne pas sous dautres distributions.

763

Chapitre 10

Lutilisation des bases de donnes

Pour viter cela, deux solutions soffrent vous: Vous pouvez lancer le script dinstallation avec loption permettant de ne pas faire le contrle des pr-requis.
$ ./runInstaller -ignoreSysPrereqs

10. Lutilisation des bases de donnes

Ou bien, vous faire passer pour un autre (enfin... faire passer votre distribution par une autre) Pour cela crez ou modifiez (aprs en avoir fait une sauvegarde) le fichier /etc/ redhat-release afin quil contienne lunique ligne: Red Hat Enterprise Linux AS release 3 (Taroon) et relancez runInstaller.
Une fois que vous aurez cliqu sur le bouton Suivant, vous verrez apparatre :

Figure 10.20 : Emplacement des scripts dinstallation

Cette fentre de dialogue vous demande de confirmer le chemin du rpertoire oraInventory o seront dposs les scripts dinstallation (celui ci est bas sur la valeur dfinie par ORACLE_HOME) ainsi que le groupe auquel les fichiers ainsi crs doivent appartenir. Vous pouvez conserver les valeurs par dfaut et valider. Durant cette pr-installation, vous serez invits excuter un script depuis le compte utilisateur root.

764

Oracle

Figure 10.21 : Pr-installation sous le compte root

10. Lutilisation des bases de donnes

Pour cela, il suffit de suivre les instructions. Dans une fentre (xterm) ouvrez une session root et excutez la commande
# /usr/local/oracle10g/oraInventory/orainstRoot.sh

Vous pouvez maintenant reprendre le cours normal de linstallation en cliquant sur Continue.

Figure 10.22 : Emplacement des fichiers

Il vous est maintenant demand de prciser le chemin du rpertoire contenant le logiciel dinstallation ainsi que le chemin du rpertoire destination. L, encore, vous pouvez conserver les valeurs par dfaut et valider. Le logiciel installe alors tous les scripts ncessaires linstallation du serveur. Vous tes maintenant prt installer le serveur.

765

Chapitre 10

Lutilisation des bases de donnes

Installation du serveur Oracle


Une fois les tapes prcdentes passes, vous arrivez lcran suivant :

10. Lutilisation des bases de donnes

Figure 10.23 : Slection du type dinstallation

Pour une premire installation, nous nous contenterons dune installation "standard". Attention, si vous souhaitez installer le composant contenant les messages pour une langue autre que langlais, avant de cliquer sur Next, slectionnez Product Languages.
Figure 10.24 : Slection des langues

Cest tout simple, il suffit dajouter les langues dsires. Puis cliquez sur Ok. Et cliquez sur le bouton Next de la fentre principale (prsente prcdemment). Le script contrle alors les diffrents paramtres de lenvironnement...

766

Oracle

10. Lutilisation des bases de donnes

Figure 10.25 : Analyse de lenvironnement

... et poursuit linstallation (apparemment y compris si des erreurs sont dtectes)

Figure 10.26 : Cration dune base

Vous pouvez choisir de ninstaller que le serveur de la base de donnes mais autant en profiter pour crer galement la base de donnes. Pour cela, conservez les valeurs par dfaut, savoir "Create a starter database" de type "General Purpose", puis cliquez sur Next.

767

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

Figure 10.27 : Paramtres de la base

Il vous est maintenant demand de donner un nom cette base de donnes un nom interne SID et un nom externe global (dans notre cas, nous avons simplement choisi le terme "mabase"). Cliquez sur Next.

Figure 10.28 : Options de gestion de la base

Passons sur les possibilits de gestion de la base. Cliquez sur Next.

768

Oracle

10. Lutilisation des bases de donnes

Figure 10.29 : Emplacement des donnes

Il est temps de prciser o doivent tre stockes les donnes de la base de donnes. Nous avons choisi /data/orainst. Cliquez sur Next.

Figure 10.30 : Possibilits de sauvegarde

Passons sur les possibilits de sauvegarde (backup). Cliquez sur Next.

769

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

Figure 10.31 : Spcification des mots de passe

Par soucis de simplicit, nous avons choisi dutiliser le mme mot de passe pour tous les comptes; savoir "biblephp" (ce que nous retrouverons dans les fichiers de configuration des scripts). Cliquez sur Next. Un premier traitement se dclenche alors.

Figure 10.32 : Rcapitulatif des paramtrages choisis

Cette fois, linstallation est imminente. Juste le temps de vrifier que toutes les conditions sont remplies. En loccurrence, la copie dcran montre un cas derreur (espace disque insuffisant) assez facilement corrig. Cliquez sur Install.

770

Oracle

10. Lutilisation des bases de donnes

Figure 10.33 : En cours dinstallation

Cette fois cest parti. Linstallation risque dtre perturbe par quelques messages derreur comme suit mais ne paniquez pas, ils ne devraient pas porter consquence. Cliquez simplement sur Continue.
Figure 10.34 : Message derreur lors de linstallation

Figure 10.35 : Ne pas tenir compte des messages derreur et continuer

Le logiciel dinstallation passe alors la configuration des diffrents lments.

771

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

Figure 10.36 : Les assistants poursuivent linstallation sans votre intervention

Vous navez rien faire, les oprations senchanent delles mme.


Figure 10.37 : La base de donnes se cre enfin

La base de donnes se cre.

Complment dinstallation
Afin que la base de donnes (mabase) soit systmatiquement dmarre lorsque lon lance Oracle, vous devez modifier le fichier /etc/oratab.conf afin de remplacer le N la fin de la ligne par un Y.
mabase:/usr/local/oracle10g/product/10.1.0/db_1:Y

772

Oracle

De plus vous tes invits modifier le fichier listener.ora dans le rpertoire $ORACLE_HOME/ network/admin afin dajouter les lignes relatives mabase. Le fichier ressemblera alors :
SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = /usr/local/oracle10g/product/10.1.0/db_1) (PROGRAM = extproc) ) (SID_DESC = (GLOBAL_DBNAME = mabase) (ORACLE_HOME = /usr/local/oracle10g/product/10.1.0/db_1) (SID_NAME = mabase) ) ) LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS_LIST= (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC)) ) (ADDRESS_LIST= (ADDRESS = (PROTOCOL = TCP)(HOST=192.168.1.1)(PORT=1521)) ) ) )

10. Lutilisation des bases de donnes

Ce fichier indique principalement que le listener doit tre lcoute en TCP sur la machine 192.168.1.1 (la machine du serveur de bases de donnes) sur le port 1521 (port par dfaut). Il indique, en outre, quil y a sur ce serveur une base de donne "mabase", hberge sous /usr/local/oracle10g/product/10.1.0/db_1, et qui sera identifie comme tant "mabase" (par les clients).

Mais il est o ce serveur ? Afin de vous viter dinutiles soucis, si vous indiquez un nom de serveur plutt quune adresse IP assurez quOracle na pas de mal lidentifier. Le plus simple tant alors de dclarer ce serveur dans le fichier /etc/hosts.

Dmarrage du serveur de bases de donnes


Pour dmarrer linterface qui va permettre de communiquer avec le serveur Oracle (et que lon vient de configurer via listener.ora), lancez (sous le compte oracle et avec les variables denvironnement dfinies dans le fichier .bashrc):
$ lsnrctl start

773

Chapitre 10

Lutilisation des bases de donnes

Pour dmarrer le serveur Oracle, suivez les instructions suivantes :


$ dbstart

Test du serveur Oracle (en local)


10. Lutilisation des bases de donnes
Vous pouvez maintenant tester la connexion au serveur Oracle.
$ sqlplus system/biblephp@mabase SQL > CREATE TABLE test (id INTEGER); SQL > INSERT INTO test VALUES (1234); SQL > SELECT * FROM test; SQL > DROP TABLE test;

Si vous avez pu enchaner les requtes prcdentes sans gnrer derreur, cest probablement que le serveur fonctionne correctement.

Utilisateurs par dfaut Le system/biblephp indiqu est un couple <nom dutilisateur>/<mot de passe>. Or lors de linstallation nous avons choisi dassocier le mot de passe biblephp tous les comptes.

Arrt du serveur de bases de donnes


Sachez que vous pourrez arrter Oracle (aprs avoir mis fin toutes les connexions, quelles aient t ouvertes par sql/plus ou via PHP) en tapant les commandes :
$ dbshut $ lsnrctl stop

Conguration de PHP avec support dOracle


Sous Linux
Pour accder une base de donnes Oracle depuis PHP, vous navez qu recompiler PHP avec loption withoci8=$ORACLE_HOME (en remplaant toutefois $ORACLE_HOME par sa valeur).

Vous pouvez vous reporter au chapitre "Installation" pour plus de dtails sur la faon de compiler PHP.
Il se peut que, durant la compilation de PHP, vous aperceviez un message dalerte vous invitant compiler Apache (si tel est votre serveur) avec loption pthread en cas de problme (ce qui na pas t notre cas).

774

Oracle

Vrication
Variables denvironnement Afin de pouvoir accder la base de donnes, le serveur web doit avoir dans ses variables denvironnement celles dfinies pour le compte oracle (ORACLE_HOME, ORACLE_SID, etc.). Pour cela, vous devez intgrer un appel source ~oracle/ .bashrc dans le .bashrc du compte sous lequel tourne le serveur web, ou simplement faire manuellement cet appel juste avant de lancer (dans la mme fentre) le serveur web.
Vous pouvez maintenant tester un script ne contenant que le code <?php phpinfo(); ?> et vous devez apercevoir les lignes suivantes :

10. Lutilisation des bases de donnes

Figure 10.38 : phpinfo()

Utilisation
Lutilisation basique de la base de donnes sopre selon le schma suivant :
j j j j

Connexion

grce

aux

fonctions

oci_connect(),

oci_pconnect()

ou

oci_new_connect().

Soumission de la requte via les fonctions oci_parse() et oci_execute(). Validation ou annulation de la transaction via les fonctions oci_commit() ou oci_rollback() (si la requte na pas t automatiquement valide). Dconnexion grce la fonction oci_close() (dans le cas dune connexion non persistante).

A lpoque de PHP 4 La plupart des fonctions dcrites ici existaient dj sous PHP 4 mais portaient un autre nom. Pour chacune dentre elles nous indiquerons donc leur prcdente identit. Il est noter que pour des raisons de compatibilit, il reste possible dutiliser lancien nom sous PHP 5.

Connexion
La connexion une base de donnes Oracle sopre grce la fonction oci_connect().

775

Chapitre 10

Lutilisation des bases de donnes

oci_connect() (ociLogon() PHP4)


tablit une connexion (non persistante) avec le serveur de bases de donnes. Syntaxe resource oci_connect(string $utilisateur, string $motDePasse [, string $base]) Nom dutilisateur. Mot de passe de lutilisateur. Nom de la base (ORACLE_SID). Si le serveur web et la base de donnes sont sur la mme machine et que le listener ne tourne pas, alors vous devez laisser ce champ vide. Identifiant de connexion au serveur de bases de donnes, ou FALSE en cas dchec.

10. Lutilisation des bases de donnes

$utilisateur $motDePasse $base

retour

Si, au sein dun mme script, vous dcidez douvrir plusieurs connexions avec oci_connect(), vous aurez alors peut-tre la surprise de constater que les oprations de commit et callback sappliquent toutes les transactions effectues, quelle que soit la connexion slectionne. Si ce nest pas le comportement que vous cherchez obtenir, vous devez alors privilgier la fonction oci_new_connect().

oci_new_connect() (ociNLogon() PHP4)


tablit une nouvelle connexion (non persistante) avec le serveur de bases de donnes ne partageant pas les oprations de commit et callback avec les autres connexions ouvertes au sein du script. Syntaxe $utilisateur $motDePasse $base resource oci_new_connect(string $utilisateur, string $motDePasse [, string $base]) Nom dutilisateur. Mot de passe de lutilisateur. Nom de la base (ORACLE_SID). Si le serveur web et la base de donnes sont sur la mme machine et que le listener ne tourne pas, alors vous devez laisser ce champ vide. Identifiant de connexion au serveur de bases de donnes, ou FALSE en cas dchec.

retour

Lutilisation dune connexion persistante requiert lappel oci_pconnect().

oci_pconnect() (ociPLogon() PHP4)


tablit une connexion persistante avec le serveur de bases de donnes.

776

Oracle

Syntaxe $utilisateur $motDePasse $base

resource oci_pconnect(string $utilisateur, string $motDePasse [, string $base]) Nom dutilisateur. Mot de passe de lutilisateur. Nom de la base (ORACLE_SID). Si le serveur web et la base de donnes sont sur la mme machine et que le listener ne tourne pas, alors vous devez laisser ce champ vide. Identifiant de connexion au serveur de bases de donnes, ou FALSE en cas dchec.

10. Lutilisation des bases de donnes

retour

Excution de la requte SQL


Lexcution dune requte SQL se passe au minimum en deux temps par un appel oci_parse() suivi de oci_execute().

oci_parse() (ociParse() PHP4)


Analyse et prpare une requte SQL. Syntaxe $idBaseDonnees $requete retour resource oci_parse(resource $idBaseDonnees, string $requete) Identifiant de connexion une base de donnes tel que retourn par oci_connect(), oci_new_connect() ou oci_pconnect(). Requte SQL Identifiant de requte SQL, ou FALSE en cas dchec (ex. : identifiant de base de donnes non valide, mais pas dans le cas dune requte SQL non valide).

Nous verrons par la suite quil est galement possible dutiliser des requtes prpares (contenant des paramtres qui pourront tre modifis juste avant que celles-ci ne soient excutes).

oci_execute() (ociExecute() PHP4)


Excute une requte SQL. Syntaxe $idRequete $modeCommit boolean oci_execute(resource $idRequete [,int $modeCommit]) Identifiant de requte SQL tel que retourn par oci_parse(). Prcise si vous souhaitez que la requte soit immdiatement valide ou non. Vous avez le choix entre les valeurs : OCI_COMMIT_ON_SUCCESS (valeur par dfaut) : la requte est immdiatement valide (par un COMMIT).

777

Chapitre 10

Lutilisation des bases de donnes

OCI_DEFAULT : la requte devra tre ultrieurement valide par oci_commit() ou annule par oci_rollback(). retour TRUE en cas de succs, FALSE sinon.

10. Lutilisation des bases de donnes

Option OCI_COMMIT_ON_SUCCESS Ne vous laissez pas surprendre : si vous choisissez loption (par dfaut) OCI_COMMIT_ON_SUCCESS, un COMMIT sera ncessairement appliqu (validant ainsi les prcdentes oprations effectues avec loption OCI_DEFAULT). Ceci est vrai mme si la requte effectue nest pas une requte de mise jour de la base (ex. : un SELECT).
La requte ainsi excute peut tre de nimporte quel type. Ce peut tre un simple INSERT ou SELECT, comme une requte de cration de procdure stocke ou un appel une procdure stocke. Dans le cas dune requte retournant un rsultat (typiquement une requte SELECT), il faudra galement analyser le rsultat. Mais nous verrons cela un peu plus loin.

Commit/rollback
Si vous avez opt pour loption OCI_DEFAULT de la fonction oci_execute(), vous pourrez valider ou annuler vos transactions avec les fonctions suivantes :

oci_commit() (ociCommit() PHP4)


Valide les transactions. Syntaxe $idBaseDonnees retour boolean oci_commit(resource $idBaseDonnees) Identifiant de connexion une base de donnes tel que retourn par oci_connect(), oci_new_connect() ou oci_pconnect(). TRUE en cas de succs, FALSE sinon (cest essentiellement le cas pour un identifiant non valide).

oci_rollback() (ociRollback() PHP4)


Annule les transactions. Syntaxe $idBaseDonnees boolean oci_rollback(resource $idBaseDonnees) Identifiant de connexion une base de donnes tel que retourn par oci_connect(), oci_new_connect() ou oci_pconnect().

778

Oracle

retour

TRUE en cas de succs, FALSE sinon (cest essentiellement le cas pour un identifiant non valide).

Dconnexion
Pour vous dconnecter opration thoriquement facultative mais toutefois vivement conseille , vous disposez de la fonction oci_close().

10. Lutilisation des bases de donnes

oci_close() (ociLogoff() PHP4)


Met fin la connexion la base de donnes et libre les ressources associes. Syntaxe $idBaseDonnees void oci_close(resource $idBaseDonnees) Identifiant de connexion une base de donnes tel que retourn par oci_connect(), oci_new_connect() ou oci_pconnect().

Premier exemple
Nous voici donc mme de construire notre premier script utilisant une base de donnes.

Vrifiez les paramtres Prenez garde ! Avant dexcuter ce script, assurez-vous que les paramtres prdfinis ne risquent pas de conduire la suppression des donnes dune de vos bases qui, par concidence, existerait dj.
Comme cela est fortement conseill, nous avons, ici, isol les paramtres de connexion dans un fichier aisment reprable.

Listing 10.58 : parametres_bd_inc.php


<?php // Paramtres de connexion la base de donnes // Nhsitez pas les modifier selon vos besoins $utilisateur = "system"; $motDePasse = "manager"; $base ?> = "mabase";

779

Chapitre 10

Lutilisation des bases de donnes

Notre script principal sera donc :

Listing 10.59 : insert01.php


<?php

10. Lutilisation des bases de donnes

// Paramtres du script require_once("parametres_bd_inc.php"); $table = "tableexemple"; // inclusion du script contenant les fonctions require_once("insert01_bd_inc.php"); // Connexion la base de donnes $idConnexion = oci_pconnect($utilisateur, $motDePasse, $base); if (!$idConnexion) { die("<b>Impossible de se connecter la base de donnes". " [$base] sous le compte [$utilisateur]". " avec le mot de passe [$motDePasse].</b>"); }

// Appel de la fonction principale if (EX_initialiseBD($idConnexion, $table)) { echo "Voil, une nouvelle table avec quelques donnes,". "vous pouvez le vrfier avec votre client de base ". " de donnes ou via les scripts suivants."; } else { echo "La cration ou lalimentation de la table choue."; } // Pas de dconnexion dans le cas dune connexion persistante // oci_close($idConnexion); ?>

et ncessitera :

Listing 10.60 : insert01_bd_inc.php


<?php /** Fonction charg de crer et dalimenter une table * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_initialiseBD($idConnexion, $table) { // Cration de la table

780

Oracle

$requete = "DROP TABLE $table"; $idRequete = oci_parse($idConnexion, $requete); @oci_execute($idRequete); $requete = "CREATE TABLE $table (filmId INTEGER, film VARCHAR(64))"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE;

10. Lutilisation des bases de donnes

// Cration dune squence pour les identifiants de film $requete = "DROP SEQUENCE seq_$table"; $idRequete = oci_parse($idConnexion, $requete); @oci_execute($idRequete); $requete = "CREATE SEQUENCE seq_$table"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; // Cration dun trigger pour remplir automatiquement // le champ identifiant de film chaque ajout de film $requete = "DROP TRIGGER compteur_$table"; $idRequete = oci_parse($idConnexion, $requete); @oci_execute($idRequete); $requete = "CREATE TRIGGER compteur_$table BEFORE INSERT ON $table ". "FOR EACH ROW ". "BEGIN ". "SELECT seq_$table.NEXTVAL INTO :NEW.filmId FROM DUAL; ". "END;"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; // Ajoute quelques donnes $idRequete = oci_parse($idConnexion, "INSERT INTO $table (film) VALUES (Forrest Gump)"); oci_execute($idRequete, OCI_DEFAULT); $idRequete = oci_parse($idConnexion, "INSERT INTO $table (film) VALUES (Matrix)"); oci_execute($idRequete, OCI_DEFAULT); $idRequete = oci_parse($idConnexion, "INSERT INTO $table (film) VALUES (La cit de la peur)"); oci_execute($idRequete, OCI_DEFAULT); // Validation des transactions // Uniquement parce que loption OCI_DEFAULT a t choisie. oci_commit($idConnexion); return TRUE; } ?>

781

Chapitre 10

Lutilisation des bases de donnes

Lecture des enregistrements


Dans le cas dune requte retournant une liste de donnes (typiquement un SELECT), il convient de rcuprer lidentifiant de requte et de lutiliser pour lire, en boucle, ligne aprs ligne, chaque enregistrement. Il existe diverses fonctions, chacune permettant de rcuprer les champs des enregistrements sous diffrentes formes.

10. Lutilisation des bases de donnes

Les informations peuvent ainsi tre retournes :


j j j

Champ par champ ; Enregistrement par enregistrement (sous la forme dun tableau index, dun tableau associatif ou encore dun tableau la fois index et associatif) ; Par bloc denregistrements.

Lecture champ par champ


Pour une lecture champ par champ, vous pouvez passer dun enregistrement au suivant par lappel oci_fetch(), et accder lun quelconque des champs par appel oci_result().

oci_fetch() (ociFetch() PHP4)


Passe lenregistrement suivant. Syntaxe $idRequete retour boolean oci_fetch(resource $idRequete) Identifiant de requte tel que retourn par oci_execute(). TRUE en cas de succs, FALSE sinon (plus denregistrement lire).

oci_result() (ociResult() PHP4)


Retourne la valeur dun champ dun enregistrement. Syntaxe $idRequete $champ retour mixed oci_result(resource $idRequete, mixed $champ) Identifiant de requte tel que retourn par oci_execute(). Au choix, soit le nom du champ (en majuscules), soit lindex du champ dans la requte (le premier champ ayant lindex 0). La valeur du champ.

Listing 10.61 : select_cc_bd_inc.php


<?php /** * Fonction listant le contenu dune table

782

Oracle

* contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requte $requete = "SELECT * FROM $table"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; // Boucle de lecture (et daffichage) des enregistrements while (oci_fetch($idRequete, $enreg)) { echo "FilmId=".oci_result($idRequete, "FILMID")." "; echo "Film=".oci_result($idRequete, "FILM")."<br />"; } return TRUE; } ?>

10. Lutilisation des bases de donnes

Lecture enregistrement par enregistrement


La forme la plus simple est celle retourne par la fonction oci_fetch_row().

oci_fetch_row()
Retourne un enregistrement, retourn par une requte SQL, sous la forme dun tableau index. Syntaxe $idRequete retour array oci_fetch_row(resource $idRequete) Identifiant de requte tel que retourn par oci_execute(). Tableau index contenant autant dlments que de champs retourns par la requte.

Listing 10.62 : select_eei_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table)

783

Chapitre 10

Lutilisation des bases de donnes

{ // Requte $requete = "SELECT * FROM $table"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; // Boucle de lecture (et daffichage) des enregistrements while ($enreg = oci_fetch_row($idRequete)) { echo "FilmId=".$enreg[0]." Film=".$enreg[1]."<br />"; } return TRUE; } ?>

10. Lutilisation des bases de donnes

Mais il est galement possible de retourner un enregistrement sous la forme dun tableau index et associatif avec, pour cls, les noms des champs (en majuscules).

oci_fetch_array()
Retourne un enregistrement, retourn par une requte SQL, sous la forme dun tableau index et/ou associatif. Syntaxe $idRequete $mode array oci_fetch_array(resource $idRequete [, int $mode]) Identifiant de requte tel que retourn par oci_execute(). Combinaison par OU logique des options suivantes : OCI_ASSOC : lenregistrement est retourn sous la forme dun tableau associatif o les cls sont les noms des champs (en majuscules) et les valeurs, celles des champs. Il ny a pas de cl cre pour les champs ayant une valeur NULL (sauf si loption est combine avec OCI_RETURN_NULLS). OCI_NUM (valeur par dfaut) : lenregistrement est retourn sous la forme dun tableau index (lindex 0 correspondant au premier champ de lenregistrement). Il ny a pas dindex cr pour les champs ayant une valeur NULL (sauf si loption est combine avec OCI_RETURN_NULLS). OCI_BOTH : combinaison de OCI_ASSOC et OCI_NUM. OCI_RETURN_NULLS : complte les tableaux avec des index ou cls, y compris pour les valeurs NULL. OCI_RETURN_LOBS : retourne les valeurs des champs de type CLOB, BLOB et non leurs descripteurs (voir plus loin). retour Tableau associatif ou index selon le mode choisi.

Cest ce mode de lecture de donnes que nous privilgierons; il est en effet fort pratique pour les champs dont on connat le nom (ce qui est le plus souvent le cas), et permet galement de faire rfrence des champs sans nom, comme par exemple un champ SUM(nomchamp). Notez toutefois quil est possible daffecter un nom (ex: somme) ce genre de champ en indiquant SUM(nomchamp) AS somme.

784

Oracle

Lexemple prcdent gagnera ainsi en lisibilit et deviendra:

Listing 10.63 : select_eea_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requte $requete = "SELECT * FROM $table"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; // Boucle de lecture (et daffichage) des enregistrements while ($enreg = oci_fetch_array($idRequete, OCI_BOTH)) { echo "FilmId=".$enreg["FILMID"]." Film=".$enreg["FILM"]."<br />"; } return TRUE; } ?>
oci_fetch_array est lquivalent de la fonction PHP4 ociFetchInto(), (toujours disponible mais amene disparatre) mais cette dernire une syntaxe lgrement diffrente.

10. Lutilisation des bases de donnes

ociFetchInto() (PHP4)
Retourne un enregistrement, retourn par une requte SQL, sous la forme dun tableau index, associatif, ou encore index et associatif. Syntaxe $idRequete $enregistrement $mode boolean ociFetchInto(resource $idRequete, array &$enregistrement [, int $mode]) Identifiant de requte tel que retourn par ociExecute(). Rfrence sur un tableau dans lequel seront copies les donnes de lenregistrement. Combinaison par OU logique des options suivantes : OCI_ASSOC : lenregistrement est retourn sous la forme dun tableau associatif o les cls sont les noms des champs (en majuscules) et les valeurs, celles des champs. Il ny a pas de cl

785

Chapitre 10

Lutilisation des bases de donnes

cre pour les champs ayant une valeur NULL (sauf si loption est combine avec OCI_RETURN_NULLS). OCI_NUM (valeur par dfaut) : lenregistrement est retourn sous la forme dun tableau index (lindex 0 correspondant au premier champ de lenregistrement). Il ny a pas dindex cr pour les champs ayant une valeur NULL (sauf si loption est combine avec OCI_RETURN_NULLS). OCI_BOTH : combinaison de OCI_ASSOC et OCI_NUM. OCI_RETURN_NULLS : complte les tableaux avec des index ou cls, y compris pour les valeurs NULL. OCI_RETURN_LOBS : retourne les valeurs des champs de type CLOB, BLOB et non leurs descripteurs (voir plus loin). retour TRUE en cas de succs, FALSE sinon (plus denregistrement lire).

10. Lutilisation des bases de donnes

Lecture des enregistrements en un bloc


Il est galement possible de retourner lensemble des enregistrements par un appel unique la fonction oci_fetch_all() (ce qui nest pas ncessairement la faon la plus lgante de procder).

oci_fetch_all() (ociFetchStatement() PHP4)


Retourne lensemble des enregistrements sous la forme dun tableau. Syntaxe $idRequete int oci_fetch_all(resource $idRequete, array &$tableauEnregistrements) Identifiant de requte tel que retourn par oci_execute().

$tableauEnregistrements Rfrence sur une variable dans laquelle sera copi un tableau associatif ayant pour cls les champs (en majuscules) des enregistrements, et pour valeur un tableau index contenant les valeurs pour chaque enregistrement. retour Nombre denregistrements retourns.

Association des champs retourns par une requte des variables PHP
Il est galement possible de lire le rsultat dune requte SQL en associant directement un champ de lenregistrement une variable PHP. Pour cela, vous pouvez utiliser la fonction oci_define_by_name().

786

Oracle

oci_dene_by_name() (ociDeneByName() PHP4)


Associe une variable PHP un champ retourn par une requte (de type SELECT). Syntaxe $idRequete $champ $variable $typeChamp boolean oci_define_by_name(resource $idRequete, string $champ, mixed &$variable [, int $typeChamp]) Identifiant de requte tel que retourn par oci_execute(). Nom du champ (en majuscules) de lenregistrement. Rfrence sur la variable PHP devant tre lie la variable SQL. Type compatible avec le champ SQL. Ce paramtre peut prendre une valeur parmi les suivantes : OCI_B_BFILE. OCI_B_CFILEE. OCI_CLOB sil sagit dun champ de type CLOB (objet large de type texte). OCI_BLOB sil sagit dun champ de type BLOB (objet large de type binaire). OCI_ROWID sil sagit dun identifiant denregistrement. OCI_B_CURSOR sil sagit dun curseur (pointeur de rsultat). OCI_B_BIN. OCI_B_SQLT_NTY sil sagit dune collection. OCI_SYSDATE. Par dfaut, le champ est retourn sous le type string. retour Le contenu ou pointeur vers le champ.

10. Lutilisation des bases de donnes

Si vous avez pris soin dappeler cette fonction avant de faire un appel oci_execute(), alors, chaque appel oci_fetch(), les contenus des variables ainsi associes aux champs de lenregistrement seront mis jour avec les valeurs de lenregistrement suivant.

Listing 10.64 : select_bind_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requte $requete = "SELECT * FROM $table"; $idRequete = oci_parse($idConnexion, $requete); oci_define_by_name($idRequete, "FILMID", $filmId); oci_define_by_name($idRequete, "FILM", $film); if (!oci_execute($idRequete)) return FALSE;

787

Chapitre 10

Lutilisation des bases de donnes

// Boucle de lecture (et daffichage) des enregistrements while (oci_fetch($idRequete)) { echo "FilmId=".$filmId." Film=".$film."<br />"; } return TRUE; }

10. Lutilisation des bases de donnes

?>

Si le champ associ est de type BLOB ou CLOB, vous devrez faire appel, au pralable, oci_new_descriptor(), comme cela est dcrit dans le chapitre sur les objets de grande taille.

Nombre denregistrements
Nombre denregistrements retourns
Si lon inclus lutilisation de ociFetchStatement() qui retourne un tableau dont il est ais de connatre la taille, il existe trois faons de dterminer le nombre denregistrements retourns par une requte. Si vous souhaitez uniquement connatre le nombre denregistrements, mais ne souhaitez pas immdiatement lire ces enregistrements, alors il vous suffit de faire une requte COUNT() comme suit :

Listing 10.65 : count_bd_inc.php


<?php /** * Fonction affichant le nombre denregistrements * dans une table * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la tabme **/ function EX_compte($idConnexion, $table) { // Requete $requete = "SELECT COUNT(*) FROM $table"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; // Lecture du rsultat if ($enreg = oci_fetch_row($idRequete)) { echo "Il y a ".$enreg[0]." enregistrements dans". " la table $table<br />"; return TRUE; } else { echo "Etes-vous sr que la table $table existe ?<br />";

788

Oracle

return FALSE; } } ?>

Si vous souhaitez connatre le nombre denregistrements, mais que vous souhaitez lire les enregistrements sans pour autant avoir besoin au pralable den connatre le nombre, il suffit de les compter au fur et mesure de leur lecture.

10. Lutilisation des bases de donnes

Listing 10.66 : count_select_bd_inc.php


<?php /** * Fonction affichant le nombre denregistrements * dans une table * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la tabme **/ function EX_compte($idConnexion, $table) { // Requete $requete = "SELECT * FROM $table"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; // Boucle de lecture (et de dcompte) des enregistrements $nb = 0; while ($enreg = oci_fetch_row($idRequete)) { // vous pouvez manipuler $enreg a votre guise // mais noubliez pas de le compter $nb++; } echo "Il y a $nb enregistrements dans la table $table<br />"; return TRUE; } ?>

Sachant quune requte SELECT * est plus longue quune requte SELECT COUNT(*), privilgiez la premire mthode si vous navez que faire du contenu des enregistrements.

Nombre denregistrements modis


Il est possible de dterminer le nombre denregistrements modifis (par une requte de type INSERT ou UPDATE, mais lexclusion des enregistrements retourns par SELECT) avec la fonction oci_num_rows().

789

Chapitre 10

Lutilisation des bases de donnes

oci_num_rows() (ociRowCount() PHP4)


Retourne le nombre denregistrements modifis par la requte. Syntaxe int oci_num_rows(resource $idRequete) Identifiant de requte tel que retourn par oci_execute(). Nombre denregistrements modifis. $idRequete retour

10. Lutilisation des bases de donnes

Dans notre exemple, nous modifierons les enregistrements sans vritablement les modifier.

Listing 10.67 : count_update_bd_inc.php


<?php /** * Fonction affichant le nombre denregistrements * dans une table * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_compte($idConnexion, $table) { // Requete $requete = "UPDATE $table SET filmId=filmId+0"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; echo "Il y a eu ".oci_num_rows($idRequete). " enregistrements modifis<br />"; return TRUE; } ?>

Mise prot des requtes prpares


Oracle permet lanalyse, la compilation et le stockage des requtes avant utilisation. Ceci permet dexcuter une srie de requtes similaires, sans avoir renouveler chaque fois les oprations danalyse et de compilation. Pour cela, il suffit de prparer une requte dans laquelle les lments variables sont remplacs par des noms prcds de : (ex. : INSERT INTO matable (film) VALUES (:film)), et dassocier cette variable SQL une variable PHP. Cette association variable SQL/variable PHP se ralise par la fonction oci_bind_by_name().

790

Oracle

oci_bind_by_name() (ociBindByName() PHP4)


Associe une variable de requte SQL une variable PHP. Syntaxe boolean oci_bind_by_name(resource $idRequete, string $variableSQL, mixed &$variablePHP [, int $longueurChamp , [int $typeChamp]]) Identifiant de requte tel que retourn par oci_execute(). Nom de la variable dans la requte SQL. Rfrence sur la variable PHP devant tre lie la variable SQL. Longueur du champ SQL. Type du champ SQL. Ce paramtre peut prendre une valeur parmi les suivantes : OCI_B_BFILE. OCI_B_CFILEE. OCI_CLOB sil sagit dun champ de type CLOB (objet large de type texte). OCI_BLOB sil sagit dun champ de type BLOB (objet large de type binaire). OCI_ROWID sil sagit dun identifiant denregistrement. OCI_B_CURSOR sil sagit dun curseur (pointeur de rsultat). OCI_B_BIN. OCI_B_SQLT_NTY sil sagit dune collection. OCI_SYSDATE. TRUE en cas de succs, FALSE sinon.

10. Lutilisation des bases de donnes

$idRequete $variableSQL $variablePHP $longueurChamp $typeChamp

retour

En utilisant les requtes prpares, le script dinitialisation de la table dexemple devient :

Listing 10.68 : insert02_bd_inc.php


<?php /** Fonction charg de crer et dalimenter une table * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_initialiseBD($idConnexion, $table) { // Cration de la table $requete = "DROP TABLE $table"; $idRequete = oci_parse($idConnexion, $requete); @oci_execute($idRequete); $requete = "CREATE TABLE $table (filmId INTEGER, film VARCHAR(64))"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; // Cration dune squence pour les identifiants de film

791

Chapitre 10

Lutilisation des bases de donnes

$requete = "DROP SEQUENCE seq_$table"; $idRequete = oci_parse($idConnexion, $requete); @oci_execute($idRequete); $requete = "CREATE SEQUENCE seq_$table"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE;

10. Lutilisation des bases de donnes

// Cration dun trigger pour remplir automatiquement // le champ identifiant de film chaque ajout de film $requete = "DROP TRIGGER compteur_$table"; $idRequete = oci_parse($idConnexion, $requete); @oci_execute($idRequete); $requete = "CREATE TRIGGER compteur_$table BEFORE INSERT ON $table ". "FOR EACH ROW ". "BEGIN ". "SELECT seq_$table.NEXTVAL INTO :NEW.filmId FROM DUAL; ". "END;"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; // Prpare une requte $idRequete = oci_parse($idConnexion, "INSERT INTO $table (film) VALUES (:film)"); // Associe une variable SQL une variable PHP oci_bind_by_name($idRequete, ":film", $film, 64); // 3 insertion en mode "auto commit" $film = Forrest Gump; if (!oci_execute($idRequete)) return FALSE; $film = Matrix; if (!oci_execute($idRequete)) return FALSE; $film = La cit de la peur; if (!oci_execute($idRequete)) return FALSE; return TRUE; } ?>

Utilisation des objets de grande taille (BLOB, CLOB)


PHP vous permet, bien entendu, de manipuler les champs de type BLOB et CLOB mis votre disposition par la base de donnes Oracle. Lorsque vous voudrez crer un objet de type LOB, vous devrez faire appel la fonction oci_new_descriptor() afin de crer un objet PHP qui vous servira en manipuler le contenu.

792

Oracle

oci_new_descriptor() (ociNewDescriptor() PHP4)


Cre un objet PHP permettant la manipulation des objets de grande taille. Syntaxe $idBaseDonnees $typeObjet object oci_new_descriptor(resource $idConnexion [, int $typeObjet]) Identifiant de connexion une base de donnes tel que retourn par oci_connect(), oci_new_connect() ou oci_pconnect(). Au choix : OCI_D_FILE. OCI_D_LOB sil sagit dun objet LOB. OCI_ROWID sil sagit dun identifiant denregistrement. Lobjet demand.

10. Lutilisation des bases de donnes

retour

Ces objets de grande taille sont reprsents sous PHP par des objets (PHP) possdant un attribut "descriptor" contenant un pointeur (resource). Ces objets OCILOB proposent diffrentes mthodes dont les essentielles :
j j j j j
free() pour librer les ressources alloues par lobjet. load() pour rcuprer le contenu du champ (BLOB, CLOB) ; save() pour insrer un objet dans la base ; saveFile() pour sauvegarder le contenu du champ dans un fichier ; writeToFile() pour sauvegarder le contenu du champ dans un fichier ;

mais aussi append(), close(), eof(), erase(), flush(), read(), rewind(), seek(), setBuffering(), size(), tell(), truncate(), write(), writeTemporary()

PHP 5.0.0 pas encore totalement au point ? Il semblerait quil ait t prvu que les mthodes saveFile(); writeToFile(), writeTemporary() (qui existaient dj sous PHP4) soient renommes en import(), export(), write_temporary() ce nest toutefois pas le cas avec PHP 5.0.0.

OCILOB->save()
Insre un objet dans un champ de type LOB. Syntaxe $donnees retour boolean save(string $donnees) Donnes constituant lobjet. TRUE en cas de succs, FALSE sinon.

793

Chapitre 10

Lutilisation des bases de donnes

OCILOB->load()
Retourne le contenu dun champ de type LOB. Syntaxe string load(void) Contenu du champ, ou FALSE en cas dchec.

10. Lutilisation des bases de donnes

retour

OCILOB->saveFile()
Sauve le contenu dun champ de type LOB dans un fichier. Syntaxe $nomFichier retour boolean saveFile(string $nomFichier) Nom du fichier dans lequel copier le contenu de lobjet. TRUE en cas de succs, FALSE sinon.

OCILOB->writeToFile()
Sauve une portion du contenu dun champ de type BLOB dans un fichier. Syntaxe $nomFichier $debut $longueur retour boolean writeToFile(string $nomFichier [, int $debut [, int $longueur]]) Nom du fichier dans lequel copier le contenu de lobjet. Octet partir duquel commencer la copie de lobjet. Nombre doctets crire dans le fichier. TRUE en cas de succs, FALSE sinon.

OCILOB->free()
Libre les ressources alloues par lobjet. Syntaxe retour boolean free(void) TRUE en cas de succs, FALSE sinon.

Voici un exemple dutilisation : dans un premier temps, nous ajoutons un objet BLOB dans la base, puis nous le rcuprons de deux faons diffrentes pour le sauvegarder dans un fichier ou lafficher.

794

Oracle

Listing 10.69 : blob_bd_inc.php


<?php // Fonction charg de donner un exemple dutilisation // des BLOB // Compatibilite: PHP 5

10. Lutilisation des bases de donnes

function EX_blob($idConnexion, $table) { // Cration dune table de test $idRequete = oci_parse($idConnexion, "DROP TABLE $table"); @oci_execute($idRequete); $idRequete = oci_parse($idConnexion, "CREATE TABLE $table (id INTEGER,". "monblob BLOB)"); oci_execute($idRequete); //----------------------------------// Insertion dun objet de type blob //----------------------------------$requete = "INSERT INTO $table (id, monblob) VALUES (1, EMPTY_BLOB())". " RETURNING monblob INTO :blob"; $idRequete = oci_parse($idConnexion, $requete); // Cration dun descripteur de BLOB $blob = oci_new_descriptor($idConnexion, OCI_D_LOB); oci_bind_by_name($idRequete, ":blob", $blob, -1, OCI_B_BLOB); if (!oci_execute($idRequete, OCI_DEFAULT)) die("echec."); // Insertion des donnes // cela ncessite une transaction (do le OCI_DEFAULT) $blob->save("On supposera quil y a l une grande quantit de donnes". " de type binaire (issue par exemple de la lecture dun ". " fichier image)"); oci_commit($idConnexion); echo "Donnes enregistres<br />"; $blob->free(); //-----------------------------------------------------------// Lecture dun objet de type BLOB par un simple oci_fetch_assoc //-----------------------------------------------------------$requete = "SELECT monblob FROM $table WHERE id=1"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; echo "<b>Lecture avec oci_fetch_assoc</b><br />"; if (! ($enreg = oci_fetch_assoc($idRequete))) return FALSE; $blob = $enreg["MONBLOB"];

795

Chapitre 10

Lutilisation des bases de donnes

// Une fois le descripteur rcupr // Il est possible de... // Rcuprer le contenu de lobjet (pour lafficher) echo "<b>Affichage avec la mthode load()</b><br />"; echo $blob->load()."<br />";

10. Lutilisation des bases de donnes

// Sauvegarder lobjet dans un fichier // $sts = $blob->export("blob.txt"); $sts = $blob->writeToFile("blob.txt"); // Sauvegarder une partie de lobjet dans un fichier // $sts = $blob->export("blob2.txt", 3, 5); $sts = $blob->writeToFile("blob2.txt", 3, 5); $blob->free(); //-----------------------------------------------------------// Lecture dun objet de type BLOB par ociDefineByName //-----------------------------------------------------------$requete = "SELECT monblob FROM $table WHERE id=1"; $idRequete = oci_parse($idConnexion, $requete); // Cration dun descripteur de BLOB $blob = oci_new_descriptor($idConnexion, OCI_D_LOB); oci_define_by_name($idRequete, "MONBLOB", $blob, OCI_B_BLOB); if (!oci_execute($idRequete)) return FALSE; if (!oci_fetch($idRequete)) return FALSE; // Une fois le descripteur rcupr // Il est possible de... // Rcuprer le contenu de lobjet (pour lafficher) echo "<b>Lecture avec oci_define_by_name</b><br />"; echo $blob->load(); $blob->free(); return TRUE; } ?>

Lajout de lobjet se fait selon les tapes suivantes : 1. 2. Prparation dune requte dinsertion ajoutant un objet BLOB vide et retournant lobjet ; Cration dun objet (PHP) ;

796

Oracle

3. 4.

Association de cet objet PHP lobjet SQL ; Excution proprement dite. Les appels aux mthodes dcriture de lobjet BLOB devant obligatoirement se faire au sein dune transaction, il est important, ici, de slectionner le mode OCI_DEFAULT. Appel de la mthode save() afin de prciser le contenu de lobjet BLOB ; Et enfin, validation de la transaction avec oci_commit() ; Libration des ressources.

5. 6. 7.

10. Lutilisation des bases de donnes

La lecture de lobjet BLOB peut se faire de diffrentes faons :


j

Si vous faites appel oci_fetch_assoc(), oci_fetch_row() ou encode oci_fetch_array() (comme avec un champ de type standard), vous rcuprez alors un objet PHP, sur lequel vous pouvez appeler directement la mthode voulue. Si vous faites appel oci_bind_by_name(), vous devrez, au pralable, allouer les ressources de lobjet PHP associ avec oci_new_descriptor().

Gestion des erreurs


Jusque-l, en cas derreur, nous nous sommes contents dafficher un message gnrique. Il est cependant possible de dterminer plus prcisment lorigine de lerreur. Cela est possible notamment en rcuprant un code derreur via la fonction oci_error().

oci_error() (ociError() PHP4)


Retourne le code derreur du dernier appel la connexion ou la requte. Syntaxe $idBaseDonnees OuRequete array oci_error([resource $idBaseDonneesOuRequete]) Identifiant de connexion une base de donnes tel que retourn par oci_connect(), oci_new_connect() ou oci_pconnect(), ou identifiant de requte tel que retourn par oci_execute(). Si ce paramtre nest pas prcis, cest la dernire erreur rencontre, et non lie un identifiant de connexion ou de requte (ex. : problme de connexion), qui est retourne. Tableau associatif contenant la cl "code", laquelle est associ un code derreur (un entier) et la cl "message" laquelle est associ un message derreur (une chane de caractres en anglais). FALSE en cas dabsence derreur.

retour

797

Chapitre 10

Lutilisation des bases de donnes

Tableau 10.16 : Exemples de codes et messages derreur


Code 900 1017 Message ORA-00900: invalid SQL statement ORA-01017: invalid username/password; logon denied ORA-12154: TNS:could not resolve service name Description Requte SQL non valide. Lidentifiant de connexion la base nest pas valide. La connexion la base (via le listener) na pas pu seffectuer.

10. Lutilisation des bases de donnes

12154

Vous pourrez, par exemple, vous servir des codes derreur pour afficher vos propres messages derreur. Dans lexemple suivant, nous montrons comment traduire les messages derreur (en fait cela ne sappliquera qu lchantillon de codes qui vient dtre prsent).

Listing 10.70 : error_inc.php


<?php // Propose une version Franaise de ociError function ociErrorFr($id="") { if ($id == "") { $errEn = oci_error(); } else { $errEn = oci_error($id); } if ($errEn === FALSE) return FALSE; switch ($errEn["code"]) { case 900 : $errEn["message"] = "ORA-00900: Requte SQL invalide"; break; case 1017 : $errEn["message"] = "ORA-01017: Nom utilisateur/Mot de passe invalide:". " connexion refuse"; break; case 12154 : $errEn["message"] = "ORA-12154: Aucune rfrence trouve par le TNS"; break; } return $errEn; } ?>

798

Oracle

Et voici un script gnrant lensemble des erreurs ci-dessus, afin de bien mettre en vidence le bon fonctionnement de cette fonction personnalise.

Listing 10.71 : error.php


<?php

10. Lutilisation des bases de donnes

// Paramtres du script require_once("parametres_bd_inc.php"); $table = "error01"; // Chargement de la fonction de traduction des messages derreur require_once("error_inc.php"); // Erreur didentification $idConnexion = @oci_pconnect(xyz, xyz, $base); print_r(ociErrorFr()); echo "<br />"; // Base de donnes inaccessible $idConnexion = @oci_pconnect($utilisateur, $motDePasse, "xyz"); print_r(ociErrorFr()); echo "<br />"; // Connexion la base de donnes $idConnexion = oci_pconnect($utilisateur, $motDePasse, $base); if (!$idConnexion) { die("<b>Impossible de se connecter la base de donnes". " [$base] sous le compte [$utilisateur]". " avec le mot de passe [$motDePasse].</b>"); } // requte invalide $idRequete = @oci_parse($idConnexion, "XYZ"); @oci_execute($idRequete); echo "derniere erreur<br />"; print_r(ociErrorFr()); echo "derniere erreur connexion<br />"; print_r(ociErrorFr($idConnexion)); echo "derniere erreur requete<br />"; print_r(ociErrorFr($idRequete)); ?>

Ce script gnre alors une page contenant les messages :


Array( [code] => 1017 [message] => ORA-01017: Nom utilisateur/Mot de passe invalide: connexion refuse ) Array( [code] => 12154 [message] => ORA-12154: Aucune rfrence trouve par le TNS )

799

Chapitre 10

Lutilisation des bases de donnes

derniere erreur derniere erreur connexion derniere erreur requete Array( [code] => 900 [message] => ORA-00900: Requte SQL invalide )

10. Lutilisation des bases de donnes

Exemples dapplications
Compteur de clics
Une application courante dutilisation des bases de donnes, et simple mettre en uvre, consiste crer un compteur de clics. En effet, peut-tre souhaitez-vous proposer, sur votre site, un certain nombre de liens vers des sites Internet (annuaire web) ou vers des fichiers (bibliothques de scripts). Peut-tre que certains (ou la totalit) de ces liens sont proposs par un partenaire. Bref, tout cela vous incite savoir quelles sont les pages les plus frquemment consultes (pour connatre les centres dintrt des visiteurs) et combien de visiteurs vous avez redirigs vers votre sponsor. La mthode la plus classique consiste stocker en base de donnes lensemble des liens ainsi proposs, et remplacer les traditionnels liens de la forme http://www.domaine.com par un lien vers un script charg dincrmenter le compteur correspondant au site indiqu, et de rediriger le client vers le site grce la fonction header(). Pour notre exemple, nous utiliserons une table appele url contenant trois champs :
j j j

urlid, identifiant de lURL (champ auto-incrment) ; url, lURL proprement dite ; nbclic, le nombre de clics.

Le script de redirection (appel ici compteurclic_redirection.php) devra alors accepter un paramtre (urlid) et devra, partir de ce paramtre, dterminer quelle est la valeur du champ url, incrmenter nbclic pour cette URL, et rediriger vers url. Les appels ce script auront alors la forme http://localhost/compteurclic_redirection.php?urlid=3 (pour accder lURL ayant lidentifiant 3). supposer que lURL 3 corresponde au site http://www .sqlfacil.com, cela signifie que le lien <a href="http://www.sqlfacile.com"> devra tre remplac par <a href="compteurclic_redirection.php?urlid=3> si lon souhaite en compter le nombre de clics. Concrtement, cette table pourra tre cre et alimente avec la fonction CC_initialiseBD() du script suivant :

Listing 10.72 : compteurclic_admin_inc.php


<?php // Fonction charg de crer et dalimenter // la table "compteur de clics" function CC_initialiseBD($idConnexion, $table)

800

Oracle

{ // Cration de la table $requete = "DROP TABLE $table"; $idRequete = oci_parse($idConnexion, $requete); @oci_execute($idRequete);

10. Lutilisation des bases de donnes

$requete = "CREATE TABLE $table (urlId INTEGER,". "url VARCHAR(128) NOT NULL,". "nbclic INTEGER DEFAULT 0,". "UNIQUE(url))"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; // Cration dune squence pour les identifiants durl $requete = "DROP SEQUENCE seq_$table"; $idRequete = oci_parse($idConnexion, $requete); @oci_execute($idRequete); $requete = "CREATE SEQUENCE seq_$table"; $idRequete = oci_parse($idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; // Cration dun trigger pour remplir automatiquement // le champ identifiant durl chaque ajout dune url // (compteur) $requete = "DROP TRIGGER compteur_$table"; $idRequete = oci_parse($idConnexion, $requete); @oci_execute($idRequete); $idRequete = oci_parse($idConnexion, "CREATE TRIGGER compteur_$table". " BEFORE INSERT ON $table ". "FOR EACH ROW ". "BEGIN ". "SELECT seq_$table.NEXTVAL INTO :NEW.urlId FROM DUAL; ". "END;"); oci_execute($idRequete); // Prpare une requte $idRequete = oci_parse($idConnexion, "INSERT INTO $table (url) VALUES (:url)"); // Associe une variable SQL une variable PHP oci_bind_by_name($idRequete, ":url", $url, 129); // Alimentation de la base de donnes $url = "http://www.php.net"; oci_execute($idRequete); $url = "http://www.phpfacile.com";

801

Chapitre 10

Lutilisation des bases de donnes

oci_execute($idRequete); $url = "http://www.sqlfacile.com"; oci_execute($idRequete); $url = "http://www.xmlfacile.com"; oci_execute($idRequete);

10. Lutilisation des bases de donnes

$url = "http://www.ootoogo.com"; oci_execute($idRequete); return TRUE; } ?>

Les oprations de connexion napparaissent pas dans ce script, mais vous pouvez consulter le script compteurclic_admin.php si vous le souhaitez. La lecture de la liste des liens disponibles en base de donnes pourra se faire via la fonction CC_recupereLiens() du script suivant :

Listing 10.73 : compteurclic_inc.php


<?php // // // // // Fonction retournant les informations de liens sous forme dun tableau associatif possedants les cls - "lien" associ au tableau des liens hypertextes - "nbclic" associ au tableau des nombres de clics

function CC_recupereLiens($idConnexion, $table) { // Nom du script charg du comptage et de la redirection $script = "compteurclic_redirection.php"; // Prparation de la requte SELECT $idRequete = oci_parse($idConnexion, "SELECT * FROM $table"); // Excution de la requte oci_execute($idRequete); // Rcupration des enregistrements les uns aprs les autres while (oci_fetch_into($idRequete, $enreg, OCI_ASSOC)) { $liens["lien"][] = "<a href=\"$script?urlid=".$enreg["URLID"]."\">". $enreg["URL"]."</a>"; $liens["nbclic"][] = $enreg["NBCLIC"]; } return $liens; }

802

Oracle

?>

Laffichage des liens consiste uniquement mettre en page le contenu du tableau ainsi rcupr (voir la fonction du script compteurclic_affichage_inc.php). Comme cela a t prcis, le lien <a href="http://www.sqlfacile.com">http://www .sqlfacile.com</a> a t remplac par <a href="compteurclic_redirection .php?urlid=3">http://www.sqlfacile.com </a>. La redirection vers le site www.sqlfacile .com est donc la charge du script compteurclic_redirection.php.

10. Lutilisation des bases de donnes

Listing 10.74 : compteurclic_redirection.php


<?php // Paramtres du script require_once("parametres_bd_inc.php"); $table = "compteurclic"; // Connexion la base de donnes $idConnexion = @oci_pconnect($utilisateur, $motDePasse, $base); if (!$idConnexion) { die("<b>Impossible de se connecter la base de donnes". " [$base] sous le compte [$utilisateur]". " avec le mot de passe [$motDePasse].</b>"); } // Rcupration du paramtre urlid pass // en paramtre de ce script par la mthode GET $urlid = $_GET["urlid"]; // Recherche dans la base de donne de lurl // correspondant $urlid $idRequete = @oci_parse($idConnexion, "SELECT * FROM $table WHERE urlid=$urlid"); @oci_execute($idRequete); @oci_fetch_into($idRequete, $enreg, OCI_ASSOC) or die("<b>Impossible de trouver cette url<b>"); // Nous connaissons maintenant lurl // nous pourrons nous rediriger vers $enreg["URL"]; // une fois le compteur incrment $url = $enreg["URL"]; $idRequete = @oci_parse($idConnexion, "UPDATE $table SET nbclic=nbclic+1". " WHERE urlid=$urlid"); @oci_execute($idRequete); // // // // Dans le cas dune connexion non persistante (utilisation de oci_connect ou oci_new_connect) il faudrait galement la ligne suivante oci_close($idConnexion);

803

Chapitre 10

Lutilisation des bases de donnes

// Cest lheure de la redirection header("Location: $url"); // // // // // REM: Lappel header ne fonctionnera pas si des donnes ont dj t mises vers le navigateur. Ce qui peut arriver si lun des appels prcdents affiche un message dalerte. Il tait donc important de faire prcder ces appels par le signe @

10. Lutilisation des bases de donnes

// REM 2: Avec Oracle, nous aurions pu utiliser une procdure stocke // ralisant la fois lopration de lecture et celle de mise jour // du compteur ?>

Utilisation du bouton retour Si, aprs avoir suivi un lien, vous revenez sur la page cliccompte.php en utilisant le bouton retour (back), le contenu de la page ne sera pas ractualis. Par consquent, le nombre de visites affich ne sera pas correct. Noubliez donc pas, dans ce cas, de rafrachir (bouton actualiser) la page.

SuperTheque
Lessentiel du code de lapplication a t prsent en introduction de ce chapitre. Il ne restait plus qua connatre les fonctions Oracle pour implmenter linterface RessourceInterface cest dsormais chose faite:

Listing 10.75 : RessourceOracle_class.php


<?php include_once("RessourceInterface_class.php"); include_once(dirname(__FILE__)."/../config/oracle_cfg.php"); /** * RessourceOracle_class.php * Classe dacces a une base de donnees Oracle * Cette classe doit implementer toutes les methodes de linterface * RessourceInterface. * Compatibilite: PHP 5 */ class Ressource implements RessourceInterface { var $idConnexion; public function connexion() { global $oci_serveur, $oci_utilisateur, $oci_motDePasse; global $oci_base;

804

Oracle

if (!isset($this->idConnexion)) { $idConnexion = oci_pconnect($oci_utilisateur, $oci_motDePasse, $oci_base); if (!$idConnexion) return FALSE; $this->idConnexion = $idConnexion; } return TRUE; } public function deconnexion() { // Rien a faire, il sagit dune connexion persistante } public function reset() { $requete = "DROP TABLE types"; $idRequete = oci_parse($this->idConnexion, $requete); @oci_execute($idRequete); // Ne pas tenir compte dune eventuelle erreur // la table nexiste peut-etre tout simplement pas $requete = "CREATE TABLE types (". "id INTEGER PRIMARY KEY,". "type VARCHAR(255))"; $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; $requete = "DROP SEQUENCE seq_types"; $idRequete = oci_parse($this->idConnexion, $requete); @oci_execute($idRequete); $requete = "CREATE SEQUENCE seq_types"; $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; $requete = "DROP TRIGGER compteur_types"; $idRequete = oci_parse($this->idConnexion, $requete); @oci_execute($idRequete); $requete = "CREATE TRIGGER compteur_types ". "BEFORE INSERT ON types ". "FOR EACH ROW ". "BEGIN ". "SELECT seq_types.NEXTVAL INTO :NEW.id FROM DUAL; ". "END;"; $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE;

10. Lutilisation des bases de donnes

$types = array("Album", "Film", "Livre", "Musique");

805

Chapitre 10

Lutilisation des bases de donnes

foreach ($types as $type) { $requete = "INSERT INTO types (type) VALUES ($type)"; $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; } $requete = "DROP TABLE articles"; $idRequete = oci_parse($this->idConnexion, $requete); @oci_execute($idRequete); // Ne pas tenir compte dune eventuelle erreur // la table nexiste peut-etre tout simplement pas $requete = "CREATE TABLE articles (". "id INTEGER PRIMARY KEY,". "albumId INTEGER,". "titre VARCHAR(255),". "typeId INTEGER,". "commentaire VARCHAR(255))"; $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; $requete = "DROP SEQUENCE seq_articles"; $idRequete = oci_parse($this->idConnexion, $requete); @oci_execute($idRequete); $requete = "CREATE SEQUENCE seq_articles"; $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; $requete = "DROP TRIGGER compteur_articles"; $idRequete = oci_parse($this->idConnexion, $requete); @oci_execute($idRequete); $requete = "CREATE TRIGGER compteur_articles ". "BEFORE INSERT ON articles ". "FOR EACH ROW ". "BEGIN ". "SELECT seq_articles.NEXTVAL INTO :NEW.id FROM DUAL; ". "END;"; $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; } public function addArticle($albumId, $titre, $typeId, $commentaire) { $requeteDebut = "INSERT INTO articles (albumId, titre, typeId"; $requeteFin = ") VALUES ($albumId,". "".sqlite_escape_string($titre).",". "$typeId";

10. Lutilisation des bases de donnes 806

Oracle

if ($commentaire != "") { $requeteDebut .= ",commentaire"; $requeteFin .= ",".sqlite_escape_string($commentaire).""; } $requete = $requeteDebut . $requeteFin . ")"; $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE;

10. Lutilisation des bases de donnes

} public function getArticle($articleId) { $requete = "SELECT * FROM articles WHERE id=$articleId"; $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; $article = NULL; if ($enreg = oci_fetch_array($idRequete)) { $article = $this->enreg2Article($enreg); } return $article; } public function getArticles(Filtre $filtre, Plage $plage, Tri $tri) { $requete = "SELECT * FROM articles"; if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". addSlashes($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL. " AND typeId=".$filtre->getTypeId(); } if ($tri->getSens() == -1) { $triSQL = "ORDER BY ".$tri->getChamp()." DESC"; } else if ($tri->getSens() == 1) { $triSQL = "ORDER BY ".$tri->getChamp()." ASC"; } $requete = $requete." WHERE ".$conditionSQL." ". $triSQL; $requete = "SELECT * FROM (". "SELECT id, albumId, titre, typeId, commentaire,". " ROWNUM noligne ". "FROM (".$requete.")". ") WHERE noligne BETWEEN ".($plage->getPremierArticle()+1).

807

Chapitre 10

Lutilisation des bases de donnes

" AND ".($plage->getPremierArticle()+ $plage->getNbArticleMax()); $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; $articles = NULL; while ($enreg = oci_fetch_array($idRequete)) { $articles[] = $this->enreg2Article($enreg); } return $articles; } public function getNbTotalArticles(Filtre $filtre) { $requete = "SELECT COUNT(*) FROM articles"; if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". addSlashes($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL. " AND typeId=".$filtre->getTypeId(); } $requete = $requete." WHERE ".$conditionSQL; $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; if ($enreg = oci_fetch_array($idRequete)) { return $enreg[0]; } else return FALSE; } public function getTypes() { $requete = "SELECT * FROM types"; $idRequete = oci_parse($this->idConnexion, $requete); if (!oci_execute($idRequete)) return FALSE; $types = NULL; while ($enreg = oci_fetch_array($idRequete)) { $types[$enreg["ID"]] = $enreg["TYPE"]; } return $types; } public function getAlbumTypeId() {

10. Lutilisation des bases de donnes 808

Oracle

return 1; }

private function enreg2Article($enreg) { // ATTENTION: Avec Oracle les noms des cles // du tableau sont en majuscules. $article = new Article(); $article->setId($enreg["ID"]); $article->setAlbumId($enreg["ALBUMID"]); $article->setTitre($enreg["TITRE"]); $article->setTypeId($enreg["TYPEID"]); $article->setCommentaire($enreg["COMMENTAIRE"]); return $article; } } ?>

10. Lutilisation des bases de donnes

Comme vous le constatez, la principale difficult nest pas tant au niveau des fonctions disponibles quau niveau de la construction des requtes SQL. La requte sera simple lorsquil ne sagit que de rcuprer un enregistrement identifi par la cl Id (comme cest le cas avec getArticle()) elle sera bien plus complexe sil sagit des rcuprer un ensemble denregistrements rpondant des critres prcis et tris (comme cest le cas avec getArticles()).

Requtes avec des apostrophes


Lors de la construction de la requte, il faut bien garder lesprit que lun des lments de la requte (typiquement un champ de type texte saisi par lutilisateur, comme ici le titre ou le commentaire) peut contenir une apostrophe qui pourrait tre confondu avec le dlimiteur de chane. Pensez donc bien faire un appel addSlashes() lorsque cela peut savrer ncessaire.

Affichage par page


Des bases de donnes telles que MySQL proposent une instruction LIMIT permettant de ne retourner quun sous-ensemble des rsultats de la requte, en prcisant lindex du premier enregistrement et le nombre de rsultats retourner. Il ny a malheureusement pas dquivalent sous Oracle ; il faut donc avoir recours quelques acrobaties pour obtenir le mme rsultat. Ainsi, pour retourner les vingt premiers enregistrements partir du onzime de la requte <requete>, il faut excuter la requte :
SELECT * FROM (SELECT champ1, champ2, ..., ROWNUM noligne FROM (<requete>)) WHERE noligne BETWEEN 11 AND 30)

Tri
Modifier lordre daffichage des annonces nest pas non plus bien sorcier. Le tri peut seffectuer directement au niveau de la requte SQL grce linstruction ORDER BY.

809

Chapitre 10

Lutilisation des bases de donnes

Moteur de recherche (ltre)


Pour filtrer, il suffit dutiliser linstruction WHERE. Dans notre cas, nous souhaitons autoriser lutilisation de jokers (comme %) afin, par exemple, de rechercher les titres commenant par une chane donne. Cest pourquoi, nous ne ferons pas un test de type titre=motcle mais titre LIKE motcle (o motcle pourrait avoir la valeur "La 7eme compagnie%").

10. Lutilisation des bases de donnes

En savoir plus
... sur le rsultat dune requte
Il vous est ainsi possible de connatre le nombre de champs retourns par une requte (et, par consquent, le nombre de champs dune table dans le cas dune requte SELECT * FROM <nom_table> sur une table non vide).

oci_num_elds() (ociNumCols() PHP4)


Retourne le nombre de champs dans les enregistrements retourns par une requte SQL. Syntaxe $idRequete retour int oci_num_fields(resource $idRequete) Identifiant de requte tel que retourn par oci_execute(). Nombre de champs.

Mais aussi, le nom de ces champs :

oci_eld_name() (ociColumnName() PHP4)


Retourne le nom des champs dans les enregistrements retourns par une requte SQL. Syntaxe $idRequete $index string oci_field_name(resource $idRequete, int $index) Identifiant de requte tel que retourn par oci_execute(). Index du champ dont vous souhaitez connatre le nom. Le nombre total de champs peut tre obtenu en faisant appel oci_num_fields().ATTENTION : lindexation commence 1. Nom du champ.

retour

Cependant, les champs ont dautres informations nous livrer que leur nom. Pour cela, vous disposez des fonctions :

810

Oracle

oci_eld_type() (ociColumnType() PHP4)


Retourne le type des champs dans les enregistrements retourns par une requte SQL. Syntaxe $idRequete $index string oci_field_type(resource $idRequete, int $index) Identifiant de requte tel que retourn par oci_execute(). Index du champ dont vous souhaitez connatre le type. Le nombre total de champs peut tre obtenu en faisant appel oci_num_fields().ATTENTION : lindexation commence 1. Type du champ, ou FALSE en cas derreur.

10. Lutilisation des bases de donnes

retour

oci_eld_size() (ociColumnSize() PHP4)


Retourne la taille (en octets) des champs de la table. Syntaxe $idRequete $index int oci_field_size(resource $idRequete, int $index) Identifiant de requte tel que retourn par oci_execute(). Index du champ dont on souhaite connatre la taille. Le nombre total de champs peut tre obtenu en faisant appel oci_num_fields(). ATTENTION : lindexation commence 1. Taille (en octets) occupe par le champ, ou FALSE en cas derreur.

retour

Listing 10.76 : info01_inc.php


<?php // Fonction affichant certaines informations lies // la structure dune table function describe($idConnexion, $table) { // Prparation de la requte SELECT $idRequete = oci_parse($idConnexion, "SELECT * FROM $table"); // Excution de la requte oci_execute($idRequete); // Rcupration du nombre de champs retourns $nbChamps = oci_num_fields($idRequete); // Pour chaque champ, rcupration des informations // - nom du champ // - type du champ // - taille du champ for ($i=1; $i<=$nbChamps; $i++) {

811

Chapitre 10

Lutilisation des bases de donnes

echo "<b>".oci_field_name($idRequete, $i)."</b>"; echo " de type <i>".oci_field_type($idRequete, $i)."</i>"; echo " de longueur <i>".oci_field_size($idRequete, $i)."</i><br />"; } } ?>

10. Lutilisation des bases de donnes

Les numros de version


La fonction voque ici nest pas dune utilisation trs courante, mais pourra ventuellement vous servir si vous tes amen utiliser des instructions avances de la base de donnes Oracle (instructions implmentes dans des versions rcentes, par exemple).

oci_server_version() (ociServerVersion() PHP4)


Retourne le numro de version du serveur Oracle. Syntaxe $idBaseDonnees retour string oci_serveur_version(resource $idBaseDonnees) Identifiant de connexion une base de donnes tel que retourn par oci_connect(), oci_new_connect() ou oci_pconnect(). Numro de version du serveur.

La chane retourne sera de la forme :


Oracle Database 10g Release 10.1.0.2.0 - Production

10.12. SQLite
A la diffrence des autres bases de donnes prsentes, SQLite est totalement intgre PHP 5.

Installation
Comme SQLite est intgre PHP 5, la procdure dinstallation est extrmement facile vu quil ny a rien faire.

Installer SQLite pour PHP 4 (ou 3) Sous windows, il vous suffit de rcuprer le fichier php_sqlite.dll disponible sur le cdrom et de charger la librairie.

812

SQLite

Utilisation
Comme indiqu dans le chapitre dintroduction, lutilisation basique de la base de donnes sopre selon le schma suivant :
j j j

Connexion grce aux fonctions sqlite_open() ou sqlite_popen(). Soumission de la requte via la fonction sqlite_query(), sqlite_array_query() ou
sqlite_unbuffered_query().

10. Lutilisation des bases de donnes

Dconnexion grce la fonction sqlite_close().

Connexion
Comme pour toute base de donnes avant mme de pouvoir effectuer une requte, une connexion doit tre tablie avec la base de donnes.

sqlite_open()
tablit une connexion (non persistante) avec le serveur de bases de donnes. La base de donnes est cre si elle nexiste pas dj. Syntaxe $nomFichier resource sqlite_open(string $nomFichier [, int $mode [, string &$messageErreur]]) Nom du fichier reprsentant la base de donnes. Si le fichier nexiste pas il est cre (et la base de donnes associe galement). Le chemin peut tre relatif ou absolu, assurer vous davoir lautorisation en criture dans le rpertoire o vous voulez crer le fichier. A ce jour cet argument est ignor, il est cens dfinir le mode daccs a la base de donnes. La syntaxe est celle du monde Unix (cf. chmod) par dfaut sa valeur est 0666 (lecture et criture pour tous), on pourrait autoriser la lecture seule pour tous par la valeur 0444. Message derreur expliquant pourquoi la base de donnes na pu tre ouverte. Identifiant de connexion au serveur de bases de donnes, ou FALSE en cas dchec.

$mode

&$messageErreur retour

Base de donnes en mmoire Vous pouvez crer une base de donnes en mmoire en remplaant le nom du fichier par :memory: mais attention cela ne peut servir que pour une base de donnes temporaire vu quelle sera efface ds la fin du script en cours.
Lutilisation dune connexion persistante requiert, la place, lappel la fonction sqlite_popen().

813

Chapitre 10

Lutilisation des bases de donnes

sqlite_popen()
tablit une connexion persistante avec le serveur de bases de donnes. Si une connexion persistante est disponible, elle sera utilise ; sinon, une nouvelle connexion persistante sera cre. Syntaxe $nomFichier resource sqlite_popen(string $nomFichier [, int $mode [, string &$messageErreur]]) Nom du fichier reprsentant la base de donnes. Si le fichier nexiste pas il est cre (et la base de donnes associe galement). Le chemin peut tre relatif ou absolu, assurer vous davoir lautorisation en criture dans le rpertoire o vous voulez crer le fichier. A ce jour cet argument est ignor, il est cens dfinir le mode daccs a la base de donnes. La syntaxe est celle du monde Unix (cf. chmod) par dfaut sa valeur est 0666 (lecture et criture pour tous), on pourrait autoriser la lecture seule pour tous par la valeur 0444. Message derreur expliquant pourquoi la base de donnes na pu tre ouverte. Identifiant de connexion au serveur de bases de donnes, ou FALSE en cas dchec.

10. Lutilisation des bases de donnes

$mode

&$messageErreur retour

Excution de la requte SQL


Pour excuter une requte SQL, il y a diffrentes mthode en fonction de lutilisation du rsultat. Pour une requte qui retourne un nombre consquant de lignes (plus de 45), lutilisation de sqlite_unbuffered_query() est conseille et lest encore plus si lon veut parcourir une une les lignes du rsultat. La fonction sqlite_query() quand elle lance une requte sur la base de donnes et retourne un rsultat plus manipulable que sqlite_unbuffered_query() car lensemble des lignes est mis en mmoire, on peut en connatre le nombre exact ou faire des marches arrires.

sqlite_query()
Excute une requte SQL. Cette fonction est idale pour faire des mises jour de tables mais pour un SELECT retournant de nombreux rsultats, la fonction sqlite_unbuffered_query() est plus approprie. Syntaxe resource sqlite_query((string $requete, resource $idConnexion) resource sqlite_query(resource $idConnexion, string $requete) $requete $idConnexion retour Requte SQL. Identifiant de connexion une base de donnes tel que retourn par sqlite_open() ou sqlite_popen(). Identifiant de requte SQL, ou FALSE en cas dchec.

814

SQLite

sqlite_unbuffered_query()
Excute une requte SQL sans mise en mmoire du rsultat. Cette fonction est particulirement adaptes pour un parcours unique dun ensemble de lignes. Syntaxe resource sqlite_unbuffered_query(string $requete, resource $idConnexion) resource sqlite_unbuffered_query(resource $idConnexion, string $requete) $requete $idConnexion retour Requte SQL. Identifiant de connexion une base de donnes tel que retourn par sqlite_open() ou sqlite_popen(). Identifiant de requte SQL, ou FALSE en cas dchec.

10. Lutilisation des bases de donnes

Vous serrez certainement ammens vouloir plus de flexibilit et pouvoir accder differentes lignes du rsultat dans un ordre diffrent de lordre de sortie. Pour cela vous mettrez probablement les donnes dans un tableau. La fonction sqlite_array_query() fait exactement ce travail pour vous mais de faon plus rapide, elle retourne un tableau des lignes du rsultat. Mais attention, ces oprations sont extremement coteuses en mmoire, il faut donc utiliser ces mthodes que trs ponctuellement pour des rsultats de moins de 45 lignes environ.

sqlite_array_query()
Excute une requte SQL et stocke le rsultat dans un tableau. Syntaxe resource sqlite_array_query(string $requete, resource $idConnexion [, int $typeResultat [, boolean $decodeBinaire]]) resource sqlite_array_query(resource $idConnexion, string $requete [, int $typeResultat [, bool $decodeBinaire]]) $requete $idConnexion $typeResultat Requte SQL. Identifiant de connexion une base de donnes tel que retourn par sqlite_open() ou sqlite_popen(). Par dfaut cette valeur est mise a SQLITE_BOTH qui signifie que les indices du tableau seront le numro et le nom de colonne. Pour navoir que le numro de colonne il suffit de mettre SQLITE_NUM et pour le nom de colonne, SQLITE_ASSOC. Par dfaut (TRUE) PHP dcodera le rsultat binaire si il a t encod par sqlite_escape_string(). Identifiant de requte SQL, ou FALSE en cas dchec.

$decodeBinaire retour

815

Chapitre 10

Lutilisation des bases de donnes

Dans le cas dune requte retournant un rsultat (typiquement une requte SELECT), il faudra galement analyser le rsultat. Mais nous verrons cela un peu plus loin.

Dconnexion
10. Lutilisation des bases de donnes
Pour vous dconnecter opration thoriquement facultative mais toutefois vivement conseille , vous disposez de la fonction sqlite_close().

sqlite_close
Met fin la connexion la base de donnes et libre les ressources associes. Syntaxe $idConnexion void sqllite_close(resource $idConnexion) Identifiant de connexion une base de donnes tel que retourn par sqlite_open() ou sqlite_popen(). Si la connexion tait persistante, elle est frme et retire de la liste des connexions persistantes.

Lecture des enregistrements


Dans ce premier exemple nous allons juste nous connecter la base de donnes, crer une table, y insrer une donne et la retrouver par trois requtes SQL successives. Nous avons vu les fonctions douverture, de fermeture et de requte, voyons une fonction qui nous manque pour le cours exemple qui suit.

sqlite_fetch_array()
Retourne la ligne courante du rsultat dune requte sous la forme dun tableau, le curseur passe la ligne suivante une fois la fonction trmine. Les lments pourront tre rcuprs soit par leur indice de colonne, soit par le nom de colonne. Syntaxe $idRequete $typeResultat array sqlite_fetch_array(resource $idRequete [, int $typeResultat [, booleanl $decodeBinaire]]) Identifiant de la requte. Par dfaut cette valeur est mise a SQLITE_BOTH qui signifie que les indices du tableau seront le numro et le nom de colonne. Pour navoir que le numro de colonne il suffit de mettre SQLITE_NUM et pour le nom de colonne, SQLITE_ASSOC. Par dfaut (TRUE) PHP dcodera le rsultat binaire si il a t encod par sqlite_escape_string(). Un tableau reprsentant la ligne suivante du resultat en cours de lecture.

$decodeBinaire retour

816

SQLite

Listing 10.77 : sqlite_open.php


<?php // Ouverture et creation de la base de donnees maBaseDeDonnees $bd = sqlite_open(maBaseDeDonnees, 0666, $sqliteerror) or die($sqliteerror); // Creation de la table maTable caracterisee par deux colonnes, maColonne1 dentier // et maColonne2 de chaines dau plus 25 caracteres sqlite_query($bd, CREATE TABLE maTable (maColonne1 int, maColonne2 varchar(16))); // Insertion de donnees sqlite_query($bd, "INSERT INTO maTable VALUES (12, toto)"); // Recherche des donnees $result = sqlite_query($bd, select * from maTable); // Recuperation de la premiere ligne de resultat $ligne = sqlite_fetch_array($result); // Affichage de la ligne par les indices de colonnes echo($ligne[0].":".$ligne[1]."<br />\n"); // Affichage de la ligne par les noms de colonnes echo($ligne[maColonne1].":".$ligne[maColonne2]."<br />\n"); sqlite_close($bd); ?>

10. Lutilisation des bases de donnes

La fonction sqlite_current() trs similaire a sqlite_fetch_array() permet de mettre une ligne dans un tableau sans passer la ligne suivante. Cette fonction ne fonctionnera pas si vous avez utilis sqlite_unbuffered_query().

sqlite_current()
Retourne la ligne courante du rsultat dune requte sous la forme dun tableau sans dplacer le curseur. Les lments pourront tre rcuprs soit par leur indice de colonne, soit par le nom de colonne. Syntaxe $idRequete $typeResultat array sqlite_current(resource $idRequete [, int $typeResultat [, boolean $decodeBinaire]]) Identifiant de la requte. Par dfaut cette valeur est mise a SQLITE_BOTH qui signifie que les indices du tableau seront le numro et le nom de colonne. Pour navoir que le numro de colonne il suffit de mettre SQLITE_NUM et pour le nom de colonne, SQLITE_ASSOC. Par dfaut (TRUE) PHP dcodera le rsultat binaire si il a t encod par sqlite_escape_string(). Un tableau reprsentant la ligne suivante du resultat en cours de lecture.

$decodeBinaire retour

Pour ne pas avoir crer un tableau lorsque lon veux rcuperer quun seul champ dune table (par exemple lidentifiant lors dune requte du type SELECT id FROM maTable, la fonction

817

Chapitre 10

Lutilisation des bases de donnes

sqlite_fetch_single() ou sqlite_fetch_string() qui est un alias, permet de rcuprer directement le premier champ et de passer la ligne suivante.

10. Lutilisation des bases de donnes

sqlite_fetch_single(), sqlite_fetch_string()
Permet de rcuprer directement la valeur du premier champ dun rsultat. Syntaxe $idRequete $decodeBinaire retour string sqlite_fetch_single(resource $idRequete [, boolean $decodeBinaire]]) Identifiant de la requte. Par dfaut (TRUE) PHP dcodera le rsultat binaire si il a t encod par sqlite_escape_string(). La valeur du premier champ de la ligne en cours.

Listing 10.78 : sqlite_fetch_single.php


<?php // Ouverture et creation de la base de donnees test $bd = sqlite_open(test, 0666, $sqliteerror) or die($sqliteerror); // Creation de la table maTable sqlite_query($bd, CREATE TABLE maTable (maColonne1 varchar(25), maColonne2 varchar(16))); // Insertion de donnees sqlite_query($bd, "INSERT INTO maTable VALUES (Laurent, Guedon)"); sqlite_query($bd, "INSERT INTO maTable VALUES (Pierre-Emmanuel, Muller)"); sqlite_query($bd, "INSERT INTO maTable VALUES (Damien, Heute)"); sqlite_query($bd, "INSERT INTO maTable VALUES (Thomas, Heute)"); // Recherche des donnees $result = sqlite_unbuffered_query($bd, select * from maTable); echo sqlite_fetch_single($result, SQLITE_NUM); echo sqlite_fetch_single($result, SQLITE_NUM); echo sqlite_fetch_single($result); echo sqlite_fetch_single($result); sqlite_close($bd); ?>

Le rsultat attendu est le suivant : (au formattage de texte prs)


Laurent Pierre-Emmanuel Damien Thomas

Si une ligne possde de nombreuses colonnes ou est particulirement volumineuse (avec des champs binaires par exemple) il est avantageux de ne pas charger toute la ligne mais seulement la colonne intresssante.

818

SQLite

sqlite_column()
Retourne le contenu de la colonne de la ligne courante. Syntaxe $idRequete $indiceOuNom $decodeBinaire retour mixed sqlite_column(resource $idRequete, mixed $indiceOuNom [, boolean $decodeBinaire]) Identifiant de requte. Numro de colonne ou son nom. Par dfaut (TRUE) PHP dcodera le rsultat binaire si il a t encod par sqlite_escape_string(). Le contenu de la colonne demande.

10. Lutilisation des bases de donnes

Pour parcourir un ensemble de rsultats, la fonction sqlite_has_more() permet de savoir sil reste des lignes en attente dtre traites.

sqlite_has_more()
Cette fonction permet lors du parcours dun rultat savoir si il reste des lignes parcourir. Syntaxe $idRequete retour boolean sqlite_has_more(resource $idRequete) Identifiant de requte. TRUE si il reste des lignes a analyser.

Listing 10.79 : sqlite_unbuffered_query.php


<?php // Ouverture et creation de la base de donnees test $bd = sqlite_open(test, 0666, $sqliteerror) or die($sqliteerror); // Creation de la table maTable sqlite_query($bd, CREATE TABLE maTable (maColonne1 varchar(25), maColonne2 varchar(16))); // Insertion de donnees sqlite_query($bd, "INSERT INTO maTable VALUES (Laurent, Guedon)"); sqlite_query($bd, "INSERT INTO maTable VALUES (Pierre-Emmanuel, Muller)"); sqlite_query($bd, "INSERT INTO maTable VALUES (Damien, Heute)"); sqlite_query($bd, "INSERT INTO maTable VALUES (Thomas, Heute)"); // Recherche des donnees $result = sqlite_unbuffered_query($bd, select * from maTable); // Recuperation une a une des lignes de resultat while (sqlite_has_more($result)) { $ligne = sqlite_fetch_array($result, SQLITE_NUM); echo($ligne[0]." ".$ligne[1]."<br />\n"); } sqlite_close($bd); ?>

819

Chapitre 10

Lutilisation des bases de donnes

Dplacement du curseur
Le parcours dune table seffectue avec un curseur. La plupart des fonctions de lecture de lignes dplacent le curseur la ligne suivante. Il peut-tre intressant de dplacer le curseur de manire plus contrle. Pour dplacer le curseur sur la ligne suivante, il suffit de faire appel sqlite_next().

10. Lutilisation des bases de donnes

sqlite_next()
Cette fonction permet de dplacer le curseur la ligne suivante. Elle ne fonctionnera pas si vous avez utilis sqlite_unbuffered_query(). Syntaxe $idRequete retour boolean sqlite_next(resource $idRequete) Identifiant de requte. TRUE si il y avait une ligne suivante, FALSE si cetait la dernire ligne.

sqlite_rewind()
Cette fonction permet de rammener le curseur la premire ligne. Elle ne fonctionnera pas si vous avez utilis sqlite_unbuffered_query(). Syntaxe $idRequete retour boolean sqlite_rewind(resource $idRequete) Identifiant de requte. FALSE si le rsultat de la requte est vide.

sqlite_seek()
Cette fonction permet dammener le curseur la ligne voulue. Elle ne fonctionnera pas si vous avez utilis sqlite_unbuffered_query(). Syntaxe $idRequete $numeroLigne retour boolean sqlite_seek(resource $idRequete, int $numeroLigne) Identifiant de requte. Numro de la ligne o ammener le curseur. FALSE si la ligne nexiste pas, TRUE sinon.

Gestion des erreurs


Lors de louverture dune base de donnes leventuel message derreur peut-tre rcupr en passant une chane de caractre par rfrence. Deux autres fonctions servent la gestion des

820

SQLite

erreurs, la premire permet de rcuprer le code derreur de la dernire opration effectue sur une connexion.

sqlite_last_error()
Retourne le code derreur de la dernire opration effectue sur une connexion donne. (0 si il ny a pas eu derreur) Syntaxe $idConnexion retour resource sqlite_last_error(resource $idConnexion) Identifiant de connexion une base de donnes tel que retourn par sqlite_open() ou sqlite_popen(). Code derreur.

10. Lutilisation des bases de donnes

A partir de ce code, il est possible davoir une explication textuelle grce sqlite_error_string().

sqlite_error_string()
Retourne le message derreur correspondant au code fourni. Syntaxe $codeErreur retour string sqlite_error_string(int $codeErreur) Code derreur tel que retourn par sqlite_last_error(). Message derreur.

Appliquer une fonction automatiquement


Particularit de SQLite, il est possible dappliquer une fonction PHP sur le rsultat au niveau de la requte. Avant mme de voir la description de sqlite_create_function(), voici un petit exemple lutilisant. Le programme suivant ouvre une connexion avec une base de donnes en mmoire, cre une table et y insre des donnes. Ensuite y est dfini la fonction nomComplet() qui concatne deux paramtres spar dun espace. Lappel a sqlite_create_function() permet de dclarer SQLite une fonction nom() lie nomComplet() et qui prend deux arguments en paramtre. La requte est particulire, on applique la fonction nom() sur les deux colonnes ce qui a pour consquence de navoir plus quune colonne rsultat et ainsi il suffit de faire appel sqlite_fetch_single() pour rcuprer le rsultat voulu.

Listing 10.80 : sqlite_create_function.php


<?php // Ouverture et creation de la base de donnees $bd = sqlite_open(:memory:, 0666, $sqliteerror) or die($sqliteerror); // Creation de la table maTable

821

Chapitre 10

Lutilisation des bases de donnes

sqlite_query($bd, CREATE TABLE maTable (maColonne1 varchar(25), maColonne2 varchar(16))); // Insertion de donnees sqlite_query($bd, "INSERT sqlite_query($bd, "INSERT sqlite_query($bd, "INSERT sqlite_query($bd, "INSERT

10. Lutilisation des bases de donnes

INTO INTO INTO INTO

maTable maTable maTable maTable

VALUES VALUES VALUES VALUES

(Laurent, Guedon)"); (Pierre-Emmanuel, Muller)"); (Damien, Heute)"); (Thomas, Heute)");

// Fonction de creation du nom complet function nomComplet($prenom, $nom) { return $prenom." ".$nom; } // Declaration a SQLite de la fonction nomComplet sqlite_create_function($bd, nom, nomComplet, 2); // Recherche des donnees en appliquant la fonction nom $result = sqlite_unbuffered_query($bd, select nom(maColonne1, maColonne2) from maTable); // Recuperation une a une des lignes de resultat while (sqlite_has_more($result)) { echo sqlite_fetch_single($result, SQLITE_NUM)."<br />\n"; } sqlite_close($bd); ?>

Le rsultat attendu est le suivant :


Laurent Guedon Pierre-Emmanuel Muller Damien Heute Thomas Heute

sqlite_create_function()
Permet de dclarer une fonction appele directement dans la requte SQL. Syntaxe $idConnexion $nomFonction $fonction $nombreArguments void sqlite_create_function(resource $idConnexion, string $nomFonction, string mixed $fonction [, int $nombreArguments]) Identifiant de connexion une base de donnes tel que retourn par sqlite_open() ou sqlite_popen(). Nom de la fonction laquelle on veut associer la fonction PHP. Nom de la fonction que vous avez dfini prcdement. Nombre darguments que prend la fonction.

822

SQLite

En plus de traiter les lignes, il est possible de dfinir une fonction qui aura pour objectif de traiter lensemble des lignes.

sqlite_create_aggregate()
Permet de dclarer une fonction traitant lensemble des lignes du rsultat. Syntaxe void sqlite_create_aggregate(resource $idConnexion, string $nomFonction, string mixed $fonction, mixed $fonctionFinale [, int $nombreArguments]) Identifiant de connexion une base de donnes tel que retourn par sqlite_open() ou sqlite_popen(). Nom de la fonction laquelle on veut associer la fonction PHP. Nom de la fonction que vous avez dfini prcdement. Nom de la fonction par laquelle passer lensemble du rultat. Nombre darguments que prend la fonction.

10. Lutilisation des bases de donnes

$idConnexion $nomFonction $fonction $fonctionFimale $nombreArguments

Voici un exemple qui ne sert rien dautre que de mieux comprendre :

Listing 10.81 : sqlite_create_aggregate.php


<?php // Ouverture et creation de la base de donnees test $bd = sqlite_open(:memory:, 0666, $sqliteerror) or die($sqliteerror); // Creation de la table maTable sqlite_query($bd, CREATE TABLE maTable (maColonne1 varchar(25), maColonne2 varchar(16)));

// Fonction de creation du nom complet function nomComplet(&$cumul, $prenom, $nom) { $cumul[] = $prenom." ".$nom; } function cumulNom(&$cumul) { return $cumul[0].":".$cumul[1].":".$cumul[2].":".$cumul[3]; }

// Declaration a SQLite de la fonction nomComplet sqlite_create_aggregate($bd, nom, nomComplet, cumulNom, 2); // Insertion de donnees sqlite_query($bd, "INSERT INTO maTable VALUES (Laurent, Guedon)"); sqlite_query($bd, "INSERT INTO maTable VALUES (Pierre-Emmanuel, Muller)");

823

Chapitre 10

Lutilisation des bases de donnes

sqlite_query($bd, "INSERT INTO maTable VALUES (Damien, Heute)"); sqlite_query($bd, "INSERT INTO maTable VALUES (Thomas, Heute)"); // Recherche des donnees en appliquant la fonction nom $result = sqlite_unbuffered_query($bd, select nom(maColonne1, maColonne2) from maTable);

10. Lutilisation des bases de donnes

echo sqlite_fetch_single($result, SQLITE_NUM)."<br />\n"; sqlite_close($bd); ?>

Le rsultat obtenu est le suivant :


Laurent Guedon:Pierre-Emmanuel Muller:Damien Heute:Thomas Heute

Quelques explications peuvent tre utiles. Chacune des entres est soumise la fonction nomComplet() en plus dune rfrence vers une variable ($cumul dans lexemple). Cette dernire permet de garder un pointeur vers un objet (ici un simple tableau). la fin du traitement de chacune des lignes ce mme pointeur est fourni la fonction cumulNom() qui est charge deffectuer les dernires oprations sur lobjet. Bien sur dans lexemple on aurait pu faire bien plus simple, mais a naurait pas t drle...

Exemples dapplications
Compteur de clics
Une application courante dutilisation des bases de donnes, et simple mettre en uvre, consiste crer un compteur de clics. En effet, peut-tre souhaitez-vous proposer, sur votre site, un certain nombre de liens vers des sites Internet (annuaire web) ou vers des fichiers (bibliothques de scripts). Peut-tre que certains (ou la totalit) de ces liens sont proposs par un partenaire. Bref, tout cela vous incite savoir quelles sont les pages les plus frquemment consultes (pour connatre les centres dintrt des visiteurs) et combien de visiteurs vous avez redirigs vers votre sponsor. La mthode la plus classique consiste stocker en base de donnes lensemble des liens ainsi proposs, et remplacer les traditionnels liens de la forme http://www.domaine.com par un lien vers un script charg dincrmenter le compteur correspondant au site indiqu, et de rediriger le client vers le site grce la fonction header().

Vous pouvez vous reporter lannexe "Les en-ttes" pour plus de renseignements sur la redirection.
Pour notre exemple, nous utiliserons une table appele url contenant trois champs :
j j

urlid, identifiant de lURL (champ auto-incrment) ; url, lURL proprement dite ;

824

SQLite

nbclic, le nombre de clics.

Le script de redirection (appel ici compteurclic_redirection.php) devra alors accepter un paramtre (urlid) et devra, partir de ce paramtre, dterminer quelle est la valeur du champ url, incrmenter nbclic pour cette URL, et rediriger vers url. Les appels ce script auront alors la forme http://localhost/compteurclic_redirection.php?urlid=3 (pour accder lURL ayant lidentifiant 3). supposer que lURL 3 corresponde au site http://www.sqlfacile.com cela signifie que le lien <a href="http://www.sqlfacile.com "> devra tre remplac par <a href="compteurclic_redirection.php?urlid=3> si lon souhaite en compter le nombre de clics. Concrtement, cette table pourra tre cre et alimente avec la fonction CC_initialiseBD() du script suivant :

10. Lutilisation des bases de donnes

Listing 10.82 : compteurclic_bd_inc.php (dbut)


<?php /** * Fonction de connexion une base de donnes * * @return resource Identifiant de connexion */ function CC_connexion() { $idConnexion = sqlite_open(BaseDeDonneesCompteurClics, 0666, $sqliteerror); if (!$idConnexion) return FALSE; return $idConnexion; } /** * Fonction de deconnexion. * (Ne fait rien sachant que la fonction * de connexion tablit une connexion persistante) */ function CC_deconnexion() { return TRUE; } /** * Fonction charg de crer et dalimenter * la table "compteur de clics" **/ function CC_initialiseBD($idConnexion, $table) { // Cration de la table $requete = "DROP TABLE $table"; @sqlite_query($idConnexion, $requete); $requete = "CREATE TABLE $table (".

825

Chapitre 10

Lutilisation des bases de donnes

"urlId INTEGER ". "AUTO_INCREMENT PRIMARY KEY,". "url VARCHAR(128) NOT NULL,". "nbclic INTEGER DEFAULT 0,". "UNIQUE(url))"; if (!sqlite_query($idConnexion, $requete)) return FALSE;

10. Lutilisation des bases de donnes

// Alimentation de la table $requete = "INSERT INTO $table (url)". " VALUES (http://www.php.net)"; if (!sqlite_query($idConnexion, $requete)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.phpfacile.com)"; if (!sqlite_query($idConnexion, $requete)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.sqlfacile.com)"; if (!sqlite_query($idConnexion, $requete)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.xmlfacile.com)"; if (!sqlite_query($idConnexion, $requete)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.ootoogo.com)"; if (!sqlite_query($idConnexion, $requete)) return FALSE; return TRUE; } ?>

La lecture de la liste des liens disponibles en base de donnes pourra se faire via la fonction CC_recupereLiens() du script suivant :

Listing 10.83 : compteurclic_bd_inc.php (milieu)


<?php /** * Fonction retournant les informations de liens * sous forme dun tableau associatif possedants * les cls * - "lien" associ au tableau des liens hypertextes * - "nbclic" associ au tableau des nombres de clics **/ function CC_recupereLiens($idConnexion, $table) { // Nom du script charg du comptage et de la redirection $script = "compteurclic_redirection.php"; // Requte SELECT $requete = "SELECT * FROM $table";

826

SQLite

$idResultat = sqlite_query($idConnexion, $requete); // Rcupration des enregistrements les uns aprs les autres while ($enreg = sqlite_fetch_array($idResultat)) { $liens["lien"][] = "<a href=\"$script?urlid=". $enreg["urlId"]."\">". $enreg["url"]."</a>"; $liens["nbclic"][] = $enreg["nbclic"]; } return $liens; }

10. Lutilisation des bases de donnes

Laffichage des liens consiste uniquement mettre en page le contenu du tableau ainsi rcupr (voir la fonction du script compteurclic_html_inc.php). Comme cela a t prcis, le lien <a href="http://www.sqlfacile.com">http://www .sqlfacile.com</a> a t remplac par <a href="compteurclic_redirection .php?urlid=3">http://www.sqlfacile.com </a>. La redirection vers le site www.sqlfacile .com est donc la charge du script compteurclic_redirection.php.

Listing 10.84 : compteurclic_redirection.php


<?php // Paramtres du script require_once("compteurclic_bd_inc.php"); $table = "compteurclic"; // Connexion la base de donnes $idConnexion = @CC_connexion(); if (!$idConnexion) { die("<b>Impossible de se connecter la base de donnes</b>"); } // Rcupration de lurl et incrmentation du compteur // pour lurl dindentifiant pass en paramtre de ce script // par la mthode GET $url = @CC_recupereUrl($idConnexion, $_GET["urlid"]); // Deconnexion @CC_deconnexion(); // Cest lheure de la redirection if ($url) { header("Location: $url"); } else { echo "Dsol, nous ne pouvons vous proposer ce lien"; }?>

Ce script appelle principalement la fonction CC_recupereUrl() suivante :

827

Chapitre 10

Lutilisation des bases de donnes

Listing 10.85 : compteurclic_bd_inc.php (fin)


<?php /** * Fonction rcuprant une url partir de son identifiant * et incrmentant le compteur de clics **/ function CC_recupereUrl($idConnexion, $urlid) { global $table; // Rcupre lurl $requete = "SELECT * FROM $table WHERE urlid=$urlid"; $idResultat = sqlite_query($idConnexion, $requete); if ($enreg = sqlite_fetch_array($idResultat)) { $url = $enreg["url"]; // Incrmente le compteur $requete = "UPDATE $table SET nbclic=nbclic+1 WHERE urlid=$urlid"; sqlite_query($idConnexion, $requete); } else { $url = FALSE; } return $url; }?>

10. Lutilisation des bases de donnes

Utilisation du bouton retour Si, aprs avoir suivi un lien, vous revenez sur la page compteurclic.php en utilisant le bouton retour (back), le contenu de la page ne sera pas ractualis. Par consquent, le nombre de visites affich ne sera pas correct. Noubliez donc pas, dans ce cas, de rafrachir (bouton actualiser) la page.

SuperTheque
Lessentiel du code de lapplication a t prsent en introduction de ce chapitre. Il ne restait plus qua connatre les fonctions SQLite pour implmenter linterface RessourceInterface cest dsormais chose faite:

Listing 10.86 : RessourceSQLite_class.php


<?php include_once("RessourceInterface_class.php"); include_once(dirname(__FILE__)."/../config/sqlite_cfg.php"); /** * RessourceSQLite_class.php * Classe dacces a une base de donnees SQLite

828

SQLite

* Cette classe doit implementer toutes les methodes de linterface * RessourceInterface. * Compatibilite: PHP 5 */ class Ressource implements RessourceInterface { var $idConnexion;

10. Lutilisation des bases de donnes

public function connexion() { global $sqlite_base; if (!isset($this->idConnexion)) { $idConnexion = sqlite_popen($sqlite_base); if (!$idConnexion) return FALSE; $this->idConnexion = $idConnexion; } return TRUE; } public function deconnexion() { // Rien a faire, il sagit dune connexion persistante } public function reset() { $requete = "DROP TABLE types"; $idResultat = @sqlite_query($requete, $this->idConnexion); // Pas de raison de retourner un erreur // si la suppression echoue (si la table nexiste pas) $requete = "CREATE TABLE types (". "id INTEGER PRIMARY KEY,". "type VARCHAR(255))"; $idResultat = sqlite_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; $types = array("Album", "Film", "Livre", "Musique"); foreach ($types as $type) { $requete = "INSERT INTO types (type) VALUES ($type)"; $idResultat = sqlite_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; } $requete = "DROP TABLE articles"; $idResultat = @sqlite_query($requete, $this->idConnexion); // Pas de raison de retourner un erreur // si la suppression echoue (si la table nexiste pas) $requete = "CREATE TABLE articles (". "id INTEGER PRIMARY KEY,".

829

Chapitre 10

Lutilisation des bases de donnes

"albumId INTEGER,". "titre VARCHAR(255),". "typeId INTEGER,". "commentaire VARCHAR(255))"; $idResultat = sqlite_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; }

10. Lutilisation des bases de donnes

public function addArticle($albumId, $titre, $typeId, $commentaire) { $requeteDebut = "INSERT INTO articles (albumId, titre, typeId"; $requeteFin = ") VALUES ($albumId,". "".sqlite_escape_string($titre).",". "$typeId"; if ($commentaire != "") { $requeteDebut .= ",commentaire"; $requeteFin .= ",".sqlite_escape_string($commentaire).""; } $requete = $requeteDebut . $requeteFin . ")"; $idResultat = sqlite_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; } public function getArticle($articleId) { $requete = "SELECT * FROM articles WHERE id=$articleId"; $idResultat = sqlite_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; $article = NULL; if ($enreg = sqlite_fetch_array($idResultat)) { $article = $this->enreg2Article($enreg); } return $article; } public function getArticles(Filtre $filtre, Plage $plage, Tri $tri) { $requete = "SELECT * FROM articles"; if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". sqlite_escape_string($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL.

830

SQLite

" AND typeId=".$filtre->getTypeId(); } if ($tri->getSens() == -1) { $triSQL = "ORDER BY ".$tri->getChamp()." DESC"; } else if ($tri->getSens() == 1) { $triSQL = "ORDER BY ".$tri->getChamp()." ASC"; } $limiteSQL = "LIMIT ".$plage->getNbArticleMax(). " OFFSET ".$plage->getPremierArticle(); $requete = $requete." WHERE ".$conditionSQL." ". $triSQL." ".$limiteSQL; $idResultat = sqlite_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; $articles = NULL; while ($enreg = sqlite_fetch_array($idResultat)) { $articles[] = $this->enreg2Article($enreg); } return $articles; } public function getNbTotalArticles(Filtre $filtre) { $requete = "SELECT COUNT(*) FROM articles"; if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". sqlite_escape_string($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL. " AND typeId=".$filtre->getTypeId(); } $requete = $requete." WHERE ".$conditionSQL; $idResultat = sqlite_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; if ($enreg = sqlite_fetch_array($idResultat)) { return $enreg[0]; } else return FALSE; } public function getTypes() { $requete = "SELECT * FROM types";

10. Lutilisation des bases de donnes 831

Chapitre 10

Lutilisation des bases de donnes

$idResultat = sqlite_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; $types = NULL; while ($enreg = sqlite_fetch_array($idResultat)) { $types[$enreg["id"]] = $enreg["type"]; } return $types; } public function getAlbumTypeId() { // Avec SQLite les champs auto-incrementes commencent a 1 return 1; }

10. Lutilisation des bases de donnes

private function enreg2Article($enreg) { $article = new Article(); $article->setId($enreg["id"]); $article->setAlbumId($enreg["albumId"]); $article->setTitre($enreg["titre"]); $article->setTypeId($enreg["typeId"]); $article->setCommentaire($enreg["commentaire"]); return $article; } } ?>

Comme vous le constatez, la principale difficult nest pas tant au niveau des fonctions disponibles quau niveau de la construction des requtes SQL. La requte sera simple lorsquil ne sagit que de rcuprer un enregistrement identifi par la cl Id (comme cest le cas avec getArticle()) elle sera bien plus complexe sil sagit des rcuprer un ensemble denregistrements rpondant des critres prcis et tris (comme cest le cas avec getArticles()).

Requtes avec des apostrophes


Lors de la construction de la requte, il faut bien garder lesprit que lun des lments de la requte (typiquement un champ de type texte saisi par lutilisateur, comme ici le titre ou le commentaire) peut contenir une apostrophe qui pourrait tre confondu avec le dlimiteur de chane. Pensez donc bien faire un appel sqlite_escape_string() lorsque cela peut savrer ncessaire.

Affichage page par page


La meilleure faon avec SQLite pour nextraire quun sous-ensemble des enregistrements retourns par une requte SQL consiste utiliser les instructions LIMIT et OFFSET. LIMIT permet de prciser combien denregistrements doivent tre retourns et OFFSET partir duquel commencer (sachant que le premier enregistrement porte lindex 0).

832

SQLite

Ainsi, SELECT * FROM nomtable LIMIT 10 OFFSET 0; retourne les dix premiers enregistrements (de lindex 0 lindex 9) et SELECT * FROM nomtable LIMIT 20 OFFSET 10; retourne les vingt suivants (de lindex 10 lindex 29).

Tri
Modifier lordre daffichage des annonces nest pas non plus bien sorcier. Le tri peut seffectuer directement au niveau de la requte SQL, grce linstruction ORDER BY.

10. Lutilisation des bases de donnes

Moteur de recherche (ltre)


Pour filtrer, il suffit dutiliser linstruction WHERE. Dans notre cas, nous souhaitons autoriser lutilisation de jokers (comme %) afin, par exemple, de rechercher les titres commenant par une chane donne. Cest pourquoi, nous ne ferons pas un test de type titre=motcle mais titre LIKE motcle (o motcle pourrait avoir la valeur "La 7eme compagnie%").

En savoir plus...
Dans le cas dune requte mise en mmoire (cest dire sqlite_query() ou sqlite_array_query()), il est possible de connatre le nombre de ligne du rsultat.

sqlite_num_rows()
Permet de compter le nombre de lignes du rsultat. Syntaxe $idRequete retour int sqlite_num_rows(resource $idRequete) Identifiant de requte. Nombre de lignes du rsultat.

Il est galement possible de connatre le nombre de colonnes en faisant appel sqlite_num_fields().

sqlite_num_elds()
Permet de compter le nombre de colonnes du rsultat. Syntaxe $idRequete retour int sqlite_num_fields(resource $idRequete) Identifiant de requte. Nombre de colonnes du rsultat.

Pour connatre le nom dune colonne par son indice, il suffit de faire appel sqlite_field_name().

833

Chapitre 10

Lutilisation des bases de donnes

sqlite_eld_name()
Retourne le nom dune colonne Syntaxe int sqlite_field_name(resource $idRequete, int numeroColonne) Identifiant de requte. Numro de la colonne dont on veut le nom. Nom de la colonne. $idRequete $numeroColonne retour

10. Lutilisation des bases de donnes

Autre fonction trs utile, sqlite_last_insert_rowid() permet de connatre lidentifiant qui a t automatiquement attribu la dernire insertion avec une colonne auto-incrmente.

sqlite_last_insert_rowid()
Permet de rcuprer lidentifiant automatiquement attribu. Syntaxe $idConnexion retour int sqlite_last_insert_rowid(resource $idConnexion) Identifiant de connexion une base de donnes tel que retourn par sqlite_open() ou sqlite_popen(). Identifiant attribu.

Lors dune mise jour il peut tre utile de savoir combien de lignes ont t modifies en utilisant sqlite_changes().

sqlite_changes()
Retourne le nombre de lignes modifies par la dernire requte effectue sur la base de donnes dont lidentifiant est pass en paramtre. Syntaxe $idConnexion retour int sqlite_changes(resource $idConnexion) Identifiant de connexion une base de donnes tel que retourn par sqlite_open() ou sqlite_popen(). Nombre de lignes modifies.

Lorsque un accs la base de donnes doit-tre effectu, le serveur attend que le fichier soit libre (non utilis par un autre processus). Par dfaut au bout de soixante secondes, le serveur gnre une erreur. Il est possible de changer cette valeur en utilisant sqlite_busy_timeout().

834

SQLite

sqlite_busy_timeout()
Permet de dfinir le temps avant lequel le serveur de base de donnes gnre une erreur sil narrive pas accder au fichier. Syntaxe $idConnexion $temps void sqlite_busy_timeout(resource $idConnexion, int $temps) Identifiant de connexion une base de donnes tel que retourn par sqlite_open() ou sqlite_popen(). Temps en millisecond avant gnration dune erreur.

10. Lutilisation des bases de donnes

Grer lencodage
Pour encoder des donnes binaires (qui pourrait inclure le caractre NUL au milieu des donnes) il faut utiliser sqlite_udf_encode_binary().

sqlite_udf_encode_binary()
Encode la donne. Syntaxe $donnee retour string sqlite_udf_encode_binary(string $donnee) Donne encoder. Donne encode.

Lors de la rcupration de cette donne, il faut faire lopration inverse en utilisant sqlite_udf_decode_binary().

sqlite_udf_decode_binary()
Dcode la donne. Syntaxe $donnee retour string sqlite_udf_decode_binary(string $donnee) Donne dcoder. Donne dcode.

sqlite_escape_string() permet en outre dviter les problmes lis aux apostrophes.

835

Chapitre 10

Lutilisation des bases de donnes

sqlite_escape_string()
Double les apostrophes et rend les donnes binaires Syntaxe string sqlite_escape_string(string $donnee) Donne encoder. Donne encode. $donnee retour

10. Lutilisation des bases de donnes

A propos de SQLite
Il est possible de rcuprer des informations sur la bibliothque installe.

sqlite_libversion()
Retourne la version de SQLite utilise. Syntaxe retour string sqlite_libversion() Numro de version.

sqlite_libencoding()
Retourne lencodage utilis. (ISO-8859-1 ou UTF-8) Syntaxe retour string sqlite_libencoding() Encodage utilis (iso8859 ou utf8).

10.13. SQL Server (MS)


SQL Server est la solution de base de donnes propose par Microsoft pour ses systmes dexploitation Windows NT et XP.

Installation
Microsoft SQL Server nexiste, bien entendu, que sous Windows. Nous nous contenterons ici de dcrire une installation standard, sans prendre en compte les problmes doptimisation et de scurit. Le but tant que vous puissiez installer PHP et SQL Server sur des machines de test pour vous familiariser avec cet environnement avant de passer un serveur de bases de donnes destin la production.

836

SQL Server (MS)

Pr-requis
Pour commencer, vous devez vous procurer le CD-ROM dinstallation ou tlcharger une version dvaluation ladresse http://www.microsoft.com/sql/downloads/default.asp.

Installation du serveur de bases de donnes


Nous supposerons ici que le serveur de bases de donnes est install sur la mme machine que le serveur web. La version teste est la version Microsoft SQL Server 2000 de dmonstration. La premire des choses faire est de lancer le fichier autorun.exe de votre dossier.

10. Lutilisation des bases de donnes

Figure 10.39 : Dossier dinstallation

Il faut ensuite cliquer sur Composants de SQL Server 2000, puis Installer le serveur. Le programme dinstallation demandera alors si le serveur est installer sur la machine courante ou sur une machine distante. Ici, linstallation se fera sur la machine courante.

837

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

Figure 10.40 : Emplacement du serveur

Il faudra ensuite choisir entre la configuration par dfaut et la configuration personnalise. Nous prendrons celle par dfaut. Le nom et la socit de lutilisateur sont ensuite demands.

Figure 10.41 : Nom et socit

838

SQL Server (MS)

Nous choisirons ensuite dinstaller la fois le serveur et les outils clients.

10. Lutilisation des bases de donnes

Figure 10.42 : Type dinstallation

Les options dinstallation sont ensuite configurables. Nous garderons les valeurs par dfaut :

Figure 10.43 : Type dinstallation 2/2

839

Chapitre 10

Lutilisation des bases de donnes

Ladministrateur du service est dfinir : par dfaut, cela peut tre lutilisateur qui installe le serveur, ou bien un autre qui peut tre sur un domaine diffrent.

10. Lutilisation des bases de donnes

Figure 10.44 : Administrateur

Pour finir, il est demand de prciser le mode dauthentification. Il faut absolument mettre les deux modes dauthentification (SQL serveur et Windows), sinon la connexion par PHP ne fonctionnera pas.

Dmarrage du serveur de bases de donnes


Le serveur stant install en tant que service, son lancement est automatique.

Cration dune base


Pour crer une base de donnes, il faut tout dabord lancer le programme appel SQL Server Enterprise Manager, puis ouvrir les dossiers jusqu Bases de donnes. L, un clic bouton droit sur ce dossier fait apparatre un menu contextuel affichant Nouvelle base de donnes.

840

SQL Server (MS)

10. Lutilisation des bases de donnes

Figure 10.45 : Ajouter une base de donnes

Il suffit alors de donner un nom la base de donnes et, ventuellement, de modifier les chemins pour sauvegarder les donnes et les fichiers de traces.

Ajouter un utilisateur
Pour ajouter un utilisateur, il faut dabord crer une connexion. Vous devez alors saisir un nom, slectionner Authentification SQL Server, entrer un mot de passe, puis slectionner la base de donnes qui vous intresse (voir fig. 10.46). Ensuite, pour ajouter un utilisateur la base de donnes, il faut aller sur longlet Accs aux bases de donnes et cliquer sur les bases auxquelles vous souhaitez donner accs, puis choisir les droits daccs. Dans le cas prsent, public, db_owner, db_datareader et db_datawriter ont t slectionns.

841

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

Figure 10.46 : Ajout dune connexion

Figure 10.47 : Ajout dun utilisateur

842

SQL Server (MS)

Test du serveur de bases de donnes


Pour tester simplement que le serveur est bien install, il suffit de lancer lAnalyseur de requtes. Aprs avoir slectionn la bonne base dans le menu droulant, il suffit dcrire une ou plusieurs requtes puis de lancer lexcution par [F5] dans la fentre Requte. Normalement, un message apparatra dans la fentre de la requte.

10. Lutilisation des bases de donnes

Pour vrifier, il suffit daller ouvrir le rpertoire de la base de donnes, puis le rpertoire Tables utilisateur. Pour ouvrir la table prcdemment cre, il suffit de cliquer avec le bouton droit dessus et de faire Ouvrir. Le ou les enregistrements apparatront dans une nouvelle fentre.

Conguration de PHP avec support SQLServer


Lextension MS SQL nest disponible que sur les systmes Windows 32 bits. Pour les autres plateformes, il est tout de mme possible dinterroger une base de donnes MS SQL laide de lextension Sybase. Vous devez, dans un premier temps, vous assurer davoir un fichier php_mssql.dll (fourni aussi bien avec larchive du PHP Group quavec EasyPHP) dans le rpertoire de vos extensions PHP. Il vous suffit ensuite de modifier le fichier php.ini pour ajouter ou dcommenter une ligne.
extension=php_mssql.dll

Quelques paramtres sont configurables dans le fichier php.ini :


[MSSQL] ; Permet ou interdit les connexions persistantes. mssql.allow_persistent = On ; Nombre maximum de connexions persistantes (-1 pour illimit). mssql.max_persistent = -1 ; Nombre maximum de connexions persistantes et non persistantes ; (-1 pour illimit). mssql.max_links = -1 ; Svrit minimum des erreurs afficher. mssql.min_error_severity = 10 ; Svrit minimum des messages afficher. mssql.min_message_severity = 10 ; Compataibilit avec la version 3.0 de PHP mssql.compatability_mode = Off ; Plage valide 0 - 2147483647. ;mssql.textlimit = 4096 ; Plage valide 0 - 2147483647. ;mssql.textsize = 4096 Par dfaut = 4096.

Par dfaut = 4096.

; Limit le nombre denregistrement par groupe.

843

Chapitre 10

Lutilisation des bases de donnes

; 0 = tous les enregistrements dans le mme groupe. ;mssql.batchsize = 0

Vrication
10. Lutilisation des bases de donnes
Vous pouvez maintenant tester un script ne contenant que le code <?php phpinfo(); ?>. Vous devez apercevoir les lignes suivantes :

Figure 10.48 : phpinfo()

Utilisation
Lutilisation basique de la base de donnes sopre selon le schma suivant :
j j j

Connexion

grce

aux

fonctions

mssql_connect()

ou

mssql_pconnect()

et

mssql_select_db().

Soumission de la requte via la fonction mssql_query(). Dconnexion grce la fonction mssql_close() (dans le cas dune connexion non persistante).

Connexion
La connexion une base de donnes Microsoft SQL Server ncessite deux oprations. Il faut, dans un premier temps, se connecter au serveur de bases de donnes avec la fonction mssql_connect(); la slection de la base sopre dans un second temps avec mssql_select_db().

844

SQL Server (MS)

mssql_connect()
tablit une connexion (non persistante) avec le serveur de bases de donnes. Syntaxe $nomServeur $port $utilisateur $motDePasse retour resource mssql_connect([string $nomServeur [:$port] [, string $utilisateur [, $motDePasse]]]) Nom du serveur (par dfaut "localhost"). Port sur lequel la connexion au serveur de bases de donnes seffectue. Nom dutilisateur. Mot de passe de lutilisateur. Identifiant de connexion au serveur de bases de donnes, ou FALSE en cas dchec.

10. Lutilisation des bases de donnes

Lutilisation dune connexion persistante requiert, la place, lappel la fonction mssql_pconnect().

mssql_pconnect()
tablit une connexion persistante avec le serveur de bases de donnes. Si une connexion persistante est disponible, elle sera utilise ; sinon, une nouvelle connexion persistante sera cre. Syntaxe $nomServeur $port $utilisateur $motDePasse retour resource mssql_pconnect([string $nomServeur [:$port] [, string $utilisateur [, $motDePasse]]]) Nom du serveur (par dfaut "localhost"). Port sur lequel la connexion au serveur de bases de donnes seffectue. Nom dutilisateur. Mot de passe de lutilisateur. Identifiant de connexion au serveur de bases de donnes, ou FALSE en cas dchec.

mssql_select_db()
Slectionne une base de donnes. Syntaxe $baseDonnees boolean mssql_select_db(string $baseDonnees [, resource $idConnexion]) Nom de la base de donnes.

845

Chapitre 10

Lutilisation des bases de donnes

$idConnexion

Identifiant de connexion au serveur de bases de donnes tel que retourn par mssql_connect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. TRUE en cas de succs, FALSE sinon (ex. : base de donnes inexistante).

retour

10. Lutilisation des bases de donnes

Excution de la requte SQL


Lexcution dune requte SQL sopre par un simple appel mssql_query().

mssql_query()
Excute une requte SQL. Syntaxe $requete $idConnexion resource mssql_query(string $requete [, resource $idConnexion]) Requte SQL. Identifiant de connexion une base de donnes tel que retourn par mssql_connect() ou mssql_pconnect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Identifiant de requte SQL, ou FALSE en cas dchec.

retour

Dans le cas dune requte retournant un rsultat (typiquement une requte SELECT), il faudra galement analyser le rsultat. Mais nous verrons cela un peu plus loin.

Dconnexion
Pour se dconnecter opration thoriquement facultative mais toutefois vivement conseille , vous disposez de la fonction mssql_close().

mssql_close()
Met fin la connexion la base de donnes et libre les ressources associes. Syntaxe $idConnexion boolean mssql_close([resource $idConnexion]) Identifiant de connexion une base de donnes tel que retourn par mssql_connect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. TRUE si lopration a t effectue avec succs, FALSE en cas dchec.

retour

846

SQL Server (MS)

Premier exemple
Nous voil donc mme de construire notre premier script utilisant une base de donnes.

Vrifiez les paramtres Prenez garde ! Avant dexcuter ce script, assurez-vous que les paramtres prdfinis ne risquent pas de conduire la suppression des donnes dune de vos bases qui, par concidence, existerait dj.
Comme cela est fortement conseill, nous avons, ici, isol les paramtres de connexion dans un fichier aisment reprable.

10. Lutilisation des bases de donnes

Listing 10.87 : parametres_bd_inc.php


<?php // Paramtres de connexion la base de donnes // Nhsitez pas les modifier selon vos besoins $serveur $base $utilisateur $motDePasse ?> = = = = "localhost"; "maBase"; "Emma"; "emma";

Notre script principal sera donc :

Listing 10.88 : insert01.php


<?php // Paramtres du script require_once("parametres_bd_inc.php"); $table = "maTable"; // Inclusion du script contenant les fonctions require_once("insert01_bd_inc.php"); // Connexion la base de donnes $idConnexion = mssql_pconnect($serveur, $utilisateur, $motDePasse); if (!$idConnexion) { die("<b>Impossible de se connecter la base de donnes</b>"); } if (!mssql_select_db($base)) { die("<b>Impossible de se connecter la base de donnes</b>"); } // Appel de la fonction principale if (EX_initialiseBD($idConnexion, $table)) { echo "Voil, une nouvelle table avec quelques donnes, ".

847

Chapitre 10

Lutilisation des bases de donnes

"vous pouvez le vrifier avec votre client de base ". " de donnes ou via les scripts suivants."; } else { echo "La cration ou lalimentation de la table choue."; } // Pas de dconnexion dans le cas dune connexion persistante // mssql_close($idConnexion); ?>

10. Lutilisation des bases de donnes

et ncessitera :

Listing 10.89 : insert01_bd_inc.php


<?php /** * Fonction charge de crer et dalimenter une table * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_initialiseBD($idConnexion, $table) { // Supprime la prcdente table $requete = "DROP TABLE $table"; @mssql_query($requete, $idConnexion); // Cre la table $requete = "CREATE TABLE $table (filmId int ". " IDENTITY PRIMARY KEY,". "film VARCHAR(64))"; if (!mssql_query($requete, $idConnexion)) return FALSE; // Ajoute quelques donnes $requete = "INSERT INTO $table (film) VALUES (Forrest Gump)"; if (!mssql_query($requete, $idConnexion)) return FALSE; $requete = "INSERT INTO $table (film) VALUES (Matrix)"; if (!mssql_query($requete, $idConnexion)) return FALSE; $requete = "INSERT INTO $table (film) VALUES (La cit de la peur)"; if (!mssql_query($requete, $idConnexion)) return FALSE; return TRUE; } ?>

Les procdures stockes


Les procdures stockes offrent de multiples avantages, puisquelles permettent dexcuter plusieurs requtes en un seul appel (une seule interrogation du serveur de bases de donnes par

848

SQL Server (MS)

le serveur web). De plus, ces requtes ne sont analyses quune seule fois, et non chaque sollicitation, tout en permettant des appels successifs avec des paramtres diffrents. De ce fait, les procdures stockes permettent deffectuer des requtes plus rapidement. Lutilisation se justifie particulirement lorsque les mmes requtes sont excutes de nombreuses fois en ne changeant que quelques valeurs. Il est possible dcrire une requte pour produire une procdure stocke ; il est aussi possible dutiliser un outil daide fourni avec Microsoft SQL Server, plus prcisment dans le logiciel Enterprise Manager fourni avec SQL Server. Aprs avoir ouvert SQL Server Enterprise Manager, il faut choisir Outils>Assistants, ouvrir longlet Base de donnes , cliquer sur Assistant cration de procdure stocke puis OK.
Figure 10.49 :

10. Lutilisation des bases de donnes

Assistant

Il faut ensuite dfinir sur quelle base de donnes la procdure stocke doit sappliquer.
Figure 10.50 :

Base de donnes implique

Puis il faut dfinir la ou les tables concerne(s) ainsi que la manire dont elles le sont (Insertion, suppression et/ou mise jour). Dans notre exemple, nous voulons simplement crer une procdure pour insrer une URL dans la table compteurclic.

849

Chapitre 10

Lutilisation des bases de donnes

Figure 10.51 : Tables impliques

10. Lutilisation des bases de donnes

Il est ensuite possible de modifier les proprits dune procdure stocke pour ne slectionner que les champs que lon veut passer en paramtre. (Ici, les deux autres champs peuvent tre remplis par dfaut par la base de donnes.)
Figure 10.52 :

Dtails

Il est galement possible dintervenir sur la requte SQL. Dans notre cas, puisquil ne sagit que dune requte dinsertion, cela sapparente plus une requte prpare qu une vritable procdure stocke. Mais quimporte ! titre dexemple, cela est largement suffisant. Voici un script qui ajoutera lURL http://www.toutestfacile.com la table compteurclic.

Listing 10.90 : procstock.php


<?php $idConnexion = mssql_pconnect("localhost", "Emma", "emma"); if (!$idConnexion) { die("<b>Impossible de se connecter la base de donnes</b>"); } if (!mssql_select_db("maBase")) {

850

SQL Server (MS)

die("<b>Impossible de se connecter la base de donnes</b>"); } $url= "http://www.toutestfacile.com"; $procedure = mssql_init("insert_compteurclic_1"); mssql_bind($procedure, "@url_1", $url , SQLVARCHAR, FALSE, FALSE, 128); mssql_execute($procedure); ?>

10. Lutilisation des bases de donnes

mssql_init()
Initialise une procdure stocke (distante ou non). Syntaxe $nomProcedure $idConnexion int mssql_init(string $nomProcedure [, resource $idConnexion]); Nom de la procdure excuter. Identifiant de connexion une base de donnes tel que retourn par mssql_connect(). Par dfaut, cest lidentifiant de la dernire connexion qui est utilis. Un identifiant de procdure stocke.

retour

mssql_bind()
Ajoute un paramtre une procdure stocke (distante ou non). Syntaxe boolean mssql_bind(int $idProcedure, int $nomParametre, mixed $variable, int $type [, boolean $paramDeSortie [, boolean $null [, int $longMax]]]) Identifiant de procdure stocke tel que retourn par mssql_init(). Le nom du paramtre prcd du signe @ dfinissant une variable dans les procdures stockes de MS SQL. Elle peut tre passe par valeur ou par rfrence. Le type du paramtre, au choix parmi : SQLTEXT, SQLVARCHAR, SQLCHAR, SQLINT1, SQLINT2, SQLINT4, SQLBIT et SQLFLT8. TRUE sil sagit dun paramtre de sortie, FALSE (par dfaut) sinon. TRUE si le paramtre vaut NULL, FALSE (par dfaut)sinon. Longueur du champ (1 par dfaut). Ce paramtre est utilis pour les types CHAR et VARCHAR ; cette valeur doit tre la mme que celle dfinie lors de la cration de la table. TRUE en cas de succs, FALSE sinon.

$idProcedure $nomParametre $variable $type $paramDeSortie $null $longMax

retour

851

Chapitre 10

Lutilisation des bases de donnes

mssql_execute()
Excute une procdure stocke sur une base de donnes Microsoft SQL Server. Syntaxe mixed mssql_execute(int $idProcedure) Identifiant de procdure stocke tel que retourn par mssql_init(). Identifiant de rsultat de requte si la procdure retourne un rsultat, TRUE si la procdure ne retourne pas de rsultat, FALSE en cas derreur. $idProcedure retour

10. Lutilisation des bases de donnes

Lecture des enregistrements


Dans le cas dune requte retournant une liste de donnes (typiquement un SELECT), il convient de rcuprer lidentifiant de requte et de lutiliser gnralement pour lire, en boucle, ligne aprs ligne, chaque enregistrement (ou lensemble dun bloc). Il existe diverses fonctions, chacune permettant de rcuprer les champs des enregistrements sous diffrentes formes. Les informations peuvent ainsi tre retournes :
j j

Champ par champ ; Enregistrement par enregistrement (sous la forme dun tableau index, associatif, ou la fois index et associatif).

Lecture champ par champ


Bien que cela prsente peu dintrt, sachez quil existe une fonction appele mssql_result() permettant daccder au rsultat champ par champ.

mssql_result()
Retourne un champ dun enregistrement. Syntaxe $resultat $enregistrement $champ retour string mssql_result(resource $resultat, int $enregistrement, mixed $champ) Identifiant de rsultat tel que retourn par mssql_query(). Numro de lenregistrement. Numro ou nom du champ. Le champ demand, ou FALSE en cas derreur.

Vitesse
mssql_result() est une fonction TRS lente par rapport ses homologues mssql_fetch_row(), mssql_fetch_array() et mssql_fetch_object().

852

SQL Server (MS)

Lecture enregistrement par enregistrement


La forme la plus simple est celle retourne par la fonction mssql_fetch_row().

mssql_fetch_row()
Retourne un enregistrement, retourn par une requte SQL, sous la forme dun tableau index. Syntaxe $idResultat retour array mssql_fetch_row(resource $idResultat) Identifiant de rsultat tel que retourn par mssql_query(). Tableau index contenant autant dlments que de champs retourns par la requte, ou FALSE sil ny a plus denregistrement lire.

10. Lutilisation des bases de donnes

Listing 10.91 : select_eei_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requete $requete = "SELECT * FROM $table"; $idResultat = mssql_query($requete, $idConnexion); if (!$idResultat) return FALSE; // Boucle de lecture (et daffichage) des enregistrements while ($enreg = mssql_fetch_row($idResultat)) { echo "FilmId=".$enreg[0]." ". "Film =" .$enreg[1]."<br />"; } return TRUE; } ?>

Mais il est galement possible de retourner un enregistrement sous la forme dun tableau associatif (o les cls portent les noms des champs), grce la fonction mssql_fetch_assoc() qui a la mme syntaxe que mssql_fetch_row(). Il est surtout possible davoir les deux fonctions pour le prix dune avec la fonction
mssql_fetch_array().

853

Chapitre 10

Lutilisation des bases de donnes

mssql_fetch_array()
Retourne un enregistrement, retourn par une requte SQL, sous la forme dun tableau index et/ou associatif. Syntaxe $idResultat retour array mssql_fetch_array(resource $idResultat) Identifiant de rsultat tel que retourn par mssql_query(). Tableau index et/ou associatif, ou FALSE sil ny a plus denregistrement.

10. Lutilisation des bases de donnes

Cest ce mode de lecture des donnes que nous privilgierons. Il est en effet fort pratique pour les champs dont on connat le nom (ce qui est le plus souvent le cas), et permet galement de faire rfrence des champs sans nom, comme par exemple un champ SUM(nomchamp). Notez toutefois quil est possible daffecter un nom (ex: somme) ce genre de champ en indiquant SUM(nomchamp) AS somme. Lexemple prcdent gagnera ainsi en lisibilit et deviendra :

Listing 10.92 : select_eea_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requete $requete = "SELECT * FROM $table"; $idResultat = mssql_query($requete, $idConnexion); if (!$idResultat) return FALSE; // Boucle de lecture (et daffichage) des enregistrements while ($enreg = mssql_fetch_array($idResultat)) { echo "FilmId=".$enreg["filmId"]." ". "Film =" .$enreg["film"]."<br />"; } return TRUE; } ?>

Pour votre culture personnelle, sachez quil existe galement une fonction (dun intrt discutable) qui permet de retourner lenregistrement sous la forme dun objet possdant des variables internes portant les mmes noms (en minuscules) que les champs. Cette fonction sappelle mssql_fetch_object() et possde la mme syntaxe que mssql_fetch_row(), si ce nest quelle retourne un objet et non un tableau.

854

SQL Server (MS)

La boucle de lecture se transforme alors en :


<?php while ($enreg = mssql_fetch_object($idResultat)) { echo "FilmId = ".$enreg->filmid." Film = ".$enreg->film."<br />"; } ?>

10. Lutilisation des bases de donnes

Requtes multiples
La fonction mssql_query() permet de lancer plusieurs requtes en un unique appel. Il est ainsi possible de faire mssql_query("SELECT * FROM table1; SELECT * FROM table2"). Lidentifiant de rsultat alors retourn est celui de la premire requte, mais vous pouvez passer au rsultat de la requte suivante grce mssql_next_result().

mssql_next_result()
Dplace le pointeur sur le prochain groupe de rsultats lorsquil y en a plusieurs, par exemple lorsque deux requtes sont excutes la fois. Syntaxe $resultat retour boolean mssql_next_result(resource $resultat) Identifiant de rsultat tel que retourn par mssql_query(). TRUE si un autre groupe de rsultat est disponible, FALSE sinon.

Danger Le fait que mssql_query() permette dexcuter plusieurs requtes en une seule fois constitue un danger potentiel. Si, par exemple, votre serveur est configur de faon ce que magic_quote soit dsactive et que addSlashes() ne soit pas appel, alors une requte du genre :
SELECT * FROM matable WHERE champ=$param;

peut se tranformer en :
SELECT * FROM matable WHERE champ=blabla; DROP TABLE matable; ; si lutilisateur qui il a t demand de saisir la valeur de $param dans un champ dun formulaire a saisi "blabla; DROP TABLE matable; ".

Libration des ressources occupes par une rponse SQL


Il est possible, voire conseill, de librer la mmoire occupe par le rsultat dune requte (notamment lorsquil est volumineux et que les requtes sont nombreuses) laide de mssql_free_result().

855

Chapitre 10

Lutilisation des bases de donnes

mssql_free_result()
Cette fonction permet de librer la mmoire avant la fin du script (elle est automatiquement libre la fin dun script). Syntaxe $idResultat retour boolean mssql_free_result(resource $resultat) Identifiant de rsultat tel que retourn par mssql_query(). TRUE en cas de succs, FALSE sinon.

10. Lutilisation des bases de donnes

Nombre denregistrements
Nombre denregistrements retourns
Il existe trois faons de dterminer le nombre denregistrements retourns par une requte. Si vous souhaitez uniquement connatre le nombre denregistrements, mais ne souhaitez pas immdiatement lire ces enregistrements, alors il vous suffit de faire une requte COUNT() comme suit :

Listing 10.93 : count_bd_inc.php


<?php /** * Fonction affichant le nombre denregistrements * dans une table * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la tabme **/ function EX_compte($idConnexion, $table) { // Requte $requete = "SELECT COUNT(*) FROM $table"; $idResultat = mssql_query($requete, $idConnexion); // Lecture du rsultat if ($enreg = mssql_fetch_row($idResultat)) { echo "Il y a ".$enreg[0]." enregistrements dans la table.<br />"; return TRUE; } else { echo "Etes vous sr que la table $table existe ?<br />"; return FALSE; } } ?>

856

SQL Server (MS)

Si vous souhaitez connatre le nombre denregistrements, mais que vous souhaitez lire les enregistrements sans pour autant avoir besoin au pralable den connatre le nombre, il suffit de les compter au fur et mesure de leur lecture.

Listing 10.94 : count_select_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requete $requete = "SELECT * FROM $table"; $idResultat = mssql_query($requete, $idConnexion); if (!$idResultat) return FALSE; // Boucle de lecture (et de comptage) des enregistrements $nb = 0; while ($row = mssql_fetch_row($idResultat)) { // Vous pouvez manipuler $enreg votre guise //echo "FilmId=".$enreg[0]." ". // "Film =" .$enreg[1]."<br />"; $nb++; } echo "Il y a $nb enregistrements dans la table.<br />"; return TRUE; } ?>

10. Lutilisation des bases de donnes

Enfin, ce que vous attendez tous : si vous souhaitez connatre le nombre denregistrements avant de les lire, vous pouvez faire appel la fonction mssql_num_rows().

mssql_num_rows()
Retourne le nombre denregistrements retourns par la requte SQL. Syntaxe $idResultat retour int mssql_num_rows(resource $idResultat) Identifiant de rsultat tel que retourn par mssql_query(). Nombre denregistrements.

857

Chapitre 10

Lutilisation des bases de donnes

Listing 10.95 : count_num_rows_bd_inc.php


<?php /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $idConnexion resource Identifiant de connexion BD * @param $table string Nom de la table **/ function EX_listeContenu($idConnexion, $table) { // Requete $requete = "SELECT * FROM $table"; $idResultat = mssql_query($requete, $idConnexion); if (!$idResultat) return FALSE; echo "Il y a ".mssql_num_rows($idResultat)." enregistrements ". "dans la table<br />"; return TRUE; } ?>

10. Lutilisation des bases de donnes

Sachant quune requte SELECT * est plus longue quune requte SELECT COUNT(*), privilgiez la premire mthode si vous navez que faire du contenu des enregistrements.

Nombre denregistrements modis


Pour dterminer le nombre denregistrements modifis, vous pouvez appeler la fonction mssql_rows_affected(). Elle prend en argument lidentifiant de connexion, et retourne le nombre dlments affects par la dernire requte.

Gestion des erreurs


Jusque-l, en cas derreur, nous nous sommes contents dafficher un message gnrique. Il est cependant possible de dterminer plus prcisment lorigine de lerreur. Cela est notamment possible en rcuprant le dernier message via la fonction mssql_get_last_message().

mssql_get_last_message()
Retourne le code derreur du dernier appel. Syntaxe retour string mssql_get_last_message(void) Le dernier message obtenu.

858

SQL Server (MS)

Modier lapparition des messages derreur


Chaque erreur et message possde un degr dimportance. Il est possible de prciser le degr dimportance minimal des erreurs et messages afficher laide de deux fonctions :

10. Lutilisation des bases de donnes

mssql_min_error_severity()
Modifie le degr dimportance minimal des erreurs afficher. Syntaxe $degre void mssql_min_error_severity(int $degre) Degr dimportance minimal.

mssql_min_message_severity()
Modifie le degr dimportance minimal des messages afficher. Syntaxe $degre void mssql_min_message_severity(int $degre) Degr dimportance minimal.

Exemples dapplications
Compteur de clics
Une application courante dutilisation des bases de donnes, et simple mettre en uvre, consiste crer un compteur de clics. En effet, peut-tre souhaitez-vous proposer, sur votre site, un certain nombre de liens vers des sites Internet (annuaire web) ou vers des fichiers (bibliothques de scripts). Peut-tre que certains (ou la totalit) de ces liens sont proposs par un partenaire. Bref, tout cela vous incite savoir quelles sont les pages les plus frquemment consultes ( connatre les centres dintrt des visiteurs) et combien de visiteurs vous avez redirigs vers votre sponsor. La mthode la plus classique consiste stocker, en base de donnes, lensemble des liens ainsi proposs, et remplacer les traditionnels liens de la forme http://www.domaine.com par un lien vers un script charg dincrmenter le compteur correspondant au site indiqu, et de rediriger le client vers le site grce la fonction header(). Pour notre exemple, nous utiliserons une table appele url contenant trois champs :
j j j

urlid, identifiant de lURL (champ auto-incrment) ; url, lURL proprement dite ; nbclic, le nombre de clics.

859

Chapitre 10

Lutilisation des bases de donnes

Le script de redirection (appel ici compteurclic_redirection.php) devra alors accepter un paramtre (urlid) et devra, partir de ce paramtre, dterminer quelle est la valeur du champ url, incrmenter nbclic pour cette URL, et rediriger vers url. Les appels ce script auront alors la forme http://localhost/compteurclic_redirection.php?urlid=3 (pour accder lURL ayant lidentifiant 3). supposer que lURL 3 corresponde au site http://www .sqlfacile.com, cela signifie que le lien <a href="http://www.sqlfacile.com">devra tre remplac par <a href="compteurclic_redirection.php?urlid=3> si lon souhaite en compter le nombre de clics. Concrtement, cette table pourra tre cre et alimente avec la fonction CC_initialiseBD() du script suivant :

10. Lutilisation des bases de donnes

Listing 10.96 : compteurclic_bd_inc.php (dbut)


<?php //-----------------------------------// Charge les paramtres de connexion // la base de donnes. //-----------------------------------require_once("parametres_bd_inc.php"); /** * Fonction de connexion une base de donnes * sappuie sur les paramtres fournis * dans parametres_bd_inc.php. * * @return resource Identifiant de connexion */ function CC_connexion() { global $serveur, $base, $utilisateur, $motDePasse; $idConnexion = mssql_pconnect($serveur, $utilisateur, $motDePasse); if (!$idConnexion) return FALSE; mssql_select_db($base); return $idConnexion; } /** * Fonction de deconnexion. * (Ne fait rien sachant que la fonction * de connexion tablit une connexion persistante) */ function CC_deconnexion($idConnexion) { return TRUE; } /** * Fonction charg de crer et dalimenter

860

SQL Server (MS)

* la table "compteur de clics" **/ function CC_initialiseBD($idConnexion, $table) { // Cration de la table $requete = "DROP TABLE $table"; @mssql_query($requete, $idConnexion);

10. Lutilisation des bases de donnes

$requete = "CREATE TABLE $table (". "urlId INTEGER ". "IDENTITY PRIMARY KEY,". "url VARCHAR(128) NOT NULL,". "nbclic INTEGER DEFAULT 0,". "UNIQUE(url))"; if (!mssql_query($requete, $idConnexion)) return FALSE; // Alimentation de la table $requete = "INSERT INTO $table (url)". " VALUES (http://www.php.net)"; if (!mssql_query($requete, $idConnexion)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.phpfacile.com)"; if (!mssql_query($requete, $idConnexion)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.sqlfacile.com)"; if (!mssql_query($requete, $idConnexion)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.xmlfacile.com)"; if (!mssql_query($requete, $idConnexion)) return FALSE; $requete = "INSERT INTO $table (url)". " VALUES (http://www.ootoogo.com)"; if (!mssql_query($requete, $idConnexion)) return FALSE; return TRUE; } ?>

La lecture de la liste des liens disponibles en base de donnes pourra se faire via la fonction CC_recupereLiens() du script suivant :

Listing 10.97 : compteurclic_bd_inc.php (milieu)


<?php /** * Fonction retournant les informations de liens * sous forme dun tableau associatif possedants * les cls * - "lien" associ au tableau des liens hypertextes

861

Chapitre 10

Lutilisation des bases de donnes

* - "nbclic" associ au tableau des nombres de clics **/ function CC_recupereLiens($idConnexion, $table) { // Nom du script charg du comptage et de la redirection $script = "compteurclic_redirection.php";

10. Lutilisation des bases de donnes

// Requte SELECT $requete = "SELECT * FROM $table"; $idResultat = mssql_query($requete, $idConnexion); // Rcupration des enregistrements les uns aprs les autres while ($enreg = mssql_fetch_array($idResultat)) { $liens["lien"][] = "<a href=\"$script?urlid=". $enreg["urlId"]."\">". $enreg["url"]."</a>"; $liens["nbclic"][] = $enreg["nbclic"]; } return $liens; } ?>

Laffichage des liens consiste uniquement mettre en page le contenu du tableau ainsi rcupr (voir la fonction du script compteurclic_html_inc.php). Comme cela a t prcis, le lien <a href="http://www.sqlfacile.com">http://www .sqlfacile.com</a> a t remplac par <a href="compteurclic_redirection .php?urlid=3">http://www.sqlfacile.com </a>. La redirection vers le site www.sqlfacile .com est donc la charge du script compteurclic_redirection.php.

Listing 10.98 : compteurclic_redirection.php


<?php // Paramtres du script require_once("compteurclic_bd_inc.php"); $table = "compteurclic"; // Connexion la base de donnes $idConnexion = @CC_connexion(); if (!$idConnexion) { die("<b>Impossible de se connecter la base de donnes</b>"); } // Rcupration de lurl et incrmentation du compteur // pour lurl dindentifiant pass en paramtre de ce script // par la mthode GET $url = @CC_recupereUrl($idConnexion, $_GET["urlid"]); // Deconnexion @CC_deconnexion();

862

SQL Server (MS)

// Cest lheure de la redirection if ($url) { header("Location: $url"); } else { echo "Dsol, nous ne pouvons vous proposer ce lien"; } ?>

10. Lutilisation des bases de donnes

Ce script appelle principalement la fonction CC_recupereUrl() suivante :

Listing 10.99 : compteurclic_bd_inc.php (fin)


<?php /** * Fonction rcuprant une url partir de son identifiant * et incrmentant le compteur de clics **/ function CC_recupereUrl($idConnexion, $urlid) { global $table; // Rcupre lurl $requete = "SELECT * FROM $table WHERE urlid=$urlid"; $idResultat = mssql_query($requete, $idConnexion); if ($enreg = mssql_fetch_array($idResultat)) { $url = $enreg["url"]; // Incrmente le compteur $requete = "UPDATE $table SET nbclic=nbclic+1 WHERE urlid=$urlid"; mssql_query($requete, $idConnexion); } else { $url = FALSE; } return $url; } ?>

Utilisation du bouton retour Si, aprs avoir suivi un lien, vous revenez sur la page compteurclic.php en utilisant le bouton retour (back), le contenu de la page ne sera pas ractualis. Par consquent, le nombre de visites affich ne sera pas correct. Noubliez donc pas, dans ce cas, de rafrachir (bouton actualiser) la page.

863

Chapitre 10

Lutilisation des bases de donnes

SuperTheque
Lessentiel du code de lapplication a t prsent en introduction de ce chapitre. Il ne restait plus qua connatre les fonctions MS SQLServer pour implmenter linterface RessourceInterface cest dsormais chose faite:

10. Lutilisation des bases de donnes

Listing 10.100 : RessourceMSSQLServer_class.php


<?php include_once("RessourceInterface_class.php"); include_once(dirname(__FILE__)."/../config/mssql_cfg.php"); /** * RessourceMSSQLServer_class.php * Classe dacces a une base de donnees MS SQL Server * Cette classe doit implementer toutes les methodes de linterface * RessourceInterface. * Compatibilite: PHP 5 */ class Ressource implements RessourceInterface { var $idConnexion; public function connexion() { global $mssql_serveur, $mssql_utilisateur, $mssql_motDePasse; global $mssql_base; if (!isset($this->idConnexion)) { $idConnexion = mssql_pconnect($mssql_serveur, $mssql_utilisateur, $mssql_motDePasse); if (!$idConnexion) return FALSE; mssql_select_db($mssql_base); $this->idConnexion = $idConnexion; } return TRUE; } public function deconnexion() { // Rien a faire, il sagit dune connexion persistante } public function reset() { $requete = "DROP TABLE types"; $idResultat = @mssql_query($requete, $this->idConnexion); //if (!$idResultat) return FALSE; $requete = "CREATE TABLE types (". "id INTEGER IDENTITY PRIMARY KEY,". "type VARCHAR(255))";

864

SQL Server (MS)

$idResultat = mssql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; $types = array("Album", "Film", "Livre", "Musique"); foreach ($types as $type) { $requete = "INSERT INTO types (type) VALUES ($type)"; $idResultat = mssql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; } $requete = "DROP TABLE articles"; $idResultat = @mssql_query($requete, $this->idConnexion); $requete = "CREATE TABLE articles (". "id INTEGER IDENTITY PRIMARY KEY,". "albumId INTEGER,". "titre VARCHAR(255),". "typeId INTEGER,". "commentaire VARCHAR(255) NULL)"; $idResultat = mssql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; } public function addArticle($albumId, $titre, $typeId, $commentaire) { $requeteDebut = "INSERT INTO articles (albumId, titre, typeId"; $requeteFin = ") VALUES ($albumId,". "".addSlashes($titre).",". "$typeId"; if ($commentaire != "") { $requeteDebut .= ",commentaire"; $requeteFin .= ",".addSlashes($commentaire).""; } $requete = $requeteDebut . $requeteFin . ")"; $idResultat = mssql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; } public function getArticle($articleId) { $requete = "SELECT * FROM articles WHERE id=$articleId"; $idResultat = mssql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; $article = NULL; if ($enreg = mssql_fetch_array($idResultat)) { $article = $this->enreg2Article($enreg); } return $article;

10. Lutilisation des bases de donnes 865

Chapitre 10

Lutilisation des bases de donnes

} public function getArticles(Filtre $filtre, Plage $plage, Tri $tri) { $nbTotalArticles = $this->getNbTotalArticles($filtre); if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". addSlashes($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL. " AND typeId=".$filtre->getTypeId(); } if ($tri->getSens() == -1) { $triSQL = "ORDER BY ".$tri->getChamp()." DESC"; $triInverseSQL = "ORDER BY ".$tri->getChamp()." ASC"; } else if ($tri->getSens() == 1) { $triSQL = "ORDER BY ".$tri->getChamp()." ASC"; $triInverseSQL = "ORDER BY ".$tri->getChamp()." DESC"; } if ($plage->getPremierArticle()+$plage->getNbArticleMax() < $nbTotalArticles) { $requete = "SELECT * FROM (SELECT TOP ". $plage->getNbArticleMax(). " * FROM (SELECT TOP ". ($plage->getPremierArticle()+ $plage->getNbArticleMax()). " * FROM articles"; $requete = $requete." WHERE ".$conditionSQL." ". $triSQL.")". " AS filtre1 ".$triInverseSQL.")". " AS filtre2 ".$triSQL; } else { $requete = "SELECT * FROM (SELECT TOP ". ($nbTotalArticles - $plage->getPremierArticle()). " * FROM articles"; $requete = $requete." WHERE ".$conditionSQL." ". $triInverseSQL.")". " AS filtre1 ".$triSQL; } $idResultat = mssql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE;

10. Lutilisation des bases de donnes 866

SQL Server (MS)

$articles = NULL; while ($enreg = mssql_fetch_array($idResultat)) { $articles[] = $this->enreg2Article($enreg); } return $articles; }

10. Lutilisation des bases de donnes

public function getNbTotalArticles(Filtre $filtre) { $requete = "SELECT COUNT(*) FROM articles"; if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". addSlashes($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL. " AND typeId=".$filtre->getTypeId(); } $requete = $requete." WHERE ".$conditionSQL; $idResultat = mssql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; if ($enreg = mssql_fetch_array($idResultat)) { return $enreg[0]; } else return FALSE; }

public function getTypes() { $requete = "SELECT * FROM types"; $idResultat = mssql_query($requete, $this->idConnexion); if (!$idResultat) return FALSE; $types = NULL; while ($enreg = mssql_fetch_array($idResultat)) { $types[$enreg["id"]] = $enreg["type"]; } return $types; } public function getAlbumTypeId() { return 1; }

867

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

private function enreg2Article($enreg) { $article = new Article(); $article->setId($enreg["id"]); $article->setAlbumId($enreg["albumId"]); $article->setTitre($enreg["titre"]); $article->setTypeId($enreg["typeId"]); $article->setCommentaire($enreg["commentaire"]); return $article; } } ?>

Comme vous le constatez, la principale difficult nest pas tant au niveau des fonctions disponibles quau niveau de la construction des requtes SQL. La requte sera simple lorsquil ne sagit que de rcuprer un enregistrement identifi par la cl Id (comme cest le cas avec getArticle()) elle sera bien plus complexe sil sagit des rcuprer un ensemble denregistrements rpondant des critres prcis et tris (comme cest le cas avec getArticles()).

Requtes avec des apostrophes


Lors de la construction de la requte, il faut bien garder lesprit que lun des lments de la requte (typiquement un champ de type texte saisi par lutilisateur, comme ici le titre ou le commentaire) peut contenir une apostrophe qui pourrait tre confondu avec le dlimiteur de chane. Pensez donc bien faire un appel addSlashes() lorsque cela peut savrer ncessaire.

Affichage par page


Contrairement dautres bases de donnes, Microsoft SQL Server ne dispose pas dinstruction permettant de rcuprer N enregistrements partir de lenregistrement dindex I. Il est par contre possible de ne rcuprer que les N premiers enregistrements grce linstruction TOP. Il est donc possible de rcuprer les I + N premiers articles puis daller directement larticle I grce la fonction PHP mssql_data_seek(), qui permet de modifier le pointeur de sorte que le premier appel une fonction telle que mssql_fetch_row() ne renvoie pas la premire ligne, mais la I-ime.

mssql_data_seek()
Permet de dplacer le pointeur pour un appel mssql_fetch_row(), mssql_fetch_array() ou encore mssql_fetch_object(). Syntaxe boolean mssql_data_seek(resource $idResultat, int $numeroLigne)

868

SQL Server (MS)

$idResultat $numeroLigne retour

Identifiant de rsultat tel que retourn par mssql_query(). Numro de la ligne sur laquelle il faut dplacer le pointeur. TRUE en cas de succs, FALSE sinon.

Si le nombre denregistrements dans la base est vraiment important (et que lon recherche les donnes correspondant un numro de page lev), alors lutilisation de TOP napportera finalement que peu de choses (puisque, de toute faon, il y aura bien plus de N enregistrements retourns). Il peut alors tre intressant de demander la base de donnes de ne retourner que les N enregistrements partir de celui dindex I, quitte lui donner plus de travail avec selon les cas, une requte:
SELECT * FROM (SELECT TOP <N> * FROM (SELECT TOP <I+N> * FROM table ORDER BY champ) AS filtre1 ORDER BY champ DESC) AS filtre2 ORDER BY champ.

10. Lutilisation des bases de donnes

si I+N est infrieur au nombre total denregistrements rpondant aux critres de slection ou la requte:
SELECT * FROM (SELECT TOP <nbTotalArticles I> * FROM table ORDER BY champ DESC) AS filtre1 ORDER BY champ.

dans le cas contraire.

Tri
Modifier lordre daffichage des annonces nest pas non plus bien sorcier. Le tri peut seffectuer directement au niveau de la requte SQL grce linstruction ORDER BY.

Moteur de recherche (ltre)


Pour filtrer, il suffit dutiliser linstruction WHERE. Dans notre cas, nous souhaitons autoriser lutilisation de jokers (comme %) afin, par exemple, de rechercher les titres commenant par une chane donne. Cest pourquoi, nous ne ferons pas un test de type titre=motcle mais titre LIKE motcle (o motcle pourrait avoir la valeur "La 7eme compagnie%").

En savoir plus...
... sur le rsultat dune requte
Il vous est possible de connatre le nombre de champs retourns par une requte (et par consquent le nombre de champs dune table dans le cas dune requte SELECT * FROM <nom_table> sur une table non vide).

mssql_num_elds()
Retourne le nombre de champs du rsultat. Syntaxe int mssql_num_fields(resource $resultat)

869

Chapitre 10

Lutilisation des bases de donnes

$resultat retour

Identifiant de rsultat tel que retourn par mssql_query(). Nombre de champs disponibles dans le rsultat.

10. Lutilisation des bases de donnes

mssql_fetch_eld()
Retourne un objet contenant des informations sur un champ. Syntaxe $resultat $numeroColonne object mssql_fetch_field(resource $resultat [, int $numeroColonne]) Identifiant de rsultat tel que retourn par mssql_query(). Numro de la colonne dont on veut des informations. Si ce paramtre nest pas pass, les informations obtenues sont celles qui nont pas t rcupres par mssql_fetch_field(). Un objet possdant les attributs : name : nom de la colonne ; si cette colonne est le fruit dune fonction, alors le nom retourn sera computed suivi dun nombre. column_source : table do provient la colonne. max_length : taille maximale de la colonne. numeric : 1 si la colonne est une colonne contenant des valeurs numriques.

retour

mssql_eld_length()
Retourne la taille dun champ. Syntaxe $resultat $numeroChamp int mssql_field_length(resource $resultat [, int $numeroChamp]) Identifiant de rsultat tel que retourn par mssql_query(). Numro du champ sur lequel vous souhaitez des informations. Si ce paramtre nest pas pass, les informations obtenues sont celles qui nont pas t rcupres par mssql_fetch_field(). La taille du champ.

retour

mssql_eld_name()
Retourne le nom dun champ. Syntaxe string mssql_field_name(resource $resultat [, int $numeroChamp])

870

Les couches dabstraction

$resultat $numeroChamp

Identifiant de rsultat tel que retourn par mssql_query(). Numro du champ dont on veut des informations. Si ce paramtre nest pas pass, les informations obtenues sont celles qui nont pas t rcupres par mssql_fetch_field(). Le nom du champ.

retour

10. Lutilisation des bases de donnes

mssql_eld_type()
Retourne le type dun champ. Syntaxe $resultat $numeroChamp string mssql_field_name(resource $resultat [, int $numeroChamp]) Identifiant de rsultat tel que retourn par mssql_query(). Numro du champ dont on veut des informations. Si ce paramtre nest pas pass, les informations obtenues sont celles qui nont pas t rcupres par mssql_fetch_field(). Le type du champ.

retour

mssql_eld_seek()
Dplace le pointeur de champ vers un autre. Syntaxe $resultat $numeroColonne retour boolean mssql_field_seek(resource $resultat, int $numeroColonne) Identifiant de rsultat tel que retourn par mssql_query(). Numro de la colonne o dplacer le pointeur. TRUE en cas de succs, FALSE sinon.

10.14. Les couches dabstraction


Comme le dmontre le sous-chapitre prcdent et la liste de bases de donnes associe, il existe, quasiment, une bibliothque spcifique pour chaque serveur, alors que, quelle que soit la base, la nature des oprations raliser est toujours du mme type (connexion, soumission dune requte, lecture des rsultats, etc.). Tenant compte de cette observation, daucuns proposent des bibliothques fournissant des fonctions identiques quelle que soit la base de donnes interroge (on parle alors de couche dabstraction). Cest du moins lobjectif, car, gnralement, dans les faits, seul un petit nombre de bases de donnes est support.

871

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

Lintrt des couches dabstraction est bien videmment de permettre de raliser facilement un script pouvant sadapter nimporte quelle base de donnes. Mais, l encore, il sagit bien souvent dun vu pieu. En effet, comme vous avez pu le constater si vous avez lu le chapitre ODBC, toutes les bases de donnes nimplmentent pas les mmes instructions SQL, et chacune propose sa propre version. Ainsi, mme avec une couche dabstraction, le code doit tre adapt et test pour chaque type de base de donnes. Cela ne rend toutefois pas totalement inutiles les couches dabstraction. Parmi les couches dabstraction existantes nous avons :
j j

La bibliothque Dbx ; La bibliothque PEAR. Nous ne traiterons ici que la couche dabstraction PEAR qui est la plus complte et nous semble par consquent la plus intressante.

Pear DB
La dsormais clbre bibliothque PEAR propose galement une couche dabstraction pour les bases de donnes. Celle-ci supporte lheure actuelle (avec plus ou moins de bonheur) les bases de donnes MySQL, PostgresSQL, Interbase, MiniSQL, MS SQL Server, Oracle 8i, Sybase, Informix, Frontbase, ainsi que les liaisons ODBC.

Installation
Lutilisation de PEAR DB ne ncessite aucune installation spcifique (hormis linstallation des bases de donnes que vous souhaitez utiliser et leur "intgration" PHP). Il suffit dactiver le support PEAR au niveau de PHP.

Vous pouvez vous reporter aux sections propres aux bases de donnes pour plus de dtails sur la faon de faire pour les "intgrer" PHP.

Conguration de PHP avec le support PEAR


Si vous ne disposez pas du paquetage DB ou si vous souhaitez obtenir la dernire version disponible tapez simplement (dans une console) la commande suivante
pear upgrade DB

Chaque script ncessitant lutilisation de PEAR DB devra inclure la ligne :


require_once("DB.php");

Utilisation
Lutilisation basique de la base de donnes sopre selon le schma suivant :
j

Connexion grce la mthode statique de DB::connect().

872

Les couches dabstraction

j j

Soumission de la requte via la mthode DB>query(). Dconnexion grce la mthode DB>disconnect() (dans le cas dune connexion non persistante).

Connexion
La connexion la base de donnes sopre grce la mthode statique DB::connect().

10. Lutilisation des bases de donnes

DB::connect()
tablit une connexion (persistante ou non) avec le serveur de bases de donnes. Syntaxe $baseDeDonnees object DB::connect(string $baseDeDonnees [, boolean $persistance]) Prcise la base de donnes selon la syntaxe typeServeur [(syntaxeSQL)]://[utilisateur[:motDePasse]@] [protocole(][serveur][)][/baseDeDonnees], o : typeServeur peut prendre lune des valeurs suivantes "fbsql" pour Frontbase, "ibase" pour Interbase, "ifx" pour Informix, "mysql" pour MySQL, "msql" pour MiniSQL, "mssql" pour MS SQL Server, "oci8" pour Oracle 8i, "odbc" pour une liaison ODBC, "pgsql" pour PostgreSQL ou "sybase" pour Sybase. syntaxeSQL peut prendre les valeurs "dbase", " fbsql", "ibase", "firebird", "ifx", "msql", "mssql", "mysql", "oci8", "sql92", "pgsql", "sybase". utilisateur est le nom de lutilisateur. motDePasse est le mot de passe de lutilisateur. protocole peut prendre les valeurs "tcp" ou "unix" (socket). serveur est nom du serveur ventuellement suivi de : puis du numro du port (protocole "tcp") ou le fichier de socket (protocole "unix") baseDeDonnees est le nom de la base de donnes, ou ventuellement le nom et le chemin du fichier de base de donnes. Indiquez TRUE si vous souhaitez une connexion persistante, FALSE (valeur par dfaut) sinon. Objet DB en cas de succs, objet DB_Error sinon.

$persistance retour

Excution de la requte SQL


Lexcution dune requte SQL sopre par un simple appel la mthode DB>query().

DB->query()
Excute une requte SQL.

873

Chapitre 10

Lutilisation des bases de donnes

Syntaxe $requete retour

mixed query(string $requete) Requte SQL. Dans le cas dune requte ne retournant pas de rsultat (ex. : CREATE, INSERT, UPDATE), la mthode retourne la constante DB_OK (1) en cas de succs, ou un objet DB_Error sinon.

10. Lutilisation des bases de donnes

Dans le cas dune requte retournant des rsultats (ex : SELECT) la mthode retourne un objet DB_Result en cas de succs, ou un objet DB_Error sinon. Une des fonctions les plus intressantes de cette couche dabstraction est probablement la suivante:

DB->limitQuery()
Excute une requte SQL en ne demandant quun sous-ensemble des rsultats ( la manire de linstruction LIMIT que lon peut retrouver avec MySQL et SQLite). Syntaxe $requete $premier Enregistrement retour mixed limitQuery(string $requete, int $premierEnregistrement, int $nbEnregistrements) Requte SQL. Index du premier enregistrement retourner. Dans le cas dune requte ne retournant pas de rsultat (ex. : CREATE, INSERT, UPDATE), la mthode retourne la constante DB_OK (1) en cas de succs, ou un objet DB_Error sinon.

$nbEnregistrements Nombre denregistrement maximum retourner

Dans le cas dune requte retournant des rsultats (ex : SELECT) la mthode retourne un objet DB_Result en cas de succs, ou un objet DB_Error sinon. Nous verrons par la suite que, pour les bases de donnes le supportant, il est galement possible dutiliser des requtes prpares (contenant des paramtres qui pourront tre modifis juste avant que celles-ci ne soient excutes), et de dsactiver le mode auto commit (validation automatique) pour avoir accs aux oprations de commit (validation) et rollback (annulation). Dans le cas dune requte retournant un rsultat (typiquement une requte SELECT), il faudra galement analyser le rsultat. Mais nous verrons cela un peu plus loin.

Dconnexion
Pour vous dconnecter opration thoriquement facultative mais toutefois vivement conseille , vous disposez de la mthode DB>disconnect().

874

Les couches dabstraction

DB->disconnect()
Met fin la connexion la base de donnes et libre les ressources associes. Syntaxe retour boolean disconnect() TRUE en cas de succs, FALSE sinon.

10. Lutilisation des bases de donnes

Premier exemple
Nous voil donc mme de construire notre premier script utilisant une base de donnes.

Vrifiez les paramtres Prenez garde ! Avant dexcuter ce script, assurez-vous que les paramtres prdfinis ne risquent pas de conduire la suppression des donnes dune de vos bases qui, par concidence, existerait dj.
Comme cela est fortement conseill, nous avons, ici, isol les paramtres de connexion dans un fichier aisment reprable.

Listing 10.101 : parametres_bd_inc.php


<?php // Paramtres de connexion la base de donnes // Nhsitez pas les modifier selon vos besoins // // // // // // // $typeServeur "mysql" "pgsql" "oci8" "MSAccess" "IBMDB2" ... = = = = = peut prendre lune des valeurs suivante MySQL PostgreSQL Oracle 8i MS Access IBM DB2

$typeServeur $serveur $base $utilisateur $motDePasse ?>

"mysql"; "localhost"; "mabase"; "root"; "";

Notre script principal sera donc :

Listing 10.102 : insert01.php


<?php // Paramtres du script

875

Chapitre 10

Lutilisation des bases de donnes

require_once("parametres_bd_inc.php"); $table = "tableexemple"; // Inclusion du script contenant les fonctions require_once("insert01_bd_inc.php"); // Connexion la base de donnes switch ($typeServeur) { case "MSAccess" : $typeServeurPear = "odbc"; break; default : $typeServeurPear = $typeServeur; } $dsn = "$typeServeurPear://"; if (!empty($utilisateur)) $dsn .= $utilisateur; if (!empty($motDePasse)) $dsn .= ":$motDePasse"; $dsn .= "@tcp($serveur)"; if (!empty($base)) $dsn .= "/$base"; $bd = DB::connect($dsn, TRUE); if (DB::isError($bd)) { echo $dsn." ".$bd->message; return FALSE; } if ($bd === FALSE) { die("<b>Impossible de se connecter la base de donnes</b>"); } // Appel de la fonction principale if (EX_initialiseBD($bd, $table)) { echo "Voil, une nouvelle table avec quelques donnes, ". "vous pouvez le vrifier avec votre client de base ". " de donnes ou via les scripts suivants."; } else { echo "La cration ou lalimentation de la table choue."; } // Pas de dconnexion dans le cas dune connexion persistante // $db->disconnect();

10. Lutilisation des bases de donnes

?>

et ncessitera :

Listing 10.103 : insert01_bd_inc.php


<?php require_once("DB.php"); /**

876

Les couches dabstraction

* Fonction charge de crer et dalimenter une table * * @param $bd object Base de donnes * @param $table string Nom de la table **/ function EX_initialiseBD($bd, $table) { // Supprime la prcdente table $requete = "DROP TABLE $table"; @$bd->query($requete); // Cre la table $requete = "CREATE TABLE $table (filmId INTEGER, ". "film VARCHAR(64))"; $sts = $bd->query($requete); if (DB::isError($sts)) return FALSE; // Ajoute quelques donnes $requete = "INSERT INTO $table VALUES (1, Forrest Gump)"; $sts = $bd->query($requete); if (DB::isError($sts)) return FALSE; $requete = "INSERT INTO $table VALUES (2, Matrix)"; $sts = $bd->query($requete); if (DB::isError($sts)) return FALSE; $requete = "INSERT INTO $table VALUES (3, La cit de la peur)"; $sts = $bd->query($requete); if (DB::isError($sts)) return FALSE; return TRUE; } ?>

10. Lutilisation des bases de donnes

Commit/rollback
Par dfaut, les requtes sont automatiquement valides (mode auto commit). Il est toutefois possible, pour certaines bases de donnes, de modifier ce comportement en utilisant la mthode DB>autoCommit().

DB->autoCommit()
Active ou dsactive le mode de validation automatique des transactions (auto commit). Syntaxe $mode mixed autoCommit([boolean $mode]) TRUE pour activer le mode auto commit, FALSE (valeur par dfaut) sinon.

877

Chapitre 10

Lutilisation des bases de donnes

retour

DB_OK si la base de donnes supporte les transactions, ou lobjet DB_Error sinon.

Si vous avez opt pour un mode de validation non automatique, vous pourrez valider ou annuler vos transactions avec les fonctions suivantes :

10. Lutilisation des bases de donnes

DB->commit()
Valide la transaction en cours. Syntaxe retour mixed commit(void) DB_OK si la base de donnes supporte les transactions, ou lobjet DB_Error sinon.

DB->rollback()
Annule la transaction en cours. Syntaxe retour mixed rollback(void) DB_OK si la base de donnes supporte les transactions, ou lobjet DB_Error sinon.

Lecture des enregistrements


Dans le cas dune requte retournant une liste de donnes (typiquement un SELECT), il convient de rcuprer lobjet DB_Result et de lutiliser pour lire, en boucle, ligne aprs ligne, chaque enregistrement. Il existe pour cela deux mthodes au comportement similaire, mais avec des syntaxes diffrentes. Nous verrons ensuite quil est galement possible dexcuter des requtes et de rcuprer les enregistrements sans mme passer par un objet DB_Result.

Lecture enregistrement par enregistrement

DB_Result->fetchRow()
Retourne lenregistrement courant et dplace le curseur vers lenregistrement suivant. Syntaxe $mode mixed fetchRow([int $mode [,int $enregistrementIdx]]) Dtermine le format de la rponse, cela peut prendre lune des valeurs suivantes :

878

Les couches dabstraction

DB_FETCHMODE_ASSOC pour restituer lenregistrement sous la forme dun tableau associatif o les cls sont les noms de champs. DB_FETCHMODE_OBJECT pour restituer lenregistrement sous la forme dun objet. DB_FETCHMODE_ORDERED pour restituer lenregistrement sous la forme dun tableau index (commenant 0) et contenant les valeurs des champs (dans lordre de la requte). DB_FETCHMODE_DEFAULT (valeur par dfaut si la mthode setFetchMode() na pas t appele) pour restituer lenregistrement sous sa forme par dfaut (probablement DB_FETCHMODE_ORDERED). $enregistrementIdx Index de lenregistrement restituer. retour Selon le mode choisi, en cas de succs : un tableau index, associatif, un objet, ou NULL sil ny a plus denregistrement lire.

10. Lutilisation des bases de donnes

La fonction suivante listera donc le contenu de la table :

Listing 10.104 : select_eea_bd_inc.php


<?php require_once("DB.php"); /** * Fonction listant le contenu dune table * contenant 2 champs (filmId et film) * * @param $bd object Base de donnes * @param $table string Nom de la table **/ function EX_listeContenu($bd, $table) { // Requete $requete = "SELECT * FROM $table"; $resultat = $bd->query($requete); if (DB::isError($resultat)) return FALSE; // Boucle de lecture (et daffichage) des enregistrements while ($enreg = $resultat->fetchRow(DB_FETCHMODE_ASSOC)) { echo "FilmId=".$enreg["filmId"]." ". "Film =" .$enreg["film"]."<br />"; } return TRUE; } ?>

Lautre mthode similaire est DB_Result>fetchInto.

879

Chapitre 10

Lutilisation des bases de donnes

DB_Result->fetchInto()
Retourne lenregistrement courant et dplace le curseur vers lenregistrement suivant. Syntaxe int fetchInto(array &$enregistrement [, int $mode [, int $enregistrementIdx]]) Variable dans laquelle copier lenregistrement. Dtermine le format de la rponse, cela peut prendre lune des valeurs suivantes : DB_FETCHMODE_ASSOC pour restituer lenregistrement sous la forme dun tableau associatif o les cls sont les noms de champs. DB_FETCHMODE_OBJECT pour restituer lenregistrement sous la forme dun objet. DB_FETCHMODE_ORDERED pour restituer lenregistrement sous la forme dun tableau index (commenant 0) et contenant les valeurs des champs (dans lordre de la requte). DB_FETCHMODE_DEFAULT (valeur par dfaut si la mthode setFetchMode() na pas t appele) pour restituer lenregistrement sous sa forme par dfaut (probablement DB_FETCHMODE_ORDERED). $enregistrementIdx Index de lenregistrement restituer. retour La constante DB_OK (1) en cas de succs, FALSE sinon.

10. Lutilisation des bases de donnes

$enregistrement $mode

Sans objet DB_Result


Lobjet DB de la bibliothque PEAR propose une srie de mthodes permettant daccder directement aux rsultats dune requte, et rpondant aux cas dutilisation les plus frquents.

DB->getOne()
Retourne le premier champ du premier enregistrement retourn par une requte (ex. : du type SELECT champ FROM table WHERE id=valeur). Syntaxe $requete $parametres retour string getOne(mixed $requete [, array $parametres]) Requte SQL, ou identifiant dune requte prpare tel que retourn par DB>prepare(). Paramtres de la requte prpare. La valeur du champ, ou un objet DB_Error en cas derreur.

880

Les couches dabstraction

Voir lexemple dutilisation dans le paragraphe "Compter les enregistrements".

DB->getRow()
Retourne le premier enregistrement retourn par une requte (ex. : du type SELECT * FROM table WHERE id=valeur). Syntaxe $requete $parametres $mode mixed getRow(mixed $requte [, array $parametres [, int $mode]]) Requte SQL, ou identifiant dune requte prpare tel que retourn par DB>prepare(). Paramtres de la requte prpare (NULL si vous souhaitez simplement prciser le mode). Dtermine le format de la rponse, cela peut prendre lune des valeurs suivantes : DB_FETCHMODE_ASSOC pour restituer lenregistrement sous la forme dun tableau associatif o les cls sont les noms de champs. DB_FETCHMODE_OBJECT pour restituer lenregistrement sous la forme dun objet. DB_FETCHMODE_ORDERED pour restituer lenregistrement sous la forme dun tableau index (commenant 0) et contenant les valeurs des champs (dans lordre de la requte). DB_FETCHMODE_DEFAULT (valeur par dfaut si la mthode setFetchMode() na pas t appele) pour restituer lenregistrement sous sa forme par dfaut (probablement DB_FETCHMODE_ORDERED). retour Selon le mode choisi, en cas de succs : un tableau index, associatif, un objet, ou NULL si la requte ne retourne aucun enregistrement ; voire un objet DB_Error en cas derreur.

10. Lutilisation des bases de donnes

DB->getCol()
Retourne lensemble des valeurs dun champ des enregistrements retourns par une requte. Syntaxe $requete $champ $parametres mixed getRow(mixed $requte [, string $champ [, array $parametres]]) Requte SQL, ou identifiant dune requte prpare tel que retourn par DB>prepare(). Index ou nom du champ. Paramtres de la requte prpare.

881

Chapitre 10

Lutilisation des bases de donnes

retour

Tableau index contenant les valeurs pour chaque enregistrement retourn, ou un objet DB_Error en cas derreur.

10. Lutilisation des bases de donnes

DB->getAssoc()
Retourne lensemble des enregistrements retourns par une requte sous la forme dun tableau associatif bas sur la valeur du premier champ. Syntaxe $requete $modeTableau array getAssoc(mixed $requete [, boolean $modeTableau [, array $parametres ]]) Requte SQL, ou identifiant dune requte prpare tel que retourn par DB>prepare(). TRUE pour forcer lutilisation dun tableau, mme dans les cas o chaque cl du tableau nest associe qu une seule valeur, FALSE (valeur par dfaut) sinon. Paramtres de la requte prpare. Dans le cas denregistrements avec un seul champ, retourne la constante DB_ERROR_TRUNCATED. Dans le cas denregistrements avec deux champs et $modeTableau FALSE, retourne un tableau associatif ayant pour cls les valeurs du premier champ et pour valeurs celles du second champ. Dans le cas denregistrements avec deux champs et $modeTableau TRUE, retourne un tableau associatif ayant pour cls les valeurs du premier champ et pour valeur un tableau contenant les valeurs du second champ correspondant. Dans le cas denregistrements avec plus de trois champs, retourne un tableau associatif ayant pour cls les valeurs du premier champ et pour valeur un tableau contenant les valeurs des autres champs correspondants. En cas derreur, retourne un objet DB_Error. noter : sil y a des doublons dans les valeurs du premier champ, seuls les derniers enregistrements associs ces valeurs doublons sont conservs.

$parametres retour

DB->getAll()
Retourne lensemble des enregistrements retourns par une requte sous la forme dun tableau index. Syntaxe $requete $parametres array getAll(mixed $requete [, array $parametres [, int $mode]]) Requte SQL, ou identifiant dune requte prpare tel que retourn par DB>prepare(). Paramtres de la requte prpare.

882

Les couches dabstraction

$mode

Dtermine le format de la rponse ; cela peut prendre lune des valeurs suivantes : DB_FETCHMODE_ASSOC pour restituer les enregistrements sous la forme dun tableau index contenant un tableau associatif o les cls sont les noms de champs. DB_FETCHMODE_ORDERED pour restituer les enregistrements sous la forme dun tableau index contenant un tableau index associ aux valeurs des champs (dans lordre de la requte). DB_FETCHMODE_FLIPPED combin par OU logique avec les modes ci-dessus permet dintervertir les rles des champs et enregistrements dans le tableau. (Avec DB_FETCHMODE_ASSOC cela donne un tableau associatif, o les cls sont les noms des champs, contenant un tableau index des valeurs pour chaque enregistrement. Avec DB_FETCHMODE_ORDERED, cela donne un tableau index (o chaque entre reprsente un champ, dans lordre de la requte) contenant les valeurs pour chaque enregistrement. DB_FETCHMODE_DEFAULT (valeur par dfaut si la mthode setFetchMode() na pas t appele) pour restituer lenregistrement sous sa forme par dfaut (probablement DB_FETCHMODE_ORDERED).

10. Lutilisation des bases de donnes

retour

Un tableau dont la structure dpend du mode choisi, ou un objet DB_Error en cas derreur.

Nombre denregistrements
Nombre denregistrements retourns
Il existe trois faons de dterminer le nombre denregistrements retourns par une requte. Si vous souhaitez uniquement connatre le nombre denregistrements, mais ne souhaitez pas immdiatement lire ces enregistrements, alors il vous suffit de faire une requte COUNT() comme suit :

Listing 10.105 : count_bd_inc.php


<?php require_once("DB.php"); /** * Fonction affichant le nombre denregistrements * dans une table * * @param $bd object Base de donnes * @param $table string Nom de la tabme **/ function EX_compte($bd, $table) { // Requte $requete = "SELECT COUNT(*) FROM $table";

883

Chapitre 10

Lutilisation des bases de donnes

$resultat = $bd->getOne($requete); if (DB::isError($resultat)) return FALSE; echo "Il y a $resultat enregistrements dans la table.<br />"; return TRUE; } ?>

10. Lutilisation des bases de donnes

Il est galement envisageable de les compter au fur et mesure de leur lecture (sils sont lus, par exemple, avec la mthode getRow()). Mais, surtout, ce que vous attendez tous : si vous souhaitez connatre le nombre denregistrements avant de les lire, vous pouvez faire appel la mthode DB_Result>numRows().

DB_Result->numRows()
Indique le nombre denregistrements retourns par une requte. Syntaxe retour int numRows(void) Nombre denregistrements retourns, ou un objet DB_Error en cas derreur.

Listing 10.106 : count_num_rows_bd_inc.php


<?php require_once("DB.php"); /** * Fonction affichant le nombre denregistrements * dans une table * * @param $bd object Base de donnes * @param $table string Nom de la tabme **/ function EX_compte($bd, $table) { // Requte $requete = "SELECT * FROM $table"; $resultat = $bd->query($requete); if (DB::isError($resultat)) return FALSE; echo "Il y a ".$resultat->numRows()." enregistrements". " dans la table.<br />"; return TRUE; } ?>

884

Les couches dabstraction

Sachant quune requte SELECT * est plus longue quune requte SELECT COUNT(*), privilgiez la premire mthode si vous navez que faire du contenu des enregistrements.

Nombre denregistrements modis


Pour dterminer le nombre denregistrements modifis, vous pouvez appeler la mthode DB>affectedRows().

10. Lutilisation des bases de donnes

DB->affectedRows()
Indique le nombre denregistrements modifis lors de lexcution de la requte (de type INSERT, UPDATE). Syntaxe retour int affectedRows(void) Nombre denregistrements modifis ou un objet DB_Error en cas derreur.

Mise prot des requtes prpares


Certains serveurs de bases de donnes permettent lanalyse, la compilation et le stockage des requtes avant utilisation. Ceci permet dexcuter une srie de requtes similaires sans avoir renouveler chaque fois les oprations danalyse et de compilation (mais seulement en changeant certaines valeurs). Mme si cela ne sapplique que pour certains serveurs, les mthodes qui suivent restent applicables quelle que soit la base de donnes (couche dabstraction oblige). Pour les bases de donnes ne supportant pas les requtes prpares, cela sera tout simplement mul. Pour cela, il suffit de prparer une requte dans laquelle les lments variables sont remplacs par des points dinterrogation (ex. : INSERT INTO matable (film) VALUES (?)). Il suffira de prciser ces valeurs au moment de son excution. La prparation de la requte se fait via la fonction DB>prepare().

DB->prepare()
Prpare une requte SQL. Syntaxe $requete retour resource prepare(string $requete) Requte SQL prparer. Identifiant de la requte prpare (ce nest pas une vritable ressource, mais plutt un index si la base de donnes ne supporte pas les requtes prpares).

Lexcution proprement dite est assure par DB>execute().

885

Chapitre 10

Lutilisation des bases de donnes

DB->execute()
Excute une requte prpare. Syntaxe object execute(resource $idRequetePreparee, array $parametres) Tableau index contenant les valeurs des diffrents paramtres de la requte prpare. La constante DB_OK en cas de succs dune requte ne retournant pas de rsultat, un objet DB_Result en cas de succs dune requte retournant un rsultat, un objet DB_Error sinon.

10. Lutilisation des bases de donnes

$idRequetePreparee Identifiant de la requte prpare. $parametres retour

Mais il est galement possible denchaner automatiquement plusieurs appels.

DB->executeMultiple()
Excute une requte prpare pour lensemble des donnes dun tableau. Syntaxe object executeMultiple(resource $idRequetePreparee, array $parametres) Tableau index contenant une entre par requte excuter. Chaque entre contient un tableau contenant les valeurs des diffrents paramtres de la requte prpare. La constante DB_OK en cas de succs dune requte ne retournant pas de rsultat, un objet DB_Result en cas de succs dune requte retournant un rsultat, un objet DB_Error sinon.

$idRequetePreparee Identifiant de la requte prpare. $parametres

retour

Un exemple dutilisation est donn plus loin avec le script compteurclic.

Champs auto-increments
Une des difficults rencontres pour crer des scripts utilisables avec diffrents serveurs de bases de donnes concerne les champs auto-incrments. La solution propose par la bibliothque PEAR consiste crer une squence.

DB->createSequence()
Cre une squence. Syntaxe mixed createSequence(string $nom)

886

Les couches dabstraction

$nom retour

Nom de la squence. DB_OK en cas de succs, un objet DB_Error sinon.

Concrtement, cela se traduit par la cration dune squence pour les bases de donnes supportant ce type dobjet ; pour les autres, une table simulant une squence est cre (ce qui est le cas pour MySQL. La table porte alors le nom indiqu accompagn du suffixe "_seq").

10. Lutilisation des bases de donnes

Malheureusement, ceci ne constitue quune solution de remplacement aux champs auto-incrments. Ds lors, plus rien nest automatique, et vous devez, avant chaque insertion dans la table, rcuprer la valeur suivante de la squence. Cela seffectue par un appel la mthode nextId().

DB->nextId()
Rcupre la valeur suivante dune squence. Syntaxe $nom retour int nextId(string $nom) Nom de la squence. Valeur suivante, ou un objet DB_Error en cas dchec.

Vous pouvez galement supprimer une squence.

DB->dropSequence()
Supprime une squence. Syntaxe $nom retour mixed dropSequence(string $nom) Nom de la squence supprimer. DB_OK en cas de succs, un objet DB_Error sinon.

Un exemple dutilisation des squences est donn plus loin avec le script compteurclic.

Traitement des chanes de caractres

DB->escapeSimple()
Prpare une chane de caractres pour une insertion dans une requte SQL (par "chappement" des caractres particuliers comme les guillemets ou apostrophes). En dautres termes il sagit dun quivalent des fonctions mysql_escape_string(), sqlite_escape_string(), etc.

887

Chapitre 10

Lutilisation des bases de donnes

Syntaxe $nom retour

string escapeSimple(string $nom) Chane de caractres traiter. La chane de caractres prte tre insre dans une requte SQL.

Gestion des erreurs


10. Lutilisation des bases de donnes
Afin de dterminer si la valeur retourne par une mthode est un objet DB_Error ou non, lobjet DB vous propose la mthode DB::isError().

DB::isError()
Teste si largument est un objet DB_Error ou non. Syntaxe $argument retour boolean isError(mixed $argument) Argument tester. TRUE sil sagit dun objet DB_Error, FALSE sinon.

Il est cependant possible de dterminer plus prcisment lorigine de lerreur. Il est notamment possible de lire le contenu de lobjet DB_Error. DB_Error est ainsi compos (entre autres) des attributs :
j
level, niveau derreur parmi :

1024 erreur ;
DB_WARNING (-1 000) avertissement ; DB_WARNING_READ_ONLY (-1 001) avertissement.

code, une des valeurs suivantes :

DB_ERROR (-1) erreur inconnue ; DB_ERROR_SYNTAX (-2) la requte comporte une erreur de syntaxe ; DB_ERROR_CONSTRAINT (-3) violation de contrainte ; DB_ERROR_NOT_FOUND (-4) la base nexiste pas ; DB_ERROR_ALREADY_EXISTS (-5) une requte CREATE a t demande pour une table,

squence, etc. existant dj ;


DB_ERROR_UNSUPPORTED (-6) ; DB_ERROR_MISMATCH (-7) ; DB_ERROR_INVALID (-8) ; DB_ERROR_NOT_CAPABLE (-9) ; DB_ERROR_TRUNCATED (-10) la mthode DB>getAssoc() a t appele alors que le rsultat ne comporte quun seul champ ; DB_ERROR_INVALID_NUMBER (-11) ;

888

Les couches dabstraction

DB_ERROR_INVALID_DATE (-12) ; DB_ERROR_DIVZERO (-13) division par zro ; DB_ERROR_NODBSELECTED (-14) aucune base slectionne ; DB_ERROR_CANNOT_CREATE (-15) ; DB_ERROR_CANNOT_DELETE (-16) ;

10. Lutilisation des bases de donnes

DB_ERROR_CANNOT_DROP (-17) ; DB_ERROR_NOSUCHTABLE (-18) lune des tables nexiste pas ; DB_ERROR_NOSUCHFIELD (-19) lun des champs nexiste pas ; DB_ERROR_NEED_MORE_DATA (-20) ; DB_ERROR_NOT_LOCKED (-21) ; DB_ERROR_VALUE_COUNT_ON_ROW (-22) ; DB_ERROR_INVALID_DSN (-23) paramtre $baseDeDonnees de DB>connect() non

valide ;
DB_ERROR_CONNECT_FAILED (-24) ; DB_ERROR_EXTENSION_NOT_FOUND (-25) ; DB_ERROR_NOSUCHDB (-25 sic) ; DB_ERROR_ACCESS_VIOLATION (-26) ; message, le message derreur ; nativecode, (si disponible) le code derreur retourn par la base de donnes +" ** "+ le message derreur (du moins avec MySQL).

Exemples dapplications
Nous ne reviendrons pas en dtail sur les scripts suivants, car ils concernent des exemples prsents dans les chapitres traitant des diffrentes bases de donnes. Nous supposons que vous vous tes pench sur le cas dau moins une de ces bases et que vous avez, par consquent, compris le mode de fonctionnement de ces scripts. Nous nous contenterons donc de vous prsenter les corrections apporter pour lutilisation de la bibliothque Dbx.

Compteur de clics
Le script compteurclic_bd_inc.php deviendra ainsi :

Listing 10.107 : compteurclic_bd_inc.php


<?php require_once("DB.php"); //-----------------------------------// Charge les paramtres de connexion // la base de donnes. //-----------------------------------require_once("parametres_bd_inc.php");

889

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

/** * Fonction de connexion une base de donnes * sappuie sur les paramtres fournis * dans parametres_bd_inc.php. * * @return object Objet DB (base de donnes) */ function CC_connexion() { global $typeServeur, $serveur, $base, $utilisateur, $motDePasse; switch ($typeServeur) { case "IBMDB2" : case "MSAccess" : $typeServeurPear = "odbc"; break; default : $typeServeurPear = $typeServeur; } $dsn = "$typeServeurPear://"; if (!empty($utilisateur)) $dsn .= $utilisateur; if (!empty($motDePasse)) $dsn .= ":$motDePasse"; $dsn .= "@tcp($serveur)"; if (!empty($base)) $dsn .= "/$base"; $bd = DB::connect($dsn, TRUE); if (DB::isError($bd)) { echo $bd->message; return FALSE; } return $bd; } /** * Fonction de deconnexion. * (Ne fait rien sachant que la fonction * de connexion tablit une connexion persistante) */ function CC_deconnexion($bd) { return TRUE; } /** * Fonction charg de crer et dalimenter * la table "compteur de clics" **/ function CC_initialiseBD($bd, $table) {

890

Les couches dabstraction

global $typeServeur; $default = "DEFAULT 0";

// Cration de la table $requete = "DROP TABLE $table"; @$bd->query($requete); $requete = "CREATE TABLE $table (". "urlId INTEGER PRIMARY KEY,". "url VARCHAR(128) NOT NULL,". "nbclic INTEGER $default,". "UNIQUE(url))"; $sts = $bd->query($requete); if (DB::isError($sts)) { echo $sts->message; return FALSE; } $bd->dropSequence($table); $sts = $bd->createSequence($table); if (DB::isError($sts)) { echo $sts->message; return FALSE; } // Alimentation de la table $requete = "INSERT INTO $table (urlId,url) VALUES (?,?)"; $reqPreparee = $bd->prepare($requete); $tabUrl = array ( array ($bd->nextId($table), http://www.php.net), array ($bd->nextId($table), http://www.phpfacile.com), array ($bd->nextId($table), http://www.sqlfacile.com), array ($bd->nextId($table), http://www.xmlfacile.com), array ($bd->nextId($table), http://www.ootoogo.com) ); $sts = $bd->executeMultiple($reqPreparee, $tabUrl); if (DB::isError($sts)) { echo $sts->message; return FALSE; } return TRUE; } /** * Fonction retournant les informations de liens * sous forme dun tableau associatif possedants * les cls

10. Lutilisation des bases de donnes 891

Chapitre 10

Lutilisation des bases de donnes

* - "lien" associ au tableau des liens hypertextes * - "nbclic" associ au tableau des nombres de clics **/ function CC_recupereLiens($bd, $table) { // Nom du script charg du comptage et de la redirection $script = "compteurclic_redirection.php";

10. Lutilisation des bases de donnes

// Requte SELECT $requete = "SELECT * FROM $table"; $resultat = $bd->query($requete); if (DB::isError($resultat)) return FALSE; // Rcupration des enregistrements les uns aprs les autres while ($enreg = $resultat->fetchRow(DB_FETCHMODE_ASSOC)) { $liens["lien"][] = "<a href=\"$script?urlid=". $enreg["urlId"]."\">". $enreg["url"]."</a>"; $liens["nbclic"][] = $enreg["nbclic"]; } return $liens; } /** * Fonction rcuprant une url partir de son identifiant * et incrmentant le compteur de clics **/ function CC_recupereUrl($bd, $urlid) { global $table; // Rcupre lurl $requete = "SELECT * FROM $table WHERE urlid=$urlid"; $enreg = $bd->getRow($requete, NULL, DB_FETCHMODE_ASSOC); if (DB::isError($enreg)) return FALSE; if ($enreg) { $url = $enreg["url"]; // Incrmente le compteur $requete = "UPDATE $table SET nbclic=nbclic+1 WHERE urlid=$urlid"; $bd->query($requete); } else { $url = FALSE; } return $url; } ?>

892

Les couches dabstraction

Grce lutilisation des squences PEAR, ce script pourrait sadapter diffrents types de bases de donnes, puisquil saffranchit des disparits existantes dans la dclaration des champs auto-incrments. Mais, malheureusement, cela nest pas suffisant, puisquil devrait tre galement adapt, par exemple, pour MS Access, qui ne supporte pas linstruction SQL "DEFAULT". Il devrait de mme tre adapt pour MS SQL Server, puisque nous avons constat un dysfonctionnement li lutilisation des mthodes prepare(), execute() ou executeMultiple(). La couche dabstraction PEAR ne permet donc pas de pallier tous les problmes de compatibilit. Les scripts contenant les fonctions daffichage, quant eux, ne sont pas modifis (do lintrt de les dissocier des fonctions de traitement). Dailleurs, les scripts principaux ne le sont pas non plus, puisquils naccdent pas directement la base de donnes, nappellant que des fonctions de "haut niveau".

10. Lutilisation des bases de donnes

SuperTheque
Lessentiel du code de lapplication a t prsent en introduction de ce chapitre. Il ne restait plus qu connatre les fonctions PEAR DB pour implmenter linterface RessourceInterface cest dsormais chose faite:

Listing 10.108 : RessourcePEARDB_class.php


<?php include_once("RessourceInterface_class.php"); include_once(dirname(__FILE__)."/../config/peardb_cfg.php"); include_once("DB.php"); /** * RessourcePEARDB_class.php * Classe dacces a une base de donnees via PEARDB * Cette classe doit implementer toutes les methodes de linterface * RessourceInterface. * Compatibilite: PHP 5 */ class Ressource implements RessourceInterface { var $bd; public function connexion() { global $pear_typeServeur; global $pear_serveur, $pear_utilisateur, $pear_motDePasse; global $pear_base; switch ($pear_typeServeur) { case "IBMDB2" : case "MSAccess" : $typeServeurPear = "odbc"; break; default : $typeServeurPear = $pear_typeServeur;

893

Chapitre 10

Lutilisation des bases de donnes

} $dsn = "$typeServeurPear://"; if (!empty($pear_utilisateur)) $dsn .= $pear_utilisateur; if (!empty($pear_motDePasse)) $dsn .= ":$pear_motDePasse"; $dsn .= "@tcp($pear_serveur)"; if (!empty($pear_base)) $dsn .= "/$pear_base";

10. Lutilisation des bases de donnes

$bd = DB::connect($dsn, TRUE); if (DB::isError($bd)) { echo $dsn." ".$bd->message; return FALSE; } $this->bd = $bd; return TRUE; } public function deconnexion() { // Rien a faire, il sagit dune connexion persistante } public function reset() { $requete = "DROP TABLE types"; $resultat = $this->bd->query($requete); // Pas de raison de retourner un erreur // si la suppression echoue (si la table nexiste pas) $requete = "CREATE TABLE types (". "id INTEGER PRIMARY KEY,". "type VARCHAR(255))"; $resultat = $this->bd->query($requete); if (DB::isError($resultat)) { echo $resultat->message; return FALSE; } $this->bd->dropSequence("types"); $resultat = $this->bd->createSequence("types"); if (DB::isError($resultat)) { echo $resultat->message; return FALSE; }

$types = array("Album", "Film", "Livre", "Musique"); foreach ($types as $type) { $requete = "INSERT INTO types (id, type) VALUES (". $this->bd->nextId("types").",$type)";

894

Les couches dabstraction

$resultat = $this->bd->query($requete); if (DB::isError($resultat)) { echo $resultat->message; return FALSE; } }

10. Lutilisation des bases de donnes

$requete = "DROP TABLE articles"; $resultat = $this->bd->query($requete); // Pas de raison de retourner un erreur // si la suppression echoue (si la table nexiste pas) $requete = "CREATE TABLE articles (". "id INTEGER PRIMARY KEY,". "albumId INTEGER,". "titre VARCHAR(255),". "typeId INTEGER,". "commentaire VARCHAR(255))"; $resultat = $this->bd->query($requete); if (DB::isError($resultat)) { echo $resultat->message; return FALSE; } $this->bd->dropSequence("articles"); $resultat = $this->bd->createSequence("articles"); if (DB::isError($resultat)) { echo $resultat->message; return FALSE; } } public function addArticle($albumId, $titre, $typeId, $commentaire) { $requeteDebut = "INSERT INTO articles (id, albumId, titre, typeId"; $requeteFin = ") VALUES (".$this->bd->nextId("articles").",". "$albumId,". "".$this->bd->escapeSimple($titre).",". "$typeId"; if ($commentaire != "") { $requeteDebut .= ",commentaire"; $requeteFin .= ",".$this->bd->escapeSimple($commentaire).""; } $requete = $requeteDebut . $requeteFin . ")"; $resultat = $this->bd->query($requete); if (DB::isError($resultat)) { echo $resultat->message;

895

Chapitre 10

Lutilisation des bases de donnes

return FALSE; } } public function getArticle($articleId) { $requete = "SELECT * FROM articles WHERE id=$articleId"; $resultat = $this->bd->query($requete); if (DB::isError($resultat)) { echo $resultat->message; return FALSE; } $enreg = $this->bd->getRow($idResultat); if (DB::isError($enreg)) return NULL; $article = $this->enreg2Article($enreg); return $article; } public function getArticles(Filtre $filtre, Plage $plage, Tri $tri) { $requete = "SELECT * FROM articles"; if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". $this->bd->escapeSimple($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL. " AND typeId=".$filtre->getTypeId(); } if ($tri->getSens() == -1) { $triSQL = "ORDER BY ".$tri->getChamp()." DESC"; } else if ($tri->getSens() == 1) { $triSQL = "ORDER BY ".$tri->getChamp()." ASC"; } $requete = $requete." WHERE ".$conditionSQL." ". $triSQL; $resultat = $this->bd->limitQuery($requete, $plage->getPremierArticle(), $plage->getNbArticleMax()); if (DB::isError($resultat)) { echo $resultat->message; return FALSE; } $articles = NULL;

10. Lutilisation des bases de donnes 896

Les couches dabstraction

while ($enreg = $resultat->fetchRow(DB_FETCHMODE_ASSOC)) { $articles[] = $this->enreg2Article($enreg); } return $articles; } public function getNbTotalArticles(Filtre $filtre) { $requete = "SELECT COUNT(*) FROM articles"; if ($filtre->getAlbumId() != -1) { $conditionSQL = "albumId=".$filtre->getAlbumId(); } if ($filtre->getTitre() != "") { $conditionSQL = $conditionSQL. " AND titre LIKE ". $this->bd->escapeSimple($filtre->getTitre()).""; } if ($filtre->getTypeId() != -1) { $conditionSQL = $conditionSQL. " AND typeId=".$filtre->getTypeId(); } $requete = $requete." WHERE ".$conditionSQL; $resultat = $this->bd->getOne($requete); if (DB::isError($resultat)) { echo $resultat->message; return FALSE; } return $resultat; } public function getTypes() { $requete = "SELECT * FROM types"; $resultat = $this->bd->query($requete); if (DB::isError($resultat)) { echo $resultat->message; return FALSE; } $types = NULL; while ($enreg = $resultat->fetchRow(DB_FETCHMODE_ASSOC)) { $types[$enreg["id"]] = $enreg["type"]; } return $types; } public function getAlbumTypeId() { return 1; }

10. Lutilisation des bases de donnes 897

Chapitre 10

Lutilisation des bases de donnes

10. Lutilisation des bases de donnes

private function enreg2Article($enreg) { $article = new Article(); $article->setId($enreg["id"]); $article->setAlbumId($enreg["albumId"]); $article->setTitre($enreg["titre"]); $article->setTypeId($enreg["typeId"]); $article->setCommentaire($enreg["commentaire"]); return $article; } }

En revanche, lutilisation des mthodes PEAR permettant la manipulation des squences, si elle nest pas optimale, permet toutefois de saffranchir des diffrences entre les serveurs de bases de donnes concernant les champs auto-incrments.

En savoir plus...
Il est possible de rcuprer un certain nombre dinformations sur le serveur de bases de donnes (ses bases, ses tables, etc.) grce la mthode getListOf().

DB->getListOf()
Retourne la liste des bases, tables, etc. Syntaxe $cle array getListOf(string $cle) Mot-cl parmi : "databases" pour rcuprer un tableau index des bases disponibles sur le serveur. "tables" pour rcuprer un tableau index des tables disponibles dans la base laquelle vous tes connect. "users" pour rcuprer la liste des utilisateurs. "views" pour rcuprer la liste des vues disponibles dans la base laquelle vous tes connect. "functions" pour rcuprer la liste des fonctions. retour Le tableau index demand, ou DB_Error en cas dchec.

Il est galement possible de tester les fonctionnalits offertes par le serveur de bases de donnes ou la faon dont PEAR les gre.

898

Les couches dabstraction

DB->provides()
Teste la gestion dune fonctionnalit par PEAR ou le serveur de bases de donnes. Syntaxe $fonctionnalite retour string provides(string $fonctionnalite) Fonctionnalit tester (ex. : "transactions", "limit", etc.) Selon les cas : TRUE si la fonctionnalit est supporte par le serveur de bases de donnes. "alter" si PEAR a besoin de modifier la requte de lutilisateur pour lutiliser. "emulate" si PEAR mule la fonctionnalit. FALSE si elle nest pas supporte par le serveur. DB_error en cas dchec. "prepare", "pconnect",

10. Lutilisation des bases de donnes 899

Chapitre 11

Les annuaires LDAP


11.1 11.2 11.3 11.4 Le schma LDAP . . . . . . . . . . . Installation . . . . . . . . . . . . . . Linterrogation de LDAP avec PHP Exemple dapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905 905 908 938

ux origines du standard LDAP, on retrouve des organisations internationales de normalisation. En effet, de grands groupes de tlcommunications ainsi que lInternational Organization for Standardization (ISO), avaient la volont de normaliser le protocole de messagerie. Aprs la publication de leurs travaux (la norme X400), ils dvelopprent la norme cense interconnecter les annuaires des diffrents pays. Cest ainsi que naquirent les normes X500.

Protocole LDAP LDAP (Lightweight Directory Access Protocol) est un protocole permettant la standardisation de laccs des donnes provenant dun annuaire, permettant ainsi diffrentes applications daccder une source commune. 11. Les annuaires LDAP
Avec cette norme, il tait enfin possible dinterroger, partir de nimporte quelle application, tous les annuaires mondiaux ; ce qui pouvait donc, terme, permettre de crer un vaste rpertoire mondial.

Figure 11.1 : Principe dun annuaire X500

Une application cliente peut interroger lannuaire laide du protocole DAP (Directory Access Protocol). Lapplication passe alors par une couche dabstraction : le DUA (Directory User Agent). Celui-ci interroge ensuite lannuaire et retourne les informations au DUA, qui effectue alors le travail inverse en retournant les donnes au client. Ainsi, toutes les applications voulant profiter dun annuaire central devaient simplement dvelopper la couche dabstraction laide dune API (voir fig. 11.2). Lun des intrts du protocole X500 est galement la possibilit de placer diffrents serveurs dannuaires en parallle, les annuaires dialoguant entre eux laide du protocole DSP (Directory System Protocol). Les normes X500 ont galement standardis le schma que peut avoir un annuaire. Les diffrentes donnes sont organises suivant leur appartenance des classes dobjets, qui elles-mmes sont dfinies par diffrents attributs. Ces attributs peuvent possder une ou plusieurs valeurs. Chaque classe dfinie par rapport une classe parente hrite de tous les attributs de la classe mre dont elle drive. Afin dviter certains problmes, la norme a galement adopt la standardisation des annuaires dcrivant les personnes, les organisations, etc.

903

Chapitre 11

Les annuaires LDAP

11. Les annuaires LDAP

Figure 11.2 : Exemple dapplication dun annuaire au sein dune entreprise

La complexit de la mise en uvre dun schma complet rend son utilisation complexe pour une petite structure de type PMI ou PME. De plus, le DAP permettant la connexion des clients se trouve tre trs complexe utiliser, car il ncessite lquipement du poste client en matriel spcifique. En effet, le protocole nutilise pas TCP/IP, et, de ce fait, il est ncessaire dintgrer sur les clients une carte rseau de type X25. Larrive en force dInternet pousse donc un nouveau groupe se pencher sur la problmatique. Ainsi, en se basant sur les normes X500 et le support du protocole TCP/IP, est publie la version 2 de LDAP en 1994, puis la version 3 en 1997. Vous pouvez retrouver les spcifications (en anglais) de cette dernire version dans les RFC qui vont de 2251 2256 aux adresses allant de http://www.ietf.org/rfc/rfc2251.txt http://www .ietf.org/rfc/rfc2256.txt. (des traductions en franais sont disponibles au format PDF depuis des liens proposs sur http://abcdrfc.free.fr). Les avantages de cette norme sont :
j j j j j

Support du modle de donnes X500 ; Ouverture sur linternet par son support TCP/IP ; Scurisation de laccs aux donnes par personne ou groupe de personnes ; Les requtes sont normalises permettant ainsi une recherche plus efficace ; LDAP permet linterrogation de plusieurs annuaires de faon transparente pour le client.

Il existe plusieurs annuaires. Des annuaires commerciaux (sites en anglais) :


j j j j j

eDirectory de Novell (http://www.novell.com/products/edirectory/) ; Active Directory de Microsoft (http://www.microsoft.com/windows2000/technologies/directory/AD/default.asp) ; SunOne Directory Server de Sun (http://wwws.sun.com/software/products/directory_srvr/home_directory.html) ; Oracle (http://www.oracle.com) ; IBM Directory Server (http://www-3.ibm.com/software/network/directory/).

Ainsi que quelques (trop) rares annuaires libres (sites en anglais) :

904

Installation

j j

OpenLDAP (http://www.openldap.org) ; Apple Open Directory (http://developer.apple.com/darwin/projects/opendirectory/).

11.1. Le schma LDAP


Le principe de LDAP est expliqu partir de ce schma :

11. Les annuaires LDAP

Figure 11.3 : Vision classique dun annuaire LDAP

Afin de nommer chaque classe, on utilise un ou plusieurs attributs les dfinissant. Ainsi, on commence par la classe racine qui possde un DN (Distinguished Name) gal dc=universite, dc=fr. Suivent les classes reprsentes par leur RDN (Relative Distinguished Name), le DN unique dune entre tant lajout de son RDN au DN de la classe mre de lobjet spar par une virgule. Ainsi, lentre reprsente par le RDN gal ou=tudiants possde un DN quivalent ou=tudiants, dc=universite, dc=fr. Ainsi, le DN de ltudiant 1 est : cn=tudiant 1, ou=tudiants, dc=universite, dc=fr. Le DN du professeur 2 est : cn=prof 2, ou=Professeurs, dc=universite, dc=fr. Nous navons pas la prtention dans cet ouvrage de vous faire connatre sur le bout des doigts le protocole LDAP et son utilisation. Internet regorge de liens qui devraient pouvoir vous tre utiles dans votre apprentissage des annuaires. Vous pouvez toujours commencer par visiter le site web du CRU (Comit Rseau des Universits), qui possde une page trs intressante avec de nombreux liens et de documents : http://www.cru.fr/ldap/.

11.2. Installation
Nous nous contenterons ici de dcrire une installation standard sans tenir compte des problmes doptimisation et de scurit. Le but est que vous puissiez installer PHP et LDAP sur des machines de test, pour vous familiariser avec cet environnement avant de passer un serveur dannuaire destin la production. Pour des raisons de cot videntes, nous avons opt pour un serveur OpenLDAP.

Installation du serveur OpenLDAP


Linstallation du serveur LDAP est facilite par sa mise disposition sur certaines distributions Linux. Malgr tout, pour ceux qui dsirent compiler le serveur pour leur plateforme (par

905

Chapitre 11

Les annuaires LDAP

exemple pour ceux qui utilisent un environnement Windows avec Cygwin install), nous allons rapidement dcrire son installation standard.

Installation
Vous devez, avant toute chose, rcuprer larchive qui se trouve sur le site dOpenLDAP ladresse http://www.openldap.org/software/download/ (nous mettons votre disposition la version 2.1.3 sur le CD-ROM daccompagnement de ce livre). Dans un premier temps, dcompactez larchive laide de la commande suivante :
$ tar zxvf openldap-2.1.3.tgz $ cd openldap-2.1.3

11. Les annuaires LDAP

Passez ensuite la configuration, puis la compilation.


$ ./configure $ make depend $ make

Passez en mode administrateur en tapant la commande su et en entrant votre mot de passe root.
# make install

Conguration
Ouvrez ensuite votre diteur ftiche, et ditez le fichier /usr/local/etc/openldap/slapd.conf. Modifiez les paramtres suffix, rootdn et rootpw de la faon suivante :
# Indiquez ici la racine correspondant votre domaine suffix "dc=ldap, dc=tild, dc=com" # Indiquez ici le DN de ladministrateur de lannuaire rootdn "cn=root, dc=ldap, dc=tild, dc=com" # Indiquez ensuite le mot de passe de ladministrateur rootpw coucou

Dans notre cas, le domaine spcifi est ldap.tild.com (ces paramtres doivent indiquer le nom de votre domaine). Vrifiez que le rpertoire spcifi par le paramtre directory existe bien. Lancez le serveur LDAP avec la commande :
/usr/local/libexec/slapd

Vous pouvez vrifier que le serveur est bien lanc en excutant la commande suivante :
ldapsearch -xs base (objectclass=*) namingContexts

La commande doit vous retourner un rsultat similaire celui-ci :


#

906

Installation

# filter: (objectclass=*) # requesting: namingContexts # # ldap,dc=tild,dc=com dn: dc=ldap,dc=tild,dc=com # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1

11. Les annuaires LDAP

Il faut ensuite crer le schma racine de lannuaire. Pour cela, vous allez crer un fichier texte au format LDIF. Ouvrez votre diteur (toujours le mme, ou changez si vous voulez) et entrez les lignes suivantes :
dn: dc=ldap,dc=tild,dc=com objectclass: dcObject objectclass: organization o: Tild dc: tild dn: cn=root,dc=ldap,dc=tild,dc=com objectclass: organizationalRole cn: root

Enregistrez-le sous monpremierschema.ldif par exemple, et appelez la commande suivante :


ldapadd -x -D " cn=root,dc=ldap,dc=tild,dc=com" -W -f monpremierschema.ldif

Voil, votre annuaire est prt recevoir de nouvelles entres. Maintenant, nous nallons pas continuer les ajouter avec le client ldapadd : prfrons (cest un peu le sujet de ce livre) utiliser le langage PHP. Mais avant toute chose, installons le module LDAP.

Installation du module LDAP pour PHP


Installation sous Windows
Avec larchive du PHP Group
Vous devez, dans un premier temps, vous assurer de possder un fichier php_ldap.dll (fourni avec larchive du PHP Group) dans le rpertoire contenant vos extensions PHP. Il vous suffit ensuite de modifier le fichier php.ini pour ajouter ou dcommenter une ligne.
extension=php_ldap.dll

907

Chapitre 11

Les annuaires LDAP

Avec EasyPHP
Linstallation dEasyPHP possde, par dfaut, le module de connexion LDAP.

Installation sous Linux


Pour installer le module LDAP, vous devez possder les librairies installes sur votre machine. Si vous avez suivi linstallation du serveur LDAP de notre premire partie, vous les possdez certainement. Ensuite, recompilez PHP avec loption suivante : --with-ldap.

11. Les annuaires LDAP

Vous pouvez vrifier la bonne installation du module en crant une page qui ne contient que le code suivant :
<?php phpinfo(); ?>

Lancez un navigateur et appelez la page. Vous devez apercevoir les lignes suivantes :

Figure 11.4 : La fonction phpinfo() vous renseigne sur les modules qui sont installs.

Vrifiez que la section LDAP existe.

11.3. Linterrogation de LDAP avec PHP


Lutilisation simple de PHP pour interroger un annuaire LDAP sopre selon le schma suivant :
j j j j

Connexion un serveur LDAP ; Identification sur serveur ; Oprations sur la base LDAP ; Fermeture de la connexion avec le serveur LDAP.

Connexion, authentication et dconnexion sur le serveur LDAP


Connexion sur lannuaire
Pour vous connecter au serveur LDAP, vous devrez utiliser la fonction ldap_connect().

908

Linterrogation de LDAP avec PHP

ldap_connect()
tablit une connexion entre le client (PHP) et lannuaire LDAP. Syntaxe $serveur $port retour resource ldap_connect([string $annuaire [, int $port]]) Adresse de lannuaire LDAP. Par dfaut, la connexion seffectue sur le serveur local. Port sur lequel on doit se connecter. Par dfaut, le port est le 389. Identifiant de la connexion lannuaire.

11. Les annuaires LDAP

Grer lerreur de connexion Lorsque le serveur nexiste pas ou que la connexion na pas t effectue, linstruction ldap_connect() ne retourne pas derreur. Pour grer les erreurs de liaison avec lannuaire, vous devez, au pralable, excuter la fonction ldap_bind().

Authentication sur un annuaire


Linstruction ldap_bind() vous permettra de vous identifier auprs du serveur LDAP.

ldap_bind()
Effectue une liaison entre lannuaire et le client LDAP (PHP dans notre cas). Syntaxe $idLdap $dnUtilisateur boolean ldap_bind(resource $idLdap [, string $dnUtilisateur [, string $motDePasse]]) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). DN (Distinguished Name) de lutilisateur qui demande la connexion. Ce paramtre est optionnel ; si vous ne le prcisez pas, la connexion seffectuera en mode anonyme. Mot de passe de lutilisateur demandant la connexion. Ce paramtre est optionnel. TRUE si la liaison avec lannuaire a t effectue, FALSE dans le cas contraire.

$motDePasse retour

Dconnexion de lannuaire
La dconnexion de lannuaire seffectue avec la fonction ldap_unbind() ou son alias ldap_close().

909

Chapitre 11

Les annuaires LDAP

ldap_close()
Se dconnecte du serveur LDAP. Syntaxe $idLdap retour boolean ldap_unbind(resource $idLdap) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). TRUE si la connexion a bien t ferme, FALSE dans le cas contraire.

11. Les annuaires LDAP

Changer le DN de la connexion LDAP Ne confondez pas ldap_unbind() avec une fonction qui pourrait permettre de changer lutilisateur connect lannuaire. Malgr son nom, linstruction ldap_unbind() ferme la connexion, et vous devrez alors excuter une nouvelle fois la fonction ldap_connect(). Pour changer dutilisateur, appelez simplement de nouveau ldap_bind() avec un nouveau DN.

Oprations sur un annuaire LDAP


Vous pouvez effectuer quatre oprations standard sur les entres dun serveur LDAP :
j j j j

Ajouter une entre ; Modifier une entre ; Supprimer une entre ; Renommer une entre.

Ajouter une entre


Lajout dune entre dans lannuaire seffectue avec linstruction ldap_add().

ldap_add()
Ajoute une entre dans un annuaire. Syntaxe $idLdap $dn $attributs retour boolean ldap_add(resource $idLdap, string $dn, array $attributs) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). DN de lentre ajouter. Tableau associatif contenant les diffrents attributs de lobjet ajouter. TRUE si lobjet a bien t ajout, FALSE dans le cas contraire.

910

Linterrogation de LDAP avec PHP

Pour ajouter une entre, vous devez crer un tableau associatif contenant tous les attributs ajouter en cls ainsi que les valeurs de ces attributs. Si un attribut peut contenir plusieurs valeurs, celles-ci sont alors rentres dans un nouveau tableau.
<?php $attributs[attribut1] = valeur1; $attributs[attribut2] = valeur2; // Attribut contenant plusieurs valeurs $attributs[attribut3][0] = valeur3; $attributs[attribut3][1] = valeur4; ?>

Voici un exemple dajout dans lannuaire avec un script PHP.

11. Les annuaires LDAP

Listing 11.1 : ldap_add.php


<?php // Connexion lannuaire $idLdap = ldap_connect("localhost",389); $rootDn = cn=root,dc=ldap,dc=tild,dc=com; $rootPasse = coucou; if (!ldap_bind($idLdap, $rootDn, $rootPasse)){ die("La connexion na pas t effectue."); } // On construit le tableau avec les diffrents attributs $attributs[o] = Tild; $attributs[givenname] = Laurent; $attributs[street] = 5 rue Nominoe; $attributs[sn] = GUEDON; $attributs[l] = RENNES; $attributs[objectclass] = person; $attributs[mail][0] = tendencies@free.fr; $attributs[mail][1] = laurent@tild.com; $attributs[cn] = lolo; // DN de lentre ajouter $dn = cn=lolo,dc=ldap,dc=tild,dc=com; if (@ldap_add($idLdap, $dn, $attributs)) { echo "Lentre a t ajoute !"; }else{ echo "Problme, lentre na pas t ajoute !"; } // Dconnexion de lannuaire ldap_close($idLdap); ?>

911

Chapitre 11

Les annuaires LDAP

Modier une entre Modier les attributs dune entre


Pour la modification des entres, nous utiliserons la fonction ldap_mod_replace() ou son alias ldap_modify().

ldap_mod_replace()
11. Les annuaires LDAP
Modifie une entre de lannuaire LDAP. Cette fonction peut affecter plusieurs attributs la fois. Syntaxe $idLdap $dn $attributs retour boolean ldap_mod_replace(resource $idLdap, string $dn, array $attributs) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). DN de lentre modifier. Tableau associatif contenant les diffrents attributs de lobjet qui doivent tre modifis. TRUE si lentre a bien t modifie dans lannuaire, FALSE dans le cas contraire.

La cration du tableau $entree est identique celle de ldap_add(). Vous devez spcifier dans le tableau les diffrents attributs qui doivent tre modifis.

Modification dun attribut valeur multiple Attention aux attributs contenant plusieurs valeurs. Si vous ne modifiez quune seule de ces valeurs, alors lattribut supprimera les autres en conservant la valeur modifie. Prenons un exemple et imaginons lentre multiple suivante :
<?php $attributs[mail][0] = "webmaster@tild.com"; $attributs[mail][1] = "info@tild.com"; $attributs[mail][2] = "contact@tild.com"; ?>

Si vous pensez remplacer "contact@tild.com" par "laurent@tild.com", et donc que vous modifiez lentre de cette faon :
<?php $attributs[mail][2] = "laurent@tild.com"; ldap_mod_replace($idLdap, "cn=lolo,dc=ldap,dc=tild,dc=com", $attributs); ?>

vous supprimez alors les autres valeurs de lattribut multiple mail, et ne retrouvez que la valeur "laurent@tild.com". Vous pouvez le vrifier en rentrant la commande sur votre console :

912

Linterrogation de LDAP avec PHP

$ ldapsearch -x -b dc=ldap,dc=tild,dc=com (objectclass=*)

Ajouter des attributs une entre


Linstruction ldap_mod_add() permet dajouter un attribut une entre dj existante.

ldap_mod_add()
Ajoute un attribut une entre de lannuaire LDAP.

11. Les annuaires LDAP

Syntaxe $idLdap $dn $attributs

boolean ldap_mod_add(resource $idLdap, string $dn, array $attributs) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). DN de lentre devant contenir les attributs ajouter. Tableau associatif contenant les diffrents attributs ajouter ainsi que leurs valeurs. Si un attribut est dj existant, la fonction lui ajoute une nouvelle valeur. Il est possible de spcifier lajout dun attribut valeur multiple de la mme faon que linstruction ldap_add(). TRUE si les attributs ont bien t ajouts, FALSE dans le cas contraire.

retour

<?php // Voici le tableau contenant les attributs ajouter $attributs[description] = Un des auteurs de la bible du PHP; // Si lentre existe, alors "tendencies@free.fr" sera // ajout comme une nouvelle valeur de lattribut mail $attributs[mail] = tendencies@free.fr; ldap_mod_add($idLdap, $baseDn, $attributs); ?>

Supprimer les attributs dune entre


Il est aussi possible de supprimer lattribut dune entre existante. Pour cela, nous ferons appel la fonction ldap_mod_del().

ldap_mod_del()
Supprime un attribut dune entre de lannuaire LDAP. Syntaxe $idLdap boolean ldap_mod_del(resource $idLdap, string $dn, array $attributs) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect().

913

Chapitre 11

Les annuaires LDAP

$dn $attributs

DN de lentre contenant les attributs supprimer. Tableau associatif contenant les diffrents attributs supprimer. Les valeurs de chaque attribut doivent tre indiques. Cela permet de supprimer simplement une seule valeur lorsque lattribut en possde plusieurs. Tous les attributs doivent exister ; dans le cas contraire, linstruction retourne une erreur et nen supprimera aucune. TRUE si la ou les attributs dsigns ont bien t supprims, FALSE dans le cas contraire.

retour

11. Les annuaires LDAP

// Voici le tableau contenant les attributs supprimer $entree[description] = Un des auteurs de la bible PHP; $entree[mail] = tendencies@free.fr; $dn = cn=lolo,dc=kangouroo,dc=homelinux,dc=org; if (ldap_mod_del($idLdap, $dn, $entree)) { echo "Les attributs ont t supprims !"; }else{ echo "Problme, les attributs nont pas t supprims !"; }

Supprimer une entre de lannuaire


La suppression dune entre est ralise par lappel la fonction ldap_delete().

ldap_delete()
Supprime une entre dun annuaire LDAP. Syntaxe $idLdap $dn retour boolean ldap_delete(resource $idLdap, string $dn) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Le DN (Distinguished Name) de lentre supprimer. TRUE si lopration de suppression a t excute avec succs, FALSE dans le cas contraire.

Vous ne pouvez pas supprimer une entre qui nest pas vide. Pour effectuer cette opration, vous devez, dans un premier temps, supprimer toutes les entres existantes dans lentre pre. Nous effectuerons cette opration laide dune fonction rcursive.

Listing 11.2 : ldap_delete.inc.php


<?php /** * Fonction de suppression des entres rcursives ou non * @input $dn string le DN de llment supprimer

914

Linterrogation de LDAP avec PHP

* $recursive boolean Indique si la fonction * doit suppprimer rcursivement * @return boolean reussite ou chec de lopration */ function supprimerEntree($idLdap, $dn, $recursive=FALSE) { if ($recursive){ // On rcupre les entres fils $reponse = ldap_list($idLdap, $dn, "ObjectClass=*"); $entree = ldap_get_entries($idLdap, $reponse); for($i=0;$i<$entree[count];$i++){ // On supprime les entres trouves en appellant // la fonction supprimerEntree if (!supprimerEntree($idLdap, $entree[$i][dn], TRUE)) { return FALSE; } } } // On supprime lentre courante if (ldap_delete($idLdap, $dn)) { return TRUE; } else { return FALSE; } } ?>

11. Les annuaires LDAP

prsent, venons-en lutilisation de cette fonction :

Listing 11.3 : ldap_delete.php


<?php include("ldap_delete.inc.php "); // Connexion lannuaire $idLdap = ldap_connect("localhost",389); $rootDn = cn=root,dc=ldap,dc=tild,dc=com; $rootPasse = coucou; if (!ldap_bind($idLdap, $rootDn, $rootPasse)){ die("La connexion na pas t effectue."); } // DN de lentre crer et ensuite supprimer $baseDn = o=test,dc=ldap,dc=tild,dc=com; // Cration dune entre "organisation" $groupe[objectclass][0] = organization; $groupe[objectclass][1] = top; $groupe[o] = test .$i; ldap_add($idLdap, $baseDn, $groupe);

915

Chapitre 11

Les annuaires LDAP

// cration des membres dans le groupe for ($i=0;$i<10;$i++) { $entree[objectclass][0] = top; $entree[objectclass][1] = person; $entree[cn] = personne.$i; echo On ajoute l\utilisateur personne.$i. dans l\annuaire<br />; ldap_add($idLdap, cn=personne.$i.",".$baseDn, $entree); } // Recherche et affichage des entres dans le groupe $reponse = ldap_list($idLdap, $baseDn, "ObjectClass=*"); $resultat = ldap_get_entries($idLdap, $reponse); echo "Il y a ".$resultat[count]." entres dans le groupe<br />"; for($i=0;$i<$resultat[count];$i++){ echo "*".$resultat[$i][dn]."<br />"; } echo "Suppression de lentre rcursivement<br />"; if (supprimerEntree($idLdap, $baseDn, TRUE)) { echo "Lentre a t supprime !<br />"; }else{ echo "Problme, lentre na pas t supprime !<br />"; } // On vrifie le resultat de la suppression $reponse = ldap_list($idLdap, "dc=ldap,dc=tild,dc=com", "&((o=test)(ObjectClass=*))"); $resultat = ldap_get_entries($idLdap, $reponse); if ($resultat[count]==0) { echo "Il ny a aucune entre dn=o=test<br />"; } // Dconnexion de lannuaire ldap_close($idLdap); ?>

11. Les annuaires LDAP

Et voici maintenant le rsultat de lexcution de notre script :


On On On On On On On On On On Il ajoute ajoute ajoute ajoute ajoute ajoute ajoute ajoute ajoute ajoute y a 10 lutilisateur personne0 lutilisateur personne1 lutilisateur personne2 lutilisateur personne3 lutilisateur personne4 lutilisateur personne5 lutilisateur personne6 lutilisateur personne7 lutilisateur personne8 lutilisateur personne9 entres dans le groupe dans dans dans dans dans dans dans dans dans dans lannuaire lannuaire lannuaire lannuaire lannuaire lannuaire lannuaire lannuaire lannuaire lannuaire

916

Linterrogation de LDAP avec PHP

*cn=personne0,o=test,dc=ldap,dc=tild,dc=com *cn=personne1,o=test,dc=ldap,dc=tild,dc=com *cn=personne2,o=test,dc=ldap,dc=tild,dc=com *cn=personne3,o=test,dc=ldap,dc=tild,dc=com *cn=personne4,o=test,dc=ldap,dc=tild,dc=com *cn=personne5,o=test,dc=ldap,dc=tild,dc=com *cn=personne6,o=test,dc=ldap,dc=tild,dc=com *cn=personne7,o=test,dc=ldap,dc=tild,dc=com *cn=personne8,o=test,dc=ldap,dc=tild,dc=com *cn=personne9,o=test,dc=ldap,dc=tild,dc=com Suppression de lentre rcursivement Lentre a t supprime ! Il ny a aucune entre dn=o=test

11. Les annuaires LDAP

Renommer une entre


Pour renommer, copier ou dplacer une entre, nous utiliserons la fonction ldap_rename().

ldap_rename()
Renomme, copie ou dplace une entre dans larbre LDAP. Syntaxe $idLdap $dn $nouveauRdn $nouvelleBaseDn $supprimer retour boolean ldap_rename(int $idLdap, string $dn, string $nouveauRdn, string $nouvelleBaseDn, boolean $supprimer) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Le DN (Distinguished Name) de lentre supprimer. Nouveau RDN (Relative Distinguished Name) de lentre. Nouvelle base DN parente pour lentre. Indique sil faut conserver lancienne entre ou non. TRUE si lentre a bien t dplace, FALSE dans le cas contraire.

La version du protocole v2 ne supporte pas cette fonction de PHP. Il faut ncessairement indiquer que nous utilisons la version 3 de LDAP pour utiliser ldap_rename(). Pour cela, utilisez linstruction ldap_set_option() dcrite plus loin.

Listing 11.4 : ldap_rename.php


<?php $idLdap = ldap_connect("localhost",389); // On passe en protocole v3 seul capable de supporter la copie ldap_set_option($idLdap, LDAP_OPT_PROTOCOL_VERSION, 3); // Noubliez pas de modifier ces paramtres selon

917

Chapitre 11

Les annuaires LDAP

// votre configuration $rootDn = cn=root, dc=tild; $rootPasse = coucou; if (!ldap_bind($idLdap, $rootDn, $rootPasse)){ die("La connexion na pas t effectue."); } // DN de lentre copier $dn = o=test,ou=test,dc=tild; // nouveau DN $rdn = o=test2; // nouvelle base $baseDn = ou=test,dc=tild; // On dplace lentre. $resultat = ldap_rename($idLdap, $dn, $rdn, $baseDn, TRUE); if ($resultat) { echo "Lentre a t copie !<br />"; } else { echo "Lentre na pas t copie !<br />"; // Affichage de lerreur echo ldap_error($idLdap); } // Dconnexion de lannuaire ldap_close($idLdap); ?>

11. Les annuaires LDAP

Recherche dans un annuaire LDAP


La recherche dans un annuaire seffectue en deux tapes :
j j

Lancement de la recherche ; Rcupration des rsultats.

Lancement dune recherche dans un annuaire


La recherche dans un annuaire LDAP peut tre effectue de plusieurs faons :
j j j

Rechercher une correspondance sur un niveau ; Rechercher une correspondance sur plusieurs niveaux ; Rechercher une correspondance sur une entre spcifique.

Recherche dans un annuaire sur un niveau


La recherche sur un niveau seffectue par lappel linstruction ldap_list().

918

Linterrogation de LDAP avec PHP

ldap_list()
Recherche laide dun filtre les entres sur un niveau. Syntaxe resource ldap_list(resource $idLdap, string $baseDn, string $filtre [, array $attributs [, int $attributsSeul [, int $nbLimit [, int $tempsExecution [, int $alias]]]]]) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Le DN (Distinguished Name) indiquant la base de votre recherche.

$idLdap $baseDn $filtre $attributs $attributsSeul

11. Les annuaires LDAP

Filtre LDAP permettant de rcuprer les informations demandes. Paramtre optionnel permettant de ne recevoir que les attributs dsirs. Paramtre indiquant de ne retourner que les noms des attributs sans leurs valeurs. 0 (valeur par dfaut) indique de rcuprer les valeurs et les attributs, 1 indique que seuls les attributs sont retourns. Indique le nombre de rsultats rcuprer. Par dfaut, la valeur est fixe 0, ainsi tous les rsultats de la recherche sont renvoys. Indique la dure maximale dune recherche en secondes. Par dfaut, la valeur est fixe 0, cest--dire quil ny a pas de limite sinon celle fixe par le serveur LDAP. Paramtre indiquant comment les alias des attributs doivent tre considrs. Utilisez lune des constantes suivantes : LDAP_DEREF_NEVER (valeur par dfaut), indique que les alias ne peuvent tre utiliss pour effectuer la recherche. LDAP_DEREF_SEARCHING, indique que les alias ne peuvent pas tre utiliss pour la recherche, mais que, lors du renvoi des rsultats, ceux-ci sont utiliss. LDAP_DEREF_FINDING, indique que les alias sont utiliss pour la recherche, mais que le rsultat ne les prend pas en compte. LDAP_DEREF_ALWAYS, indique que les alias ne sont jamais pris en compte, ni pour la recherche ni pour le rsultat. Pointeur sur le rsultat de la recherche.

$nbLimit $tempsExecution

$alias

retour

Recherche dans un annuaire sur plusieurs niveaux


Pour effectuer une recherche sur plusieurs niveaux, nous utiliserons la fonction ldap_search().

ldap_search()
Recherche laide dun filtre les entres sur plusieurs niveaux dun annuaire LDAP. La recherche est effectue sur le DN de la base, puis sur toutes les branches au-dessus.

919

Chapitre 11

Les annuaires LDAP

Syntaxe

resource ldap_search(resource $idLdap, string $baseDn, string $filtre [, array $attributs [, int $attributsSeul [, int $nbLimit [, int $tempsExecution [, int $alias]]]]]) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Le DN (Distinguished Name) indiquant le premier niveau o commencer votre recherche. Filtre LDAP permettant de rcuprer les informations demandes. Paramtre optionnel permettant de ne recevoir que les attributs dsirs. Paramtre indiquant de ne retourner que les noms des attributs sans leurs valeurs. 0 (valeur par dfaut) indique de rcuprer les valeurs et les attributs, 1 indique que seuls les attributs sont retourns. Indique le nombre de rsultats rcuprer. Par dfaut, la taille est fixe 0, ainsi tous les rsultats de la recherche sont renvoys. Indique la dure maximale dune recherche en secondes. Par dfaut, la valeur est fixe 0, cest--dire quil ny a pas de limite sinon celle fixe par le serveur LDAP. Paramtre indiquant comment les alias des attributs doivent tre considrs. Utilisez lune des constantes suivantes : LDAP_DEREF_NEVER (valeur par dfaut), indique que les alias ne peuvent tre utiliss pour effectuer la recherche. LDAP_DEREF_SEARCHING, indique que les alias ne peuvent pas tre utiliss pour la recherche, mais que, lors du renvoi des rsultats, ceux-ci sont utiliss. LDAP_DEREF_FINDING, indique que les alias sont utiliss pour la recherche, mais que le rsultat ne les prend pas en compte. LDAP_DEREF_ALWAYS, indique que les alias ne sont jamais pris en compte, ni pour la recherche ni pour le rsultat. Pointeur sur le rsultat de la recherche.

$idLdap $baseDn $filtre $attributs $attributsSeul

11. Les annuaires LDAP

$nbLimit $tempsExecution

$alias

retour

Recherche dans une entre


Pour effectuer votre recherche sur une entre et uniquement sur celle-ci, vous devez utiliser la fonction ldap_read().

ldap_read()
Recherche laide dun filtre sur une entre spcifique. La recherche est effectue sur le DN spcifi en paramtre. Syntaxe resource ldap_read(resource $idLdap, string $baseDn, string $filtre [, array $attributs [, int $attributsSeul [, int $nbLimit [, int $tempsExecution [, int $alias]]]]])

920

Linterrogation de LDAP avec PHP

$idLdap $baseDn $filtre $attributs $attributsSeul

Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Le DN (Distinguished Name) indiquant lentre o vous voulez effectuer votre recherche. Filtre LDAP permettant de rcuprer les informations demandes. Paramtre optionnel permettant de ne recevoir que les attributs dsirs. Paramtre indiquant de ne retourner que les noms des attributs sans leurs valeurs. 0 (valeur par dfaut) indique de rcuprer les valeurs et les attributs, 1 indique que seuls les attributs sont retourns. Indique le nombre de rsultats rcuprer. Par dfaut, la taille est fixe 0, ainsi tous les rsultats de la recherche sont renvoys. Indique la dure maximale dune recherche en secondes. Par dfaut la valeur est fixe 0, cest--dire quil ny a pas de limite sinon celle fixe par le serveur LDAP. Paramtre indiquant comment les alias des attributs doivent tre considrs. Utilisez lune des constantes suivantes : LDAP_DEREF_NEVER (valeur par dfaut), indique que les alias ne peuvent tre utiliss pour effectuer la recherche. LDAP_DEREF_SEARCHING, indique que les alias ne peuvent pas tre utiliss pour la recherche, mais que, lors du renvoi des rsultats, ceux-ci sont utiliss. LDAP_DEREF_FINDING, indique que les alias sont utiliss pour la recherche, mais que le rsultat ne les prend pas en compte. LDAP_DEREF_ALWAYS, indique que les alias ne sont jamais pris en compte, ni pour la recherche ni pour le rsultat. Pointeur sur le rsultat de la recherche.

$nbLimit $tempsExecution

11. Les annuaires LDAP

$alias

retour

Exemple de recherche
Cet exemple va vous montrer les diffrences existant entre ces trois fonctions :

Listing 11.5 : recherche.php


<html> <body> <?php // Connexion lannuaire $idLdap = ldap_connect("localhost",389); if (!ldap_bind($idLdap)){ die("La connexion na pas t effectue."); } echo "Recherche avec ldap_list()<br />"; $recherche = ldap_list($idLdap, "dc=kangouroo,dc=homelinux,dc=org", "objectclass=*"); $resultat = ldap_get_entries($idLdap, $recherche);

921

Chapitre 11

Les annuaires LDAP

echo "Il y a ".$resultat["count"]." rsultats<br />"; for ($i=0; $i<$resultat["count"]; $i++) { echo $resultat[$i][dn]."<br />"; } echo "<br />"; echo "Recherche avec ldap_search()<br />"; $recherche = ldap_search($idLdap, "dc=kangouroo,dc=homelinux,dc=org", "objectclass=*"); $resultat = ldap_get_entries($idLdap, $recherche);

11. Les annuaires LDAP

echo "Il y a ".$resultat["count"]." rsultats<br />"; for ($i=0; $i<$resultat["count"]; $i++) { echo $resultat[$i][dn]."<br />"; } echo "<br />"; echo "Recherche avec ldap_read()<br />"; $recherche = ldap_read($idLdap, "dc=kangouroo,dc=homelinux,dc=org", "objectclass=*"); $resultat = ldap_get_entries($idLdap, $recherche); echo "Il y a ".$resultat["count"]." rsultats<br />"; for ($i=0; $i<$resultat["count"]; $i++) { echo $resultat[$i][dn]."<br />"; } ldap_close($idLdap); ?> </body> </table>

Vous devez retrouver plus de rsultats avec la fonction ldap_search(), car celle-ci va scanner les entres fils. La fonction ldap_list(), quant elle, ne vous retournera que les rponses qui se trouvent directement en dessous de lentre que vous avez spcifie. ldap_read() ne vous retournera quun seul rsultat.

Rcuprer les rsultats dune recherche


Aprs avoir effectu votre recherche, il faut rcuprer les rsultats. L encore, plusieurs fonctions sont mises votre disposition. Vous pouvez, laide de celles-ci, rcuprer les rsultats de plusieurs faons :
j j

Rcuprer les rsultats en une fois ; Rcuprer les rsultats un un.

922

Linterrogation de LDAP avec PHP

Rcuprer les rsultats en une fois


Pour rcuprer les rsultats dune recherche, vous pouvez utiliser linstruction
ldap_get_entries().

ldap_get_entries()
Retourne un tableau contenant tous les lments, attributs et valeurs pour une recherche. Syntaxe $idLdap $idResultat retour array ldap_get_entries(resource $idLdap, resource $idResultat) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant sur le rsultat de la recherche tel quil est retourn par les fonctions ldap_search(), ldap_list() ou ldap_read(). Tableau contenant tous les rsultats de la recherche.

11. Les annuaires LDAP

Le tableau rsultant de lexcution de linstruction ldap_get_attributes() se prsente comme ceci :


<?php $resultat[0] // est le premier lments $resultat[n] // est llment n de votre recherche $resultat["count"] // indique le nombre dlments // retourns par votre recherche $resultat[0][dn] // indique le DN de llments $resultat[n]["count"] // Nombre dattributs pour llment n $resultat[n][0] // Nom de lattribut 0 $resultat[n][n] // Nom de lattribut n $resultat[n][attribut] // Tableau contenant les valeurs // de lattribut dsign $resultat[n][attribut][0] // Valeur 0 de lattribut $resultat[n][attribut][n] // Valeur n de lattribut $resultat[n][attribut]["count"] // Nombre de valeurs pour lattribut ?>

Excutez le script suivant en ladaptant votre annuaire LDAP pour rcuprer lisiblement sur lcran les donnes du tableau :
<?php // Effectuez ici votre connexion lannuaire // Recherche avec le filtre objectclass=person $recherche = ldap_list($idLdap, "dc=domaine,dc=com", "objectclass=person"); $resultat = ldap_get_entries($idLdap, $recherche); print_r($resultat); // Fermez votre connexion lannuaire ?>

923

Chapitre 11

Les annuaires LDAP

Voici maintenant un exemple de connexion un annuaire LDAP et daffichage des rsultats. Ici, nous rcuprons les donnes provenant dun serveur ILS, qui est un annuaire dutilisateurs de Netmeeting (logiciel de visioconfrence), et nous affichons le rsultat dans un tableau.

Listing 11.6 : netmeeting.php


<html> <head> <title>Recherche dans un annuaire netmeeting</title> </head> <body>

11. Les annuaires LDAP

<?php // Connexion lannuaire $idLdap = ldap_connect("ils.advalvas.be", 389); if (!ldap_bind($idLdap)){ die("La connexion na pas t effectue."); } $recherche = ldap_list($idLdap, "objectclass=rtperson", "(&(cn=%)(objectclass=rtperson))"); $resultat = ldap_get_entries($idLdap, $recherche); ?> <table border="0" width="100%"> <tr> <td colspan="5"> Il y a <?php echo $resultat["count"];?> rsultats </td> </tr> <tr> <td colspan="5"> <hr /> </td> </tr> <tr> <td> Nom </td> <td> Prnom </td> <td> ville </td> <td> mail </td> <td> Commentaire </td> </tr> <?php

924

Linterrogation de LDAP avec PHP

for ($i=0; $i<$resultat["count"]; $i++) { echo "<tr>"; echo " <td>".$resultat[$i][cn][0]."</td>"; echo " <td>".$resultat[$i][surname][0]."</td>"; echo " <td>".$resultat[$i][location][0]."</td>"; echo " <td>".$resultat[$i][rfc822mailbox][0]."</td>"; echo " <td>".$resultat[$i][comment][0]."</td>"; echo "</tr>"; } ?> </table> <? ldap_close($idLdap); ?> </body> </table>

11. Les annuaires LDAP

LILS nest pas un annuaire LDAP Les serveurs dannuaires de visioconfrences ne sont pas des annuaires LDAP. Ceux-ci possdent un schma particulier permettant au logiciel de visioconfrence de senregistrer dessus et deffectuer, toutes les x secondes, des connexions maintenant lentre dans lannuaire. Dans le cas contraire, celle-ci est supprime. Linterrogation utilise le protocole LDAP, ce qui nous permet dutiliser PHP pour interroger le serveur. Vous pouvez, laide dOpenLDAP, vous construire un annuaire LDAP. Le "howto" (en anglais) que vous trouverez sur la page http://www.freesoft.org/software/NetMeeting/ vous explique comment modifier lannuaire afin quil supporte le protocole trs particulier de Netmeeting.

Rcuprer les rsultats un un


Laffichage de la recherche lment par lment est compos de plusieurs tapes :
j j j

Cration dun pointeur sur le premier lment de notre recherche ; Rcupration des donnes de cet lment ; Dplacement du pointeur sur llment suivant.

Retourner un identiant sur le premier lment


Pour rcuprer lidentifiant du premier lment de notre recherche, nous utilisons la fonction ldap_first_entry().

925

Chapitre 11

Les annuaires LDAP

ldap_rst_entry()
Retourne un pointeur sur le premier lment rsultant de notre recherche. Syntaxe $idLdap $idResultat resource ldap_first_entry(resource $idLdap, resource $idResultat) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant sur le rsultat de la recherche tel quil est retourn par les fonctions ldap_search(), ldap_list() ou ldap_read(). Identifiant sur le premier lment de la recherche. Retourne FALSE en cas derreur ou lorsque la recherche na retourn aucun rsultat.

11. Les annuaires LDAP

retour

Rcupration des donnes dun lment


La rcupration des rsultats dun lment se fait par lappel la fonction ldap_get_attributes().

ldap_get_attributes()
Retourne les attributs et leurs valeurs composant llment. Syntaxe $idLdap $idEntree retour array ldap_get_attributes(resource link_identifier, resource $idEntree) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant sur llment tel quil est retourn par linstruction ldap_first_entry() ou ldap_next_entry(). Tableau contenant les diffrents attributs et les valeurs composant llment.

Dplacer le pointeur sur llment suivant


Le pointeur est dplac sur llment suivant par lutilisation de linstruction
ldap_next_entry().

ldap_next_entry()
Dplace le pointeur sur llment suivant de la recherche. Syntaxe resource ldap_next_entry(resource $idLdap, resource $idEntree)

926

Linterrogation de LDAP avec PHP

$idLdap $idEntree retour

Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant sur llment tel quil est retourn par linstruction ldap_first_entry() ou ldap_next_entry(). Identifiant sur llment suivant de la recherche, ou FALSE en cas derreur ou lorsque la recherche ne trouve plus aucun rsultat.

Exemple de recherche
Listing 11.7 : ldap_get_attributes.php
<html> <body> <?php // Connexion lannuaire $idLdap = ldap_connect("localhost",389); // Authentification sur lannuaire if (!ldap_bind($idLdap)){ die("La connexion na pas t effectue."); } // Recherche avec le filtre objectclass=person $recherche = ldap_list($idLdap, "dc=domaine,dc=com", "objectclass=person"); // On rcupre la premire entre $entree = ldap_first_entry($idLdap, $recherche); // Tant quil y a des rponses on rcupre les diffrents attributs while($entree){ $resultat = ldap_get_attributes($idLdap, $entree); // Boucle suivant le nombre dattributs trouvs // dans la recherche for($i=0; $i<$resultat[count]; $i++ ){ // Affichage de lattribut echo "$resultat[$i]="; // Affichage du rsultat, la boucle est utile si lattribut // possde de multiples valeurs for( $j=0; $j<$resultat[$resultat[$i]][count];$j++) { echo $resultat[$resultat[$i]][$j]." "; } } echo "<hr />"; // On passe lattribut suivant $entree = ldap_next_entry($idLdap, $entree); }

11. Les annuaires LDAP 927

Chapitre 11

Les annuaires LDAP

// Fermeture de la connexion avec lannuaire ldap_close($idLdap); ?> </body> </table>

Autre mthode
Nous pouvons galement rcuprer les attributs les uns aprs les autres pour chaque lment retourn par notre recherche. Pour cela, aprs avoir rcupr le premier lment, nous faisons appel linstruction ldap_first_attribute().

11. Les annuaires LDAP

ldap_rst_attribute()
Rcupre le nom du premier attribut dun lment. Syntaxe $idLdap $idEntree $idAttribut retour Pour rcuprer string ldap_first_attribute(resource $idLdap, resource $idEntree, resource &$idAttribut) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant sur llment tel quil est retourn par linstruction ldap_first_entry() ou ldap_next_entry(). Identifiant pass par rfrence. ldap_next_attribute(). Utilis par la suite par

Nom du premier attribut de llment, ou FALSE en cas derreur. les diffrents attributs suivants, il faut utiliser linstruction

ldap_next_attribute().

ldap_next_attribute()
Rcupre les noms des diffrents attributs dun lment. Syntaxe $idLdap $idEntree $idAttribut retour string ldap_next_attribute(resource $idLdap, resource $idEntree, resource &$idAttribut) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant sur llment tel quil est retourn par linstruction ldap_first_entry() ou ldap_next_entry(). Identifiant pass par rfrence. Chacun des appels cette instruction fait avancer ce pointeur sur lattribut suivant. Nom du premier attribut de llment, ou FALSE en cas derreur.

928

Linterrogation de LDAP avec PHP

Nous pouvons ensuite rcuprer les diffrentes valeurs de lattribut en appelant les fonctions ldap_get_values() ou ldap_get_values_len(). La fonction ldap_get_values() rcupre les diffrentes valeurs de lattribut spcifi.

ldap_get_values()
Retourne la ou les valeurs de lattribut dans un tableau. Syntaxe $idLdap $idEntree $attribut retour array ldap_get_values(resource $idLdap, resource $idEntree, string $attribut) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant sur llment tel quil est retourn par linstruction ldap_first_entry() ou ldap_next_entry(). Nom de lattribut. Tableau contenant les diffrentes valeurs.

11. Les annuaires LDAP

Le tableau rsultant de lexcution de linstruction ldap_get_values() se prsente comme ceci :


<?php $resultat[0] // premire valeur de lattribut $resultat[n] // valeur n de lattribut $resultat["count"] // indique le nombre de valeur de lattribut ?>

Voici un exemple complet qui permet de comprendre comment rcuprer les lments, les attributs et chacune des valeurs correspondantes.
<html> <body> <?php // Connexion lannuaire $idLdap = ldap_connect("localhost",389); // Authentification sur lannuaire if (!ldap_bind($idLdap)){ die("La connexion na pas t effectue."); } // Recherche avec le filtre objectclass=person $recherche = ldap_list($idLdap, "dc=domaine,dc=com", "objectclass=person"); // On rcupre la premire entre $entree = ldap_first_entry($idLdap, $recherche); // Tant quil y a des rponses on rcupre les diffrents attributs

929

Chapitre 11

Les annuaires LDAP

11. Les annuaires LDAP

while($entree){ // On rcupre le premier attribut $attribut = ldap_first_attribute($idLdap, $entree, $idReference); // Affichage du rsultat, la boucle est utile si lattribut // possde de multiples valeurs while($attribut){ // Affichage du nom de lattribut echo $attribut."($idReference)="; // Rcupration des valeurs de lattribut $valeurs = ldap_get_values($idLdap, $entree, $attribut); for($i=0; $i<$valeurs["count"]; $i++) { // Affichage des diffrentes valeurs echo $valeurs[$i]."($idReference)<br />"; } $attribut = ldap_next_attribute($idLdap, $entree, $idReference); } echo "<hr />"; // On passe lattribut suivant $entree = ldap_next_entry($idLdap, $entree); } // Fermeture de la connexion avec lannuaire ldap_close($idLdap); ?> </body> </table>

La fonction ldap_get_values() ne permet pas de rcuprer les valeurs des attributs binaires. Pour cela, vous devez utiliser linstruction ldap_get_values_len(). Cette fonction retourne tous les lments, ainsi que les lments binaires.

ldap_get_values_len()
Rcupre la ou les valeurs des attributs binaires. Syntaxe $idLdap $idEntree $attribut retour array ldap_get_values_len(resource $idLdap, resource $idEntree, string $attribut) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant sur llment tel quil est retourn par linstruction ldap_first_entry() ou ldap_next_entry(). Nom de lattribut. Tableau contenant les diffrentes valeurs.

930

Linterrogation de LDAP avec PHP

Lutilisation de linstruction ldap_get_values_len() est identique celle de linstruction ldap_get_values().

Ordonner les rponses


Vous pouvez ordonner les rponses en utilisant la fonction ldap_sort().

ldap_sort()
11. Les annuaires LDAP
Ordonne les rsultats dans lordre alphabtique. Syntaxe $idLdap $idResultat $filtre retour boolean ldap_sort(resource $idLdap, resource $idResultat, string $filtre) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant sur le rsultat de la recherche tel quil est retourn par les fonctions ldap_search() et ldap_list(). Indique quel est lattribut qui permet dordonner les rsultats. TRUE si les rsultats ont bien t ordonns, FALSE dans le cas contraire.

Prenez bien garde ordonner vos rsultats avant de faire appel la fonction ldap_get_entries(), car la fonction naurait alors aucun effet.

Compter les rsultats dune recherche


Il existe deux faons de dterminer le nombre denregistrements retourns par une recherche dans lannuaire. Si vous avez effectu une recherche et rcupr les rsultats laide de la fonction ldap_get_entries(), vous pouvez simplement retrouver le nombre dentres depuis le tableau qui vous est retourn de la faon suivante : $tableau["count"].
<?php $recherche = ldap_list($idLdap,"dc=domaine,dc=com ","objectclass=person"); $resultat = ldap_get_entries($idLdap, $recherche); // Affichage du nombre dentres echo "Il y a ".$resultat["count"]." entres pour votre recherche !"; ?>

Si vous avez utilis linstruction ldap_get_attributes(), alors vous ne pouvez retrouver le nombre dlments retourns par votre recherche depuis le tableau de rsultat (mais seulement le nombre dattributs). Dans ce cas, vous pouvez utiliser la fonction :

931

Chapitre 11

Les annuaires LDAP

ldap_count_entries()
Retourne le nombre de rsultats dune recherche. Syntaxe $idLdap $idResultat retour int ldap_count_entries(resource $idLdap, resource $idResultat) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant sur le rsultat de la recherche tel quil est retourn par les fonctions ldap_search(), ldap_list() ou ldap_read(). Entier indiquant le nombre de rsultats de la recherche, ou FALSE en cas derreur.

11. Les annuaires LDAP

Comparer un attribut avec une valeur


Plus rapide que deffectuer une recherche, vous pouvez simplement comparer la valeur dun attribut avec une donne. Cela vous permet, par exemple, de vrifier un mot de passe dans lannuaire. On utilise, pour cela, linstruction ldap_compare().

ldap_compare()
Compare la valeur dun attribut avec une chane passe en paramtre. noter que linstruction est insensible la casse des caractres. Syntaxe $idLdap $dn $attribut $valeur retour boolean ldap_compare(resource $idLdap, string $dn, string $attribut, string $valeur) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). DN de lentre vrifier. Attribut qui contient la chane comparer. Chane de caractres comparer avec $attribut. TRUE si les valeurs sont identiques, FALSE dans le cas contraire.

Librer la mmoire
Si vous effectuez des recherches lourdes et successives, vous pouvez avoir des problmes de mmoire. Par dfaut, lorsque vous fermez votre connexion, la mmoire est automatiquement libre. Mais, dans le cas o votre programme effectue des requtes successives, vous serez alors amen librer la mmoire entre chaque transaction. La fonction ldap_free_result() libre la mmoire en vidant les rsultats prcdents.

932

Linterrogation de LDAP avec PHP

ldap_free_result()
Vide la mmoire et efface les rsultats obtenus prcdemment. Syntaxe $idLdap retour boolean ldap_free_result(resource $idLdap) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). TRUE si la mmoire a t libre, FALSE dans le cas contraire.

Gestion des erreurs


Trois fonctions permettent de retrouver les diffrents messages derreur qui peuvent survenir. Ces fonctions sont ldap_errno(), ldap_error() ou ldap_err2str().

11. Les annuaires LDAP

ldap_errno()
Rcupre le numro de la dernire erreur rencontre par LDAP. Syntaxe $idLdap retour int ldap_errno(resource $idLdap) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Entier indiquant le numro de lerreur. 0 indique que lopration a t effectue avec succs.

ldap_error()
Rcupre le message de la dernire erreur rencontre par LDAP. Syntaxe $idLdap retour string ldap_error(resource $idLdap) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Message derreur.

Vous pouvez retrouver ce message derreur depuis le numro retourn par ldap_errno() simplement en faisant appel linstruction ldap_err2str().

933

Chapitre 11

Les annuaires LDAP

ldap_err2str()
Retourne le message associ au numro de lerreur. Syntaxe $numErreur retour string ldap_err2str(int $numErreur) Numro de lerreur. Message derreur.

Pour consulter les diffrents messages possibles, lancez le script suivant :


<?php for($i=0;$i<100;$i++) { $message = ldap_err2str($i); echo "$i&nbsp;:&nbsp;&nbsp;&nbsp;"; echo $message."<br />"; } ?>

11. Les annuaires LDAP

Opration sur le Distinguished Name (DN)


Rcuprer le DN
Nous avons vu que, lorsque nous effectuons une recherche et que nous rcuprons les rsultats par linstruction ldap_get_entries(), nous pouvons rcuprer le DN simplement depuis le tableau retourn : $tableau[$n]["dn"]. Si nous rcuprons les rsultats un un avec la fonction ldap_get_attributes(), nous devrons avoir recours linstruction ldap_get_dn().

ldap_get_dn()
Permet de rcuprer le DN par rapport un rsultat de lentre. Syntaxe $idLdap $idResultat retour string ldap_get_dn(resource $idLdap, resource $idEntree) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant sur lentre tel quil est retourn par les fonctions ldap_first_entry(). Le DN (Distinguished Name).

934

Linterrogation de LDAP avec PHP

Conversion de format
Une fonction particulire permet de convertir le DN dans un format plus convivial, lUFN (User Friendly Naming). Ce format enlve les noms des RDN (Relative Distinguished Name) du DN, et ne retourne que leurs valeurs spares par des virgules.

ldap_dn2ufn()
Nettoie le DN des noms des RDN qui le composent.

11. Les annuaires LDAP

Syntaxe $dn retour

string ldap_dn2ufn(string $dn) DN convertir. Chane de caractres contenant le DN sans les noms des RDN.

<?php $dn = "cn=Laurent GUEDON,ou=dveloppement, o=tild, c=france"; echo ldap_dn2ufn($dn); ?> Laurent GUEDON,dveloppement, tild, france

Rcuprer les composantes du DN


La fonction ldap_explode_dn() permet de rcuprer les diffrentes valeurs des RDN (Relative Distinguished Name) du DN, accompagn ou non de lidentifiant de ces RDN.

ldap_explode_dn()
Retourne un tableau contenant les diffrentes composantes du DN. Syntaxe $dn $sansRdn retour array ldap_explode_dn(string $dn, int $sansRdn) DN convertir. Indique de retourner uniquement les valeurs des RDN sans leurs identifiants. Tableau contenant le DN ainsi dcoup.

<?php $dn = "cn=Laurent GUEDON,ou=dveloppement, o=tild, c=france"; echo "affiche le tableau avec les noms des RDN\n"; $tableau = ldap_explode_dn($dn, 0); print_r($tableau); echo "\n"; echo "affiche le tableau sans les noms des RDN\n"; $tableau = ldap_explode_dn($dn, 1);

935

Chapitre 11

Les annuaires LDAP

print_r($tableau); ?> affiche le tableau avec les noms des RDN Array ( [count] => 4 [0] => cn=Laurent GUEDON [1] => ou=dveloppement [2] => o=tild [3] => c=france ) affiche le tableau sans les noms des RDN Array ( [count] => 4 [0] => Laurent GUEDON [1] => dveloppement [2] => tild [3] => france )

11. Les annuaires LDAP

Opration sur les options


Modier une option LDAP
Pour modifier une option LDAP, nous utiliserons la fonction ldap_set_option().

ldap_set_option()
Modifie une option de lannuaire LDAP. Syntaxe $idLdap $option $nouvelleValeur retour boolean ldap_set_option(resource $idLdap, int $option, mixed $nouvelleValeur) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant de loption modifier. Nouvelle valeur donner loption. TRUE en cas de succs du changement de loption, FALSE dans le cas contraire.

936

Linterrogation de LDAP avec PHP

Tableau 11.1 : Les diffrentes options modifiables par ldap_set_option()


Option LDAP_OPT_DEREF Description Ce paramtre indique comment les alias des attributs doivent tre considrs. Utilisez lune des constantes suivantes : LDAP_DEREF_NEVER, indique que les alias peuvent tre utiliss pour effectuer la recherche. LDAP_DEREF_SEARCHING, indique que les alias ne peuvent pas tre utiliss pour la recherche, mais que, lors du renvoi des rsultats, ceux-ci sont utiliss. LDAP_DEREF_FINDING, indique que les alias sont utiliss pour la recherche, mais que le rsultat ne les prend pas en compte. LDAP_DEREF_ALWAYS, indique que les alias ne sont jamais pris en compte, ni pour la recherche ni pour le rsultat. Indique le nombre de rsultats maximal qui peut tre retourn. La valeur par dfaut 0 (LDAP_NO_LIMIT) indique quil ny a pas de limite maximale. Indique le temps maximal dexcution dune requte dans lannuaire LDAP. Cette valeur affecte simplement la recherche sur le serveur. La valeur par dfaut 0 (LDAP_NO_LIMIT) indique quil ny a pas de limite de temps.

11. Les annuaires LDAP

LDAP_OPT_SIZELIMIT

LDAP_OPT_TIMELIMIT

LDAP_OPT_REFERRALS Cette option indique comment le client doit ragir lorsquune rfrence lui est retourne par le serveur. Le paramtre par dfaut est LDAP_OPT_ON, cest--dire que les rfrences sont prises en compte. LDAP_OPT_OFF empche cela. LDAP_OPT_RESTART Indique si, lors dune interruption prmature (comme un time out par exemple), les oprations interrompues doivent reprendre (LDAP_OPT_ON) ou non (LDAP_OPT_OFF). Par dfaut, loption est fixe LDAP_OPT_ON.

LDAP_OPT_PROTOCOL Indique la version du protocole LDAP utiliser : LDAP_VERSION2 _VERSION pour la version 2 ou LDAP_VERSION3 pour la version 3. Par dfaut, le protocole utilis est v2. LDAP_OPT_SERVER _CONTROLS Indique une liste de contrles au niveau du serveur. Le serveur doit les recevoir chaque fois. La valeur qui doit tre passe linstruction est un tableau contenant les diffrents contrles. array( array( // premier contrle "oid" => "x.x.x.x.x.x", "iscritical" => TRUE, ), array( // deuxime contrle "oid" => "y.y.y.y.y.y", "iscritical" => FALSE, ), ) Par dfaut, il ny aucun contrle au niveau du serveur. Listes de contrles au niveau du client.

LDAP_OPT_CLIENT _CONTROLS

937

Chapitre 11

Les annuaires LDAP

Consulter une option LDAP


Pour rcuprer une option du serveur LDAP, on utilisera la fonction :

ldap_get_option()
Rcupre une option de lannuaire LDAP. Syntaxe boolean ldap_get_option(resource $idLdap, int $option, mixed &$valeurRetour) Identifiant sur la connexion au serveur LDAP tel quil est retourn par la fonction ldap_connect(). Identifiant de loption modifier. Variable dans laquelle sera copie la valeur de loption que lon aura rcupre. TRUE en cas de succs, FALSE dans le cas contraire.

11. Les annuaires LDAP

$idLdap $option $valeurRetour retour

Vous pouvez rcuprer les mmes options que pour la fonction ldap_set_option(), plus quelques autres en lecture seule.

Tableau 11.2 : Les options supplmentaires de la fonction ldap_get_option()


Option LDAP_OPT_ERROR_NUMBER Description Retourne le numro de la dernire erreur rencontre. Identique la fonction ldap_errno(). Retourne la dernire erreur rencontre. Identique la fonction ldap_error(). Retourne ladresse et le port de la connexion au serveur LDAP.

LDAP_OPT_ERROR_STRING LDAP_OPT_HOST_NAME

Vous trouverez diverses explications (en anglais) sur les options LDAP sur le site de NETSCAPE : http://developer.netscape.com/docs/manuals/dirsdk/csdk30/functi52.htm.

11.4. Exemple dapplication


Pour illustrer ce chapitre, nous allons crer un petit annuaire coupl avec un navigateur LDAP. Ce nest pas l lune des grosses applications que vous pouvez trouver dans une entreprise pour grer le personnel et les clients, mais les bases sont l. vous de faire voluer cet annuaire par la suite afin dintgrer de nouvelles fonctions.

938

Exemple dapplication

Lauthentication sur lannuaire


Il est simple prsent de construire un petit systme dauthentification sur un annuaire. Dans un premier temps, nous allons prparer un fichier de configuration qui contiendra tout paramtre propre notre annuaire LDAP.

Listing 11.8 : exemples/configuration.php


<?php /* / Paramtres du serveur LDAP */ $serveur = "localhost"; // Adresse du serveur LDAP $port = 389; // Port du serveur LDAP $ssl = 0; // Utilisez 1 pour une connexion par SSL // DN Root $dnOrigine = "dc=mondomaine,dc=com"; // Branche utilisateur racine $dnUtilisateur = "ou=People,dc=mondomaine,dc=com"; // Attribut login dun utilisateur $loginAttribut = "cn"; // dn du manager de lannuaire LDAP $dnRoot = "cn=root,dc=mondomaine,dc=com";

11. Les annuaires LDAP

/* / Paramtres des pages */ $titre = "Bldap - Lannuaire LDAP en PHP"; $couleurBoite = "#0066CC"; $couleurText = "#FFFFFF"; ?>

Nous pouvons, prsent, crire un exemple dauthentification. Ceci commence par la page dindex qui gre les sessions des utilisateurs une fois authentifies :

Listing 11.9 : exemples/index.php


<?php include("includes/inclusion.php"); session_start(); if ($_POST["action"]) { $action = $_POST["action"]; } elseif ($_GET["action"]){

939

Chapitre 11

Les annuaires LDAP

$action = $_GET["action"]; } else { $action = ""; } switch ($action) { case "connexion": connexion(); affichehtml(); break; case "deconnexion": deconnexion(); affichehtml(); break; case "recherche": include("entete.php"); afficheRecherche(); break; case "modifier": include("entete.php"); modifierFiche(); break; case "fiche": include("entete.php"); afficheFiche(); break; default: include("entete.php"); if (!isset($_SESSION[sessionConnexionType])) { // Si aucune session na t cre afficheBoiteLogin(); } else { // Si lutilisateur est connect linterface afficheBlocRecherche(); } break; } ?> <p>&nbsp;</p> <p>&nbsp;</p> <?php include("pieddepage.php"); ?>

11. Les annuaires LDAP

Inclusion est un fichier qui contient tous les autres fichiers PHP inclure. Il ressemble ceci :

940

Exemple dapplication

Listing 11.10 : exemples/includes/inclusion.php


<?php require_once("configuration.php"); require_once("html.php"); require_once("includes/connexionLdap.php"); require_once("includes/identification.php"); require_once("includes/ldap.php"); ?>

Les fichiers entete.php et pieddepage.php contiennent le code HTML permettant de donner le look gnral de la page. Le fichier html.php contient diffrentes fonctions affichant les formulaires ou les rsultats des rponses. Les fonctions connexion() et deconnexion() sont dcrites dans le fichier identification.php qui se trouve dans le rpertoire includes.

11. Les annuaires LDAP

Listing 11.11 : exemples/includes/identification.php


<?php /** * Fonction de connexion linterface * @return $ldap ou FALSE si erreur dans lidentification */ function connexion() { global $dnUtilisateur, $loginAttribut, $dnRoot; global $motPasse, $utilisateur, $connexionType; if ($ldap = connexionLdap()) { if ($connexionType == "normal") { $_SESSION[sessionDn] = $loginAttribut. "=".$utilisateur.",".$dnUtilisateur; $_SESSION[sessionPass] = $motPasse; $_SESSION[sessionConnexionType] = $connexionType; $_SESSION[sessionRdn] = $utilisateur; } elseif ($connexionType == "manager") { $_SESSION[sessionDn] = $dnRoot; $_SESSION[sessionPass] = $motPasse; $_SESSION[sessionConnexionType] = $connexionType; $_SESSION[sessionRdn] = "Manager"; } else { $_SESSION[sessionDn] = ""; $_SESSION[sessionPass] = ""; $_SESSION[sessionConnexionType] = $connexionType; $_SESSION[sessionRdn] = "Anonyme"; } } else { return FALSE; } deconnexionLdap($ldap);

941

Chapitre 11

Les annuaires LDAP

afficheBoiteMsg("La connexion a t effectue"); return TRUE; } /** * Fonction de dconnexion de linterface */ function deconnexion() { session_unset(); session_destroy(); afficheBoiteMsg("La deconnexion a t effectue"); } ?>

11. Les annuaires LDAP

La

fonction connexion() fait appel deux fonctions connexionLdap() et deconnexionLdap() qui sont dcrites dans le fichier includes/connexionLdap.php. Suivant le rsultat de lauthentification LDAP, le script cre une session ou affiche un message indiquant que lauthentification a chou.

Listing 11.12 : exemples/includes/connexionLdap.php


<?php /** * Fonction de cration de connexion et dauthentification au serveur LDAP * @return resource Identifiant de connexion LDAP ou FALSE si problme */ function connexionLdap() { global $serveur, $port, $ssl; global $dnUtilisateur, $loginAttribut, $dnRoot; global $motPasse, $utilisateur, $connexionType; // Connexion au serveur LDAP if ($ssl) $serveur = "ldaps://".$serveur; $ldap = @ldap_connect($serveur, $port); if (!$ldap) { afficheBoiteMsgErreur("La connexion au ". serveur na pas t effectue !"); return FALSE; } // Vrification quune session nest pas dj cre if (isset($_SESSION[sessionConnexionType])) { $sessionDn = $_SESSION[sessionDn]; $sessionPass = $_SESSION[sessionPass]; $sessionConnexionType = $_SESSION[sessionConnexionType]; } else { $sessionDn = $loginAttribut."=".$utilisateur.",".$dnUtilisateur; $sessionPass = $motPasse;

942

Exemple dapplication

$sessionConnexionType = $connexionType; } // Connexion sur lannuaire en mode utilisateur "normal" if ($sessionConnexionType=="normal" && $sessionDn && $sessionPass) { // Authentification sur le serveur LDAP if (!@ldap_bind($ldap, $sessionDn, $sessionPass)) { afficheBoiteMsgErreur("Lauthentification a chou !"); return FALSE; } } // Connexion sur lannuaire en mode utilisateur "manager" elseif ($sessionConnexionType=="manager" && $sessionPass) { // Authentification sur le serveur LDAP if (!@ldap_bind($ldap, $dnRoot, $sessionPass)) { afficheBoiteMsgErreur("Lauthentification a chou !"); return FALSE; } } // Connexion sur lannuaire en mode utilisateur "anonyme" elseif ($sessionConnexionType=="anonyme") { // Authentification sur le serveur LDAP if (!@ldap_bind($ldap)) { afficheBoiteMsgErreur("Lauthentification a chou !"); return FALSE; } } else { // Problme de connexion afficheBoiteMsgErreur("Connexion impossible !"); return FALSE; } return $ldap; } /** * Fonction de dconnexion du serveur LDAP * @input $ldap Identifiant de connexion LDAP * @return rien */ function deconnexionLdap($ldap) { // Dconnexion du serveur LDAP ldap_close($ldap); } ?>

11. Les annuaires LDAP 943

Chapitre 11

Les annuaires LDAP

11. Les annuaires LDAP

Figure 11.5 : Vous pouvez maintenant vous authentifier comme utilisateur, manager ou

anonyme.

Figure 11.6 : Vous voil dans linterface en tant quanonyme

Lajout dune nouvelle entre


Lajout dune nouvelle entre peut tre fait simplement depuis un formulaire HTML. Le schma de votre annuaire doit supporter les attributs standard que nous utilisons ici. Dans le cas contraire, veuillez vous reporter la documentation dOpenLDAP afin de rsoudre les ventuels problmes. Commenons par afficher la page HTML contenant le formulaire dajout dun nouvel utilisateur.

944

Exemple dapplication

Listing 11.13 : exemples/ajout.php


<?php include("includes/inclusion.php"); session_start(); if ($_POST["action"]) { $action = $_POST["action"]; } elseif ($_GET["action"]){ $action = $_GET["action"]; } else { $action = ""; }

11. Les annuaires LDAP

include("entete.php"); switch ($action) { case "ajouter": ajouterUtilisateur(); break; default: afficheFormulaire(); break; } ?> <p>&nbsp;</p> <p>&nbsp;</p> <?php include("pieddepage.php"); ?>

La fonction afficheFormulaire() est dcrite dans le fichier html.php. Lorsque le formulaire est valid, le paramtre action=ajouter est alors pass au script, ce qui a pour effet dexcuter la fonction ajouterUtilisateur().

Listing 11.14 : exemples/includes/ldap.php


<?php /** * Fonction dajout dun utilisateur dans lannuaire * @return boolean */ function ajouterUtilisateur()

945

Chapitre 11

Les annuaires LDAP

{ global $loginAttribut, $dnUtilisateur; if (!$ldap = connexionLdap()) return FALSE; $dn = "$loginAttribut=".$_POST[$loginAttribut].",$dnUtilisateur"; if ($_POST[objectclass][0]) $entree[objectclass][0] = if ($_POST[objectclass][1]) $entree[objectclass][1] = if ($_POST[sn]) $entree[sn] = $_POST[sn]; if ($_POST[givenname]) $entree[givenname] = if ($_POST[mail]) $entree[mail] = if ($_POST[telephonenumber]) $entree[telephonenumber] = if ($_POST[telexnumber]) $entree[telexnumber] = if ($_POST[o]) $entree[o] = if ($_POST[ou]) $entree[ou] = if ($_POST[street]) $entree[street] = if ($_POST[postalcode]) $entree[postalcode] = if ($_POST[l]) $entree[l] = if ($_POST[c]) $entree[c] = if ($_POST[userpassword]) $entree[userpassword] = $entree[$loginAttribut]

$_POST[objectclass][0]; $_POST[objectclass][1];

11. Les annuaires LDAP

$_POST[givenname]; $_POST[mail]; $_POST[telephonenumber]; $_POST[telexnumber]; $_POST[o]; $_POST[ou]; $_POST[street]; $_POST[postalcode]; $_POST[l]; $_POST[c]; $_POST[userpassword];

= $_POST[$loginAttribut];

if (@ldap_add($ldap, $dn, $entree)) { afficheBoiteMsg("Le nouvel utilisateur a t ajout !"); } else { afficheBoiteMsgErreur("Problme, le nouvel". " utilisateur na pas t ajout !", $ldap); return FALSE; } // Dconnexion du serveur LDAP deconnexionLdap($ldap); return TRUE; }

946

Exemple dapplication

Recherche dans lannuaire


prsent que de nouveaux utilisateurs sont dans lannuaire, il est grand temps deffectuer une recherche qui va nous permettre de les retrouver. Cest un formulaire HTML simple qui va nous permettre de rechercher les individus selon plusieurs critres :
j j j j

La socit qui est reprsente par lattribut o ou organization ; Le pays qui est dfini par lattribut c ; Le nom qui est dsign par lattribut cn ; Le-mail reprsent par lattribut mail.

11. Les annuaires LDAP

Le formulaire est appel depuis notre page dindex par la fonction afficheBlocRecherche(). Sa description se trouve dans le fichier html.php. La fonction qui affiche le rsultat est afficheRecherche().

Listing 11.15 : exemples/html.php (extrait)


<?php /** * Fonction affichage le rsultat de la recherche */ function afficheRecherche() { global $loginAttribut; afficheBlocRecherche($contenu); <p>&nbsp;</p> <table border="0" cellpadding="1" cellspacing="0" width="90%" bgcolor="#000000" align="center"> <tr> <td> <table border="0" cellpadding="0" cellspacing="4" width="100%" bgcolor="#ffffff"> <tr> <td align="center" width="25%"> Nom </td> <td align="center" width="25%"> Identifiant </td> <td align="center" width="25%"> E-mail </td> <td align="center" width="25%"> Tlphone </td> </tr> <?php ?>

947

Chapitre 11

Les annuaires LDAP

11. Les annuaires LDAP

$resultat = rechercheLdap(); echo <tr><td colspan="4" align="center">. Il y a .$resultat["count"]. rsultat(s). pour votre recherche; for ($i=0;$i<$resultat["count"];$i++) { echo <tr>; echo <td><a href="index.php?action=fiche&identifiant=. $resultat[$i][$loginAttribut][0].">. $resultat[$i]["cn"][0].</a></td>; echo <td>.$resultat[$i]["uid"][0].</td>; echo <td>.$resultat[$i]["mail"][0].</td>; echo <td>.$resultat[$i]["telephonenumber"][0].</td>; echo </tr>; } echo </table> </td> </tr> </table>; } ?>

Enfin, cette fonction fait appel rechercheLdap(), qui soccupe deffectuer la recherche dans lannuaire et de retourner les rsultats sous la forme dun tableau.

Listing 11.16 : exemples/includes/ldap.php


<?php /** * Fonction de recherche dans la base LDAP * @return array les donnes recherches ou FALSE si problme */ function rechercheLdap() { global $dnUtilisateur; // Connexion au serveur LDAP $ldap = connexionLdap(); if (!$ldap) return FALSE; // Cration du filtre de recherche $filtre = ""; if ($_POST["societe"]) $filtre .= "(o=".$_POST["societe"].")"; if ($_POST["nom"]) $filtre .= "(cn=".$_POST["nom"].")"; if ($_POST["pays"]) $filtre .= "(c=".$_POST["pays"].")"; if ($_POST["mail"]) $filtre .= "(mail=".$_POST["mail"].")"; if (!$filtre) { $filtre = "(&(cn=*)(objectclass=*))";

948

Exemple dapplication

} else { $filtre = "(&".$filtre."(objectclass=*))"; } // Elments rcuprer $element = array("cn", "uid", "mail", "telephonenumber"); $recherche = @ldap_list($ldap, $dnUtilisateur, $filtre, $element); if (!$recherche) { afficheBoiteMsgErreur("Problme lors de la recherche !", $ldap); deconnexionLdap($ldap); return FALSE; } $resultat = @ldap_get_entries($ldap, $recherche); deconnexionLdap($ldap); return $resultat; } ?>

11. Les annuaires LDAP

Modication dune entre


Avant de modifier une entre, nous devons afficher un formulaire. Pour cela, nous allons, dans un premier temps, appeler la page index depuis le rsultat de la recherche prcdente, et lui transmettre le RDN qui nous permettra ensuite de rcuprer lutilisateur. La page index.php fait alors appel la fonction afficheFiche().

Listing 11.17 : exemples/html.php (extrait)


<?php /** * Fonction affichage de la fiche de la personne */ function afficheFiche() { ?> <table border="0" cellpadding="1" cellspacing="0" width="90%" bgcolor="#000000" align="center"> <tr> <td> <table border="0" cellpadding="0" cellspacing="4" width="100%" bgcolor="#ffffff"> <form action="index.php" method="post"> <?php $ldapResultat = rechercheLdapPersonne(); // Ceci va nous tre utile pour bien visualiser les rsultats // Un peu de couleurs ne fait pas de mal. $coul = 0; $couleur[0] = "#ffffff"; $couleur[1] = "#dddddd";

949

Chapitre 11

Les annuaires LDAP

for ($i=0;$i<$ldapResultat[0]["count"];$i++) { $attribut = $ldapResultat[0][$i]; echo <tr>; echo <td bgcolor=".$couleur[$coul].">.$attribut.</td>; echo <td bgcolor=".$couleur[$coul].">; if ($ldapResultat[0][$i]["count"]){ // Il peut y avoir plusieurs valeurs pour un attribut. // Nous allons donc vrifier combiens de donnes nous sont // retournes pour chaques attributs. // Pour cela, on compte le nombre de valeur pour lattribut // et on boucle $boucle = $ldapResultat[0][$attribut]["count"]; if ($boucle>1){ for ($nbAttr=0;$nbAttr<$boucle;$nbAttr++) { echo <input type="text" name=".$attribut. [.$nbAttr.]" value=". $ldapResultat[0][$attribut][$nbAttr]."><br />; } } else { echo <input type="text" name=".$attribut. " value=". $ldapResultat[0][$attribut][0].">; } } else { echo <input type="text" name=".$attribut.[0]". value="">; } echo <td bgcolor=".$couleur[$coul].">; echo </td>; echo </tr>; if ($coul==0) $coul=1; else $coul=0; } <tr><td> <input type="hidden" value="modifier" name="action"> <input type="submit" value="Modifier"> </td></tr> </form> </table> </td></tr> </table> <?php } ?> ?>

11. Les annuaires LDAP 950

Exemple dapplication

Cette page lance dabord la fonction rechercheLdapPersonne(), qui lui retourne un tableau contenant la liste des attributs et leurs diffrentes valeurs.

Listing 11.18 : exemples/includes/ldap.php


<?php /** * Fonction de rcupration des lments dune fiche * @return array les donnes recherches ou FALSE si problme */ function rechercheLdapPersonne() { global $dnUtilisateur, $loginAttribut; // Connexion au serveur LDAP $ldap = connexionLdap(); if (!$ldap) return FALSE; // Cration du filtre de recherche $filtre = "(&(".$loginAttribut."=". $_GET["identifiant"].")(objectclass=*))"; $recherche = @ldap_list($ldap, $dnUtilisateur, $filtre); if (!$recherche) { afficheBoiteMsgErreur("Problme lors de la recherche !", $ldap); deconnexionLdap($ldap); return FALSE; } // On rcupere lentre $resultat = @ldap_get_entries($ldap, $recherche); // Dconnexion du serveur LDAP deconnexionLdap($ldap); return $resultat; } ?>

11. Les annuaires LDAP

Ici, pas de surprise particulire. Cest une recherche classique dans un annuaire, o lon prcise simplement, en plus, comme filtre, le RDN de lutilisateur. Par la suite, la fonction afficheFiche() prend le relais et construit le code HTML de notre formulaire en fonction des attributs et de la (ou des) valeur(s) de ceux-ci. Lenvoi du formulaire effectue lappel depuis la page index.php la fonction
modifierFiche().

951

Chapitre 11

Les annuaires LDAP

Listing 11.19 : exemples/includes/ldap.php


<?php /** * Fonction de modification dun utilisateur dans lannuaire * @return boolean */ function modifierFiche() { global $loginAttribut, $dnUtilisateur; if (!$ldap = connexionLdap()) return FALSE;

11. Les annuaires LDAP

$dn = "$loginAttribut=".$_POST[$loginAttribut].",$dnUtilisateur"; $entree = $_POST; array_pop($entree); if (@ldap_mod_replace($ldap, $dn, $entree)) { afficheBoiteMsg("Lutilisateur a t modifi !"); } else { afficheBoiteMsgErreur("Problme, ". "lutilisateur na pas t modifi !", $ldap); return FALSE; } // Dconnexion du serveur LDAP deconnexionLdap($ldap); return TRUE; }

Les informations du formulaire sont rcupres et prpares pour tre utilises avec linstruction ldap_mod_replace(). Nous avions pris soin de construire notre formulaire de faon ce que le tableau $_POST soit directement utilisable par cette fonction. La prparation est alors trs simple : il suffit de supprimer $_POST["action"] laide de linstruction array_pop().

Ralisation dun arbre de navigation LDAP


Il est courant de visualiser lannuaire LDAP sous la forme dun arbre. Le langage PHP va nous permettre de raliser un systme de navigation simple sur le serveur LDAP.

Listing 11.20 : exemples/navframearbre.php


<?php include("includes/inclusion.php"); session_start();

952

Exemple dapplication

affichehtml(); ?> <?php if ($_GET[dnEn]){ $dnEn = urldecode($_GET[dnEn]); $dnEnTableau = explode(||, $dnEn); } else { $dnEnTableau[0] = ""; } echo "<p style=font-size: 10px;>"; navigateur($dnEnTableau); echo "</p>"; ?> <p>&nbsp;</p> </body> </html>

11. Les annuaires LDAP

Nous observons que la page rcupre un paramtre dnEn qui lui est envoy et le transforme en tableau. Ce paramtre va nous servir ouvrir ou fermer les branches de larbre LDAP. La fonction permettant de visualiser larbre est la fonction navigateur().

Listing 11.21 : exemples/includes/ldap.php


<?php /** * Fonction affichage de llment dorigine de larbre LDAP * @input $dnEn */ function navigateur($dnEn) { global $dnOrigine; // Connexion au serveur LDAP $ldap = connexionLdap(); echo "*&nbsp;"; // lien vers les attributs $lien = "navframedescription.php?dn=".urlencode($dnOrigine); echo "<a href=".$lien." target=description>". $dnOrigine."</a><br />\n"; extractionDonnee($dnOrigine, $dnEn, $ldap); // Dconnexion du serveur LDAP deconnexionLdap($ldap); } ?>

La fonction effectue une connexion sur le serveur LDAP, puis affiche les liens sur le premier lment de larbre, permettant de visualiser par la suite, sur une nouvelle page, ses attributs. Ensuite, il est fait appel une nouvelle fonction, extractionDonnee(), avant de se dconnecter de lannuaire.

953

Chapitre 11

Les annuaires LDAP

Listing 11.22 : exemples/includes/ldap.php


<?php /** * Fonction rcursive permettant de construire larbre LDAP * @input string $dn, array $dnEn, resource $ldap * @return $string donnes formats */ function extractionDonnee($dn, $dnEn, $ldap) { // Cration du filtre de recherche $filtre = "(&(objectclass=*))"; $recherche = @ldap_list($ldap, $dn, $filtre, array("")); // On rcupere lentre $tableau = @ldap_get_entries($ldap, $recherche); for ($i=0;$i<$tableau["count"];$i++) { // On rcupre le rdn $dntmp = split(",", $tableau[$i]["dn"]); for($j=0;$j<count($dntmp);$j++) { echo "&nbsp;"; } // Les liens sur larbre $dnEnLien = $dnEn; // On vrifie si lentre nexiste pas dj dans le tableau if ($clef = array_search($tableau[$i]["dn"], $dnEnLien)) { // Si oui on la supprime $dnEnLien[$clef]=; $caractere = -; } else { // Si non, on lajoute $dnEnLien[count($dnEn)] = $tableau[$i]["dn"]; $caractere = +; } $chainednTmp = join("||", $dnEnLien); // On peut supprimer les signes | en trop $chainedn = str_replace("||||","||",$chainednTmp); // On encode la chane cause de la methode GET utilise $chainedn = urlencode($chainedn); $lien = "navframearbre.php?dnEn=".$chainedn; echo "<a href=".$lien." target=arbre>[".$caractere."]</a> "; // lien vers les attributs $lien = "navframedescription.php?dn=".urlencode($tableau[$i]["dn"]); echo "<a href=".$lien." target=description>". $dntmp[0]."</a><br />\n";

11. Les annuaires LDAP 954

Exemple dapplication

for ($j=0;$j<count($dnEn);$j++) { if ($dnEn[$j]==$tableau[$i]["dn"]) { extractionDonnee($tableau[$i]["dn"], $dnEn, $ldap); } } } } ?>

Cette fonction est une fonction rcursive. Elle va scanner la branche de lannuaire et vrifier que le DN ne se trouve pas dans le tableau pass en paramtre. Si elle le trouve, la fonction se lance elle-mme avec ce nouveau DN comme nouvelle base de recherche. Les liens nous servent, dune part, ouvrir et fermer les branches de larbre et, dautre part, afficher une page indiquant tous les attributs et leurs valeurs. Laffichage de la page est excut par lappel la fonction afficheAttribut().

11. Les annuaires LDAP

Listing 11.23 : exemples/html.php (extrait)


<?php /** * Fonction daffichage des attributs dune entre * @input $dn */ function afficheAttribut($dn) { $resultat = NavLdapEntree($dn); echo <table border="0" cellpadding="1" cellspacing="0" width="90%" bgcolor=".$GLOBALS["couleurBoite"]." align="center"> <tr> <td> <table border="0" cellpadding="0" cellspacing="4" width="100%" bgcolor="#ffffff">; // Ceci va nous tre utile pour bien visualiser les rsultats // Un peu de couleurs ne fait pas de mal. $coul = 0; $couleur[0] = "#ffffff"; $couleur[1] = "#dddddd"; for ($i=0;$i<$resultat[0]["count"];$i++) { $attribut = $resultat[0][$i]; echo <tr>; echo <td bgcolor=".$couleur[$coul].">.$attribut.</td>; echo <td bgcolor=".$couleur[$coul].">;

955

Chapitre 11

Les annuaires LDAP

// Il peut y avoir plusieurs valeurs pour un attribut. // Nous allons donc vrifier combiens de donnes nous sont // retournes pour chaques attributs. // Pour cela, on compte le nombre de valeur pour lattribut // et on boucle for ($nbAttr=0;$nbAttr<$resultat[0][$attribut]["count"];$nbAttr++) { echo $resultat[0][$attribut][$nbAttr].<br />; } echo <td bgcolor=".$couleur[$coul].">; echo </td>; echo </tr>; if ($coul==0) $coul=1; else $coul=0; } echo </table> </td> </tr> </table>; } ?>

11. Les annuaires LDAP

Cette fonction est similaire celle nous affichant la fiche dun utilisateur. Elle utilise linstruction NavLdapEntree() en lui envoyant le DN de lentre dont nous souhaitons rcuprer les attributs.

Listing 11.24 : exemples/includes/ldap.php


<?php /** * Fonction de recherche des attributs dun dn * @input $dn * @return array les donnes recherches ou FALSE si problme */ function NavLdapEntree($dn) { // Connexion au serveur LDAP $ldap = connexionLdap(); if (!$ldap) return FALSE; // Cration du filtre de recherche $recherche = @ldap_read($ldap, $dn, "objectclass=*"); if (!$recherche) { BoiteMsgErreur("La lecture des informations". " a chou !", $ldap); deconnexionLdap($ldap); return FALSE; }

956

Exemple dapplication

// On rcupere lentre $resultat = @ldap_get_entries($ldap, $recherche); // Dconnexion du serveur LDAP deconnexionLdap($ldap); return $resultat; } ?>

11. Les annuaires LDAP

Figure 11.7 : La navigation simple dans lannuaire LDAP

957

Chapitre 12

La messagerie : envoi et lecture de mails


12.1 12.2 12.3 E-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 961 Accder son compte messagerie IMAP, POP3 ou NNTP . . . . . . . . . . . . . . . . 974 Application dexemple : le webmail . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1012

E-mail

nvoyer des e-mails ou crer une interface permettant la consultation dune bote lettres lectronique sont deux tches facilites par lexistence des bibliothques fournies par PHP.

12.1. E-mail
Linteractivit avec les visiteurs dun site Internet passe aussi par le courrier lectronique. Envoyer un e-mail un visiteur (ou client) quand un produit susceptible de lintresser est disponible ou se faire envoyer (en tant quadministrateur dun site) un courrier lorsquun message est post dans le forum sont des exemples typiques dutilisation du courrier lectronique.

Installation
Il y a relativement peu de choses faire pour profiter des fonctions de mail.

12. La messagerie : envoi et lecture de mails

Sous Windows
Il vous suffit de modifier le fichier php.ini afin dajouter ou dcommenter les lignes suivantes :
[mail function] SMTP = smtp.monfai.com sendmail_from = moi@monfai.com

Le paramtre SMTP doit prciser ladresse de votre serveur SMTP (gnralement fourni par votre fournisseur daccs ou votre hbergeur, il peut tre du genre smtp.monfai.com ou mail .monfai.com par exemple). Le paramtre sendmail_from doit prciser votre adresse e-mail.

Commentaires et tabulations Vous risquez de rencontrer des problmes si vous conservez les commentaires et tabulations parfois prsents sur les lignes de ces paramtres. Nhsitez donc pas les supprimer.
Si besoin vous pouvez modifier le port dappel du service SMTP via le paramtre
smtp_port = 25

Sous Linux
Avec la plupart des distributions, par dfaut, vous naurez probablement rien faire. Sil savrait toutefois que cela ne fonctionne pas avec un test simple (le premier exemple prsent), assurez-vous que votre environnement contient bien un client mail appel sendmail ou un quivalent comme qmail. Si ce nest pas le cas, vous devrez commencer par en installer un (pour cela, consultez la documentation lie votre distribution). Une fois cette installation faite, vous aurez recompiler PHP (sans nouvelle option particulire).

961

Chapitre 12

La messagerie : envoi et lecture de mails

Maintenant que vous tes certain de possder un client mail (qui fonctionne), sachez que, sil sagit de sendmail, tout devrait fonctionner automatiquement. Vous pouvez nanmoins prciser le nom (sil est dans le PATH) ou le chemin complet vers votre client mail, ainsi que les options utiliser avec loption sendmail_path de php.ini. Si ce paramtre nest pas prcis, la valeur par dfaut utilise est "sendmail t i". Comme dans lexemple suivant :
[mail function] sendmail_path = /usr/sbin/sendmail -t -i

Contraintes des serveurs mails Il est possible que votre serveur mail (notamment sil est mis disposition par un hbergeur) vous impose de prciser une adresse retour en cas dchec de transmission du mail. Cela peut se traduire par exemple par le message suivant (retourn dans la bote lettres locale par sendmail) : 12. La messagerie : envoi et lecture de mails
SMTP; 552 sorry, your envelope sender domain must exist Dans ce cas, vous devrez ajouter une option f suivie de votre adresse e-mail. sendmail_path = /usr/sbin/sendmail -t -i -fmoi@monfai.com

Les utilisateurs de qmail devront probablement modifier cette valeur pour y mettre :
sendmail_path = /var/qmail/bin/sendmail

Vrifier le bon fonctionnement de sendmail Pour vrifier que sendmail fonctionne sur votre machine Linux (ou Mac OS X), il suffit dcrire un petit fichier test en remplaant VOTRE_ADRESSE par votre adresse :
Subject : Test From : Moi <moi@moi.moi> To : Moi <VOTRE_ADRESSE> Cool...

Puis de taper sendmail em t i < test. Vous devriez alors recevoir un mail votre adresse.
Le fichier php.ini propose galement le paramtre
mail.force_extra_parameters =

Les paramtres prciss ici remplaceront la valeur du cinquime paramtre de la fonction mail() (y compris en safe mode)

Envoyer un e-mail simple


La fonction permettant lenvoi dun mail sappelle tout simplement mail(). Elle peut tre utilise pour envoyer des mails tout simples ou des mails complexes (avec des fichiers joints par exemple).

962

E-mail

mail()
Fonction permettant denvoyer un e-mail. Syntaxe $vers boolean mail(string $vers, string $sujet, string $message[, string $entetes [, parametres]]) Adresse e-mail o envoyer le courrier lectronique. Vous pouvez galement prciser le nom du destinataire en utilisant le format "Nom" <email@domaine.extension>. Si vous souhaitez mettre plusieurs personnes en destinataire, sparez simplement les adresses par une virgule. Sujet de le-mail. Le message envoyer. En-ttes ajouter le-mail. Chaque ligne de len-tte doit tre termine par "\r\n". Paramtres supplmentaires passer au programme denvoi de-mails (sendmail par exemple, introduit dans la version 4.0.5). Si safemode est activ, cet argument sera ignor. Retourne TRUE si le message peut tre envoy (ce qui ne prjuge en rien de lexistence de ladresse des destinataires et encore moins de la bonne rception de le-mail).

$sujet $message $entetes $parametres

12. La messagerie : envoi et lecture de mails

retour

Une fois le serveur de courrier correctement configur, vous pouvez tester un script PHP trs simple :

Listing 12.1 : email0.php


<?php echo "Envoi email..."; mail("testemail@toutestfacile.com", "Test demail", "Ceci est un test demail"); ?>

Vous devriez recevoir un e-mail si vous noubliez pas de remplacer ladresse testemail@toutestfacile.compar la vtre.

Hbergeurs (gratuits) Certains hbergeurs (notamment les gratuits) proposent une version altre de mail(), souvent appele email(). Le principe de fonctionnement devrait tre le mme, mais nous vous invitons consulter votre fournisseur afin de connatre les diffrences. Dautres ne proposent tout simplement pas de fonction permettant lenvoi de-mails.
Comme vous tes perspicace, vous avez pu constater que la fonction mail() propose quelques paramtres supplmentaires en plus des indispensables nom du destinataire, sujet et contenu du mail. Vous pouvez ainsi ajouter des informations len-tte du mail, ce qui permet notamment de spcifier ladresse de lexpditeur, une adresse de rponse et toute une srie dinformations que nous dcouvrirons petit petit. Vous pouvez galement passer des paramtres au client mail, ce qui est particulirement utile pour, par exemple, prciser ladresse laquelle doivent tre envoys les mails derreur que le serveur pourrait envoyer.

963

Chapitre 12

La messagerie : envoi et lecture de mails

Listing 12.2 : mail1.php


<?php echo "Envoi dun email avec un entete spcifique"; mail ("testemail@toutestfacile.com", "Test demail", "Ceci est un test\nsur plusieurs lignes\n" ."avec un entete et un parametre", "From: depuistestemail@toutestfacile.com\r\n" ."Cc: copietestemail@toutestfacile.com\r\n" ."Reply-To: noreply@toutestfacile.com\r\n" ."X-Mailer: Mon propre mailer !", "-ferreurstestemail@toutestfacile.com"); ?>

12. La messagerie : envoi et lecture de mails

Ce script enverra donc un mail testemail@toutestfacile.com, ainsi quune copie copietestemail@toutestfacile.com (comme le prcise le champ Cc: de len-tte). En rpondant ce mail, ces deux personnes criront noreply@toutestfacile.com (comme le prcise le champ ReplyTo: de len-tte), mme si lexpditeur sera indiqu comme tant depuistestemail@toutestfacile.com (comme le prcise le champ From: de len-tte). En cas derreur lors de lenvoi (adresse e-mail inexistante par exemple), le-mail derreur sera envoy erreurstestemail@toutestfacile.com si le programme denvoi dun e-mail est sendmail (grce son option -f).

Option -f de sendmail Si cela est possible, vous aurez tout intrt modifier le fichier php.ini pour prciser, au niveau du paramtre sendmail_path, loption "f". Cela vous vitera de rpter lopration chaque utilisation de la fonction mail().
Voici le contenu de le-mail reu (avec une partie de len-tte).
To: testemail@toutestfacile.com Subject: Test demail From: depuistestemail@toutestfacile.com CC: copietestemail@toutestfacile.com Reply-To: noreply@toutestfacile.com X-Mailer: Mon propre mailer ! Message-Id: <20020612005448.851652416E@toutestfacile.com> Date: Tue, 11 Aug 2002 20:54:48 -0400 (EDT) Content-Type: text X-UIDL: c21"!&[M!!dAR!!(],!! Ceci est un test sur plusieurs lignes avec un entete et un parametre

Source Pour visualiser prcisment le contenu de len-tte du mail reu, il vous suffit : Avec Outlook, de slectionner le mail et choisir loption options du menu View (Afficher) ou bien de sauvegarder le mail et de louvrir avec un diteur de texte ; Avec Mozilla, de slectionner le mail et choisir loption Message source du menu View.

964

E-mail

Pour envoyer un mme e-mail plusieurs destinataires, il suffit de sparer les adresses par une virgule.

Type MIME
MIME (Multipurpose Internet Mail Extension) est une extension du courrier lectronique ordinaire tel quil a t dfini. Cette norme permet de grer des contenus qui ne sont pas du texte brut. Elle est tellement incontournable que dsormais la quasi-totalit des courriers lectroniques lutilisent, mme sans avoir recours des fichiers attachs, ni mme des courriers au format HTML. Pour quun message respecte la norme MIME, len-tte doit contenir un champ MIME-Version indiquant le numro de version de la norme MIME utilise, ainsi quun champ Content-Type prcisant le type du contenu du mail et, ventuellement, dautres champs dpendant du type slectionn. Le courrier prcdent aurait t le suivant sil avait t envoy au format MIME :
To: testemail@toutestfacile.com Subject: Test demail From: depuistestemail@toutestfacile.com CC: copietestemail@toutestfacile.com Reply-To: noreply@toutestfacile.com X-Mailer: Mon propre mailer ! Message-Id: <20020612005448.851652416E@toutestfacile.com> Date: Tue, 11 Aug 2002 20:54:48 -0400 (EDT) MIME-Version: 1.0 Content-Type: text/plain charset="iso-8859-1" X-UIDL: c21"!&[M!!dAR!!(],!! Ceci est un test sur plusieurs lignes avec un entete et un parametre

12. La messagerie : envoi et lecture de mails

MIME Vous trouverez une liste de RFC (en anglais) se rapportant la norme MIME sur le site http://www.oac.uci.edu/indiv/ehood/MIME/MIME.html Certaines sont traduites aux adresses :
http://jlr31130.free.fr/rfc2045-index.html http://jlr31130.free.fr/rfc2046-index.html http://jlr31130.free.fr/rfc2047-index.html

Envoyer un e-mail au format HTML


Lutilisation de la norme MIME permet notamment denvoyer des fichiers au format HTML.

965

Chapitre 12

La messagerie : envoi et lecture de mails

Pour envoyer un fichier au format HTML, il suffit de prciser que le contenu du message (Content-type) est de lHTML (text/html). (Sinon, le destinataire verra les balises HTML qui ne seront pas interprtes.)

Listing 12.3 : mail2.php


<?php echo "Envoi dun email HTML"; mail("testemail@toutestfacile.com", "Test demail", "<html><body>". "<h1>Test Email</h1>". "<b><u>Ceci est un document HTML</u></b><br>". "Avec differentes tailles de caractres et ". "<font color=\"red\">couleurs</font>". "</body></html>", "From: moi@monsite.com\r\n" ."Content-Type: text/html; charset=\"iso-8859-1\""); ?>

12. La messagerie : envoi et lecture de mails

Envoyer un e-mail avec chiers attachs


Vous pourrez galement envoyer une image. Pour cela, il faudra bien entendu prciser le type du contenu avec Content-type, que nous positionnerons, dans notre cas, la valeur image/jpeg. Nous pourrons galement prciser quil sagit dun fichier attach portant le nom (vu du destinataire) image.jpg. Pour cela, nous ajouterons len-tte une ligne "ContentDisposition: attachment; filename=image.jpg". Mais, surtout, nous devrons rsoudre un problme. En effet, les seules donnes vritablement supportes par le mail sont les donnes de type texte. Or, nous souhaitons mettre des donnes binaires. Pour rsoudre ce problme, il suffit de respecter les normes tablies. Il faudra donc encoder le contenu binaire pour le transformer en contenu textuel (sans perte dinformation). Cela peut se faire grce lencodage en base 64 via la fonction base64_encode().

base64_encode()
Retourne une chane encode en base 64. Syntaxe $chaine retour string base64_encode(string $chaine) Chane encoder. La chane encode.

Afin dindiquer au client mail le type dencodage utilis (ici base64), vous devez utiliser len-tte ContentTransfertEncoding: base64. Pour tre totalement conforme avec la norme, les chanes de caractres issues de lencodage ne doivent pas dpasser 76 caractres. Il faut donc encore ajouter des retours la ligne (\r\n) tous

966

E-mail

les 76 caractres. Pour cela, vous disposez de la fonction chunk_split() qui ralise justement cette opration (cette fonction a t prsente dans le chapitre PHP et les chanes de caractres). Le script permettant lenvoi dune image JPEG aura donc lallure suivante :

Listing 12.4 : mail3a.php


<?php echo "Envoi dun email avec un fichier attach"; $fichier = "imagetest.jpg"; // Lecture du fichier en mode binaire (cette prcision // nest importante que pour windows) $fp = fopen($fichier, "rb"); $fichierAttache = fread($fp, filesize($fichier)); fclose($fp); Figure 12.1 :

Image envoyer (chutes du Niagara)

12. La messagerie : envoi et lecture de mails

// mise au format RFC $fichierAttache = chunk_split(base64_encode($fichierAttache)); mail("testemail@toutestfacile.com", "Test demail", $fichierAttache, "From: moi@monsite.com\r\n" ."Content-Disposition: attachment; filename=image.jpg\r\n" ."Content-Transfer-Encoding: base64\r\n" ."Content-Type: image/jpg\r\n"); ?>

Ainsi avec limage suivante : Ce script est quivalent :

Listing 12.5 : mail3b.php


<?php echo "Envoi dun email avec un fichier attach"; mail ("testemail@toutestfacile.com", "Test demail", "/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEP ERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/wAALCABGAEYBAREA/8QAHwAAAQUBAQEB AQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1Fh ByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZ WmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG x8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/9oACAEBAAA/AOmmkl8+T96/3j/EfWmi WX/nq/8A30aXzJf+er/99GkMko/5av8A99GmmWb/AJ6v/wB9Gk82b/nrJ/30aY0s3/PWT/vo0xpJ 8f62T/vo00yzj/lpJ/30azrvxVoEV3LG+pRBlkZSMMeQfpVb/hMvD+8IL1ixOOIX45x6UsvjLQIX 2SXuDjPCFh+YBqL/AITnw4Q2byQbe5hfn17VC/jzw+JAFui6EZyqNn8iKrXXj3TvLmW3dQ4B8svn k9uMfpmsObx3fo6/6REc9hGDxW4PH+kPCHjW4LZAKlcVKnjXRZHIL3CDHUx/4Vwupt52pXYWSUET OMM2O56GsS6DSvtaMkbup54qa6055Lllhh3ttUdOR+lanh/w3eXsrW8ULKT97cOPrXd6F8O4Flxf y4jx8wQAEn8q1G+F/h+ST91NOBnqxB/kBVi3+Fnh1ztP2jg8sHxVPXvAeiaVpW+CCSW6eQLGu7jJ PA+uK5TV/D9pbalLaxNxHgMwHVsc/hmn6lpls1/clF2sZGyQ3uazp9Jh3Beeo5rqPD+kAjzfJO1u rEV1dlHa2ceUKAnjgcmj+0C0h4KKOhPGa1dOcsQzkhcfnVqXU4II2aVTFj7oY4Lfh1rl/EPiAzMD Cm4xHchI43Vwd9LcSXTzu7tI5yxHFa15Av26c7f+Wjd/eojGynKFlPqGIqaGW7H3rmU+zMTV63ub

967

Chapitre 12

La messagerie : envoi et lecture de mails

vAQSsV9M8V0Oj2ZnZZLiLKAYwDgflW1e3hjg8iyijgwCCw5b8DXM3EMjzlppWYk5JJyagNpATtJU j3pp0y2fkBPwqldIPtk3/XRv50zyxRHFk1u6HpjTsGI+Uda6Oby4o/Kj4AqlLj86pzbQeKrTY3fd AX196ryIOgGay7sn7bNz/wAtG/nSfMBnA5rR0mza4lUBe9daojtLZYk4bHJqkz5JOeahlYnjtVRz 81NHO4HntUQAHHXHFZV5H/pc3zZO9jjHv9KdaQebKFQkk/7NdbYwLY2qsV+dhTJ5i7cmod3OKrXE 4ViqjLjseMiqkkzYZ8rsxkHHOO9R/agI2dBnCgkE4I9vrVW/nkV0ZD8rLx/n8q0rnw3qBuZZFmtt hdiAWbPX6Vp6HoFzDJvlkgbHIAyf6Vo3dhdSPkPEAOgyf8KqjS7vJ/eQ/wDfR/wpsmlXI4Lwn1yT /hWTdaPqTTPHFLbxjdx87Hj244qGTw7qBxsnt1O7cSGPzZOcEbeaqXPh3UjKZBPbD5wWG9uuO3Hv ULeHNY3FjeQeX0VQ7ccc9VPpX//Z", "From: moi@monsite.com\r\n" ."Content-Disposition: attachment; filename=image.jpg\r\n" ."Content-Transfer-Encoding: base64\r\n" ."Content-Type: image/jpg\r\n"); ?>

Ce que vous pouvez facilement vrifier en sauvegardant le mail et en louvrant avec un diteur de texte.

12. La messagerie : envoi et lecture de mails

Vous pouvez videmment utiliser ce script pour tout type de fichier attach (autre type dimage, excutable, fichier son, etc.). Il vous suffit dadapter len-tte Contenttype en consquence.

Envoyer un e-mail multi-part


Mais ne recevoir quun texte ou quune image na rien de palpitant. Vous serez certainement amen accompagner votre fichier dun message. Pour concevoir ce genre de-mails plus complexes, il va falloir constituer des messages lectroniques avec plusieurs parties (multi-part). Pour crer des messages avec plusieurs parties, il faut :
j j j

Prciser dans len-tte principal quil sagit dun mail multi-part. Identifier chaque partie en la sparant des autres par un dlimiteur. Indiquer pour chaque partie le type de contenu.

Le choix du dlimiteur est important, puisquil ne doit pas pouvoir tre confondu avec le contenu de le-mail, en particulier si ce mail inclut un mail multi-part (ce qui peut arriver dans le cas des mails transfrs). Ce dlimiteur peut tre quelconque, mais il parat vident quil vaut mieux choisir un dlimiteur complexe et variable plutt quun mot simple. Ce dlimiteur est donc gnralement cr alatoirement. Le dlimiteur choisi sera indiqu au client mail en lajoutant len-tte Contenttype. Voici un script comment qui permet denvoyer un courrier lectronique contenant un texte trs simple et une image en fichier attach. Chacun de ces lments est "stock" dans une partie du mail. Le corps du mail, quant lui, ne contiendra quun simple texte destin aux rares clients mail ne supportant pas le format "MIME 1.0 multipart/mixed".

Listing 12.6 : mail4.php


<html> <body> Test Email avec fichier joint <?php

968

E-mail

//---------------------------------// Construction de lentte //---------------------------------// Le dlimiteur est gnr alatoirement $delimiteur = "-----=".md5(uniqid(rand())); // Ici, on construit un en-tte contenant les informations // minimales requises. // Version du format MIME utilis $entete = "MIME-Version: 1.0\r\n"; // Type de contenu. // Ici plusieurs parties de type different "multipart/mixed" // Avec un delimiteur dfini par $delimiteur $entete .= "Content-Type: multipart/mixed; boundary=\"$delimiteur\"\r\n"; $entete .= "\r\n";

12. La messagerie : envoi et lecture de mails

//-------------------------------------------------// Construction du message proprement dit //-------------------------------------------------// Pour le cas, o le logiciel de mail du destinataire // nest pas capable de lire le format MIME de cette version // Il est de bon ton de len informer // REM: Ce message napparat pas pour les // logiciels sachant lire ce format $msg = "Je vous informe que ceci est un message au format MIME 1.0 ". "multipart/mixed.\r\n"; //--------------------------------// 1re partie du message // Le texte //--------------------------------// Chaque partie du message est spare par une frontire $msg .= "--$delimiteur\r\n"; // Et pour chaque partie on en indique le type $msg .= "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n"; // Et comment il sera cod $msg .= "Content-Transfer-Encoding:8bit\r\n"; // Il est indispensable dintroduire une ligne vide // entre len-tte et le texte $msg .= "\r\n"; // Enfin, on peut crire le texte de la 1re partie $msg .= "Ceci est un mail avec un fichier joint\r\n"; $msg .= "\r\n"; //--------------------------------// 2e partie du message // Le fichier //---------------------------------

969

Chapitre 12

La messagerie : envoi et lecture de mails

// Tout dabord lire le contenu du fichier $fichier = "monfichier.jpg"; $fp = fopen($fichier,"rb"); $fichierAttache = fread($fp, filesize($fichier)); fclose($fp); // puis convertir le contenu du fichier en une chane de caractres // certes totalement illisible, mais sans caractres exotiques // et avec des retours la ligne tout les 76 caractres // pour tre conforme au format RFC 2045 $fichierAttache = chunk_split(base64_encode($fichierAttache)); // Ne pas oublier que chaque partie du // message est spare par une frontire $msg .= "--$delimiteur\r\n"; // Et pour chaque partie on en indique le type $msg .= "Content-Type: image/jpg; name=\"$fichier\"\r\n"; // Et comment il sera cod $msg .= "Content-Transfer-Encoding: base64\r\n"; // Petit plus pour les fichiers joints // Il est possible de demander ce que le fichier // soit si possible affich dans le corps du mail $msg .= "Content-Disposition: inline; filename=\"$fichier\"\r\n"; // Il est indispensable dintroduire une ligne vide // entre len-tte et le texte $msg .= "\r\n"; // Cest ici que lon insre le code du fichier lu $msg .= $fichierAttache."\r\n"; $msg .= "\r\n\r\n"; // voil, on indique la fin par une nouvelle frontire $msg .= "--$delimiteur--\r\n"; $to = "testemail@toutestfacile.com"; $reply = "moi@monsite.com"; $from = "moi@monsite.com"; mail($to, "Test fichier attach", $msg, "Reply-to: $reply\r\nFrom: $from\r\n".$entete); ?> </body> </html>

12. La messagerie : envoi et lecture de mails

Ligne vide Ne pas oublier de laisser une ligne (\r\n) entre chaque en-tte et le message ou fichier. Il suffit de trs peu de choses pour que le mail reu ne soit pas conforme au rsultat attendu.
Dans cet exemple, nous avons choisi dafficher limage dans le corps du mail en utilisant "ContentDisposition: inline". Il aurait galement t possible de faire en sorte que limage soit jointe au mail en tant que fichier sauvegarder par lutilisateur, en remplaant

970

E-mail

inline par attachment. La nuance entre les deux dpendra galement du client mail utilis par le destinataire (en effet, certains ne supportent pas le mode inline). Le script suivant comporte deux fichiers attachs un en inline et un en attachment. Vous serez ainsi en mesure de voir la diffrence.

Listing 12.7 : mail5.php


<html> <body> Test Email avec 2 fichiers joints <?php //---------------------------------// Construction de lentte //---------------------------------$delimiteur = "-----=".md5(uniqid(rand()));

12. La messagerie : envoi et lecture de mails

$entete = "MIME-Version: 1.0\r\n"; $entete .= "Content-Type: multipart/mixed; boundary=\"$delimiteur\"\r\n"; $entete .= "\r\n"; //-------------------------------------------------// Construction du message proprement dit //-------------------------------------------------$msg = "Je vous informe que ceci est un message au format MIME 1.0". " multipart/mixed.\r\n"; //--------------------------------// 1re partie du message // Le texte //--------------------------------$msg .= "--$delimiteur\r\n"; $msg .= "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n"; $msg .= "Content-Transfer-Encoding:8bit\r\n"; $msg .= "\r\n"; $msg .= "Ceci est un mail avec 2 fichiers joints\r\n"; $msg .= "\r\n"; //--------------------------------// 2e partie du message // Le 1er fichier (inline) //--------------------------------$fichier = "monfichier.jpg"; $fp = fopen($fichier,"rb"); $fichierAttache = fread($fp, filesize($fichier)); fclose($fp); $fichierAttache=chunk_split(base64_encode($fichierAttache)); $msg .= "--$delimiteur\r\n"; $msg .= "Content-Type: image/jpg; name=\"$fichier\"\r\n";

971

Chapitre 12

La messagerie : envoi et lecture de mails

$msg $msg $msg $msg $msg

.= .= .= .= .=

"Content-Transfer-Encoding: base64\r\n"; "Content-Disposition: inline; filename=\"$fichier\"\r\n"; "\r\n"; $fichierAttache . "\r\n"; "\r\n\r\n";

//--------------------------------// 3me partie du message // Le 2me fichier (attachment) //--------------------------------$fichier = "monfichier2.jpg"; $fp = fopen($fichier,"r"); $fichierAttache = fread($fp,filesize($fichier)); fclose($fp); $fichierAttache = chunk_split(base64_encode($fichierAttache)); $msg $msg $msg $msg $msg $msg $msg .= .= .= .= .= .= .= "--$delimiteur\r\n"; "Content-Type: image/jpg; name=\"$fichier\"\r\n"; "Content-Transfer-Encoding: base64\r\n"; "Content-Disposition: attachment; filename=\"$fichier\"\r\n"; "\r\n"; $fichierAttache . "\r\n"; "\r\n\r\n";

12. La messagerie : envoi et lecture de mails

$msg .= "--$delimiteur--\r\n"; $to = "testemail@toutestfacile.com"; $reply = "moi@monsite.com"; $from = "moi@monsite.com"; mail($to, "Test avec 2 fichiers attachs", $msg, "Reply-to: $reply\r\nFrom: $from\r\n".$entete); ?> </body> </html>

Client e-mail Vous pouvez ne pas voir de diffrence selon votre client e-mail.

Envoyer un e-mail HTML avec des images


Envoyer un courrier lectronique au format HTML incluant des images est peine plus compliqu. Il existe en fait deux cas de figure. Le plus simple, mais le moins satisfaisant, consiste considrer que les images sont disponibles sur un serveur web. Il suffit, dans ce cas, de reprendre le premier exemple denvoi dun e-mail au format HTML, et de prciser des adresses compltes pour les images (du genre <img src="http://monsite.com/monimage.jpg">). Lautre solution consiste envoyer les images avec le corps du mail HTML. Pour cela, il suffit de crer un mail multi-part, comme dans les exemples prcdents. Mais la difficult (si lon peut dire) apparat lorsquil sagit de faire rfrence ces fichiers attachs depuis les balises HTML.

972

E-mail

Pour rpondre ce besoin, il est possible de donner un identifiant une partie quelconque du mail (ici, les images), grce len-tte ContentID: suivi dune chane de caractres choisie comme identifiant, et place entre < et >. Pour faire ensuite appel ces lments, il suffit de prciser lidentifiant de la partie prcd de "cid:". Ce qui donne un script du genre :

Listing 12.8 : mail6.php


<html> <body> Test Email au format HTML avec 2 images <?php //---------------------------------// Construction de len-tte //---------------------------------$delimiteur = "-----=".md5(uniqid(rand()));

12. La messagerie : envoi et lecture de mails

$entete = "MIME-Version: 1.0\r\n"; $entete .= "Content-Type: multipart/mixed; boundary=\"$delimiteur\"\r\n"; $entete .= "\r\n"; //-------------------------------------------------// Construction du message proprement dit //-------------------------------------------------$msg = "Je vous informe que ceci est un message au format MIME 1.0". " multipart/mixed.\r\n"; //--------------------------------// 1r partie du message // Le code HTML //--------------------------------$msg .= "--$delimiteur\r\n"; $msg .= "Content-Type: text/html; charset=\"iso-8859-1\"\r\n"; $msg .= "Content-Transfer-Encoding:8bit\r\n"; $msg .= "\r\n"; $msg .= "<html><body><h1>Email HTML avec 2 images</h1>"; $msg .= "<table>"; $msg .= "<tr><th>Image 1</th></tr><tr><td><img src=\"cid:image1\"></td></tr>"; $msg .= "<tr><th>Image 2</th></tr><tr><td><img src=\"cid:iamge2\"></td></tr>"; $msg .= "</table>"; $msg. = "</body></html>\r\n"; $msg.="\r\n"; //--------------------------------// 2e partie du message // Le 1er fichier //--------------------------------$fichier = "monfichier.jpg"; $fp = fopen($fichier, "rb"); $fichierAttache = fread($fp, filesize($fichier));

973

Chapitre 12

La messagerie : envoi et lecture de mails

fclose($fp); $fichierAttache = chunk_split(base64_encode($fichierAttache)); $msg $msg $msg $msg $msg $msg $msg .= .= .= .= .= .= .= "--$delimiteur\r\n"; "Content-Type: application/octet-stream; name=\"$fichier\"\r\n"; "Content-Transfer-Encoding: base64\r\n"; "Content-ID: <image1>\r\n"; "\r\n"; $fichierAttache . "\r\n"; "\r\n\r\n";

12. La messagerie : envoi et lecture de mails

//--------------------------------// 3me partie du message // Le 2me fichier //--------------------------------$fichier = "monfichier2.jpg"; $fp = fopen($fichier, "rb"); $fichierAttache = fread($fp, filesize($fichier)); fclose($fp); $fichierAttache = chunk_split(base64_encode($fichierAttache)); $msg $msg $msg $msg $msg $msg $msg .= .= .= .= .= .= .= "--$delimiteur\r\n"; "Content-Type: application/octet-stream; name=\"$fichier\"\r\n"; "Content-Transfer-Encoding: base64\r\n"; "Content-ID: <image2>\r\n"; "\r\n"; $fichierAttache . "\r\n"; "\r\n\r\n";

$msg .= "--$delimiteur--\r\n"; $to = "testemail@toutestfacile.com"; $reply = "moi@monsite.com"; $from = "moi@monsite.com"; mail($to, "Email HTML avec 2 images", $msg, "Reply-to: $reply\r\nFrom: $from\r\n".$entete); echo "A destination de $to<br />"; ?> </body> </html>

Envoyer un courrier lectronique en PHP est dune simplicit dconcertante, non ?

12.2. Accder son compte messagerie IMAP, POP3 ou NNTP


Accder un compte IMAP, POP3, ou NNTP (serveur de news) permet de consulter des messages lectroniques depuis nimporte quel navigateur, sans avoir le reconfigurer. Cela

974

Accder son compte messagerie IMAP, POP3 ou NNTP

permet aussi de personnaliser linterface et, ainsi, dautoriser ou dinterdire certaines fonctions par rapport un client email "classique". Ce principe daccs aux messages lectroniques via un site Internet est communment appel webmail. Que ce soit pour accder un compte IMAP, POP3 ou NNTP, le principe est presque identique, quelques petites diffrences prs. Avant toute chose, il faut installer la bibliothque IMAP.

Installation
Sous Windows
Avec larchive du PHP Group
Vous devez, dans un premier temps, vous assurer de disposer du fichier php_imap.dll (fourni avec larchive) dans le rpertoire des extensions PHP. Il vous suffit alors de modifier le fichier php.ini pour ajouter ou dcommenter une ligne.
extension=php_imap.dll

12. La messagerie : envoi et lecture de mails

Avec EasyPHP
Avec EasyPHP, le support dIMAP est activ par dfaut.

Sous Linux
Vous devez, dans un premier temps, rcuprer la bibliothque cliente IMAP (c-client.tar.Z) sur le site ftp://ftp.cac.washington.edu/imap/ (galement disponible sur le CD-ROM fourni). Vous pouvez la copier dans un rpertoire quelconque (par exemple, /usr/local/src/lib) , puis dcompressez larchive avec :
# uncompress c-client.tar.Z # tar xvf c-client.tar

Puis compilez-la :
# cd imap-2001a # make slx

Autres systmes dexploitation Vous aurez peut-tre choisir une autre option si vous souhaitez adapter cette procdure dinstallation pour un autre systme dexploitation (les options sont dcrites dans le fichier Makefile).
Vous devez avoir ainsi gnr un ensemble de fichiers sous le rpertoire c-client. Certains de ces fichiers doivent alors tre copis dans des rpertoires accessibles lors de la compilation de PHP.
# cp c-client/c-client.a /usr/local/lib/.

975

Chapitre 12

La messagerie : envoi et lecture de mails

et
# cp c-client/rfc822.h /usr/local/include/. # cp c-client/mail.h /usr/local/include/. # cp c-client/linkage.h /usr/local/include/.

Une fois cette opration ralise, vous pouvez recompiler PHP avec loption --with-imap.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur la compilation de PHP.

Vrication
Vous pouvez vrifier que votre environnement PHP intgre bien le support dIMAP en appelant un simple script contenant <?php phpinfo(); ?> qui devra afficher :

12. La messagerie : envoi et lecture de mails

Figure 12.2 : phpinfo()

Connexion et dconnexion un serveur


Pour pouvoir interroger un compte, il faut commencer par se connecter celui-ci. Pour cela, vous devez pralablement runir quelques informations. Il faut connatre :
j j j j

Ladresse du serveur de mail (adresse IP ou nom complet) ; Le port du service (gnralement 110 pour POP3, 143 pour IMAP et 119 pour NNTP) ; Le login daccs (celui qui sert accder au compte habituellement) ; Le mot de passe associ au login prcdent.

Dans nos exemples, la connexion se fera sur mail.monsite.com avec le login monlogin et le mot de passe monpassword. Pour les oprations de connexion, les botes lettres sont reprsentes par une chane de caractres ayant le format : {<serveur>:<port>/<type>}<boite>. Autrement dit, elle se compose de deux parties :
j

Une partie entre accolades indiquant le serveur. On y retrouve, ladresse IP ou le nom du serveur, puis le numro du port prcd de :. Puis enfin le type de serveur (IMAP par dfaut) en ajoutant /imap, /pop ou /nntp. Dans le cas dun serveur scuris, il faut ajouter /ssl aprs le type de serveur et, si le serveur est scuris avec un certificat, il faut ajouter /ssl/novalidatecert. Puis le nom de la bote lettres ouvrir (INBOX par dfaut).

976

Accder son compte messagerie IMAP, POP3 ou NNTP

Nom de bote et caractres spciaux Si le nom de la bote lettres doit contenir des caractres internationaux peu courants, alors il doit tre encod avec la fonction imap_utf7_encode() avant dtre utilis comme rfrence ou dcod avec imap_utf7_decode() lorsquil est lu.

imap_open()
Permet douvrir une connexion sur un serveur IMAP, POP3 ou NNTP. Syntaxe $bal $login $motDePasse $mode resource imap_open(string $bal, string $login, string $motDePasse [, int $mode]) Identifiant de la bote lettres {<serveur>:<port>/<type>}<boite>. Login de connexion. Mot de passe correspondant au login. Une combinaison par OU logique des valeurs. OP_ANONYMOUS : nutilise pas de .newsrc (uniquement pour NNTP). OP_HALFOPEN : permet douvrir une connexion sans slectionner de bote (uniquement pour IMAP et NNTP). OP_READONLY : permet douvrir une bote en lecture seule. CL_EXPUNGE : efface automatiquement les messages marqus comme tant effacer de la bote lors de la fermeture. retour Un identifiant, ou FALSE si la connexion na pas pu se faire. au format

12. La messagerie : envoi et lecture de mails

Voici quelques exemples : Pour ouvrir la bote lettres INBOX dun serveur IMAP sur le port 143 situ sur la machine courante :
imap_open("{localhost:143}INBOX", "monlogin", "mon password")

Pour ouvrir la bote lettres OUTBOX en lecture seule dun serveur POP3 sur le port 110 situ sur la machine mail.monsite.com :
imap_open("{mail.monsite.com:110/pop3}OUTBOX", "monlogin", "mon password", "OP_READONLY")

Pour ouvrir le groupe comp.lang.php du serveur de news NNTP sur le port 119 situ sur la machine news.monfai.com :
imap_open("{news.monfai.com:119/nntp}comp.lang.php", "", "")

977

Chapitre 12

La messagerie : envoi et lecture de mails

imap_close()
Permet de fermer une connexion un serveur POP3, IMAP ou NNTP. Syntaxe $identifiantBal $mode boolean imap_close(resource $identifiantBal [, int $mode]) Identifiant tel que retourn par imap_open(). Le seul mode disponible est : CL_EXPUNGE qui fait effacer tous les messages marqus comme tant effacer de la bote lettres en quittant. retour TRUE si lopration sest bien effectue, FALSE dans le cas contraire.

Un script de base de connexion et de dconnexion a donc lallure suivante :

12. La messagerie : envoi et lecture de mails

Listing 12.9 : imap_1.php


<html> <head><title>Exemple IMAP</title></head> <body> <?php $bal= imap_open("{mail.monsite.com:110/pop3}", "monlogin", "monpassword"); if (!$bal) die("La connexion a choue"); imap_close($bal); ?> </body> </html>

Il est galement possible tout instant de vrifier la validit dune connexion.

imap_ping()
Vrifie que la connexion IMAP est toujours active. Syntaxe $identifiantBal retour boolean imap_ping(resource $identifiantBal) Identifiant tel que retourn par imap_open(). TRUE si la connexion est toujours active.

Une fois que vous tes connect, de nombreuses possibilits soffrent vous. Cela va de la rcupration de la liste des botes lettres leur administration, en passant par la lecture de leur contenu.

978

Accder son compte messagerie IMAP, POP3 ou NNTP

Slection dune bote lettres


Si vous vous tes connect un serveur sans ouvrir de bote lettres (mode OP_HALFOPEN) ou, tout simplement, si vous souhaitez accder une autre bote lettres, vous disposez de la fonction :

imap_reopen()
Ouvre une nouvelle connexion IMAP vers une nouvelle bote lettres. Syntaxe $identifiantBal $bal $mode boolean imap_reopen(resource $identifiantBal, string $bal [, int $mode]) Identifiant tel que retourn par imap_open(). Nouvelle bote lettres ouvrir. Une combinaison par OU logique des valeurs. OP_ANONYMOUS : nutilise pas de .newsrc (uniquement pour NNTP). OP_HALFOPEN : permet douvrir une connexion sans slectionner de bote (uniquement pour IMAP et NNTP). OP_READONLY : permet douvrir une bote en lecture seule. CL_EXPUNGE : efface automatiquement les messages marqus comme tant effacer de la bote lors de la fermeture. Un identifiant, ou FALSE si la connexion na pas pu se faire.

12. La messagerie : envoi et lecture de mails

retour

Pour vous aider faire votre choix, vous aurez peut-tre besoin de connatre la liste des botes disponibles. Vous disposez pour cela de plusieurs fonctions.

imap_listMailbox()
Retourne la liste des botes lettres. Syntaxe $identifiantBal $serveur $position array imap_listMailbox(resource $identifiantBal, string $serveur, string $position) Identifiant tel que retourn par imap_open(). Serveur au format {<serveur>:<port>/<type>}. Position hirarchique de la premire bote tudier. Vous pouvez utiliser le caractre * pour tout tudier ou % pour toutes les botes du niveau slectionn (ex : comp.lang.%). Tableau index des noms complets des botes lettres.

retour

Voici un script dexemple :

979

Chapitre 12

La messagerie : envoi et lecture de mails

Listing 12.10 : imap_listmailbox.php


<?php $bal = imap_open("{mail.monsite.com:143/imap}","monlogin","monpassword"); $tableau = imap_listmailbox($bal, "{mail.monsite.com}", "*"); while (list($cle, $valeur) = each($tableau)) { echo "$cle:"; echo imap_utf7_decode($valeur)."<br />\n"; } imap_close($bal); ?>

Et un rsultat possible :
0:{mail.monsite.com}INBOX.Sent.mai-2002 1:{mail.monsite.com}INBOX.Trash 2:{mail.monsite.com}INBOX.Sent 3:{mail.monsite.com}INBOX.Drafts 4:{mail.monsite.com}INBOX

12. La messagerie : envoi et lecture de mails

Mais peut-tre voudrez vous restreindre votre recherche.

imap_scanmailbox()
Recherche une chane de caractres dans les diffrentes botes lettres et retourne les noms de celles-ci. Syntaxe $identifiantBal $serveur $position array imap_scanmailbox(resource $identifiantBal, string $serveur, string $position, string $chaineARechercher) Identifiant tel que retourn par imap_open(). Serveur au format {<serveur>:<port>/<type>}. Position hirarchique de la premire bote tudier. Vous pouvez utiliser le caractre * pour tout tudier ou % pour toutes les botes du niveau slectionn (ex. : comp.lang.%). Un tableau des diffrentes botes lettres.

$chaineARechercher Chane de caractres rechercher dans les diffrentes botes lettres. retour

Si, en revanche, vous souhaitez en savoir un peu plus sur les botes lettres, en thorie vous disposez de imap_getMailboxes() (ne nous sommes toutefois pas parvenus obtenir le rsultat escompt).

imap_getMailboxes()
Retourne la liste des botes lettres, en prcisant si elles possdent des botes "filles" ou non, ainsi que le dlimiteur hirarchique.

980

Accder son compte messagerie IMAP, POP3 ou NNTP

Syntaxe $identifiantBal $serveur $position

array imap_getMailboxes(resource $identifiantBal, string $serveur, string $position) Identifiant tel que retourn par imap_open(). Serveur au format {<serveur>:<port>/<type>}. Position hirarchique de la premire bote tudier. Vous pouvez utiliser le caractre * pour tout tudier ou % pour toutes les botes du niveau slectionn (ex. : comp.lang.%). Tableau index dobjets possdant les attributs : "name": nom complet de la bote aux lettres. "delimiter" : dlimiteur hirarchique (i.e. caractre utiliser pour accder une bote fille. Il sagit gnralement du point boitemere.boitefille). "attributes" : peut prendre les valeurs LATT_NOINFERIORS sil ny a pas de bote lettres en dessous de celle-ci, LATT_NOSELECT si celle-ci nest quun conteneur, LATT_MARKED si elle est marque, LATT_UNMARKED si elle nest pas marque.

retour

12. La messagerie : envoi et lecture de mails

Voici un exemple de script :

Listing 12.11 : imap_getmailboxes.php


<?php $bal = imap_open("{mail.monsite.com:143/imap}","monlogin","monpassword"); $tableau = imap_getMailboxes($bal, "{mail.monsite.com}", "*"); while (list($cle, $valeur) = each($tableau)) { echo "$cle:"; echo imap_utf7_decode($valeur->name).","; echo "".$valeur->delimiter.","; echo $valeur->attributes."<br>\n"; } imap_close($bal); ?>

dont un des rsultat pourrait tre :


0:{mail.monsite.com}INBOX.Sent.mai-2002,.,0 1:{mail.monsite.com}INBOX.Trash,.,0 2:{mail.monsite.com}INBOX.Sent,.,0 3:{mail.monsite.com}INBOX.Drafts,.,0 4:{mail.monsite.com}INBOX,.,4

Si vous souhaitez limiter la liste aux botes ou (plus probablement) aux news auxquelles vous avez souscrit, alors vous disposez des fonctions imap_listSubscribed() et imap_getSubscribed().

981

Chapitre 12

La messagerie : envoi et lecture de mails

imap_listSubscribed()
Rcupre les botes auxquelles lutilisateur a souscrit. Lutilisation est en tous points identique imap_listMailboxes(). Syntaxe $identifiantBal $serveur $position array imap_listSubscribed(resource $identifiantBal, string $serveur, string $position) Identifiant tel que retourn par imap_open(). Serveur au format {<serveur>:<port>/<type>}. Position hirarchique de la premire bote tudier. Vous pouvez utiliser le caractre * pour tout tudier ou % pour toutes les botes du niveau slectionn (ex. : comp.lang.%). Tableau index des noms complets des botes.

retour

12. La messagerie : envoi et lecture de mails

Si, en revanche, vous souhaitez en savoir un peu plus sur les botes lettres...

imap_getSubscribed()
Rcupre les botes auxquelles lutilisateur a souscrit. Lutilisation est en tous points identique imap_getMailboxes(). Syntaxe $identifiantBal $serveur $position array imap_getSubscribed(resource $identifiantBal, string $serveur, string $position) Identifiant tel que retourn par imap_open(). Serveur au format {<serveur>:<port>/<type>}. Position hirarchique de la premire bote tudier. Vous pouvez utiliser le caractre * pour tout tudier ou % pour toutes les botes du niveau slectionn (ex. : comp.lang.%). Tableau index dobjets possdant les attributs : "name" : nom complet de la bote lettres. "delimiter" : dlimiteur hirarchique (i.e. caractre utiliser pour accder une bote fille. Il sagit gnralement du point boitemere.boitefille). "attributes" : peut prendre les valeurs LATT_NOINFERIORS sil ny a pas de bote lettres en dessous de celle-ci, LATT_NOSELECT si celle-ci nest quun conteneur, LATT_MARKED si elle est marque, LATT_UNMARKED si elle nest pas marque.

retour

982

Accder son compte messagerie IMAP, POP3 ou NNTP

Aperu du contenu de la bote lettres

imap_check()
Retour des informations sur la bote lettres courante. Syntaxe $identifiantBal retour object imap_check(resource $identifiantBal) Identifiant tel que retourn par imap_open(). Objet contenant les attributs suivants : "Date" : Date du serveur. "Driver" : Protocole utilis pour accder la bote e-mail. POP3, IMAP ou NNTP. "Mailbox" : Nom complet de la bote de courrier lectronique. "Nmsgs" : Nombre de messages dans la bote. "Recent" : Nombre de messages marqus rcent dans la bote.

12. La messagerie : envoi et lecture de mails

Listing 12.12 : imap_check.php


<?php $bal = imap_open("{mail.monsite.com:143/imap}INBOX", "monlogin", "monpassword"); $objet = imap_check($bal); echo $objet->Date."<br />\n"; echo $objet->Driver."<br />\n"; echo $objet->Mailbox."<br />\n"; echo $objet->Nmsgs."<br />\n"; echo $objet->Recent."<br />\n"; imap_close($bal);

?>

dont voici un exemple de rsultat :


Mon, 17 Jun 2002 21:18:06 -0400 (Est (heure dt)) imap {ns0.unsite.net:143/imap/user="monlogin "}INBOX 11 0

Il est toutefois possible den savoir un peu plus, comme le dmontre la fonction suivante.

imap_mailboxMsgInfo()
Retourne des informations sur la bote lettres courante.

983

Chapitre 12

La messagerie : envoi et lecture de mails

Syntaxe $identifiantBal

object imap_mailboxmsginfo(resource $identifiantBal) Identifiant retourn par imap_open(). retour Un objet contenant les attributs : "Date" : Date du dernier changement. "Driver" : Driver. "Mailbox" : Nom complet de la bote aux lettres. "Nmsgs" : Nombre de messages. "Recent" : Nombre de messages marqus Recent. "Unread" : Nombre de messages marqus Unread (non lus). "Deleted" : Nombre de messages marqus Deleted (effacs). "Size" : Taille de la bote aux lettres.

Voici un script dexemple :

Listing 12.13 : imap_mailboxmsginfo.php


<?php $bal = imap_open("{mail.monsite.com:143/imap}", "monlogin", "monpassword"); $objet = imap_mailboxmsginfo($bal); echo "Date: " . $objet->Date ."<br />\n" ; echo "Driver: " . $objet->Driver ."<br />\n" ; echo "Mailbox: " . $objet->Mailbox ."<br />\n" ; echo "Messages: ". $objet->Nmsgs ."<br />\n" ; echo "Recent: " . $objet->Recent ."<br />\n" ; echo "Unread: " . $objet->Unread ."<br />\n" ; echo "Deleted: " . $objet->Deleted ."<br />\n" ; echo "Size: " . $objet->Size ."<br />\n" ; imap_close($bal); ?>

12. La messagerie : envoi et lecture de mails

dont le rsultat serait par exemple :


Date: Wed, 19 Jun 2002 20:45:04 -0400 (Est (heure dt)) Driver: imap Mailbox: {ns0.monsite.net:143/imap/user="monlogin"}INBOX Messages: 3 Recent: 0 Unread: 3 Deleted: 0 Size: 1832

Vous disposez galement de deux fonctions rcuprant spcifiquement le nombre de messages et le nombre de messages rcents.

imap_num_msg()
Renvoie le nombre de messages de la bote lettres courante.

984

Accder son compte messagerie IMAP, POP3 ou NNTP

Syntaxe $identifiantBal retour

int imap_num_msg(resource $identifiantBal) Identifiant tel que retourn par imap_open(). Nombre de messages.

imap_num_recent()
Renvoie le nombre de messages marqus "Recent" de la bote lettres courante. Syntaxe $identifiantBal retour int imap_num_recent(resource $identifiantBal) Identifiant tel que retourn par imap_open(). Nombre de messages marqus "Recent".

Mais il est galement possible de profiter de la connexion ouverte sur le serveur pour glaner quelques informations sur dautres botes lettres.

12. La messagerie : envoi et lecture de mails

imap_status()
Cette fonction retourne des informations sur une bote lettres diffrente de la courante. Syntaxe $identifiantBal $bal $options object imap_status(resource $identifiantBal, string $bal, int $options) Identifiant tel que retourn par imap_open(). Bote lettres sur laquelle vous souhaitez des informations. Combinaison par OU logique des valeurs suivantes permettant de dterminer quelles informations doivent tre retournes (sous forme dattributs dun objet) : SA_MESSAGES (= 1) pour stocker le nombre de messages dans lattribut "message". SA_RECENT (= 2) pour stocker le nombre de messages rcents dans lattribut "recent" SA_UNSEEN (= 4) pour stocker le nombre de messages non lus dans lattribut "unseen" SA_UIDNEXT (= 8) pour stocker le prochain UID qui sera utilis pour la bote lettres dans lattribut "uidnext". SA_UIDVALIDITY (= 16) pour stocker dans lattribut "uidvalidity" une chane de caractres qui change quand la bote lettres peut ne plus tre valide. dSA_ALL (= 31) pour attribuer toutes les valeurs prcdentes.

985

Chapitre 12

La messagerie : envoi et lecture de mails

retour

Un objet avec les attributs demands ainsi que lattribut "flags" contenant la valeur de $options.

Lecture des en-ttes


Il est fort heureusement possible de rcuprer la liste des en-ttes des messages contenus dans une bote via la fonction imap_headers().

imap_headers()
Permet de retourner les rsums den-ttes de tous les messages dune bote lettres. Syntaxe array imap_headers(resource $identifiantBal) Identifiant tel que retourn par imap_open(). Tableau associatif contenant tous les en-ttes (une simple chane rsume par message). Un tableau vide sil ny a pas de message.

12. La messagerie : envoi et lecture de mails

$identifiantBal retour

Ce qui nous permet dcrire un script qui commence tre intressant :

Listing 12.14 : imap_2.php


<html> <head><title>Exemple IMAP</title></head> <body> <p><h1>Entetes de mail dans INBOX</h1> <?php $mbox = imap_open("{mail.monsite.com:110/pop3}", "monlogin", "monpassword"); $headers = imap_headers($mbox); if (!$headers) { echo "Erreur !\n"; } else { while (list($key,$val) = each($headers)) { echo $val."<br>\n"; } } imap_close($mbox); ?> </body> </html>

dont le rsultat pourrait tre le suivant :

986

Accder son compte messagerie IMAP, POP3 ou NNTP

Figure 12.3 : Lister des messages

Il est galement possible davoir quelques informations supplmentaires sur lensemble ou un sous-ensemble de messages.

12. La messagerie : envoi et lecture de mails

imap_fetch_overview()
Donne un aperu de len-tte dun des messages. Syntaxe $identifiantBal $listeMsg array imap_fetch_overview(resource $identifiantBal, string $sequence [, int $mode]) Identifiant tel que retourn par imap_open(). Liste des numros (ou UID) ou intervalles de numros (ou UID) de messages spars par une virgule (le premier porte lindice 1). Les intervalles sont dfinis par le numro de dbut, le caractre : et le numro de fin. FT_UID si le numro du message est son UID. Un tableau index dobjets contenant les attributs suivants :

$mode retour
j j j j j j j j j j j

"subject" : le sujet du message. "from" : lauteur du message. "date" : la date de lenvoi du message. "message_id" : lidentifiant du message. "references" : rfrence lidentifiant. "size" : taille du mail en octets. "uid" : UID du message dans la bote aux lettres. "msgno" : numro du message dans la bote. "recent" : indique si le message est marqu rcent. "flagged" : indique si le message est marqu. "answered" : indique si le message a t rpondu.

987

Chapitre 12

La messagerie : envoi et lecture de mails

j j j

"deleted" : indique si le message est marqu comme tant effacer. "seen" : indique si le message a t marqu lu. "draft" : Indique si le message a t marqu comme brouillon.

Voici un petit exemple :

Listing 12.15 : imap_fetch_overview.php


<?php $bal = imap_open("{mail.monsite.com:143/imap}INBOX", "monlogin", "monpassword"); $tableau = imap_fetch_overview($bal, "1,3"); foreach ($tableau as $element) { echo $element->from."<br />\n"; echo $element->date."<br />\n"; } imap_close($bal); ?>

12. La messagerie : envoi et lecture de mails

Et son rsultat pourrait tre :


Damien Sat, 26 Jan 2002 00:19:48 +0100 Thomas HEUTE Tue, 18 Jun 2002 17:49:08 -0400

Il est toutefois possible davoir une connaissance plus dtaille des en-ttes grce, en particulier, aux fonctions imap_fetchHeader() et imap_headerInfo().

imap_fetchHeader()
Retourne len-tte dun message. Syntaxe $identifiantBal $numeroMsg $mode string imap_fetchHeader(resource $identifiantBal, int $numeroMsg [, int $mode]) Identifiant retourn par imap_open(). Indice du message ouvrir (le premier porte lindice 1). Combinaison par OU logique des options : FT_UID indiquant que le numro du message prcis est son UID. FT_INTERNAL pour retourner len-tte dans le format interne. FT_PREFETCHTEXT. retour Len-tte du message dsir.

Afin den simplifier lanalyse, vous disposez dune fonction transformant cette chane de caractres en un objet o chaque attribut est un lment de len-tte.

988

Accder son compte messagerie IMAP, POP3 ou NNTP

imap_rfc822_parse_headers()
Permet dextraire des informations dun en-tte. Syntaxe $entete $hoteDefaut retour object imap_rfc822_parse_headers(string $entete [, string $hoteDefaut]) Len-tte dun courrier imap_fetchHeader(). lectronique tel que retourn par

Le nom de domaine par dfaut. Un objet contenant de nombreux attributs (dont la liste est ci-aprs) correspondant aux diffrents champs que vous pouvez rencontrer dans len-tte du message.

j j j j j j j j j j j j j j j j j j j j j j j j j

remail: redirection automatique de mails. date, Date : date du message. subject, Subject : sujet du message. in_reply_to : adresse laquelle le message rpond. message_id : identifiant du message. newsgroups. followup_to : adresse de suivi du message. references. toaddress : ligne den-tte de TO: limite 1024 caractres. to[] : tableau de toutes les adresses de TO: sous forme dobjet. to[]>personal : nom de la personne. to[]>adl : at domain source route (???). to[]>mailbox : partie prcdant @. to[]>host : partie suivant @. fromaddress : ligne den-tte de FROM: limite 1024 caractres. from[]: tableau de toutes les adresses de FROM: sous forme dobjet. from[]>personal : nom de la personne. from[]>adl : at domain source route. from[]>mailbox : partie prcdant @. from[]>host: partie suivant @. ccaddress : ligne den-tte de CC: limite 1024 caractres. cc[] : tableau de toutes les adresses de CC: sous forme dobjet. cc[]>personal : nom de la personne. cc[]>adl : at domain source route. cc[]>mailbox : partie prcdant @.

989

12. La messagerie : envoi et lecture de mails

Chapitre 12

La messagerie : envoi et lecture de mails

j j j j j j j j j j j j

cc[]>host : partie suivant @. bccaddress : ligne den-tte de BCC: limite 1024 caractres. bcc[] : tableau de toutes les adresses de BCC: sous forme dobjet. bcc[]>personal : nom de la personne. bcc[]>adl: at domain source route. bcc[]>mailbox : partie prcdant @. bcc[]>host : partie suivant @. reply_toaddress : ligne den-tte de Reply_to: limite 1024 caractres. reply_to[] : tableau de toutes les adresses de Reply_to: sous forme dobjet. reply_to[]>personal : nom de la personne. reply_to[]>adl : at domain source route. reply_to[]>mailbox : partie prcdant @. reply_to[]>host : partie suivant @. senderaddress : ligne den-tte de Sender: limite 1024 caractres. sender[] : tableau de toutes les adresses de Sender: sous forme dobjet. sender[]>personal : nom de la personne. sender[]>adl : at domain source route. sender[]>mailbox : partie prcdant @. sender[]>host : partie suivant @. return_path[] : tableau de toutes les adresses de Returnpath: sous forme dobjet. return_path[]>personal : nom de la personne. return_path[]>adl : at domain source route. return_path[]>mailbox : partie prcdant @. return_path[]>host : partie suivant @.

12. La messagerie : envoi et lecture de mails

j j j j j j j j j j j j

Vous pouvez toutefois vous dispenser de faire deux oprations tout en rcuprant plus dinformations (on se demande bien comment cest possible).

imap_headerInfo()
Permet de lire len-tte dun message. Syntaxe object imap_headerInfo(resource $identifiantBal, int $numeroMesg [, int $tailleFrom [, int $tailleSubject [, string hoteDefaut]]]) Identifiant tel que retourn par imap_open(). Position du message ouvrir (le premier porte lindice 1).

$identifiantBal $numeroMesg

990

Accder son compte messagerie IMAP, POP3 ou NNTP

$tailleFrom $tailleSubject $hoteDefaut retour

Taille maximale de la chane de caractres From. Taille maximale de la chane de caractres Subject. Hte par dfaut. Un objet contenant de nombreux attributs (dont la liste est ci-aprs) correspondant aux diffrents champs que vous pouvez rencontrer dans len-tte du message.

imap_headerInfo() possde un alias appel imap_header() ( viter cause du risque de confusion avec imap_headers()).

En voici quelques-unes rcupres du courrier lectronique suivant :


Return-Path: <webmaster@toutestfacile.com> Delivered-To: copiecacheebcc@toutestfacile.com Received: (qmail 15229 invoked by uid 503); 17 Jun 2002 02:05:14 -0000 Received: from unknown (HELO thomas) (138.88.143.137) by ns0.ovh.net with SMTP; 17 Jun 2002 02:05:14 -0000 Date: Sun, 16 Jun 2002 22:04:14 -0400 From: ToutEstFacile <webmaster@toutestfacile.com> X-Mailer: The Bat! (v1.60m) UNREG / CD5BF9353B3B7091 Reply-To: ToutEstFacile <webmaster@toutestfacile.com> Organization: ToutEstFacile X-Priority: 3 (Normal) Message-ID: <10913313113.20020616220414@toutestfacile.com> To: imap@toutestfacile.com, copie@toutestfacile.com CC: copieCC@toutestfacile.com Subject: Ceci est le sujet du mail MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Hello imap, Ceci est le corps de mon message -Best regards, Thomas.

12. La messagerie : envoi et lecture de mails

Le code source du script charg de rcuprer les informations est le suivant :

Listing 12.16 : imap_5.php


<html> <head><title>Exemple IMAP</title></head> <body> <?php $mbox = imap_open("{mail.toutestfacile.com:110/pop3}", "imap@toutestfacile.com", "pipo"); $header = imap_headerinfo($mbox, 8); echo "message_id:".$header->message_id."<br />\n"; echo "Date:".$header->Date."<br />\n";

991

Chapitre 12

La messagerie : envoi et lecture de mails

echo "date:".$header->date."<br />\n"; echo "Subject:".$header->Subject."<br />\n"; echo "subject:".$header->subject."<br />\n"; echo "Recent:".$header->Recent."<br />\n"; echo "Unseen:".$header->Unseen."<br />\n"; echo "Answered:".$header->Answered."<br />\n"; echo "Deleted:".$header->Deleted."<br />\n"; echo "Flagged:".$header->Flagged."<br />\n"; echo "toaddress:".$header->toaddress."<br />\n"; echo "to[0]->mailbox:".$header->to[0]->mailbox."<br />\n"; echo "to[0]->host:".$header->to[0]->host."<br />\n"; echo "to[1]->mailbox:".$header->to[1]->mailbox."<br />\n"; echo "to[1]->host:".$header->to[1]->host."<br />\n"; echo "fromaddress:".$header->fromaddress."<br />\n"; echo "from[0]->personal:".$header->from[0]->personal."<br />\n"; echo "from[0]->mailbox:".$header->from[0]->mailbox."<br />\n"; echo "from[0]->host:".$header->from[0]->host."<br />\n"; echo "ccaddress:".$header->ccaddress."<br />\n"; echo "cc[0]->mailbox:".$header->cc[0]->mailbox."<br />\n"; echo "cc[0]->host:".$header->cc[0]->host."<br />\n"; echo "reply_toaddress:".$header->reply_toaddress."<br />\n"; echo "reply_to[0]->personal:".$header->reply_to[0]->personal."<br />\n"; echo "reply_to[0]->mailbox:".$header->reply_to[0]->mailbox."<br />\n"; echo "reply_to[0]->host:".$header->reply_to[0]->host."<br />\n"; echo "senderaddress:".$header->senderaddress."<br />\n"; echo "sender[0]->personal:".$header->sender[0]->personal."<br />\n"; echo "sender[0]->mailbox:".$header->sender[0]->mailbox."<br />\n"; echo "sender[0]->host:".$header->sender[0]->host."<br />\n"; echo "udate:".$header->udate."<br />\n"; imap_close($mbox); ?> </body> </html>

12. La messagerie : envoi et lecture de mails

Le rsultat obtenu est le suivant :


message_id:<10913313113.20020616220414@toutestfacile.com> Date:Sun, 16 Jun 2002 22:04:14 -0400 date:Sun, 16 Jun 2002 22:04:14 -0400 Subject:Ceci est le sujet du mail subject:Ceci est le sujet du mail Recent:N Unseen: Answered: Deleted: Flagged: toaddress:imap@toutestfacile.com,copie@toutestfacile.com to[0]->mailbox:imap to[0]->host:toutestfacile.com to[1]->mailbox:copie to[1]->host:toutestfacile.com fromaddress:ToutEstFacile

992

Accder son compte messagerie IMAP, POP3 ou NNTP

from[0]->personal:ToutEstFacile from[0]->mailbox:webmaster from[0]->host:toutestfacile.com ccaddress:copieCC@toutestfacile.com cc[0]->mailbox:copieCC cc[0]->host:toutestfacile.com reply_toaddress:ToutEstFacile reply_to[0]->personal:ToutEstFacile reply_to[0]->mailbox:webmaster reply_to[0]->host:toutestfacile.com senderaddress:ToutEstFacile sender[0]->personal:ToutEstFacile sender[0]->mailbox:webmaster sender[0]->host:toutestfacile.com udate:1024279454

Outre celles vues dans lexemple, dautres informations peuvent tre disponibles. En voici une liste complte :
j j j j j j j j j j j j j j j j j j j j j
remail : redirection automatique de mails. date, Date : date du message. udate : date au format UNIX. subject, Subject : sujet du message. in_reply_to : adresse laquelle le message rpond. message_id : identifiant du message. newsgroups. followup_to : adresse de suivi du message. references. fetchfrom : ligne den-tte de TO: formate pour tenir dans $tailleFrom. fetchsubject : $tailleSubject.

12. La messagerie : envoi et lecture de mails

ligne

den-tte

de

Subject:

formate

pour

tenir

dans

Recent : R si le message est rcent et lu, N sil est rcent mais non lu, sinon. Unseen : U si le message est non lu et non rcent. si le message a t marqu lu ou sil est non lu et rcent. Answered : A si le message a t rpondu, sinon. Deleted : D si le message est effac, sinon. Draft : X si le message est un brouillon, sinon. Flagged : F si le message est marqu, sinon. toaddress : ligne den-tte de TO: limite 1024 caractres. to[] : tableau de toutes les adresses de TO: sous forme dobjet. to[]>personal : nom de la personne. to[]>adl : at domain source route (???).

993

Chapitre 12

La messagerie : envoi et lecture de mails

j j j j j j j j j j j j

to[]>mailbox : partie prcdant @. to[]>host : partie suivant @. fromaddress : ligne den-tte de FROM: limite 1024 caractres. from[] : tableau de toutes les adresses de FROM: sous forme dobjet. from[]>personal : nom de la personne. from[]>adl : at domain source route (???). from[]>mailbox : partie prcdant @. from[]>host : partie suivant @. ccaddress : ligne den-tte de CC: limite 1024 caractres. cc[] : tableau de toutes les adresses de CC: sous forme dobjet. cc[]>personal : nom de la personne. cc[]>adl: at domain source route (???). cc[]>mailbox : partie prcdant @. cc[]>host : partie suivant @. bccaddress : ligne den-tte de BCC: limite 1024 caractres. bcc[] : tableau de toutes les adresses de BCC: sous forme dobjet. bcc[]>personal : nom de la personne. bcc[]>adl : at domain source route (???). bcc[]>mailbox : partie prcdant @. bcc[]>host : partie suivant @. reply_toaddress : ligne den-tte de Reply_to: limite 1024 caractres. reply_to[] : tableau de toutes les adresses de Reply_to: sous forme dobjet. reply_to[]>personal : nom de la personne. reply_to[]>adl : at domain source route (???). reply_to[]>mailbox : partie prcdant @. reply_to[]>host: partie suivant @. senderaddress : ligne den-tte de Sender: limite 1024 caractres. sender[] : tableau de toutes les adresses de Sender: sous forme dobjet. sender[]>personal : nom de la personne. sender[]>adl : at domain source route (???). sender[]>mailbox : partie prcdant @. sender[]>host : partie suivant @. return_path[] : tableau de toutes les adresses de Returnpath: sous forme dobjet. return_path[]>personal : nom de la personne. return_path[]>adl : at domain source route (???).

12. La messagerie : envoi et lecture de mails

j j j j j j j j j j j j j j j j j j j j j j j

994

Accder son compte messagerie IMAP, POP3 ou NNTP

j j

return_path[]>mailbox : partie prcdant @. return_path[]>host : partie suivant @.

Lecture des messages


Certes, accder la liste des messages est une chose importante, mais accder leur contenu lest encore plus ! Vous disposez l aussi de nombreuses fonctions ; la premire dentre elles est imap_body().

imap_body()
Retourne le corps dun message. Syntaxe $identifiantBal $numeroMsg $mode string imap_body(resource $identifiantBal, int $numeroMsg [, int $mode]); Identifiant tel que retourn par imap_open(). Numro du message ouvrir (le premier porte lindice 1). Combinaison par OU logique des options : FT_UID si le numro du message est son UID. FT_PEEK afin de ne pas indiquer le message comme tant lu (sil nest pas dj marqu). FT_INTERNAL afin que la chane retourne soit dans le format interne. retour Le corps du message.

12. La messagerie : envoi et lecture de mails

Il faut toutefois garder lesprit quun message peut tre compos de plusieurs parties (gnralement le corps du document que lon peut rcuprer avec imap_body(), mais aussi des fichiers joints). Aussi, avant daller plus loin, vous devez connatre la structure du message. Comme par miracle, il y a justement une fonction qui permet cela.

imap_fetchStructure()
Lit la structure dun message. Lobjet retourn contient lenveloppe, la date, la taille, les drapeaux et la structure du corps, ainsi que ces informations pour les composantes MIME du message. Syntaxe $identifiantBal $numeroMsg object imap_fetchStructure(resource $identifiantBal, int $numeroMsg [, int $mode]) Identifiant retourn par imap_open(). Indice du message ouvrir (le premier porte lindice 1).

995

Chapitre 12

La messagerie : envoi et lecture de mails

$mode retour
j

FT_UID (si le numro du message est son UID). Un objet contenant les attributs dcrits ci-aprs :

type : le type de contenu qui peut prendre lune des valeurs suivantes :

TYPETEXT sil sagit dun texte non format ; TYPEMULTIPART sil sagit dun message avec plusieurs parties . TYPEMESSAGE ; TYPEAPPLICATION ; TYPEAUDIO sil sagit dun fichier audio ; TYPEIMAGE sil sagit dun fichier image ; TYPEVIDEO sil sagit dun fichier vido ; TYPEOTHER sil sagit dun type inconnu.

12. La messagerie : envoi et lecture de mails

encoding : le type dencodage qui peut prendre lune des valeurs ENCBASE64, ENCQUOTEDPRINTABLE, ENCOTHER ; ifsubtype : TRUE si un sous-type MIME est dfini (attribut subtype) ; subtype : sous-type MIME ; ifdescription : TRUE si une description est dfinie (attribut description) ; description : description du contenu ; ifid : TRUE si une chane didentification est dfinie (attribut id) ; id : chane didentification ; lines : nombre de lignes ; bytes : nombre doctets ; ifdisposition : TRUE si lattribut disposition est dfini ; disposition : chane de disposition (ex. : inline, attachment) ; ifdparameters : TRUE si lattribut dparameters est dfini ; dparameters : un tableau dobjets o chacun des objets possde les attributs attribute et value correspondant aux paramtres de Contentdiposition de len-tte MIME ; ifparameters : TRUE si lattribut parameters est dfini ; parameters : un tableau dobjets o chacun des objets possde les attributs attribute et value ; parts : un tableau dobjets identique au niveau de la structure lobjet suprieur dcrivant chacune des parties du message.

j j j j j j j j j j j j j j j

Voici un script montrant quelques rsultats :

Listing 12.17 : imap_fetchstructure.php


<?php $bal = imap_open("{mail.monsite.com:143/imap}INBOX", "monlogin", "monpassword");

996

Accder son compte messagerie IMAP, POP3 ou NNTP

$objet = imap_fetchstructure($bal, 1); echo "\$objet->type:".$objet->type."<br />\n"; echo "\$objet->encoding:".$objet->encoding."<br />\n"; echo "\$objet->ifsubtype:".$objet->ifsubtype."<br />\n"; echo "\$objet->subtype:".$objet->subtype."<br />\n"; echo "\$objet->ifdescription:". $objet->ifdescription."<br />\n"; echo "\$objet->ifid:".$objet->ifid."<br />\n"; echo "\$objet->lines:".$objet->lines."<br />\n"; echo "\$objet->bytes:".$objet->bytes."<br />\n"; echo "\$objet->ifdisposition:".$objet->ifdisposition. "<br />\n"; echo "\$objet->ifdparameters:".$objet->ifdparameters. "<br />\n"; echo "\$objet->ifparameters:".$objet->ifparameters."<br />\n"; echo "\$objet->parameters[0]->attribute:". $objet->parameters[0]->attribute."<br />\n"; echo "\$objet->parameters[0]->value:".":". $objet->parameters[0]->value."<br />\n"; echo "\$objet->parameters[1]->attribute:". $objet->parameters[1]->attribute."<br />\n"; echo "\$objet->parameters[1]->value:". $objet->parameters[1]->value."<br />\n"; imap_close($bal); ?>

12. La messagerie : envoi et lecture de mails

dont un rsultat pourrait tre :


$objet->type:0 $objet->encoding:1 $objet->ifsubtype:1 $objet->subtype:PLAIN $objet->ifdescription:0 $objet->ifid:0 $objet->lines:3 $objet->bytes:23 $objet->ifdisposition:0 $objet->ifdparameters:0 $objet->ifparameters:1 $objet->parameters[0]->attribute:charset $objet->parameters[0]->value::us-ascii $objet->parameters[1]->attribute:format $objet->parameters[1]->value:flowed

Sil stait agi dun message contenant plusieurs parties, alors nous aurions eu type=1 (car TYPEMULTIPART=1). Si vous ne souhaitez extraire que la structure dune partie du message, vous disposez de la fonction imap_bodyStruct().

997

Chapitre 12

La messagerie : envoi et lecture de mails

imap_bodyStruct()
Rcupre la structure dune partie du message. Syntaxe $identifiantBal $numeroMsg $section retour object imap_bodyStruct(resource $identifiantBal, int $numeroMsg, int $section) Identifiant tel que retourn par imap_open(). Numro du message ouvrir (le premier porte lindice 1). Section du courrier ouvrir (le corps du message porte lindice 1). La structure de la partie du message demande.

Pour accder une partie quelconque dun message, vous devez faire appel imap_fetchBody().

12. La messagerie : envoi et lecture de mails

imap_fetchBody()
Retourne le contenu dune des parties du message. Syntaxe $identifiantBal $numeroMsg $numeroPartie $mode string imap_fetchbody(resource $identifiantBal, int $numeroMsg, int $numeroPartie [, int $mode]) Identifiant retourn par imap_open(). Indice du message ouvrir (le premier porte lindice 1). Indice de la partie retourner (le corps du message porte lindice 1). Combinaison par OU logique des options : FT_UID si le numro du message est son UID. FT_PEEK afin de ne pas indiquer le message comme tant lu (sil nest pas dj marqu). FT_INTERNAL afin de retourner le rsultat dans le format "interne". retour La partie du message dsire.

Lexemple suivant est en deux fichiers : le premier liste les messages dans la botes lettres et propose des liens vers le second de la forme imap_4.php?no=<valeur>, afin dafficher le contenu du message (le corps uniquement, les parties attaches tant ici ignores).

Listing 12.18 : imap3.php


<html> <head><title>Exemple IMAP</title></head> <body> <?php $mbox = imap_open("{mail.monsite:110/pop3}", "monlogin", "monpassword"); echo "<p><h1>Entetes de mail dans INBOX</h1>\n"; $headers = imap_headers($mbox);

998

Accder son compte messagerie IMAP, POP3 ou NNTP

if (!$headers) { echo "Erreur !\n"; } else { while (list ($key,$val) = each ($headers)) { echo "<a href=\"imap4.php?no=".($key+1)."\">". $val."</a><br>\n"; } } imap_close($mbox); ?> </body> </html>

Le script suivant ouvre donc une connexion un serveur POP3, puis extrait len-tte du mail ouvrir afin de rcuprer des informations sur lexpditeur et, enfin, crit le contenu du message.

Listing 12.19 : imap4.php

12. La messagerie : envoi et lecture de mails

<html> <head><title>Exemple IMAP</title></head> <body> <?php $mbox = imap_open("{mail.monsite.com:110/pop3}", "monlogin", "monpassword"); $header = imap_headerInfo($mbox, $no); $from = $header->from; echo "Message de:".$from[0]->personal. " [".$from[0]->mailbox."@".$from[0]->host."]<br />"; $text = imap_fetchBody($mbox, $no, 1); echo $text; imap_close($mbox); ?> </body> </html>

dont le rsultat attendu pourrait tre le suivant :


<html> <head><title>Exemple IMAP</title></head> <body> Message de: ToutEstFacile[webmaster@toutestfacile.com]<br />Ceci est un test. Cordialement, Thomas. </body> </html>

999

Chapitre 12

La messagerie : envoi et lecture de mails

Recherche et tri des messages

imap_search()
Cette fonction effectue une recherche sur les messages de la bote lettres. Syntaxe $identifiantBal $criteres $option retour array imap_search(resource $identifiantBal, string $criteres, int $option) Identifiant tel que retourn par imap_open(). Critres de recherche dtaills ci-aprs. SE_UID pour retourner les identifiants plutt que le numro de squence. Tableau index des numros de squences ou des identifiants des messages correspondant aux critres de slection.

12. La messagerie : envoi et lecture de mails

Les critres peuvent tre combins en les sparant par des espaces (ce qui aura pour effet de rechercher les messages rpondant au critre1 ET au critre2, etc.). Chaque critre est compos dun des mots-cls suivants, ventuellement suivi dune valeur (qui devra tre entre guillemets) :
j
ALL : fait une recherche dans tous les champs de tous les messages.

Critres lis aux drapeaux :


j j j j j j j j j j j
ANSWERED : pour ne chercher que parmi les messages marqus "rpondus". UNANSWERED : pour ne chercher que parmi les messages marqus "non rpondus". DELETED : pour ne chercher que parmi les messages marqus "effacs". UNDELETED : pour ne chercher que parmi les messages non marqus "effacs". FLAGGED : pour ne chercher que parmi les messages marqus (importants). UNFLAGGED : pour ne chercher que parmi les messages non marqus. NEW : pour ne chercher que parmi les nouveaux messages. OLD : pour ne chercher que parmi les anciens messages. RECENT : pour ne chercher que parmi les messages marqus "rcents". SEEN : pour ne chercher que parmi les messages marqus "lus". UNSEEN : pour ne chercher que parmi les messages marqus "non lus".

Critres lis aux adresses e-mail :


j j j j
BCC "adresse" : recherche dans le champ BCC. CC "adresse" : recherche dans le champ BCC. FROM "adresse" : recherche dans le champ FROM. TO "adresse" : recherche dans le champ TO.

1000

Accder son compte messagerie IMAP, POP3 ou NNTP

Critres lis au texte du message :


j j j j j
SUBJECT "texte" : recherche dans le champ SUBJECT. BODY "texte" : pour rechercher dans le corps des messages. TEXT "texte" : pour rechercher les messages contenant ce texte. KEYWORD "texte" : pour rechercher les messages ayant ce mot-cl. UNKEYWORD "texte" : pour rechercher les messages nayant pas ce mot-cl.

Critres lis la date :


j j j j
BEFORE "date" : pour rechercher parmi les messages antrieurs une certaine date. SINCE "date" : pour rechercher parmi les messages postrieurs une certaine date. ON "date" : pour rechercher parmi les messages mis une certaine date. NEW : pour ne chercher que parmi les nouveaux messages.

12. La messagerie : envoi et lecture de mails

Ce qui pourra donner par exemple :


imap_search($bal, "FROM \"toutestfacile.com\" SUBJECT \"Test\"");

Pour retourner la liste des messages envoys depuis une adresse contenant "toutestfacile.com" et ayant dans le mot "Test" dans le sujet.

imap_sort()
Permet de retourner une liste trie de messages. Syntaxe $identifiantBal $criteres array imap_sort(resource $identifiantBal, int $criteres, boolean $inverse, [ int $mode [, string $filtre]]) Identifiant tel que retourn par imap_open(). Au choix, lun des critres suivants : SORTDATE : tri selon la date du message. SORTARRIVAL : tri selon la date de rception du message. SORTFROM : tri selon lexpditeur. SORTSUBJECT : tri selon le sujet. SORTTO : tri selon le premier destinataire. SORTCC : tri selon le champ CC. SORTSIZE : tri selon la taille du message. TRUE pour obtenir lordre inverse. Combinaison par OU logique des options : SE_UID pour retourner les UID plutt que les indices. SE_NOPREFETCH pour ne pas pr-tlcharger les messages. Permet de ne rcuprer que certains messages ; ce filtre fonctionne comme les critres de imap_search(). Tableau index des identifiants de messages tris selon lordre choisi.

$inverse $mode

$filtre retour

1001

Chapitre 12

La messagerie : envoi et lecture de mails

Modication des drapeaux et suppression des messages


chaque message sont associs des drapeaux indiquant sil a t lu, si une rponse a t envoye, sil est sur le point dtre effac, etc. La bibliothque IMAP vous permet de modifier ces informations.

imap_setFlag_full()
Permet de marquer un ou plusieurs messages avec un drapeau spcifique. Syntaxe $identifiantBal boolean imap_setFlag_full(resource $identifiantBal, string $listeMsg, string $drapeau [, string $mode]) Identifiant tel que retourn par imap_open(). Liste des numros (ou UID) ou intervalles de numros (ou UID) de messages spars par une virgule (le premier porte lindice 1). Les intervalles sont dfinis par le numro de dbut, le caractre : et le numro de fin. Drapeau retirer "\Seen", "\Answered", "\Flagged", "\Deleted", "\Draft", "\Recent". (Noubliez pas de doubler les anti-slashes si vous dfinissez la chane entre guillemets). FT_UID si le numro du message est son UID. TRUE en cas de succs.

12. La messagerie : envoi et lecture de mails

$listeMsg

$drapeau

$mode retour Exemple :

imap_setFlag_full($bal, "1,3,5:8", "\\Seen");

imap_clearFlag_full()
Retire un drapeau dun ou plusieurs messages. Syntaxe $identifiantBal $listeMsg boolean imap_clearFlag_full(resource $identifiantBal, string $listeMsg, string $drapeau [, string $mode]) Identifiant tel que retourn par imap_open(). Liste des numros (ou UID) ou intervalles de numros (ou UID) de messages spars par une virgule (le premier porte lindice 1). Les intervalles sont dfinis par le numro de dbut, le caractre : et le numro de fin. Drapeau retirer "\Seen", "\Answered", "\Flagged", "\Deleted", "\Draft", "\Recent". (Noubliez pas de doubler les anti-slashes si vous dfinissez la chane entre guillemets).

$drapeau

1002

Accder son compte messagerie IMAP, POP3 ou NNTP

$mode retour Exemple :

FT_UID si le numro du message est son UID. TRUE en cas de succs.

imap_clearFlag_full($bal, "1,3,5:8", "\\Seen");

Pour les messages marquer comme tant effacer, vous pouvez appeler directement les fonctions suivantes :

imap_delete()
Cette fonction permet de marquer un message comme tant effacer. Syntaxe $identifiantBal $numeroMsg $drapeaux retour boolean imap_delete(resource $identifiantBal, int $numeroMsg [, int $drapeaux]) Identifiant tel que retourn par imap_open(). Numro du message effacer (le premier porte lindice 1). FT_UID (si le numro du message est son UID). TRUE en cas de succs.

12. La messagerie : envoi et lecture de mails

Voici un script qui permet deffacer le message dindice 1 :

Listing 12.20 : imap_delete.php


<?php $bal = imap_open("{mail.monsite.com:143/imap}INBOX", "monlogin", "monpassword", CL_EXPUNGE); echo imap_delete($bal, 1); imap_close($bal); ?>

imap_undelete()
Retire le drapeau indiquant que le message est effacer. Syntaxe $identifiantBal $numeroMsg retour boolean imap_undelete(resource $identifiantBal, int $numeroMsg) Identifiant tel que retourn par imap_open(). Numro du message dans la bote lettres. TRUE en cas de succs.

1003

Chapitre 12

La messagerie : envoi et lecture de mails

La suppression du message ne sera effective qu la fermeture de la bote lettres si celle-ci a t ouverte ou ferme avec loption CL_EXPUNGE. Il est toutefois possible, tout moment, de vritablement supprimer les messages marqus comme tant supprimer avec loption imap_expunge().

imap_expunge()
Efface tous les messages marqus comme tant effacer. Syntaxe $identifiantBal retour boolean imap_expunge(resource $identifiantBal) Identifiant tel que retourn par imap_open(). TRUE en cas de succs.

12. La messagerie : envoi et lecture de mails

Ajout et dplacement de messages

imap_append()
Permet dajouter un message dans une bote lettres. Syntaxe $identifiantBal $bal $message $drapeaux retour boolean imap_append(resource $identifiantBal, string $bal, string $message [, string $drapeaux]) Identifiant tel que retourn par imap_open(). Bote lettres o crire. Message crire. Drapeaux crits dans la bote lettres. TRUE si lopration a pu seffectuer, FALSE dans le cas contraire.

Le script suivant crit un message dans les brouillons :

Listing 12.21 : imap_append.php


<?php $bal = imap_open("{mail.monsite.com:143/imap}INBOX", "monlogin", "monpassword"); imap_append($bal, "{mail.monsite.com:143/imap}INBOX.Drafts", "TO:imap@toutestfacile.com\r\n". "Subject:Cool\r\n". "\r\n". "Je tcris depuis un script PHP en IMAP ! Bisous,". " Moi"); imap_close($bal); ?>

1004

Accder son compte messagerie IMAP, POP3 ou NNTP

imap_mail_copy()
Copie certains messages dans une bote lettres spcifie. Syntaxe $identifiantBal $listeMsg boolean imap_mail_copy(resource $identifiantBal, string $listeMsg, string $bal[, int $mode]) Identifiant retourn par imap_open(). Liste des numros (ou UID) ou intervalles de numros (ou UID) de messages spars par une virgule (le premier porte lindice 1). Les intervalles sont dfinis par le numro de dbut, le caractre : et le numro de fin. Botes lettres de destination. Combinaison par OU logique des options : CP_UID si la liste des messages contient des UID. CP_MOVE pour demander la suppression des messages de la bote dorigine. retour TRUE si lopration sest effectue sans erreur.

$bal $mode

12. La messagerie : envoi et lecture de mails

imap_mail_move()
Dplace certains messages dans une bote lettres spcifie. (Marque le message de la bote dorigine comme tant effacer). Syntaxe $identifiantBal $listeMsg boolean imap_mail_move(resource $identifiantBal, string $listeMsg, string $bal [, int $mode]) Identifiant retourn par imap_open(). Liste des numros (ou UID) ou intervalles de numros (ou UID) de messages spars par une virgule (le premier porte lindice 1). Les intervalles sont dfinis par le numro de dbut, le caractre : et le numro de fin. Botes lettres de destination. CP_UID si la liste des messages contient des UID. TRUE si lopration sest effectue sans erreur.

$bal $mode retour

Inscription/dsinscription un serveur de nouvelles

imap_subscribe()
Permet de sinscrire une bote lettres (pour les serveurs de "news").

1005

Chapitre 12

La messagerie : envoi et lecture de mails

Syntaxe $identifiantBal $bal retour

boolean imap_subscribe(resource $identifiantBal, string $bal) Identifiant tel que retourn par imap_open(). Bote lettres o sinscrire. TRUE si linscription sest faite.

imap_unsubscribe()
Permet de se dsabonner dune liste. Syntaxe $identifiantBal boolean imap_unsubscribe(resource $identifiantBal, string $bal) Identifiant tel que retourn par imap_open(). Bote laquelle lutilisateur doit tre dsinscrit. TRUE si lopration sest correctement droule.

12. La messagerie : envoi et lecture de mails

$bal retour

Identiants

imap_msgno()
Cette fonction retourne le numro de squence de lUID fourni. Syntaxe $identifiantBal retour int imap_msgno(resource $identifiantBal, int $uid) Identifiant tel que retourn par imap_open(). Lindice du message.

imap_uid()
Retourne lUID dun message daprs son indice dans la bote lettres. Syntaxe $identifiantBal $numeroMsg retour int imap_uid(resource $identifiantBal, int $numeroMsg) Identifiant tel que retourn par imap_open(). Indice du message dans la bote aux lettres. LUID du message.

Composition et dcomposition dadresses e-mail


Il est facile de construire une adresse e-mail contenant notamment le nom en toutes lettres du destinataire ou de lexpditeur tout en sassurant de sa conformit avec la norme RFC822.

1006

Accder son compte messagerie IMAP, POP3 ou NNTP

imap_rfc822_write_address()
Retourne une adresse e-mail respectant la norme RFC822. Syntaxe : $login $domain $nom retour Le script suivant : string imap_rfc822_write_address(string $login, string $domain, string $nom) Partie prcdant le @. Partie suivant le @. Nom ou texte associ ladresse. Une adresse norme.

Listing 12.22 : imap_rfc822_write_address.php

12. La messagerie : envoi et lecture de mails

<?php echo imap_rfc822_write_address("Emma", "tuvu.com", "Eh ! Mas tu vu ?"); ?>

retournerait :
Eh ! Mas tu vu ? <Emma@tuvu.com>

linverse, il est possible de dcomposer une liste dadresses.

imap_rfc822_parse_adrlist()
Cette fonction permet de rcuprer les diffrentes parties dune adresse e-mail respectant la norme RFC2822. Syntaxe $adresse $hoteDefaut retour array imap_rfc822_parse_adrlist(string $adresse, string $hoteDefaut) Chane de caractres de ladresse. Nom de lhte par dfaut. Un tableau dobjets ayant les attributs : personal : nom de la personne. Mailbox : partie prcdant @. Host : partie suivant @. Adl : at domain source route.

Listing 12.23 : imap_rfc822_parse_adrlist.php


<?php $adresses= "Emma TUVU <emma@tuvu.com>, bible@php.com, Starsky"; $tableau = imap_rfc822_parse_adrlist($adresses,"defaut.com");

1007

Chapitre 12

La messagerie : envoi et lecture de mails

while(list($cle,$valeur)=each($tableau)){ echo "personal: ".$valeur->personal."<br />\n"; echo "mailbox : ".$valeur->mailbox."<br />\n"; echo "host : ".$valeur->host."<br />\n"; echo "adl : ".$valeur->adl."<br />\n"; } ?>

Le rsultat est :
personal: Emma TUVU mailbox : emma host : tuvu.com adl : personal: mailbox : bible host : php.com adl : personal: mailbox : Starsky host : defaut.com adl :

12. La messagerie : envoi et lecture de mails

Gnration et envoi de mails


La bibliothque IMAP permet galement de gnrer et denvoyer des e-mails.

imap_mail()
Cette fonction permet denvoyer un courrier lectronique. Syntaxe boolean imap_mail(string $destinataire, string $sujet, string $message [, string $entete [, string $cc [, string $bcc [, string $rpath]]]]) Adresse(s) du ou des destinataires. Sujet du message. Contenu du courrier lectronique. Pour ajouter un en-tte particulier. Adresses des personnes en copie. Adresses des personnes en copie cache. Adresse de retour des messages derreur. TRUE si lopration sest effectue.

$destinataire $sujet $message $entete $cc $bcc $rpath retour

Un script trs simple prsentant cette fonction :

1008

Accder son compte messagerie IMAP, POP3 ou NNTP

Listing 12.24 : imap_mail.php


<?php imap_mail("destinataire@sonsite.com", "Test de mail", "Corps du message"); ?>

imap_mail_compose()
Permet de crer un message MIME en construisant lenveloppe et le corps. Syntaxe $enveloppe string imap_mail_compose(array $enveloppe, array $corps) Tableau associatif avec les cls : from, to, cc, bcc, remail, returnpath, date, replyto, in_reply_to, subject, message_id, custom_headers. Tableau de tableaux, chacun des sous-tableaux pouvant avoir les cls type, encoding, subtype, description, contents.data, id, charset, description.type, lines, bytes, md5. Message au format MIME.

$corps

12. La messagerie : envoi et lecture de mails

retour

Coder / dcoder

imap_8bit()
Convertit une chane 8 bits en chane imprimable selon la RFC2045, et coupe donc les lignes de plus de 75 caractres. Syntaxe $chaine retour string imap_8bit(string $chaine) Chane de caractres transformer. Une chane conforme la spcification RFC2045.

RFC2045 en anglais Pour samuser et lire la langue concurrente de celle de Molire, pour pourrez trouver la RFC2045 ladresse : http://www.faqs.org/rfcs/rfc2045.html.

imap_qprint()
Convertit un caractre imprimable en chane 8 bits. Syntaxe $chaine retour string imap_qprint(string $chaine) Chane de caractres convertir. Chane de caractres convertie.

1009

Chapitre 12

La messagerie : envoi et lecture de mails

imap_base64()
Dcode un texte cod en base64. Syntaxe $chaine retour string imap_base64(string $chaine) Chane de caractres dcoder. Chane dcode.

imap_binary()
Convertit une chane 8 bits en chane base64.

12. La messagerie : envoi et lecture de mails

Syntaxe $chaine retour

string imap_binary(string $chaine) Chane de caractres convertir. Chane convertie.

imap_utf7_decode()
Dcode une chane UTF-7 en chane 8 bits. Syntaxe $chaine retour string imap_utf7_decode(string $chaine) Chane de caractres dcoder. Chane dcode.

imap_utf7_encode()
Convertit une chane 8 bits en chane UTF-7. Cela sert pour encoder les noms de botes lettres contenant des caractres spciaux en dehors de la plage ASCII des caractres imprimables. Syntaxe $chaine retour string imap_utf7_encode(string $chaine) Chane modifier. Chane modifie.

1010

Accder son compte messagerie IMAP, POP3 ou NNTP

imap_utf8()
Convertit une chane de caractres en UTF-8. Syntaxe $chaine retour string imap_utf8(string $chaine) Chane modifier. Chane modifie.

imap_mime_header_decode()
Dcode les parties de len-tte MIME. Syntaxe $entete retour array imap_mime_header_decode(string $entete) En-tte cod. Un tableau avec deux cls, charset et text, qui est len-tte dcod.

12. La messagerie : envoi et lecture de mails

Grer les erreurs

imap_alert()
Cette fonction permet de connatre lensemble des alertes IMAP apparues depuis le dernier accs ou depuis le dernier effacement de la pile dalertes. Une fois lappel cette fonction effectu, la pile est vide. Syntaxe retour array imap_alerts(void) Tableau de tous les messages dalerte.

imap_errors()
Cette fonction permet de connatre lensemble des erreurs IMAP apparues depuis le dernier accs ou depuis le dernier effacement de la pile derreurs. Une fois lappel cette fonction effectu, la pile est vide. Syntaxe retour array imap_errors(void) Tableau de tous les messages derreur.

1011

Chapitre 12

La messagerie : envoi et lecture de mails

imap_last_error()
Retourne la dernire erreur survenue (sil y en a eu une) lors du dernier appel. Syntaxe retour string imap_last_error(void) Message derreur.

Rsultat surprenant Les quelques tests effectus nont pas vritablement permis dobtenir un message derreur.

12.3. Application dexemple : le webmail


Progressivement, voici la construction dune interface webmail minimaliste.

12. La messagerie : envoi et lecture de mails

La premire des pages permettra dentrer le nom du serveur IMAP ou POP, le login de lutilisateur et le mot de passe associ.

Figure 12.4 : Interface de connexion

Donc, le code source est le suivant :

Listing 12.25 : webmail.html


<html> <head><title>Mon ouebmle</title></head> <body> <center> <p><font color="blue"><h1>Ouabmle</h1></font></p> <form action="webmail1.php"> <table>

1012

Application dexemple : le webmail

<tr> <td>Adresse serveur IMAP:</td> <td><input type="text" name="serveur" /></td> </tr> <tr> <td rowspan="2">Type de serveur:</td> <td><input type="radio" name="typeserveur" value="imap" />IMAP</td> </tr> <tr> <td><input type="radio" name="typeserveur" value="pop" />POP</td> </tr> <tr> <td>Utilisateur:</td> <td><input type="text" name="login" /></td> </tr> <tr> <td>Mot de passe:</td> <td><input type="password" name="password" /></td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" value="Connexion" /> </td> </tr> </table> </form> </center> </body> </html>

12. La messagerie : envoi et lecture de mails

Une fois connect, lutilisateur est en mesure davoir un aperu des messages prsents dans la bote lettres :

Figure 12.5 : Liste des messages

1013

Chapitre 12

La messagerie : envoi et lecture de mails

Listing 12.26 : webmail1.php


<html> <head><title>Mon ouebmle</title></head> <body> <center> <p><font color="blue"> <h1>Bienvenue sur ouebmle 0.001Beta</h1> </font></p> <?php set_time_limit(90); // Connexion au serveur IMAP // Les donnes sont rcupres du formulaire par la mthode POST $connexion = @imap_open("{".$_POST["serveur"]."/". $_POST["typeserveur"]."}INBOX", $_POST["login"], $_POST["password"]) or die("Impossible de se connecter :("); // Les informations de la bote aux lettres INBOX // sont rcupres. $infosBal = imap_mailboxmsginfo($connexion); if($infosBal) { echo "Date: ".$infosBal->Date."<br>\n" ; echo "<b>".$infosBal->Nmsgs." messages dont ". $infosBal->Unread." non lus</b><br>\n"; echo $infosBal->Size ."Ko occups<br>\n" ; } else { echo "Erreur: ".imap_last_error(). "<br>\n"; } ?> <table> <tr> <td><b>Date</b></td> <td><b>Message de</b></td> <td><b>Sujet</b></td> <td><b>Lu</b></td> <td><b>Rpondu</b></td> </tr> <?php for ($i=1; $iNmsgs+1; $i++) { // Pour chacun des messages, on rcupre les informations lies $message = imap_headerinfo($connexion, $i); echo "<tr>\n"; // La date UNIX est transforme en date lisible echo "<td>".(date("d/m/Y H:i:s", $message->udate))."</td>\n"; echo "<td>".(htmlspecialchars($message->fromaddress))."</td>\n"; echo "<td><a href=\"webmail2.php?numero=$i". "&serveur=".$_POST["serveur"]. "&typeserveur=".$_POST["typeserveur"]. "&login=".$_POST["login"]. "&password=".$_POST["password"]."\">". ($message->Subject). "</td>\n";

12. La messagerie : envoi et lecture de mails 1014

Application dexemple : le webmail

echo "<td>"; // Les messages LU sont marqus. echo ($message->Unseen == U || $message->Recent == N) ? "Non" : "Oui"; echo"</td>"; echo "<td>"; echo ($message->Answered == A) ? "Oui" : "Non"; echo"</td>"; } imap_close($connexion); </center> </body> </html> ?>

Puis lutilisateur a la possibilit de cliquer sur un message pour voir le dtail du message ainsi quune liste des fichiers attachs.

12. La messagerie : envoi et lecture de mails

Listing 12.27 : webmail2.php


<html> <head><title>Mon ouebmle</title></head> <body> <h2><font color="blue">Message</font></h2> <?php // Connexion la bote aux lettres. $connexion = @imap_open("{".$_GET["serveur"]."/". $_GET["typeserveur"]."}INBOX", $_GET["login"], $_GET["password"]) or die("Impossible de se connecter :("); $structure = imap_fetchstructure($connexion, $_GET["numero"]); $parties = $structure->parts; $fichierAttache = array(); $i=1; if ($parties) { foreach ($parties as $partie) { // Pour chacune des sous-parties, on vrifie le type // pour lafficher ou bien lindiquer comme fichier attach. switch ($partie->type) { case TYPETEXT: echo "<pre>". imap_fetchbody($connexion, $_GET["numero"], $i)."</pre>"; break; default: $parametres = $partie->dparameters; foreach ($parametres as $parametre) { if($parametre->attribute == "filename") { $fichiersattaches[] = array($i, $parametre->value); break; } }

1015

Chapitre 12

La messagerie : envoi et lecture de mails

} $i++; } } else { // Sinon il ny a quune partie // qui est le corps du message (texte gnralement) echo "<pre>".imap_fetchbody($connexion, $_GET["numero"], $i)."</pre>"; } if ($fichiersattaches) { ?> <?php <h2><font color="blue">Fichiers attachs</font></h2> foreach($fichiersattaches as $fichierAttache) { echo $fichierAttache[1]."<br />"; }

12. La messagerie : envoi et lecture de mails

} ?> </body> </html>

Figure 12.6 : Exemple sans fichier attach

Ce webmail trs simple ne montre que les bases des applications de ce genre. En quelques lignes seulement, il a t possible dinterroger un compte et de rcuprer des messages. Libre vous dexploiter au mieux les fonctions fournies dans la bibliothque IMAP pour toffer ce script.

1016

Application dexemple : le webmail

12. La messagerie : envoi et lecture de mails

Figure 12.7 : Exemple avec fichiers attachs

Administration des botes lettres

imap_get_quota()
Rcupre les quotas dune bote lettres. Il faut que lidentifiant de la bote lettres ait t rcupr par la fonction imap_open() avec les login et mot de passe de ladministrateur. Syntaxe $identifiantBal $bal retour array imap_get_quota(resource $identifiantBal, string $bal) Identifiant tel que retourn par imap_open(). Nom de la bote lettres dont on veut les quotas (ex : user.emma). Un tableau associatif avec les cls usage pour connatre lespace occup et limit pour connatre la taille de la bote lettres.

Le script suivant est cens afficher les quotas de lutilisateur Emma :


<?php $bal = imap_open("{mail.monsite.com:143/imap}","loginadmin", "passwordadmin",OP_HALFOPEN); $tableau = imap_get_quota($bal, "user.emma"); if (is_array($tableau)) { echo "Espace occup : " . $tableau[usage]; echo "Quota : " . $tableau[limit]; } imap_close($bal); ?>

1017

Chapitre 12

La messagerie : envoi et lecture de mails

imap_set_quota()
Dfinit les quotas dune bote lettres. Il faut que lidentifiant de la bote lettres ait t rcupr par la fonction imap_open() avec les login et mot de passe de ladministrateur. Syntaxe $identifiantBal $bal $limite retour boolean imap_get_quota(resource $identifiantBal, string $bal, string $limite) Identifiant tel que retourn par imap_open(). Nom de la bote lettres dont on veut dfinir les quotas (ex. : user.emma). Limite en Ko. TRUE si le changement de quota sest effectu, FALSE sinon.

12. La messagerie : envoi et lecture de mails

imap_createMailbox()
Cre une nouvelle bote lettres. Syntaxe $identifiantBal $bal retour boolean imap_createMailbox(resource $identifiantBal, string $bal) Identifiant tel que retourn par imap_open(). Nom de la bote crer. TRUE si lopration sest bien effectue, FALSE sinon.

Accents Les noms de botes lettres contenant des accents doivent dabord tre encods par la fonction imap_utf7_encode().
Voici un exemple crant un dossier Test.

Listing 12.28 : imap_createmailbox.php


<?php $bal = imap_open("{mail.monsite.com:143/imap}INBOX", "monlogin", "monpassword"); imap_createMailbox($bal, "{mail.monsite.com:143/imap}INBOX.Test"); imap_close($bal); ?>

1018

Application dexemple : le webmail

imap_deleteMailbox()
Supprime une bote lettres. Syntaxe $identifiantBal $bal retour boolean imap_deleteMailbox(resource $identifiantBal, string $bal) Identifiant tel que retourn par imap_open(). Nom de la bote supprimer. TRUE si lopration sest bien effectue, FALSE sinon.

Voici un exemple supprimant le dossier Test.

Listing 12.29 : imap_deletemailbox.php


<?php $bal = imap_open("{mail.monsite.com:143/imap}INBOX", "monlogin", "monpassword"); imap_deleteMailbox($bal, "{mail.monsite.com:143/imap}INBOX.Test"); imap_close($bal); ?>

12. La messagerie : envoi et lecture de mails

imap_renameMailbox()
Permet de renommer une bote lettres. Syntaxe $identifiantBal $ancienNom $nouveauNom retour boolean imap_renameMailbox(resource $identifiantBal, string $ancienNom, string $nouveauNom) Identifiant tel que retourn par imap_open(). Ancien nom de la bote lettres. Nouveau nom de la bote lettres. TRUE si la bote a t renomme.

Voici un exemple dutilisation :

Listing 12.30 : imap_renamemailbox.php


<?php $bal = imap_open("{mail.monsite.com:143/imap}", "monlogin","monpassword"); imap_renameMailbox($bal,"{mail.monsite.com:143/imap}.INBOX.ancien", "{mail.monsite.com:143/imap}.INBOX.nouveau"); imap_close($bal); ?>

1019

Chapitre 13

Les images et les animations Flash


13.1 13.2 Images (utilisation de la bibliothque GD) . . . . . . . . . . . . . . . . . . . . . . . .1023 Les animations Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1082

Images (utilisation de la bibliothque GD)

13.1. Images (utilisation de la bibliothque GD)


La bibliothque GD, crite en C, permet de crer des images aux formats JPEG, PNG, WBMP, GD et de lire un certain nombre dautres formats (comme XPM et XPM). Auparavant, elle offrait la possibilit de crer des images au format GIF, mais cela nest plus support depuis la modification de la licence dutilisation du format GIF (licence qui ne concerne pas lEurope). Il est cependant possible de modifier la bibliothque GD afin de crer galement des images au format GIF. Mme si vous tes mme de dessiner de belles figures gomtriques, comme des fractales, lutilisation de cette bibliothque vous servira certainement plutt tracer des diagrammes de statistiques (histogrammes, camemberts, etc.) ou utiliser des polices dcriture exotiques. la fin de ce chapitre, nous tudierons particulirement la cration des histogrammes. travers cet exemple, nous verrons les principales fonctions disponibles grce cette bibliothque. Nous prsenterons galement quelques fonctions en marge de la bibliothque GD, qui permettent de rcuprer des informations sur un fichier (type, taille, etc.). Ce qui permet, par exemple, de faire une page de prvisualisation dimages.

Licence GIF (LZW) La licence empchant lutilisation du format GIF na dsormais plus court dans la plupart des pays. Pour certain pays toutefois celle-ci court encore jusquen juillet 2004. Il faudra donc attendre cette date pour esprer retrouver un support officiel de format GIF par la bibliothque GD.

13. Les images et les animations Flash

Installation
Sous Windows
Avec larchive du PHP Group
Sans support GIF
Vous devrez vous assurer davoir le fichier php_gd2.dll (livr dans larchive PHP distribue par le PHP Group) dans votre rpertoire contenant les extensions PHP, et ajouter votre fichier php.ini ou dcommenter une ligne
extension=php_gd2.dll

Avec les versions de PHP<4.3.2, larchive contenait galement (ou la place) un fichier php_gd.dll permettant lutilisation de la version 1 de GD. Depuis PHP 4.3.9, le support de GIF en lecture et criture est rtabli.

Avec support GIF


Si vous souhaitez disposer dune librairie GD (<2.0) supportant le format GIF, vous devez tlcharger un fichier php_gd_gif.dll (habituellement disponible sur http://www.php4win.com). Fi-

1023

Chapitre 13

Les images et les animations Flash

chier que vous copierez dans votre rpertoire contenant les extensions PHP. Il vous suffira alors dajouter votre fichier php.ini, une ligne
extension=php_gd_gif.dll

Avec EasyPHP
Sans support GIF
Avec EasyPHP 1.6, le support de GD (<2.0) est activ automatiquement. Si vous souhaitez le support de GD 2 vous devrez modifier le fichier php.ini afin de dcommenter la ligne concernant GD 2.
extension=php_gd2.dll

Avec support GIF


Si vous souhaitez le support de GD (<2.0) avec GIF, vous devez modifier le fichier php.ini afin de commenter la ligne concernant GD (<2.0) sans GIF, et dcommenter celle concernant GD (<2.0 avec support GIF.

13. Les images et les animations Flash

;extension=php_gd.dll extension=php_gd_gif.dll

Sous Linux
Linstallation de la bibliothque GD ncessite (selon les besoins) la prsence pralable des bibliothques (de dveloppement) libpng et zlib pour le format PNG, jpeg6b (ou suprieur) pour le format JPEG, freetype et/ou Xpm. Ces bibliothques sont gnralement fournies avec les distributions Linux. Il suffit alors de les installer (si cela na pas t fait prcdemment). Le plus simple consiste encore utiliser les paquetages .rpm.

Exemple avec une distribution Mandrake 9.1 Il vous suffit de "monter" le CD-ROM de la distribution (mount /mnt/cdrom), de vous dplacer dans larborescence (cd /mnt/cdrom/Mandrake/RPMS) et de lancer les installations :
rpm rpm rpm rpm rpm rpm rpm rpm rpm -U -U -U -U -U -U -U -U -U zlib1-1.1.4-5mdk.i586.rpm zlib1-devel-1.1.4-5mdk.i586.rpm libpng3-1.2.5-2mdk.i586.rpm libpng3-devel-1.2.5-2mdk.i586.rpm libjpeg62-6b-26mdk.i586.rpm libjpeg62-devel-6b-26mdk.i586.rpm freetype-1.3.1-18mdk.i586.rpm freetype2-2.1.3-12mdk.i586.rpm freetype2-devel-2.1.3-12mdk.i586.rpm

1024

Images (utilisation de la bibliothque GD)

Vous devez, dans un premier temps, rcuprer la bibliothque GD, disponible sur le site (en anglais) http://www.boutell.com/gd/ (elle est galement disponible sur le CD-ROM fourni). Si toutefois vous souhaitez galement profiter du format GIF vous devez rcuprer une version modifie sur le site (anglais) http://www.rhyme.com.au/gd/ (elle est galement disponible sur le CD-ROM fourni).Dans ce cas, vous devrez remplacer les rfrences gd2.0.15 par gd2.0.15gif030801. Vous pouvez copier larchive sous /usr/local/src/lib. Il vous suffit alors de dcompresser larchive :
# gunzip gd-2.0.15.tar.gz # tar xvf gd-2.0.15.tar

Et de lancer la gnration et linstallation :


# # # # cd gd-2.0.15 ./configure make make install

Vous devez prsent disposer dun fichier libgd.a sous le rpertoire /usr/local/lib. Vous devrez ensuite recompiler PHP avec loption withgd=/usr/local pour disposer dun GD de base (ne supportant que WBMP et ventuellement GIF). cette option, vous pouvez ajouter :
j j
withjpegdir=/usr pour le support du format JPEG ; withpngdir=/usr withzlibdir=/usr pour le support du format PNG.

13. Les images et les animations Flash

A vous dajuster les chemins prciss. Ils doivent correspondre aux rpertoires contenant le rpertoire lib/ contenant les fichiers libjpeg.*, libpng.*, libz.*, etc.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur la compilation de PHP.

Vrication
Vous pouvez vrifier le bon droulement des oprations dinstallation en appelant un simple script contenant <?php phpinfo(); ?>. Celui-ci devra laisser apparatre :
Figure 13.1 :

phpinfo()

Les lignes "Gif Read Support enabled" et "Gif Create Support enabled" napparatront que si vous avez install une version de GD supportant le format GIF.

1025

Chapitre 13

Les images et les animations Flash

Pour rcuprer des informations sur GD vous pouvez galement utiliser la fonction gd_info() qui vous donnera les principales caractristiques de la version installe.

gd_info()
Retourne des informations sur la version de GD installe. Cette fonction nexiste que depuis PHP 4.3.0. Syntaxe : retour array gd_info(void) Un tableau avec pour index : GD Version : version de GD installe Freetype Support : TRUE si le support de Freetype est install. Freetype Linkage : Si Freetype est install, cette valeur retourne with freetype, with TTF library ou with unknown library selon la faon dont a t install Freetype. T1Lib Support : TRUE si T1Lib est support. GIF Read Support : TRUE si la lecture des GIF est supporte. GIF Create Support : TRUE si la cration de GIF est supporte. JPG Support : TRUE si la manipulation de JPG est supporte. PNG Support : TRUE si la manipulation de PNG est supporte. WBMP Support : TRUE si la manipulation de WBMP est supporte. XBM Support : TRUE si la manipulation de XBM est supporte.

13. Les images et les animations Flash

Dnition de limage de base


Tout dabord, commenons par un rapide aperu des diffrents formats dimage que la bibliothque est capable de gnrer.
j

GIF : il sagit dun format de compression dimage, sans perte, limit 256 couleurs et pouvant (depuis les dernires normes) comporter une "couleur" transparente. Il est particulirement adapt aux dessins (images avec des contours nets et des rgions de couleur uniforme). PNG : il sagit dun format de compression dimage, sans perte, pouvant supporter jusqu 16 millions de couleurs. JPEG : il sagit dun format de compression dimage, avec perte, pouvant supporter jusqu 16 millions de couleurs. Le taux de compression (et donc de perte) est ajustable, et a un impact significatif sur la taille du fichier et la qualit de limage. Ce format est particulirement adapt aux photos (nombreuses nuances de couleurs et peu de contours nets). WBMP : il sagit du format dimage utilis par les applications WAP, sans perte ni compression, et limit deux couleurs. GD et GD 2 : sont des formats propres la bibliothque GD.

j j

j j

1026

Images (utilisation de la bibliothque GD)

Avant denvoyer les donnes lies limage, vous devrez prvenir le navigateur du type des donnes que vous lui communiquez. Il suffit pour cela dcrire, selon les cas :
header("Content-type: header("Content-type: header("Content-type: header("Content-type: image/gif"); image/png"); image/jpeg"); image/vnd.wap.wbmp");

vous de choisir len-tte correspondant en fonction du fichier que vous souhaitez fournir, et des possibilits offertes par la bibliothque GD installe.

Dboguer Une fois len-tte envoy au navigateur, vous ne serez plus en mesure de voir les ventuels messages derreur rapports par les fonctions appeles par la suite. Pour dboguer ce genre de script, vous serez donc amen commenter la ligne de len-tte ou la dplacer pour lappeler au tout dernier moment (juste avant denvoyer les donnes).

Vous pouvez vous reporter lannexe "Les en-ttes HTTP" pour plus dinformations.

13. Les images et les animations Flash

Pour construire limage (les donnes envoyer au navigateur), vous devez dabord dfinir un canevas (un espace de travail avec un identifiant). Pour cela, vous pouvez soit crer une nouvelle image, soit vous resservir dune image existante.
j

Pour crer une nouvelle image, il suffit de faire appel la fonction imagecreate() qui retourne un identifiant pour cette image.

imageCreate()
Cre un nouvel identifiant dimage. Pour une image de 256 couleurs. Syntaxe $largeur $hauteur retour resource imageCreate(int $largeur, int $hauteur) Largeur de limage. Hauteur de limage. Identifiant de limage.

Pour une image de 200 pixels de largeur et 300 de hauteur :


$image = imageCreate(200,300);
imageCreate() est limit une palette de 256 couleurs. Pour en utiliser plus, il faut crer limage laide de :

1027

Chapitre 13

Les images et les animations Flash

imageCreateTrueColor()
Cre un nouvel identifiant dimage. Pour une image de 16 millions de couleurs. Syntaxe $largeur $hauteur retour resource imageCreateTrueColor(int $largeur, int $hauteur) Largeur de limage. Hauteur de limage. Identifiant de limage.

Pour crer une image partir dune image existante, en fonction du type du fichier dimage que lon souhaite rcuprer, il existe toute une panoplie de fonctions qui prennent toutes en paramtre le chemin du fichier ouvrir :

imageCreateFromGD()
Cre un nouvel identifiant dimage partir dune image GD existante. Syntaxe resource imageCreateFromGD(string $nomFichier) Nom du fichier contenant les donnes devant servir de base la nouvelle image. Identifiant dimage.

13. Les images et les animations Flash

$nomFichier retour

imageCreateFromGD2()
Cre un nouvel identifiant dimage partir dune image GD 2 existante. Syntaxe $nomFichier retour resource imageCreateFromGD2(string $nomFichier) Nom du fichier contenant les donnes devant servir de base la nouvelle image. Identifiant dimage.

imageCreateFromGIF()
Cre un nouvel identifiant dimage partir dune image GIF existante. Syntaxe $nomFichier retour resource imageCreateFromGIF(string $nomFichier) Nom du fichier contenant les donnes devant servir de base la nouvelle image. Identifiant dimage.

1028

Images (utilisation de la bibliothque GD)

imageCreateFromJPEG()
Cre un nouvel identifiant dimage partir dune image JPEG existante. Syntaxe $nomFichier retour resource imageCreateFromJPEG(string $nomFichier) Nom du fichier contenant les donnes devant servir de base la nouvelle image. Identifiant dimage.

imageCreateFromPNG()
Cre un nouvel identifiant dimage partir dune image PNG existante. Syntaxe $nomFichier retour resource imageCreateFromPNG(string $nomFichier) Nom du fichier contenant les donnes devant servir de base la nouvelle image. Identifiant dimage.

13. Les images et les animations Flash

imageCreateFromWBMP()
Cre un nouvel identifiant dimage partir dune image WBMP existante. Syntaxe $nomFichier retour resource imageCreateFromWBMP(string $nomFichier) Nom du fichier contenant les donnes devant servir de base la nouvelle image. Identifiant dimage.

imageCreateFromXBM()
Cre un nouvel identifiant dimage partir dune image XBM existante. Syntaxe $nomFichier retour resource imageCreateFromXBM(string $nomFichier) Nom du fichier contenant les donnes devant servir de base la nouvelle image. Identifiant dimage.

1029

Chapitre 13

Les images et les animations Flash

imageCreateFromXPM()
Cre un nouvel identifiant dimage partir dune image XPM existante. Syntaxe $nomFichier retour resource imageCreateFromXPM(string $nomFichier) Nom du fichier contenant les donnes devant servir de base la nouvelle image. Identifiant dimage.

Une autre fonction permet de nutiliser quune partie dune image GD 2 ; sa signature est la suivante :

imageCreateFromGD2Part()
Cre un nouvel identifiant dimage partir dun sous-ensemble dune image GD 2 existante. Syntaxe resource imageCreateFromGD2Part(string $nomFichier, int $sourceX, int $sourceY, int $largeur, int $hauteur) Nom du fichier GD 2 contenant les donnes devant servir de base la nouvelle image. Ordonne du point suprieur gauche de la partie extraite (0 = gauche de limage). Abscisse du point suprieur gauche de la partie extraite (0 = haut de limage). Largeur de la partie extraite. Hauteur de la partie extraite. Identifiant de limage.

13. Les images et les animations Flash

$nomFichier $sourceX $sourceY $largeur $hauteur int

Une fois limage cre, il suffit de lenvoyer vers le navigateur laide dune des fonctions suivantes. la place, il est galement possible de sauvegarder limage dans un fichier en renseignant le paramtre $nomFichier :

imageGD()
Envoie au navigateur, ou sauvegarde dans un fichier, les donnes de limage au format GD. Syntaxe $image $nomFichier retour boolean imageGD(resource $image [, string $nomFichier]) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Nom du fichier dans lequel sauvegarder limage. FALSE en cas derreur.

1030

Images (utilisation de la bibliothque GD)

imageGD2()
Envoie au navigateur, ou sauvegarde dans un fichier, les donnes de limage au format GD 2. Syntaxe $image $nomFichier retour boolean imageGD2(resource $image [, string $nomFichier]) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Nom du fichier dans lequel sauvegarder limage. FALSE en cas derreur.

imageGIF()
Envoie au navigateur, ou sauvegarde dans un fichier, les donnes de limage au format GIF. Syntaxe $image $nomFichier retour boolean imageGIF(resource $image [, string $nomFichier]) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Nom du fichier dans lequel sauvegarder limage. FALSE en cas derreur.

13. Les images et les animations Flash

imageJPEG()
Envoie au navigateur, ou sauvegarde dans un fichier, les donnes de limage au format JPEG. Syntaxe $image $nomFichier boolean imageJPEG(resource $image [, string $nomFichier [, int $qualite]]) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Nom du fichier dans lequel sauvegarder limage. (Mettre une chane vide si vous souhaitez prciser une qualit, mais ne pas sauvegarder limage dans un fichier). Valeur entre 1 (moins bonne qualit, plus fort taux de compression) et 100 (meilleure qualit, plus faible taux de compression). Par dfaut, le facteur de qualit est denviron 75. FALSE en cas derreur.

$qualite

retour

1031

Chapitre 13

Les images et les animations Flash

imageWBMP()
Envoie au navigateur, ou sauvegarde dans un fichier, les donnes de limage au format WBMP. Syntaxe $image $nomFichier boolean imageWBMP(resource $image [, string $nomFichier [, int $couleurPrincipale]]) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Nom du fichier dans lequel sauvegarder limage. (Mettre une chane vide si vous souhaitez prciser la couleur principale, mais ne pas sauvegarder limage dans un fichier). FALSE en cas derreur.

$couleurPrincipale Couleur de premier plan (par dfaut : noir) . retour

image2WBMP()
13. Les images et les animations Flash
Envoie au navigateur, ou sauvegarde dans un fichier, les donnes de limage au format WBMP. Syntaxe $image $nomFichier boolean image2WBMP(resource $image [, string $nomFichier [, int $seuil]]) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Nom du ficher dans lequel sauvegarder limage. (Mettre une chane vide si vous souhaitez prciser un seuil, mais ne pas sauvegarder limage dans un fichier). FALSE en cas derreur.

retour

Pour librer la mmoire occupe, il suffit dappliquer la fonction imageDestroy() limage.

imageDestroy()
Libre les ressources alloues par limage. Syntaxe $image retour boolean imageDestroy(resource $image) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). TRUE.

Afin de clarifier les choses, voici un exemple tout simple dutilisation. Le script suivant affiche simplement une image au format JPEG partir dune image au format GIF. Ce qui,

1032

Images (utilisation de la bibliothque GD)

notamment si limage est une photo, permet, a priori, de rduire la taille de limage transfre. En pratique, on aura tout intrt raliser manuellement lopration une bonne fois pour toutes, plutt que dappeler ce script chaque fois que limage est consulte.

Listing 13.1 : gd_00.php


<?php // Prcise au navigateur le type de donnes // quil est sur le point de recevoir header("Content-type: image/jpeg"); // Prpare une nouvelle image partir // dune image au format GIF $image = imageCreateFromGIF("image.gif"); // Envoie limage au format JPEG // Avec un facteur de qualit de 90% imageJPEG($image, "", 90); // Libre les ressources // Mme si, cest surtout utile pour // les images intermdiaires ou bien lorsque limage // est stocke dans un fichier et que le script continue imageDestroy($image); ?>

13. Les images et les animations Flash

titre dinformation, si vous sauvegardez limage obtenue, vous constaterez, quavec limage dexemple, nous avons rduit la taille des donnes dun facteur 3. Limage pourra tre consulte directement en appelant lURL de gd_00.php depuis le navigateur ou par le biais dune page HTML contenant le code utilis pour nimporte quelle image :
<img src="gd_00.php" />

La palette de couleurs
Les couleurs possdent trois composantes : une rouge, une verte et une bleue. En informatique, chacune de ces composantes est gnralement code sur un octet, et peut donc prendre une valeur entre 0 et 255. Il est ainsi possible de dfinir 16 millions de couleurs. Cependant, tous les formats dimage ne sont pas capables de supporter 16 millions de couleurs : beaucoup nutilisent quun seul octet pour dfinir la couleur dun pixel. Il faut donc trouver le moyen de passer dune information sur 3 octets (les trois composantes de la couleur) une sur un seul octet. Pour cela, il suffit davoir une table de correspondances aussi appele palette de couleurs. Ainsi, pour pouvoir utiliser une couleur, il faut au pralable lajouter la palette et rcuprer un identifiant de couleur. Pour cela, vous devez utiliser la fonction imageColorAllocate(). La signature de cette fonction est la suivante :

1033

Chapitre 13

Les images et les animations Flash

imageColorAllocate()
Ajoute une couleur la palette de couleurs. Syntaxe $image $rouge $vert $bleu retour int imageColorAllocate(resource $image, int $rouge, int $vert, int $bleu) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Composante rouge de limage (comprise entre 0 et 255). Composante verte de limage (comprise entre 0 et 255). Composante bleue de limage (comprise entre 0 et 255). Identifiant de couleur ou 1 en cas derreur.

Notez que la premire couleur ainsi dfinie servira de couleur de fond. Voici quelques exemples de dfinition dune couleur :
$blanc $noir $gris_1 $gris_2 $gris_3 $rouge $vert $bleu $mauve $jaune = = = = = = = = = = imageColorAllocate($image, imageColorAllocate($image, imageColorAllocate($image, imageColorAllocate($image, imageColorAllocate($image, imageColorAllocate($image, imageColorAllocate($image, imageColorAllocate($image, imageColorAllocate($image, imageColorAllocate($image, 255, 255, 255); 0, 0, 0); 50, 50, 50); 100, 100, 100); 150, 150, 150); 255, 0, 0); 0, 255, 0); 0, 0, 255); 100, 0, 100); 0, 100, 100);

13. Les images et les animations Flash

Il est galement possible de dfinir une "couleur" transparente, mais il faut toutefois, au pralable, crer un nouvel lment dans la palette avec imageColorAllocate(). Peu importent alors les composantes choisies, les points utilisant cette couleur seront transparents (en fait, la couleur pourrait apparatre pour les logiciels ne grant pas la transparence). Pour cela, il suffit dindiquer lidentifiant de la couleur la fonction
imageColorTransparent().

imageColorTransparent()
Dfinit un lment de la palette comme transparent. Syntaxe $image int imageColorTransparent(resource $image [, int $couleur]) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX().

1034

Images (utilisation de la bibliothque GD)

$couleur

Identifiant de la couleur tel que retourn par la fonction imageColorAllocate(). Si ce paramtre est omis, cest la couleur par dfaut qui est utilise (la premire couleur alloue). Identifiant de la couleur rendue transparente.

retour

Voici un morceau de script pour gnrer une image au format PNG, de 250 pixels sur 200, avec un fond noir :

Listing 13.2 : gd_01.php


<?php header("Content-type: image/png"); $largeur = 250; $hauteur = 200; $image = imageCreate($largeur, $hauteur); $noir = imageColorAllocate($image, 0, 0, 0); // cest ici que lon dessinera sur limage imagePNG($image); imageDestroy($image); ?>

Le mme script avec une couleur de fond transparente :

13. Les images et les animations Flash

Listing 13.3 : gd_02.php


<?php header("Content-type: image/png"); $largeur = 250; $hauteur = 200; $image = imageCreate($largeur, $hauteur); $noir = imageColorAllocate($image, 0, 0, 0); imageColorTransparent($image, $noir); // cest ici que lon dessinera sur limage imagePNG($image); imageDestroy($image); ?>

Recherche de couleurs dans la palette


Il est galement possible de rcuprer lidentifiant dune couleur si celle-ci est disponible dans la palette (cela permet aussi de tester lexistence dune couleur dans la palette). Pour cela, vous devrez faire appel la fonction imageColorExact().

imageColorExact()
Retourne lidentifiant de la couleur si la couleur existe dans la palette.

1035

Chapitre 13

Les images et les animations Flash

Syntaxe $image $rouge $verte $bleu retour

int imageColorExact(resource $image, int $rouge, int $vert, int $bleu) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Composante rouge de la couleur dsire. Composante verte de la couleur dsire. Composante bleue de la couleur dsire. Identifiant de la couleur prcise si elle existe dans la palette, 1 sinon.

Il existe une variante tenant compte de la composante Alpha (transparence).

imageColorExactAlpha()
Retourne lidentifiant de la couleur si la couleur existe dans la palette, en tenant compte de la composante Alpha (transparence). Syntaxe int imageColorExactAlpha(resource $image, int $rouge, int $vert, int $bleu, int $alpha) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Composante rouge de la couleur dsire. Composante verte de la couleur dsire. Composante bleue de la couleur dsire. Composante Alpha de la couleur dsire. Identifiant de la couleur prcise si elle existe dans la palette, 1 sinon.

13. Les images et les animations Flash

$image $rouge $verte $bleu $alpha retour

Navoir disposition que 256 couleurs lorsque lon voudrait en utiliser 16 millions peut tre contraignant. Il est toutefois possible de dterminer quelle est, dans la palette de 256 couleurs, celle qui est la plus proche de celle que nous souhaiterions utiliser. Pour rcuprer la couleur de la palette la plus proche dune couleur que lon dfinit, il existe plusieurs fonctions, qui se diffrencient par leur manire daborder la notion de "plus proche".

imageColorClosest()
Retourne lidentifiant de la couleur de la palette la plus proche de la couleur voulue. En utilisant la distance euclidienne dans un espace trois dimensions (rouge, vert, bleu). Autrement dit $distance = sqrt(pow($rouge2$rouge1, 2)+pow($vert2$vert1, 2)+pow($bleu2$bleu1, 2)).

1036

Images (utilisation de la bibliothque GD)

Syntaxe $image $rouge $vert $bleu retour

int imageColorClosest(resource $image, int $rouge, int $vert, int $bleu) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Composante rouge de la couleur dsire. Composante verte de la couleur dsire. Composante bleue de la couleur dsire. Identifiant de la couleur la plus proche de la couleur dsire.

Il est galement possible de tenir compte de la composante Alpha (transparence).

imageColorClosestAlpha()
Retourne lidentifiant de la couleur de la palette la plus proche de la couleur voulue. Syntaxe $image $rouge $vert $bleu $alpha retour int imageColorClosestAlpha(resource $image, int $rouge, int $vert, int $bleu, int $alpha)

13. Les images et les animations Flash

Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Composante rouge de la couleur dsire. Composante verte de la couleur dsire. Composante bleue de la couleur dsire. Composante Alpha de la couleur dsire. Identifiant de la couleur la plus proche de la couleur dsire.

En pratique, la distance euclidienne applique aux composantes rouge, verte et bleue nest pas idale et noffre pas toujours, de visu, le rsultat attendu. Il est donc parfois prfrable dutiliser un autre algorithme.

imageColorClosestHWB()
Retourne lidentifiant de la couleur la plus proche en appuyant le calcul sur les composantes Couleur, Saturation et Brillance. Syntaxe $image $rouge $vert int imageColorClosestHWB(resource $image, int $rouge, int $vert, int $bleu) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Composante rouge de la couleur dsire. Composante verte de la couleur dsire.

1037

Chapitre 13

Les images et les animations Flash

$bleu $alpha retour

Composante bleue de la couleur dsire. Composante Alpha de la couleur dsire. Identifiant de la couleur la plus proche de la couleur dsire.

Il est galement possible de demander ce que la couleur soit cre, si jamais elle nest pas disponible dans la palette.

imageColorResolve()
Retourne lidentifiant de la couleur si elle est dans la palette. Si la couleur nest pas dans la palette, une nouvelle couleur est ajoute la palette. Sil ny a plus de place dans la palette, cest lidentifiant de la couleur la plus proche qui est retourn. Syntaxe $image $rouge $vert $bleu retour int imageColorResolve(resource $image, int $rouge, int $vert, int $bleu) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Composante rouge de la couleur dsire. Composante verte de la couleur dsire. Composante bleue de la couleur dsire. Identifiant de la couleur dsire ou de la couleur la plus proche de la couleur dsire.

13. Les images et les animations Flash

imageColorResolveAlpha()
Retourne lidentifiant de la couleur si elle est dans la palette, en tenant compte de la composante Alpha (transparence). Si la couleur nest pas dans la palette, une nouvelle couleur est ajoute la palette. Sil ny a plus de place dans la palette, cest lidentifiant de la couleur la plus proche qui est retourn. Syntaxe $image $rouge $vert $bleu $alpha retour int imageColorResolveAlpha(resource $image, int $rouge, int $vert, int $bleu) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Composante rouge de la couleur dsire. Composante verte de la couleur dsire. Composante bleue de la couleur dsire. Composante Alpha de la couleur dsire. Identifiant de la couleur dsire ou de la couleur la plus proche de la couleur dsire.

1038

Images (utilisation de la bibliothque GD)

Pour rcuprer les composantes (rouge, verte, bleue) dun lment de la palette, il suffit dutiliser la fonction imageColorsForIndex().

imageColorsForIndex()
Retourne les composantes rouge, verte et bleue dune couleur de la palette. Syntaxe $image $couleur retour array imageColorsForIndex(resource $image, int $couleur) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Identifiant de la couleur tel que retourn par les fonctions imageColorAllocate() et imageColorResolve(). Tableau associatif contenant les cls "red" contenant la composante rouge, "green" contenant la composante verte et "blue" contenant la composante bleue.

Modier la palette
13. Les images et les animations Flash
La fonction imageColorSet() permet de remplacer une couleur de la palette.

imageColorSet()
Remplace une couleur de la palette par une autre. Syntaxe $image $couleur $rouge $vert $bleu retour boolean imageColorSet(resource $image, int $couleur, int $rouge, int $vert, int $bleu) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Identifiant de la couleur tel que retourn par les fonctions imageColorAllocate() et imageColorResolve(). Nouvelle composante rouge de la couleur dsire. Nouvelle composante verte de la couleur dsire. Nouvelle composante bleue de la couleur dsire. FALSE en cas dchec.

Il est galement possible deffectuer facilement une correction gamma sur une image avec la fonction imageGammaCorrect().

1039

Chapitre 13

Les images et les animations Flash

imageGammaCorrect()
Effectue une correction gamma sur une image. Syntaxe $image $gammaEntree $gammaSortie retour boolean imageGammaCorrect(resource $image, double $gammaEntree, double $gammaSortie) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Gamma initial de limage (probablement 1.0). Gamma corrig. TRUE.

Une fonction permet de transformer une image TrueColor en image limite 256 couleurs :

ImageTrueColorToPalette()
13. Les images et les animations Flash
Transforme une image TrueColor en image palette. Syntaxe $image $dither void imageTrueColorToPalette(resource $image, boolean $dither, int $nbCouleurs) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). En mettant TRUE ce paramtre, cela autorise le "dithering" qui permet dobtenir des images, certes plus granuleuses, mais les couleurs seront plus proches de celles dorigine. Nombre de couleurs que lon souhaite dans la palette.

$nbCouleurs

Supprimer des couleurs


Nous avons dj vu les fonctions imageColorAllocate() et imageColorResolve() qui permettent dajouter une couleur la palette de couleurs. Sachez quil est galement possible de retirer des couleurs de la palette laide de la fonction imageColorDeallocate() dont voici la signature :

imageColorDeallocate()
Supprime une couleur de la palette de couleurs. Syntaxe $image boolean imageColorDeallocate(resource $image, int $couleur) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX().

1040

Images (utilisation de la bibliothque GD)

$couleur retour

Identifiant de la couleur supprimer, tel que retourn par les fonctions imageColorAllocate() et imageColorResolve(). FALSE en cas dchec, TRUE sinon.

Nombre de couleurs dans la palette


On peut galement compter le nombre de couleurs dfinies dans une image grce la fonction imageColorsTotal().

imageColorsTotal()
Retourne le nombre de couleurs dans la palette de limage. Syntaxe $image retour int imageColorsTotal(resource $image) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Nombre de couleurs dans la palette.

13. Les images et les animations Flash

Du texte dans les images


Plusieurs fonctions sont disponibles pour afficher du texte dans une image. Elles se distinguent notamment par le format de la police de caractres utilise. On trouve ainsi, les polices :
j j

GD, une police "bitmap" propre la bibliothque GD ; TrueType, FreeType 2, PS des polices vectorielles.

Contrairement aux polices "bitmap", les polices vectorielles gardent leur aspect quelle que soit la taille que vous leur imposez.

Police de caractres GD
imageString() est une fonction qui permet dcrire horizontalement une chane de caractres. imageStringUp() est son homologue, qui permet dcrire de bas en haut. Ces deux fonctions ont des signatures identiques :

imageString()
crit horizontalement une chane de caractres sur limage.

1041

Chapitre 13

Les images et les animations Flash

Syntaxe $image $police

void imageString(resource $image, int $police, int $x, int $y, string $texte, int $couleur) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Identifiant de la police dcriture utiliser. Entre 1 et 5 sil sagit dune police propose par dfaut PHP ; un nombre suprieur retourn par imageLoadFont() sinon. Abscisse du point suprieur gauche du texte. Ordonne du point suprieur gauche du texte. Texte afficher. Identifiant de la couleur du texte tel que retourn par la fonction imageColorAllocate().

$x $y $texte $couleur

imageStringUp()
crit verticalement, de bas en haut, une chane de caractres sur limage.

13. Les images et les animations Flash

Syntaxe $image $police

void imageStringUp(resource $image, int $police, int $x, int $y, string $texte, int $couleur) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Identifiant de la police dcriture utiliser. Entre 1 et 5 sil sagit dune police propose par dfaut ; un nombre suprieur retourn par imageLoadFont() sinon. Abscisse du point suprieur gauche du texte. Ordonne du point suprieur gauche du texte. Texte afficher. Identifiant de la couleur du texte tel que retourn par la fonction imageColorAllocate().

$x $y $texte $couleur

Les polices par dfaut (entre 1 et 5) portent les noms suivants : 1 = Tiny, 2 = Small, 3 = MediumBold, 4 = Large et 5 = Giant. En utilisant imageString() et imageStringUp(), voici ce que lon peut faire :

Listing 13.4 : gd_03.php


<?php header("Content-type: image/png"); $largeur = 200; $hauteur = 100; $image = imageCreate($largeur, $hauteur); $transparent = imageColorAllocate($image, 255, 0, 0); $noir = imageColorAllocate($image, 0, 0, 0);

1042

Images (utilisation de la bibliothque GD)

imageColorTransparent($image, $transparent); imageString($image, imageString($image, imageString($image, imageString($image, imageString($image, 1, 2, 3, 4, 5, 10, 10, 10, 10, 10, 10, 25, 40, 55, 70, "police "police "police "police "police 1", 2", 3", 4", 5", $noir); $noir); $noir); $noir); $noir);

imageStringUp($image, 5, 150, 100, "imageStringUp", $noir); imagePNG($image); imageDestroy($image); ?>

Ce script crit cinq chanes de caractres horizontalement utilisant les cinq polices dcriture disponibles, puis utilise la fonction similaire permettant dcrire verticalement.
Figure 13.2 : Utilisation dimageString et imageStringUp

13. Les images et les animations Flash

Deux fonctions similaires, et ayant la mme syntaxe que celles qui viennent dtre vues, existent et ne servent qu afficher le premier caractre dune chane de caractres. Il sagit de :

imageChar()
crit horizontalement le premier caractre dune chane de caractres sur limage.

imageCharUp()
crit verticalement, de bas en haut, le premier caractre dune chane de caractres sur limage.

Taille du texte
La fonction suivante retourne la hauteur en pixels dune police dcriture GD.

1043

Chapitre 13

Les images et les animations Flash

imageFontHeight()
Hauteur dun caractre de la police dcriture GD. Syntaxe $police retour int imageFontHeight(int $police) Identifiant de la police dcriture. Hauteur de la police (en pixels).

Celle-ci retourne la largeur :

imageFontWidth()
Largeur dun caractre de la police dcriture GD. Syntaxe $police retour int imageFontWidth(int $police) Identifiant de la police dcriture. Largeur de la police (en pixels).

13. Les images et les animations Flash

Personnalisation
Il est possible dutiliser son propre fichier de police dcriture en utilisant la fonction suivante :
imageLoadFont()

imageLoadFont()
Charge un fichier de police de caractres GD. Syntaxe $nomFichier retour int imageLoadFont(string $nomFichier) Nom du fichier de police dcriture. Identifiant de police dcriture (ayant une valeur > 5, les cinq premires tant les polices PHP par dfaut).

Police de caractres TrueType


Afin de pouvoir utiliser la police TrueType, vous devez installer la bibliothque en plus de GD.

Installation sous Linux


Rcuprez la bibliothque ladresse http://www.freetype.org/. Il sagit dun fichier freetype2.1.0.tar.gz (galement disponible sur le CD-ROM).

1044

Images (utilisation de la bibliothque GD)

Aprs avoir copi le fichier dans un rpertoire donn (ex. :/usr/local/src/lib), dcompressez le fichier
# gunzip freetype-2.1.0.tar.gz # tar xvf freetype-2.1.0.tar # cd freetype-2.1.0

Puis compilez la bibliothque :


# ./configure

Et installez-la :
# make install

Vous devez avoir maintenant une srie de fichiers libfreetype* dans le rpertoire /usr/local/lib. Vous pouvez alors recompiler PHP avec loption --with-freetype-dir=/usr/local/lib.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails.

13. Les images et les animations Flash

Vrication
Vous pouvez vrifier le bon droulement des oprations dinstallation en appelant un simple script contenant <?php phpinfo(); ?>. Celui-ci devra laisser apparatre :
Figure 13.3 :

phpinfo()

Et qui doit donc contenir une ligne "FreeType linkage ... with freetype" (ventuellement "with TTF Library").

Utilisation
Polices dcriture tant donn que les images sont gnres du ct du serveur, il nest pas utile que le client ait install les polices utilises pour la gnration des images.
Pour afficher du texte avec une telle police, il faut utiliser la fonction imageTTFText() dont la signature est la suivante :

1045

Chapitre 13

Les images et les animations Flash

imageTTFText()
crit une chane de caractres sur limage en utilisant une police TrueType. Syntaxe $image $taille $angle $x $y $couleur $police $texte retour array imageTTFText(resource $image, int $taille, int $angle, int $x, int $y, int $couleur, string $police, string $texte) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Taille du texte. Angle du texte en degrs (0 = texte horizontal, 90 = texte vertical de bas en haut). Abscisse du coin infrieur gauche du premier caractre de la chane. Ordonne du coin infrieur gauche du premier caractre de la chane. Identifiant de la couleur du texte tel que retourn par la fonction imageColorAllocate(). Nom du fichier de la police TrueType Texte afficher. Tableau contenant quatre lments indtermins.

13. Les images et les animations Flash

Par dfaut, une opration d"anti-aliasing" est effectue sur le texte. Pour retirer cet effet, il suffit de faire prcder la couleur du signe .

Trouver des polices dcriture Vous trouverez de nombreuses http://www.123fonts.com.

polices

dcriture

libres

de

droits

sur

Voici un exemple de script utilisant diffrents angles :

Listing 13.5 : gd_04.php


<?php header("Content-type: image/png"); $largeur = 250; $hauteur = 200; $image = imageCreate($largeur, $hauteur); $fond = imageColorAllocate($image, 200, 200, 200); $noir = imageColorAllocate($image, 0, 0, 0); imageTTFText($image, 20, 0, 20, 20, -$noir, "melanie.TTF", "Police TrueType A"); imageTTFText($image, 20, 0, 20, 40, $noir, "melanie.TTF", "Police TrueType B"); imageTTFText($image, 20, 0, 20, 60, -$noir, "junist.TTF", "Police TrueType C"); imageTTFText($image, 20, 0, 20, 80, $noir,

1046

Images (utilisation de la bibliothque GD)

"junist.TTF", "Police TrueType D"); imageTTFText($image, 20, 180, 130, 85, -$noir, "junist.TTF", "Police TrueType E"); imageTTFText($image, 20, 90, 200, 150, -$noir, "junist.TTF", "Police TrueType F"); imageTTFText($image, 30, 20, 5, 190, -$noir, "junist.TTF", "Police TrueType G"); imagePNG($image); imageDestroy($image); ?> Figure 13.4 : Utilisation dimageTTFText

13. Les images et les animations Flash

Taille du texte
Si vous souhaitez centrer votre texte, vous devrez connatre sa taille. Pour cela, vous pouvez faire appel :

imageTTFBBox()
Cette fonction permet de connatre les coordonnes du rectangle entourant une chane de caractres crite laide dune police TrueType. Syntaxe $taillePolice $angle $police $texte retour array imageTTFBBox(int $taillePolice, int $angle, string $police, string $texte) Taille de la police en pixels. Angle avec lequel le texte est crit. Nom du fichier de la police dcriture. Texte dont on veut connatre les coordonnes du rectangle. Un tableau huit lments (abscisse du point infrieur gauche, ordonne du point infrieur gauche, abscisse du point infrieur droit, ordonne du point infrieur droit, abscisse du point suprieur droit, ordonne du point suprieur droit, abscisse du point suprieur gauche, ordonne du point suprieur gauche).

1047

Chapitre 13

Les images et les animations Flash

Police de caractres FreeType 2


Une autre fonction imageFtText()permet dafficher du texte en utilisant des polices dcriture de type FreeType 2. Sa syntaxe est proche de celle dimageTTFText() ; un paramtre supplmentaire permet toutefois de passer dautres informations.

imageFtText()
crit une chane de caractres sur limage en utilisant une police FreeType 2. Syntaxe array imageFtText(resource $image, int $taille, int $angle, int $x, int $y, int $couleur, string $police, string $texte, array $infos) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Taille du texte. Angle du texte en degrs (0 = texte horizontal, 90 = texte vertical de bas en haut). Abscisse du coin infrieur gauche du premier caractre de la chane. Ordonne du coin infrieur gauche du premier caractre de la chane. Identifiant de la couleur du texte tel que retourn par la fonction imageColorAllocate(). Nom du fichier de la police FreeType. Texte afficher. Tableau associatif contenant dautres paramtres. Pour le moment, seule la cl "linespacing" est prise en compte et permet de spcifier la largeur de linterligne (coefficient par rapport linterligne par dfaut). Tableau contenant quatre lments indtermins.

$image $taille $angle

13. Les images et les animations Flash

$x $y $couleur $police $texte $infos

retour

Pour crire avec un interligne double de la normale, il suffit dcrire :


imageFtText($image, $taille, $angle, $x, $y, $couleur, $police, $texte, array("linespacing" => 2))

Taille du texte

imageFTBBox()
Cette fonction permet de connatre les coordonnes du rectangle entourant une chane de caractres crite laide dune police TrueType II.

1048

Images (utilisation de la bibliothque GD)

Syntaxe $taillePolice $angle $police $texte $infos retour

array imageFTBBox(int $taillePolice, int $angle, string $police, string $texte[,array $infos]) Taille de la police en pixels. Angle avec lequel le texte est crit. Nom du fichier de la police dcriture. Texte dont nous voulons connatre les coordonnes du rectangle. Informations supplmentaires telles que linterligne. Un tableau huit lments (abscisse du point infrieur gauche, ordonne du point infrieur gauche, abscisse du point infrieur droit, ordonne du point infrieur droit, abscisse du point suprieur droit, ordonne du point suprieur droit, abscisse du point suprieur gauche, ordonne du point suprieur gauche).

Police de caractres Postscript


Installation sous Linux
Installation Les polices Postscript ne peuvent tre utilises que si la bibliothque t1lib a t installe.
Rcuprez la bibliothque ladresse ftp://sunsite.unc.edu/pub/Linux/libs/graphics/. Il sagit dun fichier t1lib-1.3.1.tar.gz (galement disponible sur le CD-ROM). Aprs avoir copi le fichier dans un rpertoire donn (ex. :/usr/local/src/lib), dcompressez-le :
# gunzip t1lib-1.3.1.tar.gz # tar xvf t1lib-1.3.1.tar # cd t1lib-1.3.1

13. Les images et les animations Flash

Puis compilez la bibliothque :


# ./configure # make without_doc

Et installez-la :
# make

Vous devez avoir maintenant une srie de fichiers libt1* dans le rpertoire /usr/local/lib. Vous pouvez alors recompiler PHP avec loption --with-t1lib.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur la compilation de PHP.

1049

Chapitre 13

Les images et les animations Flash

Vrication
Les lignes retournes par <?php phpinfo(); ?> et concernant la bibliothque GD doivent alors laisser apparatre lindication "T1Lib support enabled".

Utilisation
Il est donc possible dcrire du texte en utilisant une police PostScript grce la fonction imagePSText().

imagePSText()
crit une chane de caractres sur limage en utilisant une police Postscript. Syntaxe array imagePSText(resource $image, string $texte, resource $police, int $taille, int $couleurTexte, $couleurFond, int $x, int $y [, int $largeurEspace, int $espaceCar, double $angle, int $antiAliasing]) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Texte afficher. Identifiant de police imagePSLoadFont(). Taille du texte en pixels. Identifiant de la couleur du texte tel que retourn par les fonctions imageColorAllocate() et imageColorResolve(). Identifiant de la couleur du fond tel que retourn par les fonctions imageColorAllocate()et imageColorResolve(). Abscisse du coin infrieur (base) gauche du premier caractre de la chane (par exemple, pour la lettre p, la base se situe en dessous de la "boucle" et non au bas du "pied"). Ordonne du coin infrieur (base) gauche du premier caractre de la chane (par exemple, pour la lettre p, la base se situe en dessous de la "boucle" et non au bas du "pied"). Largeur (en pixels) du caractre "espace". Espace (en pixels) entre les caractres. Angle du texte en degrs (0 = texte horizontal, 90 = texte vertical de bas en haut). Nombre de paramtres utiliser pour lanti-aliasing (4 ou 16). Tableau contenant quatre lments indtermins. tel que retourn par la fonction

$image

13. Les images et les animations Flash

$texte $police $taille $couleurTexte $couleurFond $x

$y

$largeurEspace $espaceCar $angle $antiAliasing retour

1050

Images (utilisation de la bibliothque GD)

imagePSLoadFont()
Charge une police dcriture PostScript de type 1. Syntaxe $fileName return resource imagePSLoadFont(string $fileName) Nom du fichier PostScript charger. Identifiant de la police dcriture.

Taille du texte

imagePSBBox()
Cette fonction permet de connatre les coordonnes du rectangle entourant une chane de caractres crite laide dune police PostScript de type 1. Syntaxe $texte $police $taille $largeurEspace $espaceCar $angle retour array imagePSBBox(string $texte, resource $police, int $taille [,int $largeurEspace, int $espaceCar, double $angle])

13. Les images et les animations Flash

Texte dont vous souhaitez connatre les coordonnes du rectangle de contour. Identifiant de police imagePSLoadFont(). Taille du texte en pixels. Largeur (en pixels) du caractre "espace". Espace (en pixels) entre les caractres. Angle du texte en degrs (0 = texte horizontal, 90 = texte vertical de bas en haut). Un tableau quatre lments. (abscisse du point infrieur gauche, ordonne du point infrieur gauche, abscisse du point suprieur droit, ordonne du point suprieur droit). tel que retourn par la fonction

Personnalisation
Il est possible de modifier les polices Postscript laide des fonctions suivantes :

imagePSEncodeFont()
Permet de changer le codage vectoriel dun caractre dune police. Les polices dcriture PostScript ne grent pas les caractres aprs 127. Pour utiliser une autre langue que langlais (contenant par exemple des caractres accentus), il peut tre indispensable de modifier le codage vectoriel.

1051

Chapitre 13

Les images et les animations Flash

Syntaxe $police $nomFichier retour

boolean imagePSEncodeFont(resource $police, string $nomFichier) Identifiant de la police dcriture modifier tel que retourn par imagePSLoadFont(). Nom du fichier contenant le nouveau codage vectoriel. TRUE.

imagePSExtendFont()
Permet dtendre ou de condenser une police dcriture. Syntaxe $police $extension retour boolean imagePSExtendFont(resource $police, float $extension) Identifiant de la police dcriture modifier tel que retourn par imagePSLoadFont(). Indice dextension ; sil est infrieur un alors la police sera condense. TRUE si lopration a pu se faire, FALSE sinon.

13. Les images et les animations Flash

imagePSSlantFont()
Cette fonction permet de mettre en italique une police dcriture. Syntaxe $police $coeff retour boolean imagePSSlantFont(resource $police, float $coeff) Identifiant de la police imagePSLoadFont(). Coefficient dinclinaison. TRUE si lopration a pu se faire, FALSE sinon. dcriture tel que retourn par

Libration des ressources

imagePSFreeFont()
Libre la mmoire occupe par une police dcriture PostScript de type 1. Syntaxe $police void imagePSFreeFont(resource $police) Identifiant de la police imagePSLoadFont(). dcriture tel que retourn par

1052

Images (utilisation de la bibliothque GD)

Dessiner des formes gomtriques


Il est possible de faire ses dessins point par point, en utilisant une fonction qui permet de nafficher quun seul pixel :

imageSetPixel()
Permet dafficher un pixel dune certaine couleur. Syntaxe $image $x $y $couleur retour boolean imageSetPixel(resource $image, int $x, int $y, int $couleur) Identifiant de limage sur laquelle dessiner le pixel. Abscisse du pixel dessiner. Ordonne du pixel dessiner. Identifiant de la couleur donner au pixel. TRUE.

Grce cette mme bibliothque, il est aussi possible de dessiner des traits.

13. Les images et les animations Flash

imageLine()
Permet de dessiner un trait. Syntaxe $image $x1 $y1 $x2 $y2 $couleur boolean imageLine(resource $image, int $x1, int $y1, int $x2, int $y2, int $couleur) Identifiant de limage sur laquelle dessiner le trait. Abscisse du point de dpart. Ordonne du point de dpart. Abscisse du point darrive. Ordonne du point darrive. Identifiant de la couleur du trait, IMG_COLOR_BRUSHED (voir imageSetBrush()), IMG_COLOR_STYLED (voir imageSetStyle()) ou IMG_COLOR_STYLEDBRUSHED. TRUE.

retour

Il est galement possible de dessiner des traits en pointills.

1053

Chapitre 13

Les images et les animations Flash

imageDashedLine()
Permet de dessiner un trait en pointills. Syntaxe $image $x1 $y1 $x2 $y2 $couleur retour boolean imageDashedLine( resource $image, int $x1, int $y1, int $x2, int $y2, int $couleur) Identifiant de limage sur laquelle dessiner le trait. Abscisse du point de dpart. Ordonne du point de dpart. Abscisse du point darrive. Ordonne du point darrive. Identifiant de la couleur du trait. TRUE.

Envie de vous prendre pour Picasso ? Il est possible de dessiner des arcs dellipses, des cercles, des polygones, des rectangles, des carrs...

13. Les images et les animations Flash

imageArc()
Permet de dessiner un arc dellipse ou de cercle. Syntaxe boolean imageArc(resource $image, int $centreX, int $centreY, int $largeur, int $hauteur, int $angleDebut, int $angleFin, int $couleur) Identifiant de limage sur laquelle dessiner larc dellipse. Abscisse du centre de lellipse. Ordonne du centre de lellipse. Largeur de lellipse. Hauteur de lellipse. Angle en degrs o commencer le trac. 0 correspond 3 H, 90 6 H, 180 9 H. Angle en degrs o finir le trac. Identifiant de la couleur de lellipse. TRUE.

$image $centreX $centreY $largeur $hauteur $angleDebut $angleFin $couleur retour

Listing 13.6 : gd_arc.php


<?php header("Content-type: image/png"); $largeur = 290;

1054

Images (utilisation de la bibliothque GD)

$hauteur = 50; $image = imageCreate($largeur, $hauteur); $fond = imageColorAllocate($image, 200, 200, 200); $noir = imageColorAllocate($image, 0, 0, 0); imageArc($image, imageArc($image, imageArc($image, imageArc($image, 40, 25, 60, 30 , 110, 25, 60, 30, 180, 25, 60, 30, 250, 25, 30, 30, 0, 240, $noir); 90, 180, $noir); 180, 360, $noir); 0, 360, $noir);

imagePNG($image); imageDestroy($image); ?> Figure 13.5 : imageArc()

imageFilledArc()
Permet de dessiner un arc dellipse ou de cercle plein. Syntaxe boolean imageFilledArc(resource $image, int $centreX, int $centreY, int $largeur, int $hauteur, int $angleDebut, int $angleFin, int $couleur, int $style) Identifiant de limage sur laquelle dessiner larc dellipse. Abscisse du centre de lellipse. Ordonne du centre de lellipse. Largeur de lellipse. Hauteur de lellipse. Angle en degrs o commencer le trac. 0 correspond 3 H, 90 6 H, 180 9 H. Angle en degrs o finir le trac. Identifiant de la couleur de lellipse. Permet de dfinir comment remplir larc de cercle ; quatre valeurs combinables sont dfinies : IMG_ARC_PIE, IMG_ARC_CHORD, IMG_ARC_NOFILL, IMG_ARC_EDGED. Plutt que de dcrire ces constantes, nous vous suggrons de regarder leffet de ces styles sur lexemple qui suit. TRUE.

13. Les images et les animations Flash

$image $centreX $centreY $largeur $hauteur $angleDebut $angleFin $couleur $style

retour

1055

Chapitre 13

Les images et les animations Flash

Listing 13.7 : gd_farc.php


<?php header("Content-type: image/png"); $largeur = 290; $hauteur = 210; $image = imageCreate($largeur, $hauteur); $fond = imageColorAllocate($image, 200, 200, 200); $noir = imageColorAllocate($image, 0, 0, 0); imageFilledArc($image, 40, 25, 60, 30 , 0, 240, $noir, IMG_ARC_PIE); imageFilledArc($image, 110, 25, 60, 30, 90, 180, $noir, IMG_ARC_PIE); imageFilledArc($image, 180, 25, 60, 30, 180, 360, $noir, IMG_ARC_PIE); imageFilledArc($image, 250, 25, 30, 30, 0, 360, $noir, IMG_ARC_PIE); imageFilledArc($image, 40, 65, 60, 30 , 0, 240, $noir, IMG_ARC_CHORD); imageFilledArc($image, 110, 65, 60, 30, 90, 180, $noir, IMG_ARC_CHORD); imageFilledArc($image, 180, 65, 60, 30, 180, 360, $noir, IMG_ARC_CHORD); imageFilledArc($image, 250, 65, 30, 30, 0, 360, $noir, IMG_ARC_CHORD); // IMG_ARC_NOFILL utilise tout seul revient a // utiliser imageArc() au lieu de imageFilledArc() imageFilledArc($image, 40, 105, 60, 30 , 0, 240, $noir, IMG_ARC_NOFILL); imageFilledArc($image, 110, 105, 60, 30, 90, 180, $noir, IMG_ARC_NOFILL); imageFilledArc($image, 180, 105, 60, 30, 180, 360, $noir, IMG_ARC_NOFILL); imageFilledArc($image, 250, 105, 30, 30, 0, 360, $noir, IMG_ARC_NOFILL); imageFilledArc($image, 40, 145, 60, 30 , 0, 240, $noir, IMG_ARC_EDGED); imageFilledArc($image, 110, 145, 60, 30, 90, 180, $noir, IMG_ARC_EDGED); imageFilledArc($image, 180, 145, 60, 30, 180, 360, $noir, IMG_ARC_EDGED); imageFilledArc($image, 250, 145, 30, 30, 0, 360, $noir, IMG_ARC_EDGED); // Il est egalement possible de combiner les effets imageFilledArc($image, 40, 185, 60, 30 , 0, 240, $noir, IMG_ARC_EDGED | IMG_ARC_NOFILL); imageFilledArc($image, 110, 185, 60, 30, 90, 180, $noir, IMG_ARC_EDGED | IMG_ARC_NOFILL); imageFilledArc($image, 180, 185, 60, 30, 180, 360, $noir, IMG_ARC_EDGED | IMG_ARC_NOFILL); imageFilledArc($image, 250, 185, 30, 30, 0, 360,

13. Les images et les animations Flash 1056

Images (utilisation de la bibliothque GD)

$noir, IMG_ARC_EDGED | IMG_ARC_NOFILL); imagePNG($image); imageDestroy($image); ?> Figure 13.6 : imageFilledArc()

imageEllipse()
13. Les images et les animations Flash
Permet de dessiner une ellipse ou un cercle (ncessite GD 2 ou plus). Syntaxe $image $centreX $centreY $largeur $hauteur $couleur retour boolean imageEllipse(resource $image, int $centreX, int $centreY, int $largeur, int $hauteur) Identifiant de limage sur laquelle dessiner lellipse. Abscisse du centre de lellipse. Ordonne du centre de lellipse. Largeur de lellipse. Hauteur de lellipse. Identifiant de la couleur de lellipse. TRUE.

imageFilledEllipse()
Permet de dessiner une ellipse ou un cercle rempli (ncessite GD 2 ou plus). Syntaxe $image $centreX $centreY $largeur boolean imageFilledEllipse(resource $image, int $centreX, int $centreY, int $largeur, int $hauteur) Identifiant de limage sur laquelle dessiner lellipse. Abscisse du centre de lellipse. Ordonne du centre de lellipse. Largeur de lellipse.

1057

Chapitre 13

Les images et les animations Flash

$hauteur $couleur retour

Hauteur de lellipse. Identifiant de la couleur de lellipse. TRUE.

Listing 13.8 : gd_fellipse.php


<?php header("Content-type: image/png"); $largeur = 290; $hauteur = 50; $image = imageCreate($largeur, $hauteur); $fond = imageColorAllocate($image, 200, 200, 200); $noir = imageColorAllocate($image, 0, 0, 0); imageFilledEllipse($image, imageFilledEllipse($image, imageFilledEllipse($image, imageFilledEllipse($image, imagePNG($image); imageDestroy($image); ?> Figure 13.7 : imageFilledArc() 40, 25, 60, 30, $noir); 110, 25, 60, 10, $noir); 180, 25, 10, 30, $noir); 250, 25, 30, 30, $noir);

13. Les images et les animations Flash

imageRectangle()
Permet de dessiner un rectangle. Syntaxe $image $x1 $y1 $x2 $y2 $couleur retour boolean imageRectangle(resource $image, int $x1, int $y1, int $x2, int $y2, int $couleur) Identifiant de limage sur laquelle dessiner le rectangle. Abscisse du point suprieur gauche. Ordonne du point suprieur gauche. Abscisse du point infrieur droit. Ordonne du point infrieur droit. Identifiant de la couleur du rectangle. TRUE.

1058

Images (utilisation de la bibliothque GD)

Listing 13.9 : gd_rectangle.php


<?php header("Content-type: image/png"); $largeur = 151; $hauteur = 50; $image = imageCreate($largeur, $hauteur); $fond = imageColorAllocate($image, 200, 200, 200); $noir = imageColorAllocate($image, 0, 0, 0); imageRectangle($image, imageRectangle($image, imageRectangle($image, imageRectangle($image, imagePNG($image); imageDestroy($image); ?> Figure 13.8 : imageRectangle() 10, 10, 70, 40, $noir); 80, 10, 110, 40, $noir); 120, 10, 130, 40, $noir); 140, 10, 141, 40, $noir);

13. Les images et les animations Flash

imageFilledRectangle()
Permet de dessiner un rectangle plein. Syntaxe $image $x1 $y1 $x2 $y2 $couleur retour boolean imageFilledRectangle(resource $image, int $x1, int $y1, int $x2, int $y2, int $couleur) Identifiant de limage sur laquelle dessiner le rectangle plein. Abscisse du point suprieur gauche. Ordonne du point suprieur gauche. Abscisse du point infrieur droit. Ordonne du point infrieur droit. Identifiant de la couleur du rectangle. TRUE.

Listing 13.10 : gd_frectangle.php


<?php header("Content-type: image/png"); $largeur = 151; $hauteur = 50; $image = imageCreate($largeur, $hauteur);

1059

Chapitre 13

Les images et les animations Flash

$fond = imageColorAllocate($image, 200, 200, 200); $noir = imageColorAllocate($image, 0, 0, 0); imageFilledRectangle($image, imageFilledRectangle($image, imageFilledRectangle($image, imageFilledRectangle($image, imagePNG($image); imageDestroy($image); ?> Figure 13.9 : imageFilledRectangle() 10, 10, 70, 40, $noir); 80, 10, 110, 40, $noir); 120, 10, 130, 40, $noir); 140, 10, 141, 40, $noir);

imagePolygon()
13. Les images et les animations Flash
Permet de dessiner un polygone dau plus 256 points. Syntaxe : $image $points $nombrePoints $couleur boolean imagePolygon(resource $image, array $points, int $nombrePoints, int $couleur) Identifiant dimage sur laquelle dessiner un polygone. Un tableau de points de la forme array($x1, $y1, $x2, $y2) Nombre de points du polygone (donc gnralement la moiti de la taille du tableau $points). Identifiant de la couleur du polygone, IMG_COLOR_BRUSHED (voir imageSetBrush()), IMG_COLOR_STYLED (voir imageSetStyle()) ou IMG_COLOR_STYLEDBRUSHED. TRUE.

Retour

Listing 13.11 : gd_polygone.php


<?php header("Content-type: image/png"); $largeur = 151; $hauteur = 50; $image = imageCreate($largeur, $hauteur); $fond = imageColorAllocate($image, 200, 200, 200); $noir = imageColorAllocate($image, 0, 0, 0); imagepolygon($image, array(10, 10, 70, 10, 70, 40, 10, 40), 4, $noir); imagePolygon($image, array(80, 10, 90, 30, 100, 15, 140, 10, 110, 40, 80, 35, 82, 17), 7, $noir);

1060

Images (utilisation de la bibliothque GD)

imagePNG($image); imageDestroy($image); ?> Figure 13.10 :

imagePolygon()

imageFilledPolygon()
Permet de dessiner un polygone plein dau plus 256 points. Syntaxe $image $points $nombrePoints $couleur retour boolean imageFilledPolygon(resource $image, array $points, int $nombrePoints, int $couleur) Identifiant de limage sur laquelle dessiner un polygone. Un tableau de points de la forme array($x1, $y1, $x2, $y2). Nombre de points du polygone (gnralement la moiti de la taille du tableau $points). Identifiant de la couleur de remplissage IMG_COLOR_TILED (voir imageSetTile()). TRUE. du polygone ou

13. Les images et les animations Flash

Listing 13.12 : gd_fpolygon.php


<?php header("Content-type: image/png"); $largeur = 151; $hauteur = 50; $image = imageCreate($largeur, $hauteur); $fond = imageColorAllocate($image, 200, 200, 200); $noir = imageColorAllocate($image, 0, 0, 0); imageFilledPolygon($image, array(10, 10, 70, 10, 70, 40, 10, 40), 4, $noir); imageFilledPolygon($image, array(80, 10, 90, 30, 100, 15, 140, 10, 110, 40, 80, 35, 82, 17), 7, $noir); imagePNG($image); imageDestroy($image); ?>

1061

Chapitre 13

Les images et les animations Flash

Figure 13.11 : imageFilledPolygon()

Voici un script utilisant toutes ces fonctions :

Listing 13.13 : gd_05.php


<?php header("Content-type: image/png"); $largeur = 290; $hauteur = 170; $image = imageCreate($largeur, $hauteur); $fond = imageColorAllocate($image, 200, 200, 200); $noir = imageColorAllocate($image, 0, 0, 0); imageArc($image, 40, 25, 60, 30 , 0, 240, $noir); imageFilledEllipse($image, 110, 25, 60, 30, $noir); //imageEllipse($image, 180, 40, 60, 30, $noir);

13. Les images et les animations Flash

imageFilledArc($image, imageFilledArc($image, imageFilledArc($image, imageFilledArc($image,

40, 65, 60, 30 , 0, 240, $noir, IMG_ARC_PIE); 110, 65, 60, 30 , 0, 240, $noir, IMG_ARC_CHORD); 180, 65, 60, 30 , 0, 240, $noir, IMG_ARC_NOFILL); 250, 65, 60, 30 , 0, 240, $noir, IMG_ARC_EDGED);

imageRectangle($image, 10, 90, 70, 120, $noir); imageFilledRectangle($image, 80, 90, 140, 120, $noir); imagePolygon($image, array(10, 130, 20, 150, 30, 135, 70, 130, 40, 160, 10, 155, 12, 137), 7, $noir); imageFilledPolygon($image, array(80, 130, 90, 150, 100, 135, 140, 130, 110, 160, 80, 155, 82, 137), 7, $noir); imagePNG($image); imageDestroy($image); ?> Figure 13.12 : Utilisation des fonctions de dessin gomtrique

1062

Images (utilisation de la bibliothque GD)

Changer le type de trac


Il est possible de redfinir le type du crayon utilis lors du trac laide de diffrentes mthodes.

imageSetBrush()
Permet de dfinir le pinceau utilis. Le pinceau tant une image, pour lutiliser, il faut choisir IMG_COLOR_BRUSHED ou IMG_COLOR_STYLEDBRUSHED en guise de couleur. Syntaxe $image $pinceau retour boolean imageSetBrush(resource $image, resource $pinceau) Identifiant de limage sur laquelle on veut redfinir le type de trac. Identifiant de limage qui servira tracer une ligne. TRUE.

imageSetStyle()
Permet de dfinir le style dun trait laide dun tableau de couleurs. Pour utiliser ce type de trait, il suffit de dfinir la couleur de trac comme tant la constante IMG_COLOR_STYLED. Syntaxe $image $style retour boolean imageSetStyle(resource $image, array $style) Identifiant de limage sur laquelle on veut appliquer le style de trait. Tableau de couleurs. TRUE.

13. Les images et les animations Flash

Voici un exemple traant une ligne compose de deux pixels bleus, puis deux rouges, puis deux verts, deux bleus, deux rouges, etc.

Listing 13.14 : gd_setstyle.php


<?php header("Content-type: image/png"); $image $blanc $bleu $rouge $vert = = = = = imagecreate(100, 100); imageColorAllocate($im, imageColorAllocate($im, imageColorAllocate($im, imageColorAllocate($im,

255, 255, 255); 0, 0, 255); 255, 0, 0); 0, 255, 0);

$style = array($bleu, $bleu, $rouge, $rouge, $vert, $vert); imageSetStyle($image, $style); imageLine($image, 0, 0, 100, 100, IMG_COLOR_STYLED); imagePNG($image);

1063

Chapitre 13

Les images et les animations Flash

imageDestroy($image); ?> Figure 13.13 : Le rsultat agrandi

imageSetTile()
Permet de redfinir la faon de remplir une ellipse, un rectangle Limage fournie est rpte pour remplir la surface. Pour utiliser ce type de remplissage par la suite, il suffit de passer la constante IMG_COLOR_TILED comme couleur. Syntaxe $image boolean imageSetTile(resource $image, resource $imageRemplissage) Identifiant de limage sur laquelle on veut redfinir le remplissage. TRUE.

$imageRemplissage Identifiant de limage qui servira effectuer le remplissage de surface.

13. Les images et les animations Flash

retour

Il est galement possible de simplement dfinir lpaisseur du trait :

imageSetThickness
Permet de redfinir lpaisseur du trait en pixels. Syntaxe $image $epaisseur retour boolean imageSetThickness(resource $image, int $epaisseur) Identifiant de limage sur laquelle redfinir lpaisseur du trait. paisseur du trait. TRUE.

Listing 13.15 : gd_setthickness.php


<?php header("Content-type: image/png"); $image = imageCreate(100, 100); $fond = imageColorAllocate($image, 255, 255, 255); $noir = imageColorAllocate($image ,0, 0, 0); imageSetThickness($image, 10); imageLine($image, 0, 0, 100, 100, $noir); imagePNG($image); ?>

1064

Images (utilisation de la bibliothque GD)

Figure 13.14 :

Le rsultat

Utiliser les couleurs


Rcuprer des couleurs
Il est possible de connatre la couleur dun pixel grce la fonction imageColorAt().

imageColorAt()
Retourne lidentifiant de la couleur dun pixel. Syntaxe $image $x $y retour int imageColorAt(resource $image, int $x, int $y) Identifiant dimage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Abscisse du pixel. Ordonne du pixel. Identifiant de la couleur.

13. Les images et les animations Flash

Copier des parties dimage


Il existe quelques fonctions qui permettent de copier des parties dune image dans une autre.

imageCopy()
Cette fonction copie une partie dimage dans une autre. Syntaxe boolean imageCopy(resource $imageDest, resource $imageSource, int $xDest, int $yDest, int $xSource, int $ySource, int $largeurSource, int $hauteurSource) Identifiant de limage de destination. Identifiant de limage source. Abscisse sur limage de destination. Ordonne sur limage de destination.

$imageDest $imageSource $xDest $yDest

1065

Chapitre 13

Les images et les animations Flash

$xSource $ySource $largeurSource $hauteurSource retour

Abscisse sur limage source. Ordonne sur limage source. Largeur du morceau dimage rcuprer. Hauteur du morceau dimage rcuprer. TRUE.

Listing 13.16 : gd_copy.php


<?php header("Content-type: image/png"); $image1 = imageCreateFromJpeg("Thumbnailadrien.jpg"); $image2 = imageCreateTrueColor(60,80); imageCopy($image2, $image1, 0, 0, 30, 40, 60, 80); imagePNG($image2); imageDestroy($image1); imageDestroy($image2); ?> Figure 13.15 : Thumbnailadrien.jpg

13. Les images et les animations Flash

Figure 13.16 : Partie de limage copie

Format source et destination Il faut imprativement copier une image TrueColor dans une autre image TrueColor, ou cela entranera la panne du serveur. De manire gnrale, on ne peut copier une image que dans une autre de mme type. imageCreateFromJpeg() cre une image TrueColor.

imageCopyMerge()
Cette fonction permet de copier une image dans une autre et de les fusionner selon un coefficient. Syntaxe boolean imageCopyMerge(resource $imageDest, resource $imageSource, int $xDest, int $yDest, int $xSource, int $ySource, int $largeurSource, int $hauteurSource, int $coefficientTransparence)

1066

Images (utilisation de la bibliothque GD)

$imageDest $imageSource $xDest $yDest $xSource $ySource $largeurSource $hauteurSource

Identifiant de limage de destination. Identifiant de limage source. Abscisse sur limage de destination. Ordonne sur limage de destination. Abscisse sur limage source. Ordonne sur limage source. Largeur du morceau dimage rcuprer. Hauteur du morceau dimage rcuprer.

$coefficientTransparence Cest le coefficient qui permettra de mettre une des deux images en avant. Il est compris entre 0 et 100 ; 0 naura aucun effet, alors quutiliser 100 reviendra utiliser la fonction imageCopy(). retour TRUE.

Le script suivant utilise la fonction imageCopyMerge(). Il suffit de lui passer en paramtre le coefficient de transparence pour avoir limage Thumbnailadriencopy.jpg sur avion.jpg.

Listing 13.17 : gd_copymerge.php


<?php header("Content-type: image/png"); $image1 = imageCreateFromJpeg("Thumbnailadriencopy.jpg"); $image2 = imageCreateFromJpeg("avion.jpg"); imageCopyMerge($image2, $image1, 75, 0, 0, 0, 60, 80, $_GET["coef"]); imagePNG($image2); imageDestroy($image1); imageDestroy($image2); ?>

13. Les images et les animations Flash

Et voici une page HTML qui fait appel quatre fois ce script en variant le coefficient de transparence.

Listing 13.18 : gd_copymerge.html


<html> <head><title>ImageCopyMerge()</title></head> <body> <table> <tr> <td><img src="c13-copymerge.php?coef=0" /></td> <td><img src="c13-copymerge.php?coef=25" /></td> <td><img src="c13-copymerge.php?coef=50" /></td> <td><img src="c13-copymerge.php?coef=100" /></td> </tr> <tr align="center"> <td>0</td> <td>25</td>

1067

Chapitre 13

Les images et les animations Flash

<td>50</td> <td>100</td> </tr> </table> </body> </html> Figure 13.17 : Quelques exemples

13. Les images et les animations Flash

imageCopyMergeGray()
Cette fonction permet de copier une image dans une autre et de les fusionner selon un coefficient, tout en transformant les pixels de destination en noir et blanc. Syntaxe boolean imageCopyMergeGray(resource $imageDest, resource $imageSource, int $xDest, int $yDest, int $xSource, int $ySource, int $largeurSource, int $hauteurSource, int $coefficientTransparence) Identifiant de limage de destination. Identifiant de limage source. Abscisse sur limage de destination. Ordonne sur limage de destination. Abscisse sur limage source. Ordonne sur limage source. Largeur du morceau dimage rcuprer. Hauteur du morceau dimage rcuprer. Cest le coefficient qui permettra de mettre une des deux images en avant. Il est compris entre 0 et 100 ; 0 naura aucun effet, alors quutiliser 100 reviendra utiliser la fonction imageCopy(). TRUE.

$imageDest $imageSource $xDest $yDest $xSource $ySource $largeurSource $hauteurSource $coefficient Transparence

retour

1068

Images (utilisation de la bibliothque GD)

imageCopyResized()
Cette fonction permet de recopier et de changer la taille de la slection. Syntaxe boolean imageCopyResized(resource $imageDest, resource $imageSource, int $xDest, int $yDest, int $xSource, int $ySource, int $largeurDest, int $hauteurDest, int $largeurSource, int $hauteurSource) Identifiant de limage de destination. Identifiant de limage source. Abscisse sur limage de destination. Ordonne sur limage de destination. Abscisse sur limage source. Ordonne sur limage source. Largeur du morceau dimage aprs transformation. Hauteur du morceau dimage aprs transformation. Largeur du morceau dimage rcuprer. Hauteur du morceau dimage rcuprer. TRUE.

$imageDest $imageSource $xDest $yDest $xSource $ySource $largeurDest $hauteurDest $largeurSource $hauteurSource retour

13. Les images et les animations Flash

Le script suivant dforme une image :

Listing 13.19 : gd_copyresized.php


<?php header("Content-type: image/png"); $image1 = imageCreateFromJpeg("avion.jpg"); $image2 = imageCreateTrueColor(200,100); imageCopyResized($image2, $image1, 0, 0, 0, 0, 200, 100, 135, 180); imagePNG($image2); imageDestroy($image1); imageDestroy($image2); ?> Figure 13.18 : Limage de test

Figure 13.19 :

Le rsultat

1069

Chapitre 13

Les images et les animations Flash

imageCopyResampled()
Cette fonction permet de recopier et de changer la taille de la slection en utilisant une mthode non pixelise, contrairement imageCopyResize(). Syntaxe boolean imageCopyResampled(resource $imageDest, resource $imageSource, int $xDest, int $yDest, int $xSource, int $ySource, int $largeurDest, int $hauteurDest, int $largeurSource, int $hauteurSource) Identifiant de limage de destination. Identifiant de limage source. Abscisse sur limage de destination. Ordonne sur limage de destination. Abscisse sur limage source. Ordonne sur limage source. Largeur du morceau dimage aprs transformation. Hauteur du morceau dimage aprs transformation. Largeur du morceau dimage rcuprer. Hauteur du morceau dimage rcuprer. TRUE.

$imageDest $imageSource $xDest $yDest $xSource $ySource $largeurDest $hauteurDest $largeurSource $hauteurSource retour

13. Les images et les animations Flash

Le script suivant dforme une image :

Listing 13.20 : gd_copyresampled.php


<?php header("Content-type: image/png"); $image1 = imageCreateFromJpeg("avion.jpg"); $image2 = imageCreateTrueColor(200,100); imageCopyResampled($image2, $image1, 0, 0, 0, 0, 200, 100, 135, 180); imagePNG($image2); ImageDestroy($image1); ImageDestroy($image2); ?> Figure 13.20 : Limage de test

Figure 13.21 :

Le rsultat

1070

Images (utilisation de la bibliothque GD)

Pour copier une image avec un fond transparent sur une autre image, il faut copier non seulement les couleurs, mais aussi les canaux alpha. La fonction imageAlphaBlending() permet de le faire.

imageAlphaBlending()
Cette fonction permet de modifier la faon dont seront mlanges les couleurs dune image lors dune copie. Syntaxe $image $canauxAlpha retour boolean imageAlphaBlending (resource $image, boolean $canauxAlpha) Identifiant de limage sur laquelle on veut modifier cette proprit. TRUE pour garder les canaux alpha, FALSE sinon. Par dfaut, lors de la copie, les canaux alpha sont ignors. TRUE.

Listing 13.21 : gd_alpha.php


<?php $photo = imageCreateFromJPEG(Thumbnailadrien.jpg); imageAlphaBlending($photo, true); $logo = imageCreateFromPNG(logo.png); imageCopy($photo, $logo, 10, 120, 0, 0, 50, 30); imagePNG($photo); imageDestroy($photo); imageDestroy($logo); ?> Figure 13.22 : Rsultat du script

13. Les images et les animations Flash

En demandant garder les informations des canaux alpha, le fond transparent du logo a t conserv. Il est possible depuis PHP 4.3.0 de tourner une image dun angle quelconque, cela se fait trs simplement grce la fonction imagerotate().

1071

Chapitre 13

Les images et les animations Flash

ImageRotate()
Permet de tourner une image. Syntaxe : $imageSource $angle $couleurFond retour resource imageRotate(resource $imageSource, float $angle, int $couleurFond) Image tourner. Angle selon lequel on veut tourner limage (dans le sens inverse des aiguilles dune montre) Couleur de remplissage du fond. Limage tourne de langle voulu avec un fond de couleur $couleurFond.

Voici un petit exemple de rotation dune image de 30 degrs.

Listing 13.22 : gd_imagerotate.php


<?php header("Content-type: image/jpeg"); $image = imageCreateFromJPEG("niki.jpg"); $fondbleu = imageColorAllocate($image, 100, 100, 255); $image = imageRotate($image,30,$fondbleu); imageJPEG($image); ?> Figure 13.23 : Image tourne

13. Les images et les animations Flash

Taille dune image


Il existe deux fonctions permettant de rcuprer la largeur et la hauteur dune image : ce sont les fonctions imageSX() et imageSY(). Elles prennent toutes les deux comme paramtre lidentifiant dune image :

imageSX()
Retourne la largeur de limage. Syntaxe int imageSX(resource $image)

1072

Images (utilisation de la bibliothque GD)

$image retour

Identifiant de limage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Largeur de limage (en pixels).

imageSY()
Retourne la hauteur de limage. Syntaxe $image retour int imageSX(resource $image) Identifiant de limage tel que retourn par la fonction imageCreate() et la famille de fonctions imageCreateFromXX(). Hauteur de limage (en pixels).

Un exemple : lhistogramme
Nous allons effectuer, tape par tape, un script capable de dessiner dynamiquement un histogramme affichant la consommation de diffrents alcools (en litres) par Franais.

tape 1
cette tape, nous allons simplement dfinir une image de fond :

13. Les images et les animations Flash

Listing 13.23 : gd_histo1.php


<?php header("Content-type: image/png"); $image = imageCreateFromJPEG("fondhisto.jpg"); imagePNG($image); imageDestroy($image); ?>

Ici, nous rcuprons simplement limage fondhisto.jpg, qui sera limage de fond de lhistogramme.
Figure 13.24 :

tape 1

1073

Chapitre 13

Les images et les animations Flash

tape 2
Nous allons maintenant ajouter un titre :

Listing 13.24 : gd_histo2.php


<?php header("Content-type: image/png"); $image = imageCreateFromJPEG("fondhisto.jpg"); $largeur = imageSX($image); $hauteur = imageSY($image); $fontTitre = 5; $rouge = imageColorAllocate($image, 255, 0, 0); $titre = "Consommation alcool"; imageString($image, $fontTitre, ($largeur-ImageFontWidth($fontTitre)*strlen("$titre"))/2, 0, $titre, $rouge); imagePNG($image); imageDestroy($image); ?>

13. Les images et les animations Flash

partir du script de ltape 1, nous rcuprons la largeur et la hauteur de limage, puis nous dfinissons une police dcriture parmi les cinq mises disposition par PHP. Nous allouons une nouvelle couleur, puis nous prenons soin dafficher le texte centr sur limage.
Figure 13.25 :

tape 2

tape 3
Maintenant, nous allons tracer les rectangles. Nous avons choisi de passer les donnes dans ladresse de la forme :
c13-histo.php?valeur1;libelle1;valeur2;libelle2;valeur3;libelle3

1074

Images (utilisation de la bibliothque GD)

Listing 13.25 : gd_histo3.php


<?php header("Content-type: image/png"); $image = imageCreateFromJPEG("fondhisto.jpg"); $largeur = imageSX($image); $hauteur = imageSY($image); $fontTitre = 5; $rouge = imageColorAllocate($image, 255, 0, 0); $couleur_barre = imageColorAllocate($image,0,255,0); $titre = "Consommation alcool"; imageString($image, $fontTitre, ($largeur-ImageFontWidth($fontTitre)*strlen("$titre"))/2, 0, $titre, $rouge); $valeurs = explode(";", $argv[0]); $largeurBarre = (int)(($largeur)/(1.5*sizeof($valeurs)/2+0.5)); $max = 0; for ($i=0; $i<sizeof($valeurs)/2; $i++) { if ($valeurs[$i*2]>$max) $max = $valeurs[$i*2]; } for ($i=0;$i<sizeof($valeurs)/2;$i++) { $x = (int)($largeurBarre*(0.5+$i*1.5)); $hauteurBarre = (int)(($valeurs[$i*2]*($hauteur-40))/$max); $imageBarre = imageCreate($largeurBarre, $hauteurBarre); $fondTemporaire = imageColorAllocate($imageBarre, 255, 255, 255); imageCopyMerge($image, $imageBarre, $x, $hauteur-15-$hauteurBarre, 0, 0, $largeurBarre, $hauteurBarre, 70); imageDestroy($imageBarre); } imagePNG($image); imageDestroy($fondBarre); imageDestroy($image); ?>

13. Les images et les animations Flash

Aprs avoir rcupr les valeurs passes de lURL dans un tableau, nous calculons la largeur en pixels que devra avoir chacune des barres. Ensuite, afin dexploiter au mieux lespace vertical, il faut rechercher la valeur maximale parmi celles fournies. La seconde boucle for dessine un un les rectangles de lhistogramme. Nous avons choisi ici de dfinir une image pour chacun des rectangles, afin de pouvoir faire un effet de transparence grce imageCopyMerge().

1075

Chapitre 13

Les images et les animations Flash

Figure 13.26 : tape 3 c13-histo3.php?60;vin;39.6;biere;2.4;spiritueux;8.6;cidre

tape 4
Pour ce script final, nous utiliserons une petite image PNG qui est un dgrad allant du vert au transparent. Par rapport au script prcdent, limage des barres est passe en TrueColor.

13. Les images et les animations Flash

Listing 13.26 : gd_histo4.php


<?php header("Content-type: image/png"); $image = imageCreateFromJPEG("fondhisto.jpg"); $largeur = imageSX($image); $hauteur = imageSY($image); $fontTitre = 5; $rouge = imageColorAllocate($image, 255, 0, 0); $couleur_barre = imageColorAllocate($image,0,255,0); $titre = "Consommation alcool"; imageString($image, $fontTitre, ($largeur-ImageFontWidth($fontTitre)*strlen("$titre"))/2, 0, $titre, $rouge); $valeurs = explode(";", $argv[0]); $largeurBarre = (int)(($largeur)/(1.5*sizeof($valeurs)/2+0.5)); $max = 0; for ($i=0; $i<sizeof($valeurs)/2; $i++) { if ($valeurs[$i*2]>$max) $max = $valeurs[$i*2]; } $fondBarre = imageCreateFromPNG("barhisto.png"); for ($i=0;$i<sizeof($valeurs)/2;$i++) { $x = (int)($largeurBarre*(0.5+$i*1.5)); $hauteurBarre = (int)(($valeurs[$i*2]*($hauteur-40))/$max); $imageBarre = imageCreateTrueColor($largeurBarre, $hauteurBarre);

1076

Images (utilisation de la bibliothque GD)

imageCopy($imageBarre, $image, 0, 0, $x, $hauteur-15-$hauteurBarre, $largeurBarre, $hauteurBarre); imageAlphaBlending($imageBarre, true); imageCopyResampled($imageBarre, $fondBarre, 0, 0, 0, 0, $largeurBarre, $hauteurBarre, imageSX($fondBarre), imageSY($fondBarre)); imageCopyMerge($image, $imageBarre, $x, $hauteur-15-$hauteurBarre, 0, 0, $largeurBarre, $hauteurBarre, 90); imageDestroy($imageBarre); imageStringUp($image, 3, $x, $hauteur-17, $valeurs[$i*2+1], urldecode($rouge)); } imagePNG($image); imageDestroy($fondBarre); imageDestroy($image); ?>

Pour rendre leffet souhait, il va nous falloir agrandir limage qui nous servira dessiner les rectangles, puis copier cette image sur limage de fond. Il faudra, en outre, prserver leffet de transparence dfini dans limage servant pour les rectangles. Tout dabord, nous avons cr une image TrueColor puis recopi la partie de limage de fond afin de pouvoir recrer par la suite leffet de transparence.

13. Les images et les animations Flash

Ensuite, nous devons prciser lutilisation des couches alpha, puis copier sur cette image un agrandissement du fond des rectangles. Il ne reste plus qu coller cette image sur limage de fond, en utilisant ventuellement, comme ici, un autre effet de transparence. Nous avons galement crit verticalement les libells des btons. Au final, voici ce que lon obtient pour lappel suivant :
gd_histo4.php?60;vin;39.6;biere;2.4;spiritueux;8.6;cidre Figure 13.27 : tape 4 c13-histo4.php?60;vin;39.6;biere;2.4;spiritueux;8.6;cidre

1077

Chapitre 13

Les images et les animations Flash

Rcuprer des informations sur un chier image


Il existe dautres fonctions ne faisant pas partie de la bibliothque GD, mais permettant de rcuprer des informations sur les fichiers images. Cest tout dabord la fonction getImageSize().

getImageSize()
Retourne la taille et le type dune image. Syntaxe $nomFichier retour array getImageSize(string $nomFichier [, array $info]) Nom du fichier image. Tableau index contenant : lindex 0, la largeur de limage (en pixels). lindex 1, la hauteur de limage (en pixels). lindex 2, le code du format de limage (1 = GIF, 2 = JPG, 3 = PNG, 4 = SWF, 5 = PSD, 6 = BMP, 7 = TIFF (ordre des octets intel), 8 = TIFF (ordre des octets motorola), 9 = JPC, 10 = JP2, 11 = JPX). lindex 3, une chane de caractres width=".." height="..." pouvant tre directement intgre dans une balise <img>.

13. Les images et les animations Flash

Rcuprer des informations EXIF sur un chier image


Dautres fonctions non originaires de la bibliothque GD mais EXIF permettent de rcuprer des informations sur les fichiers images. Les informations EXIF sont gnralement inscrites dans les images prises par des appareils photo numriques. On peut retrouver dans ces informations la rsolution, louverture, la focale Ces donnes varient dun constructeur lautre.

Installation
Sous Windows
Avec larchive du PHP Group
Vous devrez vous assurer davoir le fichier php_exif.dll (livr dans larchive PHP distribue par le PHP Group) dans votre rpertoire contenant les extensions PHP, et ajouter ou dcommenter une ligne
extension=php_exif.dll

Avec EasyPHP
Avec EasyPHP, le support dEXIF est activ automatiquement.

1078

Images (utilisation de la bibliothque GD)

Sous Linux
Vous devrez simplement recompiler PHP avec loption enableexif.

Vrication
Vous pouvez vrifier le succs de lopration avec un script contenant simplement la ligne <?php phpinfo(); ?> qui devra afficher :
Figure 13.28 :

phpinfo()

Utilisation

exif_imageType
Permet de dterminer le type dune image.

13. Les images et les animations Flash

Syntaxe $nomFichier retour

int exif_imageType(string $nomFichier) Nom et chemin du fichier image tudier. Type de limage. IMAGETYPE_GIF (= 1) au format GIF. IMAGETYPE_JPG (= 2) au format JPEG. IMAGETYPE_PNG (= 3) au format PNG. IMAGETYPE_SWF (= 4) au format SWF. IMAGETYPE_PSD (= 5) au format PSD. IMAGETYPE_BMP (= 6) au format BMP. IMAGETYPE_TIFF_II (= 7) au format TIFF II. IMAGETYPE_TIFF_MM (= 8) au format TIFF MM. IMAGETYPE_JPC (= 9) au format JPC. IMAGETYPE_JP2 (= 10) au format JP2. IMAGETYPE_JPX (= 11) au format JPX.

exif_read_data()
Cette fonction permet de lire len-tte EXIF dune image JPEG ou TIFF. (Disponible depuis PHP 4.2.0). Syntaxe $nomFichier array exif_read_data(string $nomFichier [, string $informations [, boolean $tableaux [, boolean $thumbnail]]]) Nom du fichier image (ne peut pas tre une URL).

1079

Chapitre 13

Les images et les animations Flash

$informations

Liste des informations (spares par des virgules) que vous souhaitez extraire. FILE : Des informations sur le fichier de limage (voir exemple) COMPUTED : Des informations sur la taille de limage entre autre. ANY_TAG IFD0 THUMBNAIL : Toutes les informations sur laperu dimage. COMMENT : Eventuel commentaire sur la photo EXIF : Donnes concernant essentiellement les photos numriques. TRUE si vous souhaitez que les informations soient regroupes par thme dans des tableaux, FALSE (par dfaut) sinon. Les informations portant des noms pouvant crer des conflits seront quoi quil arrive regroupes dans des tableaux. TRUE si la fonction doit lire le thumbnail (vignette), FALSE sinon. Tableau associatif.

$tableaux

$thumbnail retour

Voici un exemple qui permet de lire tout len-tte hormis laperu :

Listing 13.27 : exif1.php


<?php $fichier="adrien.jpg"; $exifInfos = read_exif_data($fichier); echo $fichier.":<br />\n"; foreach($exifInfos as $cle=>$info) { if($cle == "Thumbnail"){ $file = fopen("thumbnail","wb"); fwrite($file, $info); fclose($file); echo "<img src=thumbnail /><br />\n"; } else { echo "$cle: $info<br />\n"; } } ?> Figure 13.29 : Photo de test : adrien.jpg

13. Les images et les animations Flash

Voici ce qui est retourn dans le cas de cette photo (limagette a t retire) :
adrien.jpg: FILE.FileName: adrien.jpg

1080

Images (utilisation de la bibliothque GD)

FILE.FileDateTime: 1027957704 FILE.FileSize: 561805 FILE.FileType: 2 FILE.MimeType: image/jpeg FILE.SectionsFound: ANY_TAG, IFD0, THUMBNAIL, EXIF, MAKERNOTE COMPUTED.html: width="1440" height="2160" COMPUTED.Height: 2160 COMPUTED.Width: 1440 COMPUTED.IsColor: 1 COMPUTED.ByteOrderMotorola: 0 COMPUTED.CCDWidth: 15mm COMPUTED.ExposureTime: 0.017 s (1/60) COMPUTED.ApertureFNumber: f/4.5 COMPUTED.UserComment: COMPUTED.UserCommentEncoding: UNDEFINED COMPUTED.Thumbnail.FileType: 2 COMPUTED.Thumbnail.MimeType: image/jpeg COMPUTED.Thumbnail.Height: 160 COMPUTED.Thumbnail.Width: 120 IFD0.Make: Canon IFD0.Model: Canon EOS D30 IFD0.Orientation: 1 IFD0.XResolution: 180/1 IFD0.YResolution: 180/1 IFD0.ResolutionUnit: 2 IFD0.DateTime: 2001:12:25 06:35:11 IFD0.YCbCrPositioning: 1 IFD0.Exif_IFD_Pointer: 196 THUMBNAIL.Compression: 6 THUMBNAIL.XResolution: 180/1 THUMBNAIL.YResolution: 180/1 THUMBNAIL.ResolutionUnit: 2 THUMBNAIL.JPEGInterchangeFormat: 1244 THUMBNAIL.JPEGInterchangeFormatLength: 7537 <<ICI NOUS AURIONS LIMAGETTE>> EXIF.ISOSpeedRatings: 100 EXIF.ExifVersion: 0200 EXIF.DateTimeOriginal: 2001:12:25 06:35:11 EXIF.DateTimeDigitized: 2001:12:25 06:35:11 EXIF.ComponentsConfiguration: [1] EXIF.ShutterSpeedValue: 387114/65536 EXIF.ApertureValue: 284416/65536 EXIF.ExposureBiasValue: 0/6 EXIF.FocalLength: 85/1 EXIF.UserComment: EXIF.FlashPixVersion: 0100 EXIF.ColorSpace: 1 EXIF.ExifImageWidth: 1440 EXIF.ExifImageLength: 2160 EXIF.FocalPlaneXResolution: 1440000/595 EXIF.FocalPlaneYResolution: 2160000/892 EXIF.FocalPlaneResolutionUnit: 2

13. Les images et les animations Flash 1081

Chapitre 13

Les images et les animations Flash

MAKERNOTE.ModeArray: Array MAKERNOTE.UndefinedTag:0x0002: Array MAKERNOTE.ImageInfo: Array MAKERNOTE.ImageType: IMG:EOS D30 JPEG MAKERNOTE.FirmwareVersion: Firmware Version 00.00 MAKERNOTE.ImageNumber: 1979721 MAKERNOTE.OwnerName: MAKERNOTE.Camera: 422051855 MAKERNOTE.CustomFunctions: Array

Bien entendu, ces informations ne sont valables que pour cet appareil photo CANON EOS D30). Pour un autre appareil photo, les informations fournies seront probablement diffrentes, et cela sera encore plus vrai pour une autre marque dappareil photo.

exif_thumbnail()
Retourne laperu contenu dans len-tte EXIF sil y en a un. Syntaxe string exif_thumbnail(string $nomFichier[, int &$largeur[, &$hauteur]]) Nom du fichier dont vous souhaitez extraire laperu. Rfrence vers la variable $largeur ; cette variable sera assigne par la valeur de la largeur de limage. Rfrence vers la variable $hauteur ; cette variable sera assigne par la valeur de la hauteur de limage. Aperu de limage (thumbnail).

13. Les images et les animations Flash

$nomFichier $largeur $hauteur retour

13.2. Les animations Flash


Comme vous le savez certainement, il est possible, grce la technologie Flash de Macromedia, de raliser des animations multimdias interactives. Ces animations peuvent tre intgres dans une page web, pour peu que le navigateur intgre lextension (plugin) ad hoc. Ces animations sont gnralement construites une fois pour toutes, partir dun logiciel propritaire. Mais, grce aux bibliothques dont dispose PHP, il est possible de gnrer ces animations au vol, ce qui permettra (mme si ce nest pas vraiment le cas dans les exemples suivants) de faire des animations qui varient en fonction du temps, de lutilisateur, ou de tout autre paramtre dont le serveur aura connaissance. Pour parvenir ce rsultat, PHP propose un bibliothque appele Ming qui, bien que considre comme exprimentale, fonctionne dj merveille (il lui manque quand mme encore quelques fonctionnalits).

1082

Les animations Flash

Installation
La bibliothque Ming est disponible aussi bien sous Windows que sous Linux.

Sous Windows
Avec larchive du PHP Group
Vous devrez vous assurer davoir le fichier php_ming.dll (livr dans larchive PHP distribue par le PHP Group) dans votre rpertoire contenant les extensions PHP, et ajouter ou dcommenter une ligne
extension=php_ming.dll

Avec EasyPHP
Avec EasyPHP, le support de la bibliothque Ming est activ automatiquement.

Sous Linux
Dans un premier temps, vous devrez vous procurer les sources de la bibliothque. Celles-ci sont disponibles ladresse http://ming.sourceforge.net / (mais galement sur le CD-ROM fourni). Vous pourrez alors (par exemple, sous le rpertoire /usr/local/src/lib) taper les commandes suivantes :
# gunzip ming-0.2a.tgz # tar xvf ming-0.2a.tar

13. Les images et les animations Flash

afin de dcompresser les sources.


# cd ming-0.2a # make

Vous voil maintenant avec un fichier libming.so. Copiez libming.so sous /usr/local/lib.
# cp libming.so /usr/local/lib/.

Copiez ming.h sous /usr/local/include.


# cp ming.h /usr/local/include/.

Puis, vous devez recompiler PHP avec loption withming=/usr/local.

Problme dinstallation et Apache Si la librairie est mal installe, vous aurez certainement des messages du genre "child pid ... exit signal segmentation fault" dans le fichier de trace des erreurs dApache.

1083

Chapitre 13

Les images et les animations Flash

Vrication
Vous pouvez vous assurer du bon droulement de lopration dinstallation en excutant un simple script <?php phpinfo(); ?> devant afficher :
Figure 13.30 :

phpinfo()

Utilisation
Comme tout type danimation, les animations Flash sont composes dune srie de vues (en anglais, frames), et cest la succession de ces vues qui donne la sensation de mouvement. Chacune de ces vues contient un dessin "complexe", ralis par la superposition de couches contenant des dessins "lmentaires". On pourra ainsi avoir un arrire-plan, un plan principal, un premier plan, etc. Par dfaut, chaque nouvelle vue contiendra lensemble des dessins de la vue prcdente (ce qui vite, par exemple, de toujours redfinir larrire-plan). Libre ensuite au ralisateur dajouter, de supprimer ou de dplacer, entre deux vues, certains lments pour que, au final, lanimation donne une sensation de mouvement.

13. Les images et les animations Flash

Figure 13.31 :

Exemple dune courte animation


Notez toutefois que le droulement de lanimation nest pas ncessairement linaire. Comme lon peut introduire de linteractivit, il est tout moment possible de revenir une vue prcdente ou de sauter une tout autre vue.

Le schma de base
Lanimation Flash pourra, au choix, tre directement envoye au navigateur ou stocke dans un fichier. Ainsi, la cration dun animation compte trois actions principales :
j j j

Cration dun objet Animation (ou Film) par instanciation de lobjet SWFMovie() (qui ne ncessite aucun paramtre). Cration des objets qui vont constituer lanimation, et association lobjet Animation. Appel la mthode output() de lobjet Animation pour un envoi direct au navigateur, ou appel la mthode save($nomFichier) de lobjet Animation pour une sauvegarde de lanimation dans un fichier.

SWFMovie
Instancie un objet animation Flash.

1084

Les animations Flash

Syntaxe $version retour

SWFMovie SWFMovie(int $version) Numro de version de Flash. Par dfaut 4. Objet SWFMovie.

SWFMovie->output()
Envoie le code de lanimation directement au navigateur. Syntaxe retour int output(void) La signification du code retour nest pas connue.

SWFMovie->save()
Sauve le code de lanimation dans un fichier. Syntaxe $nomFichier retour int save(string $nomFichier) Nom du fichier de sauvegarde de lanimation. La signification du code retour nest pas connue. En cas derreur, le script lve une erreur de type "fatale" et sarrte.

13. Les images et les animations Flash

Envoi direct au navigateur Si vous dcidez denvoyer directement le contenu de lanimation Flash au navigateur, vous devez faire un appel la fonction header("Contenttype: application/ xshockwaveflash") avant tout appel la mthode output(). Vous pouvez choisir ici entre deux rgles de codage : Vous pouvez commencer directement le script par lappel la fonction header(). Ainsi, la lecture du code source, lobjectif du script sera de gnrer une animation Flash. Cependant, la contrepartie est que tout ventuel message derreur lev par les fonctions appeles aprs header() sera invisible, car interprt comme du code Flash. Vous pouvez galement placer linstruction header() juste avant lappel la mthode output().
Au choix :
<?php header("Content-type: application/x-shockwave-flash"); $anim = new Movie(); // Construction proprement dite de lanimation

1085

Chapitre 13

Les images et les animations Flash

?>

$anim->output();

ou
<?php $anim = new Movie(); // Construction proprement dite de lanimation header("Content-type: application/x-shockwave-flash"); $anim->output();

?>

Prsentation des vues


Une fois la cration de lanimation initialise avec linstanciation de lobjet SWFMovie, le gnrateur est prt composer la premire vue. partir de l, toutes les oprations sappliqueront donc la premire vue. Une fois cette vue ralise (cf. composition des vues), il faut appeler la mthode nextFrame() de lobjet SWFMovie pour valider la vue qui vient dtre cre. Cette fonction ne ncessite aucun paramtre, et ne retourne rien ; mais elle a galement pour effet dincrmenter le compteur de vues. Ainsi, toutes les oprations suivantes sappliqueront non pas la premire, mais la seconde vue, et ainsi de suite.

13. Les images et les animations Flash

SWFMovie()->nextFrame()
Valide la vue en cours et passe la cration de la suivante. Syntaxe void nextFrame(void)

Composition des vues


Chaque dessin qui compose une vue est ralis partir dobjets lmentaires (objets au sens informatique du terme). Parmi ces objets nous trouvons :
j j j j

Les textes ; Les formes "complexes" (bases sur des lignes, courbes, etc.) ; Les boutons ; Les zones de saisie de texte.

Certains de ces objets vont utiliser dautres objets tels que :


j j j

Les polices de caractres ; Les images ; Les dgrads ;

1086

Les animations Flash

Les remplissages.

De mme, il existe dautres objets de plus haut niveau comme :


j j

Les morphing ; Les sous-animations.

Une fois instanci, lobjet pourra alors tre associ la vue en cours par un simple appel la mthode add() de lobjet SWFMovie.

SWFMovie->add()
Ajoute un objet la vue courante de lanimation. Les objets graphiques sempilent sur la couche suprieure aux prcdents. Autrement dit, le dernier objet ajout se retrouve en premier plan. Par la suite, nous verrons quil est galement possible dajouter des objets qui ne sont pas des objets graphiques. Syntaxe $objet SWFDisplayItem add(mixed $objet) Objet ajouter la "sous-animation". Ce peut tre un objet SWFText, SWFTextField, SWFShape, SWFMorph, SWFButton, SWFAction ou SWFSprite. Un objet SWFDisplayItem uniquement dans le cas des objets graphiques. Comme nous le verrons par la suite, cela permet de placer, transformer, etc. lobjet.

13. Les images et les animations Flash

retour

Il est possible dajouter plusieurs fois le mme objet (la mme reprsentation graphique) et dobtenir ainsi plusieurs instances de SWFDisplayItem. Ce qui permet chacun de ces objets davoir sa propre vie. Les proprits de lanimation peuvent tre dfinies par appel aux mthodes suivantes :

SWFMovie->setDimension()
Dtermine les dimensions pour lesquelles lanimation a t conue. Il sagit des dimensions "idales", mais cela nempchera pas lanimation dtre affiche dans une taille suprieure si on le lui demande (via les attributs "width" et "height" de la balise HTML par exemple). Syntaxe $largeur $hauteur void setDimension(int $largeur, int $hauteur) Largeur idale de lanimation, en pixels. Hauteur idale de lanimation, en pixels.

1087

Chapitre 13

Les images et les animations Flash

SWFMovie->setBackground()
Dfinit la couleur de fond de lanimation. Syntaxe $rouge $vert $bleu void setBackground(int $rouge, int $vert, int $bleu) Composante rouge de la couleur de fond. Valeur comprise entre 0 et 255. Composante verte de la couleur de fond. Valeur comprise entre 0 et 255. Composante bleue de la couleur de fond. Valeur comprise entre 0 et 255.

SWFMovie->setRate()
Dfinit la vitesse de dfilement de lanimation. La vitesse de dfilement est toutefois dpendante de la vitesse daffichage et de traitement des instructions Flash. De ce fait, la vitesse observe peut tre plus lente que prvue, ou bien quelques vues peuvent ne pas tre affiches. Syntaxe void setRate(double $vitesseDefilement)

13. Les images et les animations Flash

$vitesseDefilement Vitesse de dfilement de lanimation en nombre dimages par seconde.

Listing 13.28 : ming_01.php


<?php // // // // // Cette animation Flash ne fait rien du tout Ce script prsente simplement la structure classique dune animation Flash

// Instanciation de lobjet animation $anim = new SWFMovie(); // // // // Dfinition des principaux paramtres - Dimension - Couleur de fond - Vitesse de dfilement

$anim->setDimension(100, 100); $anim->setBackground(255, 255, 255); $anim->setRate(1); // // Ici, on pourrait trouver // une srie dinstanciations dobjets // disons $objet1, $objet2, etc... //

1088

Les animations Flash

// Ensuite, on peut // composer la vue 1 $anim->add($objet1); $anim->add($objet2); // Valider la vue 1 $anim->nextFrame(); // Pour ventuellement passer // la composition de la vue 2. // O on pourra ajouter dautres objets $anim->add($objet3); $anim->nextFrame(); // Et enfin, on pourra envoyer le flux // directement au navigateur // aprs lavoir prvenu que ce qui suit // est une animation Flash header("Content-type: application/x-shockwave-flash"); $anim->output();

13. Les images et les animations Flash

?>

Lobjet texte (Text)


Les textes sinstancient par un appel au constructeur SWFText().

SWFText
Objet texte. Syntaxe SWFText SWFText(void) Cet objet propose une srie de mthodes permettant de dfinir la police qui doit tre utilise, lendroit o doit tre positionn le texte et, videmment, le texte qui doit tre affich.

SWFText->setFont()
Prcise quelle police de caractres doit tre utilise pour le texte qui vient. Syntaxe $police void setFont(SWFFont $police) Objet SWFFont (voir chapitre suivant).

1089

Chapitre 13

Les images et les animations Flash

SWFText->setHeight()
Prcise quelle hauteur la police de caractres doit prendre pour le texte qui vient. Syntaxe $hauteur void setHeight(int $hauteur) Hauteur de la police de caractres. Lunit de mesure est celle de lanimation (autrement dit en pixels si les dimensions "prconises" pour lanimation sont respectes).

SWFText->setColor()
Prcise la couleur utiliser pour le texte qui vient. Tant quaucun appel cette mthode nest fait, le texte est transparent. Syntaxe $rouge $vert $bleu $alpha void setColor(int $rouge, int $vert, int $bleu, [$alpha]) Composante rouge de la couleur du texte. Valeur comprise entre 0 et 255. Composante verte de la couleur du texte. Valeur comprise entre 0 et 255. Composante bleue de la couleur du texte. Valeur comprise entre 0 et 255. Composante Alpha (transparence) de la couleur du texte. Valeur optionnelle, comprise entre 0 (couleur totalement transparente) et 255 (couleur totalement opaque).

13. Les images et les animations Flash

SWFText->moveTo()
Positionne le texte qui vient. Syntaxe $x $y void moveTo(int $x, int $y) Coordonne x du prochain texte (laxe des abscisses est dirig de la gauche vers la droite). Coordonne y du prochain texte (laxe des ordonnes est dirig du haut vers le bas).

SWFText->addString()
Complte le texte afficher. Le texte sera affich avec les proprits dfinies par les mthodes vues prcdemment (et appeles avant addString()). Syntaxe $texte void addString(string $texte) Texte ajouter lobjet SWFText.

1090

Les animations Flash

En cours de dveloppement Il existe une mthode setSpacing() cense modifier lespace entre les caractres, mais dans la version teste, cette mthode ne fonctionne pas.
Voici ce que, dj, vous pouvez faire :

Listing 13.29 : ming_text01.php


<?php // Initialisation dune nouvelle animation // un rythme trs lger 1 image/seconde // pour bien dtailler la scne $anim = new SWFMovie(); $anim->setDimension(100, 100); $anim->setBackground(255, 255, 255); $anim->setRate(1); // // // // // // // Instanciation dun nouvel objet police Avant dexecuter ce script, pensez vrifier que vous possdez bien cette police dans votre environnement et que le chemin vers le fichier .fdb est bien conforme votre environnement. Sinon, vous risquez le crash de votre navigateur

13. Les images et les animations Flash

$police = new SWFFont("ming_polices/arial.fdb");

// Cration de lobjet texte1 $texte1 = new SWFText(); // Opration indispensable // prciser la police de caractre du texte $texte1->setFont($police); // Selection de la couleur du texte $texte1->setColor(0, 0, 0); // Positionnement du texte $texte1->moveTo(10, 10); $texte1->setHeight(10); $texte1->addString("Faire du Flash ..."); // Cration de lobjet texte2 $texte2 = new SWFText(); $texte2->setFont($police); $texte2->setColor(0, 0, 0); $texte2->moveTo(10, 30); $texte2->setHeight(20);

1091

Chapitre 13

Les images et les animations Flash

$texte2->addString("... avec PHP ?"); $texte2->setHeight(20); // Cration de lobjet texte3 // centr $texte3 = new SWFText(); $texte3->setFont($police); $texte3->setColor(0, 0, 0); $chaine="Finallement, cest ..."; $texte3->setHeight(5); $texte3->moveTo(50-$texte3->getWidth($chaine)/2, 40); $texte3->addString($chaine); // Cration de lobjet texte4 // avec des lettres de plus en plus grosses $texte4 = new SWFText(); $texte4->setFont($police); $texte4->setColor(255, 0, 0); $texte4->moveTo(10, 70); $texte4->setHeight(10); $texte4->addString("Fa"); $texte4->setHeight(20); $texte4->addString("ci"); $texte4->setHeight(30); $texte4->addString("le !"); // La premire vue ne contiendra // que le premier texte $anim->add($texte1); $anim->nextFrame(); // Puis la seconde vue sera enrichie // dun second texte $anim->add($texte2); $anim->nextFrame(); // puis dun troisime $anim->add($texte3); $anim->nextFrame(); // et le texte sera complet // dans la dernire vue $anim->add($texte4); // Bien quil sagisse de la dernire vue // il est indispensable de faire appel // nextFrame(); $anim->nextFrame(); header("Content-type: application/x-shockwave-flash"); $anim->output();

13. Les images et les animations Flash

?>

1092

Les animations Flash

Prciser une police de caractres Il ny a pas de police par dfaut. Avant dajouter un texte, il faut obligatoirement indiquer quelle police devra tre utilise. Couleur par dfaut Le texte tant par dfaut transparent, si vous ne voyez rien lcran, cest peut-tre tout simplement que vous avez oubli de faire un appel la mthode setColor().

Lobjet champ texte (TextField)


Les champs textes sinstancient par un appel au constructeur SWFTextField().

SWFTextField
Objet champ texte. Syntaxe $options SWFTextField SWFTextField([int $options]) Paramtre optionnel prcisant le comportement et le rendu de lobjet. Cet argument peut prendre une ou des valeurs (en les combinant par loprateur logique OU "|") parmi : SWFTEXTFIELD_NOEDIT : champ texte non ditable. SWFTEXTFIELD_PASSORD : champ mot de passe (les caractres sont remplacs laffichage par des *). SWFTEXTFIELD_DRAWBOX : trace le contour du champ texte. SWFTEXTFIELD_MULTILINE : cre un champ texte multi-ligne (selon les dimensions du champ texte). SWFTEXTFIELD_WORDWRAP : force le retour la ligne des mots. SWFTEXTFIELD_NOSELECT : champ texte que lon ne peut pas slectionner (valeur par dfaut).

13. Les images et les animations Flash

Cet objet propose une srie de mthodes permettant de dfinir la police qui doit tre utilise, la taille que doit avoir le champ texte, etc.

SWFTextField->setBounds()
Prcise la largeur et la hauteur du champ texte. Syntaxe $largeur $hauteur void setBounds(int $largeur, int $hauteur) Largeur du champ texte. Hauteur du champ texte.

1093

Chapitre 13

Les images et les animations Flash

SWFTextField->setColor()
Prcise la couleur utiliser pour le texte qui sera ajout au champ texte. Tant quaucun appel cette mthode nest fait, le texte est noir. Syntaxe $rouge $vert $bleu $alpha void setColor(int $rouge, int $vert, int $bleu, [$alpha]) Composante rouge de la couleur du texte. Valeur comprise entre 0 et 255. Composante verte de la couleur du texte. Valeur comprise entre 0 et 255. Composante bleue de la couleur du texte. Valeur comprise entre 0 et 255. Composante Alpha (transparence) de la couleur du texte. Valeur optionnelle comprise entre 0 (couleur totalement transparente) et 255 (couleur totalement opaque).

SWFTextField->setFont()
Prcise quelle police de caractres doit tre utilise pour le texte du champ texte.

13. Les images et les animations Flash

Syntaxe $police

void setFont(SWFFont $police) Objet SWFFont (voir chapitre suivant).

SWFTextField->setHeight()
Prcise quelle hauteur de police de caractres doit tre utilise pour le texte du champ texte. Syntaxe $hauteur void setHeight(int $hauteur) Hauteur de la police de caractres. Lunit de mesure est celle de lanimation (autrement dit en pixels si les dimensions "prconises" pour lanimation sont respectes).

SWFTextField->align()
Prcise lalignement du texte dans le champ texte. Syntaxe $alignement void align(int $alignement) $alignement peut prendre une valeur parmi : SWFTEXTFIELD_ALIGN_LEFT pour un alignement gauche. SWFTEXTFIELD_ALIGN_RIGHT pour un alignement droite. SWFTEXTFIELD_ALIGN_CENTER pour un texte centr. SWFTEXTFIELD_ALIGN_JUSTIFY pour un texte justifi.

1094

Les animations Flash

SWFTextField->setLeftMargin()
Prcise la largeur de la marge gauche (espace sparant le texte du bord gauche du champ texte). Syntaxe $largeur void setLeftMargin(int $largeur) Largeur de la marge.

SWFTextField->setRightMargin()
Prcise la largeur de la marge droite (espace sparant le texte du bord droit du champ texte). Syntaxe $largeur void setRightMargin(int $largeur) Largeur de la marge.

SWFTextField->setMargins()
Prcise la largeur des marges gauche (espace sparant le texte du bord gauche du champ texte) et droite (espace sparant le texte du bord droit du champ texte). Syntaxe $largeurGauche $largeurDroite void setMargins(int $largeurGauche, int $largeurDroite) Largeur de la marge gauche. Largeur de la marge droite.

13. Les images et les animations Flash

SWFTextField->setIndentation()
Prcise la largeur du retrait droite de la premire ligne du champ texte. Syntaxe $largeur void setIndentation(int $largeur) Largeur du retrait droite.

SWFTextField->setLineSpacing()
Prcise lespacement entre deux lignes de texte du champ texte. Syntaxe $hauteur void setLigneSpacing(int $hauteur) Espacement entre deux lignes.

1095

Chapitre 13

Les images et les animations Flash

SWFTextField->addString()
Prcise ou ajoute un texte au contenu du champ texte. Syntaxe $texte void addString(string $texte) Texte ajouter au champ texte.

Lobjet Police (Font)


Les polices de caractres sinstancient par un appel au constructeur SWFFont.

SWFFont
Objet police de caractres. Syntaxe SWFFont SWFFont(string $fichierPolice) Chemin vers un fichier .dbf contenant les caractristiques de la police de caractres. $fichierPolice

13. Les images et les animations Flash

Les polices Il ny a pas de police fournie par dfaut avec la bibliothque Ming. Il vous faudra donc soit en crer vous-mme, soit en rcuprer sur Internet. Par exemple ladresse : http://www.opaque.net/wiki/index.php?MingFonts.
Il ny a pas de mthode destine modifier les proprits des polices. Mais il est en revanche possible den rcuprer les proprits avec :

SWFFont->getWidth()
Indique la largeur quoccupera, dans cette police, le texte indiqu. Comme il sagit l de la largeur dans la taille par dfaut, il est prfrable de faire appel la mthode getWidth() de lobjet SWFText, et seulement aprs avoir appel la mthode setHeight() associe. Syntaxe $texte retour int getWidth(string $texte) Texte dont on veut mesurer la largeur dans cette police. Largeur du texte dans cette police.

1096

Les animations Flash

SWFFont->getAscent()
Retourne la distance qui spare la ligne de base du haut de la lettre la plus haute dans cette police (distance reprsente par un a dans le schma suivant). Syntaxe retour int getAscent(void) Distance qui spare la ligne de base du haut de la lettre la plus haute dans cette police.

SWFFont->getDescent()
Retourne la distance qui spare la ligne de base du bas de la lettre descendant le plus bas dans cette police (distance reprsente par un d dans le schma suivant). Syntaxe retour int getDescent(void) Distance qui spare la ligne de base du bas de la lettre descendant le plus bas dans cette police.

13. Les images et les animations Flash

SWFFont->getLeading()
Retourne la distance conseille entre deux lignes de texte successives. Syntaxe retour int getLeading(void) Distance comprise entre la ligne de base de la premire ligne et le haut de la plus haute lettre dans cette police de la seconde ligne (distance reprsente par un l dans le schma suivant).
Figure 13.32 :

Les proprits dune police de caractres

Lobjet forme "complexe" (Shape)


Les formes complexes sinstancient par lappel au constructeur SWFShape().

SWFShape
Objet forme "complexe". Syntaxe SWFShape SWFShape()

1097

Chapitre 13

Les images et les animations Flash

Cet objet propose de nombreuses mthodes permettant le trac de lignes ou de courbes, le remplissage de formes, etc. Lors du trac des objets, il est important de noter que les axes des coordonnes sont dirigs de gauche droite pour les x, et de haut en bas pour les y. Les mthodes de trac sont :

SWFShape->movePenTo()
Dplace le pointeur de trac. Syntaxe $x $y void movePenTo(int $x, int $y) Nouvelle abscisse du pointeur de trac. Nouvelle ordonne du pointeur de trac.

13. Les images et les animations Flash

SWFShape->movePen()
Dplace le pointeur de trac relativement sa position courante. Syntaxe $dx $dy void movePen(int $dx, int $dy) Dplacement selon laxe des x du pointeur de trac. La nouvelle abscisse absolue est alors $xPointeur+$dx. Dplacement selon laxe des y du pointeur de trac. La nouvelle ordonne absolue est alors $yPointeur+$dy.

SWFShape->drawLineTo()
Trace une droite entre la position courante du pointeur et le point prcis. Le pointeur est ensuite dplac aux coordonnes prcises. Syntaxe $x $y void drawLineTo(int $x, int $y) Abscisse du point darrive de la ligne trace. Ordonne du point darrive de la ligne trace.

1098

Les animations Flash

SWFShape->drawLine()
Trace une droite entre la position courante du pointeur et le point prcis. Le pointeur est ensuite dplac aux coordonnes prcises. Les coordonnes du point darrive sont ici relatives la position du pointeur. Syntaxe $x $y void drawLine (int $dx, int $dy) Abscisse relative du point darrive de la ligne trace, soit labscisse absolue $xPointeur+$dx. Ordonne relative du point darrive de la ligne trace, soit lordonne absolue $yPointeur+$dy.

SWFShape->drawCurveTo()
Trace une courbe de Bzier quadratique, issue de la position du pointeur et aboutissant aux dernires coordonnes donnes en prenant appui sur le point indiqu par les premires coordonnes. Le pointeur prend ensuite la position du point darrive.

13. Les images et les animations Flash

Syntaxe $x1 $y1 $x2 $y2

void drawCurveTo(int $x1, int $y1, int $x2, int $y2) Abscisse du point dappui de la courbe de Bzier. Ordonne du point dappui de la courbe de Bzier. Abscisse du point darrive de la courbe de Bzier et future abscisse du pointeur. Ordonne du point darrive de la courbe de Bzier et future ordonne du pointeur.

SWFShape->drawCurve()
Trace une courbe de Bzier quadratique, issue de la position du pointeur et aboutissant aux dernires coordonnes donnes en prenant appui sur le point indiqu par les premires coordonnes. Le pointeur prend ensuite la position du point darrive. Dans ce cas, les coordonnes sont relatives. Syntaxe $dx1 $dy1 $dx2 void drawCurve(int $dx1, int $dy1, int $dx2, int $dy2) Abscisse relative au pointeur du point dappui de la courbe de Bzier, soit labscisse absolue $xPointeur+$dx1. Ordonne relative au pointeur du point dappui de la courbe de Bzier, soit lordonne absolue $yPointeur+$dy1. Abscisse relative au point dappui du point darrive de la courbe de Bzier et future abscisse du pointeur, soit labscisse absolue $xPointeur+$dx1+$dx2.

1099

Chapitre 13

Les images et les animations Flash

$dy2

Ordonne relative au point dappui du point darrive de la courbe de Bzier et future ordonne du pointeur, soit lordonne absolue $yPointeur+$dy1+$dy2.
Figure 13.33 : Exemple de courbe de Bzier quadratique

SWFShape->drawCubicTo()
Trace une courbe de Bzier cubique, issue de la position du pointeur et aboutissant aux dernires coordonnes donnes en prenant appui sur les deux points indiqus par les premires coordonnes. Le pointeur prend ensuite la position du point darrive. Syntaxe $x1 $y1 $x2 void drawCubicTo(int $x1, int $y1, int $x2, int $y2, int $x3, int $y3) Abscisse du 1er point dappui de la courbe de Bzier. Ordonne du 1er point dappui de la courbe de Bzier. Abscisse du 2nd point dappui de la courbe de Bzier. Ordonne du 2nd point dappui de la courbe de Bzier. Abscisse du point darrive de la courbe de Bzier et future abscisse du pointeur. Ordonne du point darrive de la courbe de Bzier et future ordonne du pointeur.

13. Les images et les animations Flash

$y2 $x3 $y3

SWFShape->drawCubic()
Trace une courbe de Bzier cubique, issue de la position du pointeur et aboutissant aux dernires coordonnes donnes en prenant appui sur les deux points indiqus par les premires coordonnes. Le pointeur prend ensuite la position du point darrive. Dans ce cas, les coordonnes sont relatives. Syntaxe $dx1 $dy1 $dx2 $dy2 void drawCubic(int $dx1, int $dy1, int $dx2, int $dy2, int $dx3, int $dy3) Abscisse relative au pointeur du 1er point dappui de la courbe de Bzier, soit labscisse absolue $xPointeur+$dx1. Ordonne relative au pointeur du 1er point dappui de la courbe de Bzier, soit lordonne absolue $yPointeur+$dy1. Abscisse relative au 1er point dappui du 2nd point dappui de la courbe de Bzier, soit labscisse absolue $xPointeur+$dx1+$dx2. Ordonne relative au 1er point dappui du 2nd point darrive de la courbe de Bzier, soit lordonne absolue $yPointeur+$dy1+$dy2.

1100

Les animations Flash

$dx3

Abscisse relative au 2nd point dappui du point darrive de la courbe de Bzier et future abscisse du pointeur, soit labscisse absolue $xPointeur+$dx1+$dx2+$dx3. Ordonne relative au 2nd point dappui du point darrive de la courbe de Bzier et future ordonne du pointeur, soit lordonne absolue $yPointeur+$dy1+$dy2+$dy3.
Figure 13.34 : Exemple de courbe de Bzier cubique

$dy3

drawCubic() et drawCurve() Pour obtenir des courbes de Bzier cubiques, il est galement possible dappeler les mthodes drawCurve() et drawCurveTo() avec les six mmes paramtres que ceux de drawCubic() et drawCubicTo().

SWFShape->drawGlyph()
Trace un caractre donn la position du pointeur. Syntaxe $police $caractere void drawGlyph(SWFFont $police, char $caractere) Police dcriture utiliser. Caractre crire. Cette mthode ne permet de tracer quun caractre la fois.

13. Les images et les animations Flash

Paramtres de trac Par dfaut, pour toutes les mthodes prsentes prcdemment, la largeur du trac est nulle. Vous ne verrez donc rien tant que vous ne ferez pas appel la mthode setLine() ou aux fonctions de remplissage setLeftFill() et setRightFill(). Voir le chapitre ddi au trac et remplissage.
Voici donc un exemple de ce qui peut tre ralis :

Listing 13.30 : ming_shape01.php


<?php // // // // Lanimation ne prsentera quune image par seconde pour laisser le temps dapprcier la succession des vues

1101

Chapitre 13

Les images et les animations Flash

$anim = new SWFMovie(); $anim->setDimension(100, 100); $anim->setBackground(0, 125, 255); $anim->setRate(1); // Cration des diffrents objets // qui seront utiliss dans // lanimation // La premire forme sera une simple ligne // partant du point (50, 95) // et remontant de 45 unites // Le trac sera vert et d1 unit de large. $forme1 = new SWFShape(); $forme1->setLine(1, 0, 255, 0); $forme1->movePenTo(50, 95); $forme1->drawLine(0, -45); // La seconde forme sera un carr // de 20 units de ct // avec un trac jaune d1 unit de large $forme2 = new SWFShape(); $forme2->setLine(1, 255, 255, 0); $forme2->movePenTo(40, 50); $forme2->drawLine(0, -20); $forme2->drawLine(20, 0); $forme2->drawLine(0, 20); $forme2->drawLine(-20, 0); // La troisime forme sera simplement // le caractre * // Mais pour cela, nous devons // galement crer un objet SWFFont // Ceci ncessite donc que vous ayez // un fichier Arial.fdb dans un sous-rpertoire // ming_polices. // Si ce nest pas le cas, modifier // le nom de la police ou le chemin // spcifi pour le faire coincider // avec votre environnement. // A dfaut, mettez en commentaire // la cration de forme3 et son // ajout lanimation. $forme3 = new SWFShape(); $font = new SWFFont("ming_polices/arial.fdb"); $forme3->setLine(1, 255, 255, 255); $forme3->movePenTo(40, 70); $forme3->drawGlyph($font, "*"); // Puis une courbe $forme4 = new SWFShape(); $forme4->setLine(1, 0, 0, 0);

13. Les images et les animations Flash 1102

Les animations Flash

$forme4->movePenTo(50, 30); $forme4->drawCubic(0, -50, 60, 60, -50, 0); // et une autre $forme5 = new SWFShape(); $forme5->setLine(1, 0, 0, 0); $forme5->movePenTo(60, 40); $forme5->drawCubic(50, 0, -60, 60, 0, -50); // et une autre $forme6 = new SWFShape(); $forme6->setLine(1, 0, 0, 0); $forme6->movePenTo(50, 50); $forme6->drawCubic(0, 50, -60, -60, 50, 0); // et encore une autre $forme7 = new SWFShape(); $forme7->setLine(1, 0, 0, 0); $forme7->movePenTo(40, 40); $forme7->drawCubic(-50, 0, 60, -60, 0, 50); // Maintenant que lon a tout les objets // on passe la cration de labimation // Dans la vue 1 napparait que la forme 1 $anim->add($forme1); $anim->nextFrame(); // Puis dans la vue 2 vient sajouter la forme 2 $anim->add($forme2); $anim->nextFrame(); // dans la vue 3.... la forme 3 $anim->add($forme3); $anim->nextFrame(); // dans ma vue 4... tout le reste $anim->add($forme4); $anim->add($forme5); $anim->add($forme6); $anim->add($forme7); // ATTENTION: Mme sil sagit de la // dernire vue, ne pas oublier // lappel nextFrame(); $anim->nextFrame(); // Il est temps de voir le rsultat header("Content-type: application/x-shockwave-flash"); $anim->output();

13. Les images et les animations Flash

?>

1103

Chapitre 13

Les images et les animations Flash

Fonctions non disponibles ce jour, il nest pas possible de tracer facilement des cercles ou arcs de cercles. Les fonctions drawArc() et drawCircle() prvues cet effet ne sont pas encore fonctionnelles.

Positionnement et modication des objets


Comme cela a t voqu prcdemment, lorsque lon appelle la mthode add() de lobjet SWFMovie pour ajouter un objet de type SWFButton, SWFShape, SWFSprite ou SWFText, un objet SWFDisplayItem est retourn. Cet objet permet, grce aux mthodes suivantes, de : Donner un nom aux objets :

SWFDisplayItem->setName()
13. Les images et les animations Flash
Donne un nom lobjet afin de pouvoir lidentifier dans les scripts daction (que nous verrons plus loin). Syntaxe $nom void setName(string $nom) Nom donner lobjet.

Modifier la position des objets :

SWFDisplayItem->setDepth()
Dplace lobjet dans un couche diffrente (pour le mettre devant ou derrire un ou plusieurs autres objets). Syntaxe $couche void setDepth(int $couche) Couche dans laquelle doit tre dplac lobjet.

SWFDisplayItem->moveTo()
Dplace lorigine de lobjet vers de nouvelles coordonnes. Syntaxe $x $y void moveTo(int $x, int $y) Nouvelle abscisse pour lorigine de lobjet. Nouvelle ordonne pour lorigine de lobjet.

1104

Les animations Flash

SWFDisplayItem->move()
Dplace lorigine de lobjet vers de nouvelles coordonnes relatives sa position courante. Syntaxe $dx $dy void move(int $dx, int $dy) Abscisse relative pour lorigine de lobjet. Soit labscisse absolue $xCourant+$dx. Ordonne relative pour lorigine de lobjet. Soit lordonne absolue $yCourant+$dy.

SWFDisplayItem->rotateTo()
Fait pivoter lobjet par rapport son angle dorigine. Syntaxe $angle void rotateTo(double $angle) Angle de rotation exprim en degrs.

13. Les images et les animations Flash

SWFDisplayItem->rotate()
Fait pivoter lobjet par rapport son angle courant. Syntaxe $angle void rotate (double $dangle) Angle de rotation relatif langle courant, exprim en degrs.

Daltrer leur forme :

SWFDisplayItem->scaleTo()
Modifie la taille de lobjet par rapport sa taille dorigine. Syntaxe $coefX $coefY void scaleTo(double $coefX, double $coefY) Coefficient multiplicateur appliquer sur la largeur dorigine de lobjet. Coefficient multiplicateur appliquer sur la hauteur dorigine de lobjet.

1105

Chapitre 13

Les images et les animations Flash

SWFDisplayItem->scale()
Modifie la taille de lobjet par rapport sa taille courante. Syntaxe $coefX $coefY void scale(double $coefX, double $coefY) Coefficient multiplicateur appliquer sur la largeur courante de lobjet. Coefficient multiplicateur appliquer sur la hauteur courante de lobjet.

SWFDisplayItem->skewXTo()
Dforme lobjet par une inclinaison de laxe x selon une pente donne par rapport son inclinaison dorigine. Syntaxe $pente void skewXTo(double $pente) Coefficient de pente, ou encore tangente de langle dinclinaison.

13. Les images et les animations Flash

SWFDisplayItem->skewX()
Dforme lobjet par une inclinaison de laxe x selon une pente donne par rapport son inclinaison courante. Syntaxe $pente void skewX(double $pente) Coefficient de pente, ou encore tangente de langle dinclinaison.

SWFDisplayItem->skewYTo()
Dforme lobjet par une inclinaison de laxe y selon une pente donne par rapport son inclinaison dorigine. Syntaxe $pente void skewYTo(double $pente) Coefficient de pente, ou encore tangente de langle dinclinaison.

SWFDisplayItem->skewY()
Dforme lobjet par une inclinaison de laxe y selon une pente donne par rapport son inclinaison courante.

1106

Les animations Flash

Syntaxe $pente ou leur couleur :

void skewY(double $pente) Coefficient de pente, ou encore tangente de langle dinclinaison.

SWFDisplayItem->addColor()
Ajoute (ou soustrait selon les signes) aux composantes de la couleur dorigine les composantes de la couleur donne. Les valeurs obtenues seront videmment bornes sur lintervalle [0, 255]. Syntaxe $rouge $vert $bleu $alpha void addColor(int $rouge, int $vert, int $bleu, [int $alpha]) Composante rouge (comprise entre -255 et 255) ajouter la couleur dorigine. Composante verte (comprise entre -255 et 255) ajouter la couleur dorigine. Composante bleue (comprise entre -255 et 255) ajouter la couleur dorigine. Composante Alpha ou transparence (comprise entre -255 et 255) ajouter la couleur dorigine. Rappel : plus Alpha est proche de 0, plus lobjet est transparent ; plus il est proche de 255, plus lobjet est opaque.

13. Les images et les animations Flash

SWFDisplayItem->multColor()
Multiplie les composantes de la couleur dorigine. Les valeurs obtenues seront videmment bornes sur lintervalle [0, 255]. Syntaxe $coefRouge $coefVert $coefBleu $alpha void multColor(double $coefRouge, double $coefVert, double $coefBleu, [double $coefAlpha]) Coefficient multiplicateur pour la composante rouge (> = 0). Coefficient multiplicateur pour la composante verte (> = 0). Coefficient multiplicateur pour la composante bleue (> = 0). Coefficient multiplicateur pour la composante Alpha ou transparence (> = 0). Rappel : plus Alpha est proche de 0, plus lobjet est transparent ; plus il est proche de 255, plus lobjet est opaque.

Axe de rotation Les rotations seffectuant par rapport laxe qui a servi dorigine lors de la cration de lobjet, il est fortement conseill de faire concider cet axe avec le centre de lobjet. Lerreur classique consiste crer lobjet autour du point dans lequel il se trouve dans la premire vue.

1107

Chapitre 13

Les images et les animations Flash

Figure 13.35 : Exemple dun objet cr avec le centre lorigine Figure 13.36 : puis ayant subi une translation

Figure 13.37 : suivie dune rotation de 45 .

Figure 13.38 : Exemple dun objet cr son emplacement dans la premire vue Figure 13.39 :

puis ayant subit une rotation de 45 . 13. Les images et les animations Flash

Suppression dun objet


En revanche, pour supprimer un objet, on fera appel la mthode remove() de lobjet SWFMovie.

SWFMovie->remove()
Supprime un objet de la vue. Syntaxe void remove(SWFDisplayItem $objetSWFDisplayItem) $objetSWFDisplayItem Lobjet SWFDisplayItem qui avait t retourn par la mthode add() lorsque lobjet avait t ajout une prcdente vue. Dans lexemple suivant, nous avons deux objets identiques, dont lun est supprim dans la seconde vue.

Listing 13.31 : ming_remove.php


<?php $dessinForme = new SWFShape(); $dessinForme->setLine(1, 0, 0, 0); $dessinForme->movePenTo(-10, -10);

1108

Les animations Flash

$dessinForme->drawLine(20, 0); $dessinForme->drawLine(0, 20); $dessinForme->drawLine(-20, 0); $dessinForme->drawLine(0, -20); $anim = new SWFMovie(); $anim->setDimension(100, 100); $anim->setBackground(255, 255, 255); $anim->setRate(1); $forme1 = $anim->add($dessinForme); $forme1->moveTo(30, 30); $forme2 = $anim->add($dessinForme); $forme2->moveTo(20, 60); $anim->nextFrame(); $anim->remove($forme2); $anim->nextFrame(); header("Content-type: application/x-shockwave-flash"); $anim->output();

13. Les images et les animations Flash

?>

Trac et remplissage des formes


Les objets SWFShape possdent des mthodes permettant de fixer les paramtres de leur trac (paisseur du trait, couleur) ainsi que les paramtres de remplissage.

SWFShape->setLine()
Prcise la largeur et la couleur du trac de la forme. Syntaxe $largeur $rouge void setLine(int $largeur, [int $rouge, int $vert, int $bleu], [int $alpha]) Largeur du trac. Composante rouge de la couleur du trac (peut tre omise en mme temps que $vert, $bleu et $alpha notamment si $largeur = 0). Valeur comprise entre 0 et 255. Composante verte de la couleur du trac (peut tre omise en mme temps que $rouge, $bleu et $alpha notamment si $largeur = 0). Valeur comprise entre 0 et 255. Composante bleue de la couleur du trac (peut tre omise en mme temps que $rouge, $vert et $alpha notamment si $largeur = 0).

$vert

$bleu

1109

Chapitre 13

Les images et les animations Flash

$alpha

Composante Alpha (transparence) de la couleur du trac. Valeur comprise entre 0 (couleur totalement transparente) et 255 (couleur totalement opaque). Ce paramtre est optionnel.

SWFShape->setLeftFill()
Prcise le motif de remplissage de lintrieur de la forme lorsque celle ci est dessine dans le sens inverse des aiguilles dune montre (quand lintrieur se situe gauche du trac). Syntaxe $objetSWFFill void setLeftFill(SWFFill $objetSWFFill) Objet SWFFill prcisant le motif de remplissage (voir ci-aprs).

SWFShape->setRightFill()
Prcise le motif de remplissage de lintrieur de la forme lorsque celle ci est dessine dans le sens des aiguilles dune montre (quand lintrieur se situe droite du trac).

13. Les images et les animations Flash

Syntaxe $objetSWFFill

void setRightFill(SWFFill $objetSWFFill) Objet SWFFill prcisant le motif de remplissage (voir ci-aprs).

Diffrence entre setLeftFill() et setRightFill() Nous ne sommes pas parvenus mettre en vidence la diffrence de comportement entre setLeftFill() et setRightFill(). Sur les exemples tests, lun et lautre peuvent sappliquer indiffremment.
Comme vous pouvez le constater, les mthodes de remplissage sappuient sur des objets que nous navons pas encore vus jusque-l. Les objets SWFFill ne sont pas censs tre instancis directement. Ils sont en fait retourns par la mthode addFill() de lobjet SWFShape. Cette mthode accepte trois interfaces distinctes.

SWFShape->addFill() remplissage "solide"


Dans la syntaxe dcrite ici, associe la forme une mthode de remplissage base tout simplement sur une couleur et retourne lobjet SWFFill correspondant. Syntaxe $rouge SWFFill addFill(int $rouge, int $vert, int $bleu, [int $alpha]) Composante rouge de remplissage de la forme. Valeur comprise entre 0 et 255.

1110

Les animations Flash

$vert $bleu $alpha

Composante verte de remplissage de la forme. Valeur comprise entre 0 et 255. Composante bleue de remplissage de la forme. Valeur comprise entre 0 et 255. Composante Alpha (transparence) de la couleur du trac. Valeur comprise entre 0 (couleur totalement transparente) et 255 (couleur totalement opaque). Ce paramtre est optionnel.

SWFShape->addFill() remplissage par une image


Associe la forme une mthode de remplissage base sur un objet "image" (SWFBitmap). Syntaxe $objetSWFBitmap $mode SWFFill addFill(SWFBitmap $objetSWFBitmap, [int $mode]) Objet "image" utilis comme motif de remplissage (voir ci-aprs). Mode de remplissage. Cet argument optionnel peut prendre lune des deux valeurs dfinies par des constantes. SWFFILL_TILED_BITMAP (valeur par dfaut) si vous souhaitez que le motif se rpte " linfini". SWFFILL_CLIPPED_BITMAP si vous souhaitez que le motif napparaisse quune seule fois. Dans ce cas, avant dventuelles transformations par appel aux mthodes proposes par SWFFill, le coin suprieur gauche de limage concide avec lorigine (0,0).

13. Les images et les animations Flash

SWFshape->addFill() remplissage par un dgrad


Associe la forme une mthode de remplissage base sur un objet "dgrad" (SWFGradient). Syntaxe $mode SWFFill addFill(SWFGradient $objetSWFGradient, [int $mode]) Mode de remplissage. Cet argument optionnel peut prendre lune des deux valeurs dfinies par des constantes. SWFFILL_LINEAR_GRADIENT (valeur par dfaut) si vous souhaitez que le dgrad soit linaire (selon laxe des abscisses x, avant dventuelles transformations par appel aux mthodes proposes par SWFFill). SWFFILL_RADIAL_GRADIENT si vous souhaitez que le dgrad soit radial (par cercles concentriques centrs sur lorigine [0,0], avant dventuelles transformations par appel aux mthodes proposes pas SWFFill). $objetSWFGradient Objet "dgrad" utilis comme motif de remplissage (voir ci-aprs).

1111

Chapitre 13

Les images et les animations Flash

Listing 13.32 : ming_fill01.php


<?php // Cration dune forme quelconque ferme. $dessinForme = new SWFShape(); // Pour mieux apprci les limites, nous traons le // contour en noir. $dessinForme->setLine(1, 0, 0, 0); // Et nous remplissons la forme avec la couleur rouge $fill = $dessinForme->addFill(255, 0, 0); $dessinForme->setLeftFill($fill); $dessinForme->movePenTo(-50, -40); $dessinForme->drawCurveTo(0, -60, 60, -20); $dessinForme->drawCurveTo(10, 5, 60, 40); $dessinForme->drawCurveTo(0, 60, -30, 30); $dessinForme->drawCurveTo(-20, 0, -50, -40); $anim = new SWFMovie(); $anim->setDimension(300,100); $anim->setBackground(255, 255, 255); $anim->setRate(1); $formePleine=$anim->add($dessinForme); $formePleine->moveTo(60, 50); $anim->nextFrame(); header("Content-type: application/x-shockwave-flash"); $anim->output();

13. Les images et les animations Flash

?>

Nous voil maintenant avec deux nouveaux objets rests jusque-l inconnus. Il sagit des objets SWFBitmap et SWFGradient. Le premier sinstancie par un appel au constructeur :

SWFBitmap
Objet image utilis comme motif de remplissage. Syntaxe SWFBitmap SWFBitmap(string $fichier, [string $fichierMasqueAlpha])

1112

Les animations Flash

$fichier

Nom du fichier image charger. Ce fichier doit tre au format JPEG non progressif ou DBL (Define Dit Lossless). Les fichiers DBL peuvent tre crs partir de fichiers GIF ou PNG grce aux utilitaires gif2dbl et png2dbl fournis avec la bibliothque Ming.

$fichierMasqueAlpha Ce paramtre optionnel indique un nom de fichier .msk. Ce fichier servira de composante Alpha (transparence) pour limage JPEG. Les fichiers .msk peuvent tre crs partir de fichiers GIF grce lutilitaire gif2msk fourni avec la bibliothque Ming.

Rgression ? Depuis la version 4.2.0 et jusqu 4.2.2 (minimum), lobjet SWFBitmap ne semble plus reconnatre aucun format dimage. Gnration et utilisation des commandes gif2dbl, png2dbl et gif2msk Les commandes gif2dbl, png2dbl et gif2msk ne sont pas compiles en mme temps que la bibliothque Ming. Il faut donc, sous Linux, aller dans le sous rpertoire "util" et taper les instructions :
# make gif2dbl # make png2dbl # make gif2msk

13. Les images et les animations Flash

pour les gnrer toutes les trois. De plus, ces fichiers sources ncessitent quelques bibliothques. (Par exemple, les commandes gif2 ncessitent le fichier gif_lib.h que vous pourrez trouver dans le rpm libungifdevel. Pour cela, consultez votre distribution Linux). Lutilisation de ces commandes est trs simple (elles acceptent toutes le paramtre "--help"): Pour crer un fichier .dbl dans le mme rpertoire que le fichier .gif, il suffit de taper :
> gif2dbl fichier.gif

Pour crer un fichier .dbl dans le mme rpertoire que le fichier .png, il suffit de taper :
> png2dbl fichier.png

Pour crer un fichier .msk dans le mme rpertoire que le fichier .gif, il suffit de taper :
> gif2msk fichier.gif

Les mthodes de cet objet :

SWFBitmap->getWidth()
Retourne la largeur, en pixels, de limage. Syntaxe int getWidth(void)

1113

Chapitre 13

Les images et les animations Flash

SWFBitmap->getHeight()
Retourne la hauteur, en pixels, de limage. Syntaxe int getWidth(void) Voici un exemple de script de remplissage dune forme par une image rpte linfini.

Listing 13.33 : ming_fill02.php


<?php // Cration dune forme quelconque // ferme. $dessinForme = new SWFShape(); // Pour mieux apprcier le trac // nous traons le contour en noir $dessinForme->setLine(1, 0, 0, 0);

13. Les images et les animations Flash

// // // //

et nous souhaitons galement avoir une forme pleine base sur un remplissage par une image

// Donc, dans un premier temps // nous crons un objet SWFBitmap // en prcisant un fichier image $bitmap = new SWFBitmap("images/remplissage.jpg"); // Objet bitmap que nous pouvons alors // "dclarr" comme forme de remplissage // pour notre forme. // Par dfaut limage sera rpte linfini // Ce qui permet de rcuprer un objet // SWFFill... $fill = $dessinForme->addFill($bitmap); // ... qui va nous servir a remplir // la forme. $dessinForme->setLeftFill($fill); // Maintenant que lon a prcis // comme sera rempli la forme // on peut la tracer. $dessinForme->movePenTo(-50, -40); $dessinForme->drawCurveTo(0, -60, 60, -20); $dessinForme->drawCurveTo(10, 5, 60, 40); $dessinForme->drawCurveTo(0, 60, -30, 30);

1114

Les animations Flash

$dessinForme->drawCurveTo(-20, 0, -50, -40); $anim = new SWFMovie(); $anim->setDimension(300, 100); $anim->setBackground(255, 255, 255); $anim->setRate(1); // Il ne sagit pas a proprement parler // dune animation puisquil ny quune seule // vue mais peu importe. $formePleine=$anim->add($dessinForme); // La forme ayant t dessine autour // de lorigine (0,0) il faut la // re-centrer dans limage $formePleine->moveTo(60, 50); $anim->nextFrame(); header("Content-type: application/x-shockwave-flash"); $anim->output();

?>

13. Les images et les animations Flash

Ce qui donne le rsultat suivant :


Figure 13.40 : Remplissage par une image rpte linfini

Un autre exemple, o cette fois limage nest pas rpte linfini.

Listing 13.34 : ming_fill03.php


<?php // // // // Cet exemple reprend lexemple prcdent. A la seule diffrence que le mode de remplissage est fix SWFFILL_CLIPPED_BITMAP Limage nest donc pas reproduite linfini

$dessinForme = new SWFShape(); $dessinForme->setLine(1, 0, 0, 0); $bitmap = new SWFBitmap("images/remplissage.jpg"); // Voil, cest juste l o ca diffre. $fill = $dessinForme->addFill($bitmap, SWFFILL_CLIPPED_BITMAP); $dessinForme->setLeftFill($fill);

1115

Chapitre 13

Les images et les animations Flash

$dessinForme->movePenTo(-50, -40); $dessinForme->drawCurveTo(0, -60, 60, -20); $dessinForme->drawCurveTo(10, 5, 60, 40); $dessinForme->drawCurveTo(0, 60, -30, 30); $dessinForme->drawCurveTo(-20, 0, -50, -40); $anim = new SWFMovie(); $anim->setDimension(300, 100); $anim->setBackground(255, 255, 255); $anim->setRate(1); $formePleine=$anim->add($dessinForme); $formePleine->moveTo(60, 50); $anim->nextFrame(); header("Content-type: application/x-shockwave-flash"); $anim->output();

?>

13. Les images et les animations Flash

Ce qui donne le rsultat suivant (le coin suprieur gauche de limage concide avec lorigine [0,0] de lobjet) :
Figure 13.41 : Remplissage par une image non rpte

Quant au second, il sinstancie par un appel au constructeur :

SWFGradient
Objet "dgrad" utilis comme motif de remplissage. Syntaxe SWFGradient SWFGradient(void)

et propose lunique mthode :

SWFGradient->addEntry()
Permet de fixer les couleurs dun dgrad. Cette fonction doit tre appele autant de fois que ncessaire pour ajouter les couleurs voulues. Les appels successifs doivent se faire dans lordre croissant de $coef.

1116

Les animations Flash

Syntaxe $coef

void addEntry(double $coef, int $rouge, int $vert, int $bleu, [int $alpha]) Indique la position de la couleur dans le dgrad. Pour un dgrad linaire, une valeur 0 indique que le dgrad doit commencer tout gauche par cette couleur, une valeur de 1 indique que le dgrad doit se terminer tout droite par cette couleur. Une valeur intermdiaire de 0.3 (par exemple) indique que le dgrad doit passer par cette couleur son premier tiers (celui du ct gauche). Et videmment 0.5 indique le milieu. Pour un dgrad radial, une valeur 0 indique que le centre du dgrad doit avoir cette couleur, une valeur de 1 indique que le cercle de plus grand rayon doit avoir cette couleur. Et enfin, toutes les valeurs intermdiaires indiquent des positions intermdiaires pour la couleur. Les dgrads stalent approximativement entre les coordonnes x [-800, 800] (pour les dgrads linaires) ou les rayons [0, 800] (pour les dgrads radiaux). Prcise la composante rouge de la couleur. Valeur comprise entre 0 et 255. Prcise la composante verte de la couleur. Valeur comprise entre 0 et 255. Prcise la composante bleue de la couleur. Valeur comprise entre 0 et 255. Paramtre optionnel, prcise la composante Alpha (transparence) de la couleur. Valeur comprise entre 0 (totalement transparent) et 255 (totalement opaque).

$rouge $vert $bleu $alpha

13. Les images et les animations Flash

Figure 13.42 : Exemples de dgrads linaires (avec deux puis trois couleurs)

Figure 13.43 : Exemples de dgrads radiaux (avec deux puis trois couleurs)

Listing 13.35 : ming_gradient02.php


<?php // Cration dun carr tout simple // afin de le remplir dun dgrad $dessinForme = new SWFShape(); // Cration du dgrad

1117

Chapitre 13

Les images et les animations Flash

// compos de 3 couleurs $degrade = new SWFGradient(); $degrade->addEntry(0, 255, 0, 0); // Du Rouge $degrade->addEntry(0.3, 255, 255, 0); // En pasant par le Jaune $degrade->addEntry(1, 0, 255, 0); // Vers le Vert // On prendra un dgrad linaire $fill = $dessinForme->addFill($degrade, SWFFILL_LINEAR_GRADIENT); $dessinForme->setRightFill($fill); // Un simple carre de 1700 de cot // puisque par dfaut le dgrad // stale de -800 800 (environ) // Rassurez vous, on verra que lon // peut trs bien saffranchir de ce "problme" $dessinForme->movePenTo(-850, -850); $dessinForme->drawLine(1700, 0); $dessinForme->drawLine(0, 1700); $dessinForme->drawLine(-1700, 0); $dessinForme->drawLine(0, -1700);

13. Les images et les animations Flash

$anim = new SWFMovie(); $anim->setDimension(1750, 1750); $anim->setBackground(255, 255, 255); $anim->setRate(1); $formePleine=$anim->add($dessinForme); $formePleine->moveTo(875, 875); $anim->nextFrame(); header("Content-type: application/x-shockwave-flash"); $anim->output();

?>

Mthodes "raccourcis" Les mthodes setLeftFill() et setRightFill() possdent des variantes permettant des raccourcis. Ainsi :
j
SWFShape>setLeftFill($rouge, $vert, $bleu, [$alpha]) est un raccourci pour SWFShape>setLeftFill(SWFShape>addFill($rouge, $vert, $bleu, [$alpha]). SWFShape>setRightFill($rouge, $vert, $bleu, [$alpha]) est un raccourci pour SWFShape>setRightFill(SWFShape>addFill($rouge, $vert, $bleu, [$alpha]).

1118

Les animations Flash

Afin de mieux matriser le positionnement de lobjet de remplissage dans la forme, lobjet SWFFill propose un certain nombre de mthodes.

SWFFill->moveTo()
Dplace lorigine du motif de remplissage (par exemple, le coin suprieur gauche de limage). Syntaxe $x $y void moveTo(int $x, int $y) Nouvelle coordonne x de lobjet de remplissage. Nouvelle coordonne y de lobjet de remplissage.

SWFFill->scaleTo()
Modifie la taille du motif de remplissage. Syntaxe $coefX void scaleTo(double $coefX, double $coefY) Multiplie la largeur du motif de remplissage par le coefficient $coefX par rapport sa taille initiale. Dans le cas o le motif de remplissage est une image (et non un dgrad), son comportement est plus mystrieux. Multiplie la hauteur du motif de remplissage par le coefficient $coefY par rapport sa taille initiale. Dans le cas o le motif de remplissage est une image (et non un dgrad), son comportement est plus mystrieux.

13. Les images et les animations Flash

$coefY

SWFFill->rotateTo()
Fait pivoter le motif de remplissage. Syntaxe $angle void rotateTo(double $angle) Angle de rotation du motif de remplissage par rapport son angle initial, exprim en degrs.

SWFFill->skewXTo()
Dforme le motif de remplissage selon laxe des x. Syntaxe $pente void skewXTo(double $pente) Coefficient de pente (ou tangente de langle dinclinaison) appliqu sur laxe des x par rapport son axe dorigine.

1119

Chapitre 13

Les images et les animations Flash

SWFFill->skewYTo()
Dforme le motif de remplissage selon laxe des y. Syntaxe $pente void skewYTo(double $pente) Coefficient de pente (ou tangente de langle dinclinaison) appliqu sur laxe des y par rapport son axe dorigine.

Pour mieux positionner une image (non rpte linfini), nous avons tout intrt faire appel ces mthodes, comme le montre le script suivant :

Listing 13.36 : ming06.php


<?php // Cet exemple reprend lexemple prcdent. // A la seule diffrence que lobjet de remplissage // est dplac pour tre mieux centr dans la forme $dessinForme = new SWFShape();

13. Les images et les animations Flash

$dessinForme->setLine(1, 0, 0, 0); $bitmap = new SWFBitmap("images/remplissage.jpg"); $fill = $dessinForme->addFill($bitmap, SWFFILL_CLIPPED_BITMAP); // Jusqualors nous navons pas manipul // lobjet SWFFill obtenu // Et bien, cest maintenant chose faite // Plutot que de faire coincider le coin suprieur // gauche de limage avec lorigine de la forme (0,0) // Cest le milieu de limage que lon va faire // coincider avec lorigine de la forme // Ce qui permet galement de manipuler les // mthodes getWidth() et getHeight() de SWFBitmap $fill->moveTo(-$bitmap->getWidth()/2,-$bitmap->getHeight()/2); $dessinForme->setLeftFill($fill); $dessinForme->movePenTo(-50, -40); $dessinForme->drawCurveTo(0, -60, 60, -20); $dessinForme->drawCurveTo(10, 5, 60, 40); $dessinForme->drawCurveTo(0, 60, -30, 30); $dessinForme->drawCurveTo(-20, 0, -50, -40); $anim = new SWFMovie(); $anim->setDimension(300, 100); $anim->setBackground(255, 255, 255); $anim->setRate(1);

1120

Les animations Flash

$formePleine=$anim->add($dessinForme); $formePleine->moveTo(60, 50); $anim->nextFrame(); header("Content-type: application/x-shockwave-flash"); $anim->output();

?>

Ce qui donne le rsultat :


Figure 13.44 :

Image de remplissage centre

Ces mthodes sont galement indispensables pour bien matriser le rendu dun dgrad.

Listing 13.37 : ming_gradient05.php


<?php

13. Les images et les animations Flash

// Cration dune forme quelconque // afin de la remplir dun dgrad $dessinForme = new SWFShape(); // Cration du dgrad // compos de 2 couleurs $degrade = new SWFGradient(); $degrade->addEntry(0, 255, 0, 0); // Du Rouge $degrade->addEntry(1, 255, 255, 0); // Vers le Jaune // On prendra un dgrad linaire $fill = $dessinForme->addFill($degrade, SWFFILL_LINEAR_GRADIENT); // Par dfaut, le dgrad // stale des abscisses -800 800 // Notre forme, elle, fait a peut prs 60x60 // Nous allons donc rduire la taille // de la forme de remplissage $fill->scaleTo(60/1600); // Et juste pour le "fun" // on va en faire un dgrad 45 degrs $fill->rotateTo(45); $dessinForme->setRightFill($fill); // Notre forme quelconque // de taille approximative // 60x60

1121

Chapitre 13

Les images et les animations Flash

$dessinForme->movePenTo(-50, -40); $dessinForme->drawCurveTo(0, -60, 60, -20); $dessinForme->drawCurveTo(10, 5, 60, 40); $dessinForme->drawCurveTo(0, 60, -30, 30); $dessinForme->drawCurveTo(-20, 0, -50, -40); $anim = new SWFMovie(); $anim->setDimension(100, 100); $anim->setBackground(255, 255, 255); $anim->setRate(1); $formePleine=$anim->add($dessinForme); $formePleine->moveTo(50, 50); $anim->nextFrame(); header("Content-type: application/x-shockwave-flash"); $anim->output();

?>

Ce qui permet dobtenir le rsultat suivant :


Figure 13.45 :

13. Les images et les animations Flash

Remplissage par un dgrad ajust la forme

Le morphing
Il y a un type dobjet dont nous navons pas encore parl jusque-l. Il sagit de lobjet "morphing". Comme vous laurez compris, lobjet morphing permet de raliser des morphings : autrement dit, cela permet dafficher une succession de dessins reprsentant les tapes intermdiaires dune transition dun dessin de dpart un dessin darrive par modifications lgres. Cet objet sinstancie par un appel au constructeur SWFMorph().

SWFMorph
Objet morphing. Syntaxe SWFMorph SWFMorph(void) Cet objet propose deux mthodes :

SWFMorph->getShape1()
Retourne une rfrence sur la forme de dpart du morphing afin de pouvoir la dessiner. Syntaxe SWFShape getShape1(void)

1122

Les animations Flash

SWFMorph->getShape2()
Retourne une rfrence sur la forme darrive du morphing afin de pouvoir la dessiner. Syntaxe SWFShape getShape2(void) Le principe dutilisation de cet objet est donc de rcuprer une rfrence sur lobjet de dpart, puis dutiliser cette rfrence pour crer lobjet de dpart (par appel aux mthodes proposes par lobjet SWFShape). Et faire ensuite de mme avec lobjet darrive. Lobjet SWFDisplayItem propose une mthode ddie aux objets SWFMorph. Il sagit de la mthode :

SWFDisplayItem->setRatio()
Dtermine (pour une vue donne) quelle tape de la transformation doit tre affiche. Syntaxe $etape void setRatio(double $etape) tape de transformation souhaite. Cette valeur doit tre comprise entre 0 et 1. Si elle est fixe 0, alors cest lobjet de dpart qui est affich. Si elle est fixe 1, alors cest lobjet darrive qui est affich. Pour toutes les valeurs intermdiaires, cest un objet de transition qui est affich. Cet objet aura dautant plus lapparence de lobjet de dpart que $etape est proche de 0, et il aura dautant plus lapparence de lobjet darrive que $etape est proche de 1.

13. Les images et les animations Flash

Lalgorithme de base dune animation de type morphing aura donc lallure suivante :

Listing 13.38 : ming_morph01.php


<?php // Instanciation dun objet // de morphing $traceMorph = new SWFMorph(); // Rcupration dune rfrence // sur lobjet de dpart // du morphing $formeDepart = $traceMorph->getShape1(); // // // // Trac de la forme de dpart par appel aux mthodes de lobjet SWFShape ex: $formeDepart->drawLine(...)

1123

Chapitre 13

Les images et les animations Flash

// Rcupration dune rfrence // sur lobjet darrive // du morphing $formeArrivee = $traceMorph->getShape2(); // // // // Trac de la forme darrive par appel aux mthodes de lobjet SWFShape ex: $formeArrivee->drawLine(...)

// Instanciation de lanimation // et dfinition de ses paramtres $anim = new SWFMovie(); // Ajout de lobjet de morphing // et rcupration de lobjet // SWFDisplayItem associ $morph=$anim->add($traceMorph);

13. Les images et les animations Flash

// // // // //

Cration des vues successives contenant les diffrentes phases du morphing En faisant varier le paramtre de setRatio entre 0 et 1

$nbEtape=30; for ($i=0; $i<=$nbEtape; $i++) { $morph->setRatio($i/$nbEtape); $anim->nextFrame(); } // Emission de lanimation // vers le client header("Content-type: application/x-shockwave-flash"); $anim->output();

?>

Il est fortement conseill davoir une forme darrive qui contienne le mme nombre de segments que la forme de dpart. Si la diffrence est trop grande, vous risquez tout bonnement un "crash" du navigateur. Cependant, mme en respectant cette rgle, le rsultat nest pas parfait, puisque la forme obtenue avec setRatio(1) nest pas exactement la forme darrive dsire. Comme cest le cas, dans lexemple suivant :

1124

Les animations Flash

Listing 13.39 : ming_morph02.php


<?php // Cration dun objet Morphing $morph = new SWFMorph(); // Rcuperation dune rfrence // sur lobjet de dpart $formeDepart = $morph->getShape1(); $formeDepart->setLine(1, 0, 0, 0); // Dessin de la forme de dpart // ? inverse (16 segments) $formeDepart->movePenTo(-80, -30); $formeDepart->drawLine(10, 0); $formeDepart->drawLine(0, 10); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, -10); $formeDepart->movePenTo(-80, -10); $formeDepart->drawLine(10, 0); $formeDepart->drawLine(0, 10); $formeDepart->drawLine(-10, 10); $formeDepart->drawLine(0, 10); $formeDepart->drawLine(10, 0); $formeDepart->drawLine(0, -10); $formeDepart->drawLine(10, 0); $formeDepart->drawLine(0, 20); $formeDepart->drawLine(-30, 0); $formeDepart->drawLine(0, -20); $formeDepart->drawLine(10, -10); $formeDepart->drawLine(0, -10); // P (10 segments) $formeDepart->movePenTo(-50, -30); $formeDepart->drawLine(30, 0); $formeDepart->drawLine(0, 40); $formeDepart->drawLine(-20, 0); $formeDepart->drawLine(0, 20); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, -60); $formeDepart->movePenTo(-40, -20); $formeDepart->drawLine(10, 0); $formeDepart->drawLine(0, 20); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, -20); // H (12 segments) $formeDepart->movePenTo(-10, -30);

13. Les images et les animations Flash 1125

Chapitre 13

Les images et les animations Flash

$formeDepart->drawLine(10, 0); $formeDepart->drawLine(0, 20); $formeDepart->drawLine(10, 0); $formeDepart->drawLine(0, -20); $formeDepart->drawLine(10, 0); $formeDepart->drawLine(0, 60); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, -20); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, 20); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, -60); // P (10 segments) $formeDepart->movePenTo(30, -30); $formeDepart->drawLine(30, 0); $formeDepart->drawLine(0, 40); $formeDepart->drawLine(-20, 0); $formeDepart->drawLine(0, 20); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, -60); $formeDepart->movePenTo(-40, -20); $formeDepart->drawLine(10, 0); $formeDepart->drawLine(0, 20); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, -20); // ? (16 segments) $formeDepart->movePenTo(80, 20); $formeDepart->drawLine(10, 0); $formeDepart->drawLine(0, 10); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, -10); $formeDepart->movePenTo(90, 10); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, -10); $formeDepart->drawLine(10, -10); $formeDepart->drawLine(0, -10); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, 10); $formeDepart->drawLine(-10, 0); $formeDepart->drawLine(0, -20); $formeDepart->drawLine(30, 0); $formeDepart->drawLine(0, 20); $formeDepart->drawLine(-10, 10); $formeDepart->drawLine(0, 10); $formeDepart->movePenTo(-50, 40); $formeDepart->drawLine(100, 0); $formeDepart->drawLine(0, 10); $formeDepart->drawLine(-100, 0); $formeDepart->drawLine(0, -10);

13. Les images et les animations Flash 1126

Les animations Flash

$formeArrivee = $morph->getShape2(); $formeArrivee->setLine(1, 0, 0, 0); // F (10 segments) $formeArrivee->movePenTo(-120, -30); $formeArrivee->drawLine(30, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(-20, 0); $formeArrivee->drawLine(0, 20); $formeArrivee->drawLine(10, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(-10, 0); $formeArrivee->drawLine(0, 20); $formeArrivee->drawLine(-10, 0); $formeArrivee->drawLine(0, -60); // A (12 segments) $formeArrivee->movePenTo(-80, -30); $formeArrivee->drawLine(30, 0); $formeArrivee->drawLine(0, 60); $formeArrivee->drawLine(-10, 0); $formeArrivee->drawLine(0, -20); $formeArrivee->drawLine(-10, 0); $formeArrivee->drawLine(0, 20); $formeArrivee->drawLine(-10, 0); $formeArrivee->drawLine(0, -60); $formeArrivee->movePenTo(-70, -20); $formeArrivee->drawLine(10, 0); $formeArrivee->drawLine(0, 20); $formeArrivee->drawLine(-10, 0); $formeArrivee->drawLine(0, -20); // C (8 segments) $formeArrivee->movePenTo(-40, -30); $formeArrivee->drawLine(30, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(-20, 0); $formeArrivee->drawLine(0, 40); $formeArrivee->drawLine(20, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(-30, 0); $formeArrivee->drawLine(0, -60); // I (8 segments) $formeArrivee->movePenTo(0, -30); $formeArrivee->drawLine(10, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(-10, 0); $formeArrivee->drawLine(0, -10); $formeArrivee->movePenTo(0, -10);

13. Les images et les animations Flash 1127

Chapitre 13

Les images et les animations Flash

$formeArrivee->drawLine(10, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(0, 20); $formeArrivee->drawLine(-10, 0); $formeArrivee->drawLine(0, -20); $formeArrivee->drawLine(0, -10); $formeArrivee->drawLine(0, -10); // L (6 segments) $formeArrivee->movePenTo(30, -30); $formeArrivee->drawLine(10, 0); $formeArrivee->drawLine(0, 50); $formeArrivee->drawLine(20, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(-30, 0); $formeArrivee->drawLine(0, -60); // E (12 segments) $formeArrivee->movePenTo(70, -30); $formeArrivee->drawLine(30, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(-20, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(10, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(-10, 0); $formeArrivee->drawLine(0, 20); $formeArrivee->drawLine(20, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(-30, 0); $formeArrivee->drawLine(0, -60); // ! (8 segments) $formeArrivee->movePenTo(110, -30); $formeArrivee->drawLine(10, 0); $formeArrivee->drawLine(0, 40); $formeArrivee->drawLine(-10, 0); $formeArrivee->drawLine(0, -40); $formeArrivee->movePenTo(110, 20); $formeArrivee->drawLine(10, 0); $formeArrivee->drawLine(0, 10); $formeArrivee->drawLine(-10, 0); $formeArrivee->drawLine(0, -10); $anim = new SWFMovie(); $anim->setDimension(400, 100); $anim->nextFrame(); $vueMorph=$anim->add($morph); $vueMorph->moveTo(200, 50);

13. Les images et les animations Flash 1128

Les animations Flash

for ($i=0; $i<=20; $i++) { $vueMorph->setRatio($i/20); $anim->nextFrame(); } header("Content-type: application/x-shockwave-flash"); $anim->output();

?>

Des animations interactives


Il est possible de rendre interactives ces animations en ajoutant des objets boutons. Les boutons sont des objets qui sinstancient par un appel au constructeur SWFButton.

SWFButton
Objet bouton. Syntaxe SWFButton SWFButton(void)

13. Les images et les animations Flash

Cet objet propose deux mthodes : lune pour prciser laspect visuel du bouton, lautre pour prciser les actions dclencher. SWFButton propose galement une srie de mthodes que lon qualifiera de raccourcis. Laspect visuel peut dpendre de ltat du bouton (enfonc ou non, survol par le curseur de la souris ou non). On distingue ainsi quatre tats, dfinis par les constantes :
j j j j
SWFBUTTON_UP : ltat par dfaut, cest--dire bouton non enfonc. SWFBUTTON_OVER : bouton non enfonc, mais survol par le curseur de la souris. SWFBUTTON_DOWN : bouton enfonc. SWFBUTTON_HIT.

Pour dfinir laspect visuel du bouton, on fera donc appel (autant de fois que ncessaire pour prciser la reprsentation du bouton dans les diffrents tats) la mthode :

SWFButton->addShape()
Associe une forme un ou plusieurs tats du bouton. Syntaxe $forme $etat void addShape(SWFShape $forme, int $etat)) Objet qui doit reprsenter lobjet lorsquil est dans ltat prcis. Un ou plusieurs des tats prsents prcdemment. Pour prciser plusieurs tats, vous utiliserez loprateur logique OU (ce qui donne par exemple SWFBUTTON_UP|SWFBUTTON_OVER).

1129

Chapitre 13

Les images et les animations Flash

Qui a donn naissance aux raccourcis :


j j j j
setUp($forme) quivalant addShape($forme, SWFBUTTON_UP) ; setOver($forme) quivalant addShape($forme, SWFBUTTON_OVER) ; setDown($forme) quivalant addShape($forme, SWFBUTTON_DOWN) ; setHit($forme) quivalant addShape($forme, SWFBUTTON_HIT).

Pour dfinir les actions associes un bouton, nous ferons appel la mthode :

SWFButton->addAction()
Associe une action un bouton. Syntaxe $action $evenement void addAction(SWFAction $action, int $evenement) Action dclencher. Une des valeurs suivantes (ou combinaison avec un OU logique) : SWFBUTTON_MOUSEOVER : cet vnement est dclench linstant o le curseur de la souris entre dans lobjet (bouton non enfonc). SWFBUTTON_MOUSEOUT : cet vnement est dclench linstant o le curseur de la souris sort de lobjet (bouton non enfonc). SWFBUTTON_MOUSEDOWN cet vnement est dclench linstant o le bouton de la souris est enfonc, alors que le curseur se situe au-dessus de lobjet. SWFBUTTON_MOUSEUP : cet vnement est dclench linstant o le bouton de la souris est relch, alors que le curseur se situe au-dessus de lobjet. Cest gnralement sur cet vnement que sont dclenches les actions. SWFBUTTON_DRAGOUT : cet vnement est dclench linstant o le curseur de la souris quitte lobjet, alors que le bouton a t enfonc dans lobjet et est maintenu enfonc lors du dplacement de lobjet. Autrement dit lors dun cliquer-glisser hors de lobjet. SWFBUTTON_DRAGOVER : cet vnement est dclench linstant o le curseur de la souris entre dans lobjet, alors que le bouton a t enfonc dans lobjet et est maintenu enfonc lors du dplacement de lobjet. Autrement dit lors dun cliquer-glisser hors puis dans lobjet. SWFBUTTON_MOUSEUPOUTSIDE : cet vnement est dclench linstant o le bouton est relch en dehors de lobjet aprs avoir t enfonc dans lobjet et maintenu enfonc lors du dplacement de lobjet. Autrement dit lissue dun cliquer-glisser hors de lobjet.

13. Les images et les animations Flash

La mthode addAction() possde un raccourci :


j
setAction($action) quivalant addAction($action, SWFBUTTON_MOUSEUP).

Lobjet action sinstancie en appelant le constructeur SWFAction().

1130

Les animations Flash

SWFAction
Instancie un objet Action. Syntaxe $script SWFAction SWFAction(string $script) Action script a excuter.

Ressources Javascript Vous trouverez une liste de sites consacrs Flash (et lAction script) ladresse http://www.macromedia.com/fr/support/flash/ts/documents/flash_websites.htm. Le document de rfrence Action script est disponible en anglais ladresse : http://www.macromedia.com/support/flash/action_scripts/.
Les actions peuvent tre appliques directement lobjet animation (SWFMovie) lui-mme. Ainsi, une des premires actions que vous serez sans doute amen demander sera larrt de lanimation (afin, par exemple, de ne pas drouler toute lanimation sans avoir au pralable cliqu sur un bouton). Cela se faisant simplement par :

13. Les images et les animations Flash

<?php // (...) creation de lanimation $anim->add(new SWFAction("stop();")); ....// (...) gnration/affichage de lanimation ?>

Importance du point-virgule Il est indispensable de terminer toutes les instructions, y compris la dernire, par un point-virgule.
Nous verrons un exemple plus complet dutilisation de lAction Script aprs avoir vu les objets SWFSprite.

Les sous-animations
Afin de pouvoir grer plus facilement les diffrents lments dune animation, il est possible de crer des sous-animations. Ces sous-animations reprennent pour ainsi dire les proprits dune animation. Elles peuvent sinstancier par un appel au constructeur SWFSprite().

SWFSprite
Instancie un objet sous-animation.

1131

Chapitre 13

Les images et les animations Flash

Syntaxe retour

SWFSprite SWFSprite() Objet SWFSprite.

Et elles possdent les mthodes suivantes :

SWFSprite->add()
Ajoute un objet la sous-animation. Syntaxe $objet SWFDisplayItem add(mixed $objet) Objet ajouter la sous-animation. Ce peut tre un objet SWFText, SWFTextField, SWFShape, SWFMorph, SWFButton, SWFAction ou SWFSprite. Un objet SWFDisplayItem uniquement pour les objets graphiques.

retour

13. Les images et les animations Flash

SWFSprite->remove()
Supprime un objet de la sous-animation. Syntaxe $refObjet void remove(SWFDisplayItem $refObjet) Rfrence de lobjet supprimer tel que retourne par la mthode add().

SWFSprite->nextFrame()
Valide la vue courante et passe la suivante. Syntaxe void nextFrame(void) On notera, cependant, quil nest pas possible dimposer des vitesses de dfilement diffrentes dune sous-animation lautre. Ces sous-animations se manipulent exactement comme nimporte quel autre objet. Elles sajoutent lanimation principale par appel la mthode add(), et retournent un objet SWFDisplayItem qui permet de les dplacer, agrandir, rduire, dformer, etc. Rappelons quil est possible de leur donner un nom grce la mthode setName() de SWFDisplayItem. Ceci est particulirement utile lorsquil sagit de faire rfrence une sous-animation depuis un script "Action script".

1132

Les animations Flash

Application : jeu du solitaire


Voici, un exemple dutilisation de lAction Script faisant intervenir la notion de cliquer-dposer (drag and drop), les sous-animations (ici les pions) et quelques tests conditionnels.

Listing 13.40 : ming_solitaire.php


<?php $dessinTrou = new SWFShape(); $dessinTrou->setRightFill(0, 0, 0); $dessinTrou->movePenTo(-5, -5); $dessinTrou->drawLine(10, 0); $dessinTrou->drawLine(0, 10); $dessinTrou->drawLine(-10, 0); $dessinTrou->drawLine(0, -10); $spriteTrou = new SWFSprite(); $spriteTrou->add($dessinTrou); $spriteTrou->nextFrame(); // Le Pion sera blanc par dfaut $dessinPion = new SWFShape(); $dessinPion->setRightFill(255, 255, 255); $dessinPion->movePenTo(-4, -4); $dessinPion->drawLine(8, 0); $dessinPion->drawLine(0, 8); $dessinPion->drawLine(-8, 0); $dessinPion->drawLine(0, -8); // Le Pion sera jaune lorsque le curseur de la souris // sera dessus $dessinPionSurvole = new SWFShape(); $dessinPionSurvole ->setRightFill(255, 255, 125); $dessinPionSurvole ->movePenTo(-4, -4); $dessinPionSurvole ->drawLine(8, 0); $dessinPionSurvole ->drawLine(0, 8); $dessinPionSurvole ->drawLine(-8, 0); $dessinPionSurvole ->drawLine(0, -8); // Le Pion sera rouge lorsque le bouton de la souris // sera enfonc $dessinPionEnfonce = new SWFShape(); $dessinPionEnfonce ->setRightFill(255, 0, 0); $dessinPionEnfonce ->movePenTo(-4, -4); $dessinPionEnfonce ->drawLine(8, 0); $dessinPionEnfonce ->drawLine(0, 8); $dessinPionEnfonce ->drawLine(-8, 0); $dessinPionEnfonce ->drawLine(0, -8); $boutonPion = new SWFButton();

13. Les images et les animations Flash 1133

Chapitre 13

Les images et les animations Flash

// Dclaration des diffrents tats du pion (bouton) $boutonPion->addShape($dessinPion, SWFBUTTON_UP | SWFBUTTON_HIT); $boutonPion->addShape($dessinPionSurvole, SWFBUTTON_OVER); $boutonPion->addShape($dessinPionEnfonce, SWFBUTTON_DOWN); // Dclaration des diffrentes oprations raliser // selon les vnements // Si le bouton est enfonc, cest que lon est en train // de dplacer le pion $boutonPion->addAction(new SWFAction("startDrag(this,0);"), SWFBUTTON_MOUSEDOWN); // Si le bouton est relach, cest que lon est en train // dposer le pion $boutonPion->addAction( new SWFAction( // Arreter le dplacement du pion "stopDrag();". "deplacementValide = TRUE;". // Contrler o le pion a t dplac // Il doit sagir dun trou "if (this._droptarget.substr(1,4) != trou) {". " deplacementValide = FALSE;". "};". // Rcupration des coordonnes initiales // du pion dplac "chaine = \"\"+this;". "tableau = chaine.split(.);". "pion = tableau[tableau.length-1];". "pion = pion.substr(4);". "tableau = pion.split(x);". "pionx = parseInt(tableau[0]);". "piony = parseInt(tableau[1]);". "if (deplacementValide) {". " trou = this._droptarget.substr(5);". " tableau = trou.split(x);". " troux = parseInt(tableau[0]);". " trouy = parseInt(tableau[1]);". // Le trou doit tre 2 case a gauche, droite, haut ou bas // du point de dpart du pion " if (((Math.abs(pionx-troux) != 2)&&". " (Math.abs(piony-trouy) != 2)) ||". " ((Math.abs(pionx-troux)+Math.abs(piony-trouy))>2)) {". " deplacementValide = FALSE;". " };". "};". "if (deplacementValide) {". // Le pion doit sauter un autre pion "pionsautex=(troux+pionx)/2;". "pionsautey=(trouy+piony)/2;".

13. Les images et les animations Flash 1134

Les animations Flash

"if (_level0[pion+pionsautex+x+pionsautey]._visible". " != TRUE) {". " deplacementValide = FALSE;". "};". "};". "if (deplacementValide) {". // Si cest ok. Alors on affiche le nouveau pion // et on cache le pion dplac et le pion saut // Affichage du nouveau pion "_level0[pion+troux+x+trouy]._visible=TRUE;". // Suppression du pion saut "_level0[pion+pionsautex+x+pionsautey]._visible=FALSE;". // Suppression du pion dplac "this._visible=FALSE;". "};". // Quoiquil arrive on remet le pion sa place "this._x=12+pionx*12;". "this._y=12+piony*12;" ), SWFBUTTON_MOUSEUP | SWFBUTTON_MOUSEUPOUTSIDE); $spritePion = new SWFSprite(); $spritePion->add($boutonPion); $spritePion->nextFrame(); $anim = new SWFMovie(); $anim->setDimension(150, 150); $anim->setBackground(125, 125, 255); $anim->setRate(1); $anim->add(new SWFAction("stop();")); $larg=3; // Positionne les trous en croix for ($x=0; $x<3*$larg; $x++) { for ($y=0; $y<3*$larg; $y++) { $tierx = floor($x/$larg); $tiery = floor($y/$larg); if ( (($tierx+$tiery)%2 == 1) ||(($tierx == 1) && ($tiery == 1))) { $trou[$x][$y] = $anim->add($spriteTrou); $trou[$x][$y]->setName("trou".$x."x".$y); $trou[$x][$y]->moveTo(12+$x*12,12+$y*12); } } } // Positionne tous les pions // tous les endroits possibles for ($x=0; $x<3*$larg; $x++) { for ($y=0; $y<3*$larg; $y++) { $tierx = floor($x/$larg);

13. Les images et les animations Flash 1135

Chapitre 13

Les images et les animations Flash

$tiery = floor($y/$larg); if ( (($tierx+$tiery)%2 == 1) ||(($tierx == 1) && ($tiery == 1))) { $pion[$x][$y] = $anim->add($spritePion); $pion[$x][$y]->setName("pion".$x."x".$y); $pion[$x][$y]->moveTo(12+$x*12,12+$y*12); } } } // Masque le pion du milieu $anim->add(new SWFAction("pion4x4._visible=FALSE;")); $anim->nextFrame(); header("Content-type: application/x-shockwave-flash"); $anim->output(); Figure 13.46 : Un solitaire en Flash

?>

13. Les images et les animations Flash 1136

Chapitre 14

La cration de documents PDF


14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 14.10 14.11 14.12 14.13 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1139 Crer la base dun document PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1140 Prciser les attributs (mots-cls) du document . . . . . . . . . . . . . . . . . . . . .1144 Prciser les paramtres de la page . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1144 Afficher du texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1146 Dessiner des formes gomtriques . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1152 Modier les paramtres du trac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1157 Inclure une image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1163 Ajouter des liens et des annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1166 Ajouter des chiers attachs et aperus (thumbnails) . . . . . . . . . . . . . . . . .1170 Modier le systme de coordonnes . . . . . . . . . . . . . . . . . . . . . . . . . . . .1171 Lire, sauvegarder et restaurer les paramtres courants . . . . . . . . . . . . . . . . .1173 Crer un modle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1178

Installation

HP permet de crer des documents PDF la vole. Il est ainsi possible de crer ce type de documents partir dinformations rcupres dun formulaire ou dune base de donnes. Pour cela, nous disposons notamment de la bibliothque PDFLib.
PDFLib est gratuite sauf dans le cas dun usage commercial.

Cette bibliothque est toujours en dveloppement et de nombreuses fonctions ont t modifies. Le peu de documentation disponible et les changements soudains dans le nom et les paramtres des fonctions peuvent causer des problmes dune version lautre de PDFLib. Mais cela ne devrait pas vous empcher dutiliser cette bibliothque.

14.1. Installation
Sous Windows
Avec larchive du PHP Group
Avec PHP 5, Vous devez copier le fichier php_pdf.dll disponible dans le paquetage PECL du PHP Group dans le rpertoire des extensions PHP. Avec PHP 4, pas de soucis, la DLL fait dj parti de larchive de PHP Group. Dans tous les cas, il vous faut ensuite modifier le fichier php.ini pour ajouter ou dcommenter une ligne :
extension=php_pdf.dll

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur linstallation du paquetage PECL.

14. La cration de documents PDF

Avec EasyPHP
Le support de PDF est activ par dfaut avec EasyPHP.

Sous Linux
Lextension PDF nest plus disponible avec les sources de la version 5 de PHP. Avec PHP4, vous devez, dans un premier temps, vous procurer la bibliothque PDFLib disponible sur le site (en anglais) http://www.pdflib.com/ (il sagit du fichier PDFlib-5.0.1-Linux.tar.gz). Aprs avoir copi larchive dans un rpertoire quelconque (disons /usr/local/src/lib), vous devez la dcompresser.
# gunzip PDFlib-5.0.1-Linux.tar.gz # tar xvf PDFlib-5.0.1-Linux.tar

Il vous est ensuite possible de lancer la compilation.


# ./configure

1139

Chapitre 14

La cration de documents PDF

# make # make install

Vous disposez dsormais dune srie de fichiers libpdf* sous le rpertoire /usr/local/lib. Il vous suffit alors de recompiler PHP avec loption withpdflib=/usr/local.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur la compilation de PHP.

Les polices dcriture


Pour utiliser une police dcriture, celle-ci devra tre disponible et dclare dans un fichier pdflib.upr. Quelques polices dcriture et un fichier pdflib.upr sont fournis avec la bibliothque (sous le rpertoire fonts). Vous pouvez copier ce rpertoire dans un endroit quelconque (/usr/local/fonts par exemple). Pour utiliser les polices fournies, vous devrez modifier le fichier pfdlib.upr en dcommentant et modifiant le chemin prcis pour les polices. Ce qui, dans notre cas, donnerait (le slash devant le chemin est important) :
//usr/local/fonts

Si vous disposez dautres polices dcriture, vous devrez complter ce fichier en consquence. Le chemin vers ce fichier doit tre dclar dans une variable denvironnement PDFLIBRESOURCE.

14. La cration de documents PDF

Idalement, cette variable devra tre dfinie dans le compte sous lequel le serveur tourne. Il est toutefois possible de la dclarer au niveau des scripts PHP.
putEnv("PDFLIBRESOURCE=/chemin_vers_pdflib_url/pdflib.url");

Vrication
Pour vrifier lactivation du support de PDFLib, appelez lhabituel script contenant <?php phpinfo(); ?>. Celui-ci doit afficher :

Figure 14.1 : phpinfo()

14.2. Crer la base dun document PDF


La cration dun document PDF passe par un certain nombre dtapes obligatoires. Il faut tout dabord crer un "objet" (il ne sagit toutefois pas dun vritable objet, mais plutt dune ressource) grce la fonction pdf_new(). Les ressources ainsi alloues devront, au final, tre libres par un appel la fonction pdf_delete().

1140

Crer la base dun document PDF

pdf_new()
Cre un nouvel objet PDF en lui allouant la mmoire ncessaire. Syntaxe retour resource pdf_new(void) Un identifiant dobjet PDF.

pdf_delete()
Libre les ressources alloues pour un objet PDF. Syntaxe $objetPDF retour boolean pdf_delete(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

Une fois un objet PDF cr, vous devrez crer un document PDF. Pour cela, vous disposez de la fonction pdf_open_file() qui vous permettra de crer, au choix, un fichier ou le document en mmoire. Le document ainsi gnr devra tre valid par un appel pdf_open_close().

pdf_open_le()
Ouvre un nouveau document PDF (sous forme de fichier ou en mmoire). Syntaxe $objetPDF $nomFichier boolean pdf_open_file(resource $objetPDF , string $nomFichier) Identifiant tel que retourn par pdf_new(). Nom et chemin absolu du fichier crer. Si cet attribut est une chane vide, alors le document sera juste cr en mmoire. Avec PHP4, ce paramtre tait tout simplement optionnel. TRUE.

14. La cration de documents PDF

retour

pdf_close()
Ferme le document PDF. Syntaxe $objetPDF retour boolean pdf_close(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

1141

Chapitre 14

La cration de documents PDF

Si vous avez opt pour un document cr en mmoire, vous devrez obligatoirement faire appel la fonction pdf_get_buffer() aprs lappel pdf_close(), et avant celui pdf_delete().

pdf_get_buffer()
Permet de rcuprer le contenu de la mmoire dun objet PDF quand celui-ci na pas t sauvegard dans un fichier. Syntaxe $objetPDF retour string pdf_get_buffer(resource $objetPDF) Identifiant tel que retourn par pdf_new(). Le fichier PDF dans une chane de caractres.

Et, enfin, chaque document doit ncessairement contenir au moins une page. Lajout et la cration dune page dbute par un appel pdf_begin_page() et se termine par un appel pdf_end_page().

pdf_begin_page()
Crer une nouvelle page. Syntaxe boolean pdf_begin_page(resource $objetPDF, double $largeur, double $hauteur) Identifiant tel que retourn par pdf_new(). Largeur en points. Hauteur en points. TRUE.

14. La cration de documents PDF

$objetPDF $largeur $hauteur retour

Voici un tableau de correspondances en points des formats les plus courants :

Tableau 14.1 : Les tailles en points des formats courants de papier


Format A0 (84 x 118,8 cm) A1 (59,4 x 84 cm) A2 (42 x 59,4 cm) A3 (29,7 x 42 cm) A4 (21 x 29,7 cm) A5 (14,85 x 21 cm) A6 (10,5 x 14.85 cm) Taille en points 2380 x 3368 1684 x 2380 1190 x 1684 842 x 1190 595 x 842 421 x 595 297 x 421

1142

Crer la base dun document PDF

Format B5 (17.67 x 25 cm) Letter (8.5" x 11") Legal (8.5" x 14") Ledger (17" x 11")

Taille en points 501 x 709 612 x 792 612 x 1008 1224 x 792

pdf_end_page()
Termine la page courante. Syntaxe $objetPDF retour boolean pdf_end_page(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

Le squelette dun script de gnration dun document PDF aura donc lallure suivante dans le cas de la gnration dun fichier :
<?php $pdf = pdf_new(); pdf_open_file($pdf, "monFichier.pdf"); // Appel aux fonctions prcisant les informations // lis au fichier // Puis autant de pdf_begin_page() pdf_end_page() que ncessaire pdf_begin_page($pdf, 595, 842); // Page en A4 // Contenu de la page pdf_end_page($pdf); pdf_close($pdf); pdf_delete($pdf); ?>

14. La cration de documents PDF

Et il aura lallure suivante dans le cas dun document cr en mmoire et envoy au navigateur :
<?php $pdf = pdf_new(); pdf_open_file($pdf, ""); // Appel aux fonctions prcisant les informations // lis au fichier // Puis autant de pdf_begin_page() pdf_end_page() que ncessaire pdf_begin_page($pdf, 595, 842); // Page en A4 // Contenu de la page pdf_end_page($pdf); pdf_close($pdf); $donnees = pdf_get_buffer($pdf); pdf_delete($pdf);

1143

Chapitre 14

La cration de documents PDF

header("Content-type: application/pdf"); header("Content-length: ".strlen($donnees)); header("Content-disposition: inline; filename=test.pdf"); echo $donnees; ?>

Il est videmment possible denvoyer le document au navigateur, mme lorsque celui-ci est stock dans un fichier. Il suffit, pour cela, de lire le contenu du fichier, comme nous le ferons dans le prochain exemple.

14.3. Prciser les attributs (mots-cls) du document


Pour chaque document PDF, il est possible de dfinir des mots-cls, le nom de lauteur, etc.

pdf_set_info()
Permet de remplir les informations dun fichier PDF. Syntaxe $objetPDF boolean pdf_set_info(resource $objetPDF, string $cle, string $valeur) Identifiant tel que retourn par pdf_new(). Pouvant prendre les valeurs prdfinies "Subject", "Title", "Creator", "Author", "Keywords" ou une valeur dfinie par lutilisateur ( lexception des mots rservs "CreationDate", "Producer", "ModDate" et "Trapped"). Valeur associe la cl. TRUE.

14. La cration de documents PDF

$cle

$value retour

Lappel pdf_set_info() se fera en dehors de la cration dune page (en dehors dun bloc pdf_begin_page(), pdf_end_page()).

14.4. Prciser les paramtres de la page


Pour chaque page du document, il est possible de dfinir (ou redfinir) les paramtres devant tre utiliss.

1144

Prciser les paramtres de la page

pdf_set_value()
Permet dattribuer une valeur aux paramtres de la page (taux de compression, interligne, etc). Syntaxe $objetPDF $parametre $valeur retour boolean pdf_set_value(resource $objetPDF, string $parametre, double $valeur) Identifiant tel que retourn par pdf_new(). Paramtre dfinir. Valeur attribuer. TRUE.

Voici un tableau des valeurs pouvant tre modifies :

Tableau 14.2 : Valeurs pouvant tre modifies par pdf_set_value()


Cl compress Valeur Valeur par dfaut Dfinit la compression du document entre 0 et 9. 0 6 indique quil ny a pas de compression tandis que 9 est la compression la plus forte. Modifie la largeur de la page courante. Modifie la largeur de la page courante. Modifie la hauteur de la page courante. Modifie lespace entre deux lignes de base de deux lignes conscutives. Modifie lespace entre la position dsire du texte et 0 (et remis 0 la ligne de base. chaque nouvelle page). 0 pour du texte plein. 1 pour navoir que le contour du texte. 2 pour du texte plein et le contour. 3 pour ne pas afficher le texte, mais lajouter au chemin. Pourcentage pour largir ou rtrcir le texte. Espace entre deux caractres ajouter lespacement par dfaut. Espace ajouter la taille du caractre despacement. Dfinit le temps daffichage en secondes pour la page courante. 0

pagewidth pagewidth pageheight leading Textrise textrendering

14. La cration de documents PDF

Horizscaling charspacing wordspacing duration

100 0 0 1

Il est galement possible dajouter des signets aux pages.

1145

Chapitre 14

La cration de documents PDF

pdf_add_bookmark()
Ajoute un signet une page. Syntaxe $objetPDF $texte $parent $ouvrir retour int pdf_add_bookmark(resource $objetPDF, string $texte, int $parent, boolean $ouvrir) Identifiant tel que retourn par pdf_new(). Label du signet. Identifiant du signet parent (0 revient crer un signet la racine de larborescence). Ce paramtre est optionnel avec PHP4. Si cet argument vaut TRUE, alors les enfants du signet seront visibles. Ce paramtre est optionnel avec PHP4. Identifiant de signet (pouvant servir de paramtre parent pour un autre signet).

14.5. Afficher du texte


Avant dafficher du texte, vous devrez slectionner une police dcriture. Vous ne pouvez toutefois slectionner une police dcriture que si celle-ci a t prcdemment charge (ou tout au moins ajoute la liste des polices utilises).

14. La cration de documents PDF

pdf_ndFont()
Ajoute une police dcriture la liste des polices. Syntaxe $objetPDF $nomPolice $encodage $integrer retour int pdf_findFont(resource $objetPDF, string $nomPolice, string $encodage, boolean $integrer) Identifiant tel que retourn par pdf_new(). Nom de la police dcriture utiliser. "builtin", "macroman", "winansi", "ebcdic", "host" ou un nom dfini par lutilisateur. TRUE si la police doit tre intgre au document , FALSE sinon (le lecteur devra avoir la police sa disposition). Un identifiant de police dcriture, ou FALSE.

1146

Afficher du texte

pdf_setFont()
Dfinit la police dcriture courante. Syntaxe $objetPDF $police $taille retour boolean pdf_setFont(resource $objetPDF, int $police, double $taille) Identifiant tel que retourn par pdf_new(). Identifiant tel que retourn par pdf_findFont(). Taille de la police (en points). TRUE.

Une fois ce travail effectu, vous pouvez commencer envisager dajouter du texte votre document grce, notamment, la fonction pdf_show_xy().

pdf_show_xy()
Affiche du texte une position dfinie par ses coordonnes. Syntaxe $objetPDF $texte $x $y retour boolean pdf_show_xy(resource $objetPDF, string $texte, double $x, double $y) Identifiant tel que retourn par pdf_new(). Texte afficher. Abscisse du bord gauche du texte (lorigine du document est en bas gauche de la page). Ordonne de la ligne de base du texte (lorigine du document est en bas gauche de la page). TRUE.

14. La cration de documents PDF

Les fonctions que nous avons vues jusqu prsent nous permettent de crer le script (assez simple) suivant :

Listing 14.1 : pdf1.php


<?php $nomFichier="test.pdf"; // Creation dun pdf $pdf = pdf_new(); // Ouverture dun fichier en ecriture le nom // du fichier est un chemin absolu. pdf_open_file($pdf, $nomFichier); // Definition de lauteur du document pdf_set_info($pdf, "Author", "Thomas, Damien, Laurent et Pem");

1147

Chapitre 14

La cration de documents PDF

// Definition du titre pdf_set_info($pdf, "Title", "Mon premier PDF en PHP"); // Definition du createur du PDF pdf_set_info($pdf, "Creator", "The PHP bible team :)"); // Definition du sujet pdf_set_info($pdf, "Subject", "PDF en PHP"); // Creation dune page de 595 points par 842 (A4) // (72 points par pouce soit 28,368 par cm) pdf_begin_page($pdf, 595, 842); // Donne le label "La page" a la page pdf_add_bookmark($pdf, "La page", 0, TRUE); // Definit la police courante $font = pdf_findfont($pdf, "Courier", "host", FALSE); if ($font) { pdf_setfont($pdf, $font, 30); } else { die ("Police decriture introuvable"); }// Definit la valeur de textrendering pdf_set_value($pdf, "textrendering", 1); // Affiche le texte "Trop trop cool ce truc" aux coordonnees (50,750) // (50,750) est le point inferieur gauche de la ligne de base // La ligne de base est la ligne inferieur naturelle // (p,q,y... descendent en dessous) // Le point (0,0) est le point inferieur gauche du document) pdf_show_xy($pdf, "Trop trop cool ce truc", 50, 750); // Termine la page pdf_end_page($pdf); // Ferme le document PDF pdf_close($pdf); // Efface lobjet PDF de la memoire et les ressources associees pdf_delete($pdf); /*************************************/ /* Cette partie concerne laffichage */ /* du document, le fichier est deja */ /* cree sur le disque dur. */ /*************************************/ $taille = filesize($nomFichier); header("Content-type: application/pdf"); header("Content-Length: $taille"); header("Content-Disposition: inline; filename=test.pdf"); readfile($nomFichier); ?>

14. La cration de documents PDF 1148

Afficher du texte

Dont laffichage serait :


Figure 14.2 : crire du texte dans un fichier PDF

Il est galement possible dcrire du texte la position courante du pointeur de texte, ce qui permet, en particulier, dajouter du texte la suite du texte prcdent.

14. La cration de documents PDF

pdf_show()
Affiche du texte la position courante du pointeur. Syntaxe $objetPDF $texte retour boolean pdf_show(resource $objetPDF, string $texte) Identifiant tel que retourn par pdf_new(). Texte afficher. TRUE.

La position courante du pointeur de texte peut tre modifie tout instant grce la fonction
pdf_set_text_pos().

pdf_set_text_pos()
Modifie la position courante du pointeur de texte. Syntaxe boolean pdf_set_text_pos(resource $objetPDF, double $x, double $y)

1149

Chapitre 14

La cration de documents PDF

$objetPDF $x $y retour

Identifiant tel que retourn par pdf_new(). Abscisse du pointeur. Ordonne du pointeur. TRUE.

Vous naurez toutefois pas besoin davoir recours des calculs savants pour crire du texte sur une nouvelle ligne.

pdf_continue_text()
Affiche du texte la ligne suivante. Lespace entre deux lignes est dtermin par la variable leading qui peut tre modifie par pdf_set_value(). Syntaxe $objetPDF $texte void pdf_continue_text(int $objetPDF, string $texte) Identifiant tel que retourn par pdf_new(). Texte afficher.

De mme, lcriture sur plusieurs colonnes se trouve grandement simplifie par la fonction
pdf_show_boxed().

14. La cration de documents PDF

pdf_show_boxed()
Permet dafficher un texte dans un rectangle virtuel ; lalignement et les retours la ligne seront automatiquement grs pour tre ajusts au rectangle. Syntaxe int pdf_show_boxed(resource $objetPDF, string $texte, double $gauche, double $haut, double $largeur, double $hauteur, string $alignement, string $option) Identifiant tel que retourn par pdf_new(). Texte afficher. Abscisse du bord gauche. Ordonne du bord suprieur. Largeur du rectangle (positionner largeur et hauteur 0 revient crire sur une ligne). Hauteur du rectangle (positionner largeur et hauteur 0 revient crire sur une ligne). Au choix : "left" pour un alignement gauche. "right" pour un alignement droite. "center" pour centrer le texte.

$objetPDF $texte $gauche $haut $largeur $hauteur $alignement

1150

Afficher du texte

"justify" pour un texte justifi (sauf la dernire ligne qui sera aligne gauche). "fulljustify" pour un texte justifi (y compris la dernire ligne). $option "blind" si vous ne souhaitez pas afficher le texte mais simplement faire un test (pour, par exemple, dterminer si avec les valeurs choisies tout le texte rentre dans le rectangle). Ce paramtre est optionnel avec PHP 4. Le nombre de caractres qui nont pu tre contenus dans le rectangle.

retour

Un petit penchant pour lcriture incline ? Si vous souhaitez crire un texte inclin, il vous suffit de faire pivot sur les axes des coordonnes (comme nous le verrons plus loin).

Largeur dun texte

pdf_stringWidth()
Retourne la largeur dune chane de caractres en points en utilisant, par dfaut, la police dcriture courante. Syntaxe $objetPDF $texte $police $taille retour double pdf_stringWidth(resource $objetPDF, string $texte, int $police, double $taille) Identifiant tel que retourn par pdf_new(). Texte dont on veut connatre la largeur. Identifiant de police de caractres tel que retourn pdf_findFont(). Ce paramtre est optionnel avec PHP 4. Taille de la police dcriture. Ce paramtre est optionnel avec PHP 4. La largeur de la chane de caractres en utilisant la police dcriture dfinie. par

14. La cration de documents PDF

Les paramtres de la police dcriture

pdf_get_parameter()
Retourne des informations lies la police de caractres utilise. Syntaxe string pdf_get_parameter(int $objetPDF, string $cle, double $remplace)

1151

Chapitre 14

La cration de documents PDF

$objetPDF $cle $remplace retour

Identifiant tel que retourn par pdf_new(). Nom du paramtre rcuprer. Valeur de remplacement. Ce paramtre est optionnel avec PHP 4. La valeur du paramtre.

Tableau 14.3 : Paramtre rcuprable par pdf_get_parameter()


Cl fontencoding underline overline strikeout Description Rcupre le nom de lencodage de la police dcriture prdfinie par pdf_set_font(). Retourne la chane de caractres "true" si le texte est soulign, "false" sinon. Retourne la chane de caractres "true" si le texte est surlign, "false" sinon. Retourne la chane de caractres "true" si le texte est barr, "false" sinon.

14.6. Dessiner des formes gomtriques


Maintenant que nous avons vu comment crire du texte dans un document PDF, voyons comment nous pouvons dessiner.

14. La cration de documents PDF

Le trac se fait en dessinant des cercles, des rectangles, en traant des segments entre la position courante du curseur et un point quelconque, en modifiant la position courante du curseur, etc. Mais, quoi quil arrive, le trac doit tre valid par un appel aux fonctions pdf_*_stroke() (pour tracer le contour), pdf_*_fill() (pour remplir la forme ainsi trace) ou pdf_*_fill_stroke() (pour remplir et tracer le contour de la forme).

Les lignes
Pour tracer une ligne, vous serez sans doute amen dplacer le curseur.

pdf_moveTo()
Dfinit la nouvelle position du pointeur graphique. Syntaxe $objetPDF $x $y retour boolean pdf_moveTo(resource $objetPDF, double $x, double $y) Identifiant tel que retourn par pdf_new(). Abscisse du pointeur graphique. Ordonne du pointeur graphique. TRUE.

1152

Dessiner des formes gomtriques

pdf_lineTo()
Trace un segment depuis la position du pointeur graphique jusquaux coordonnes passes en paramtre. Syntaxe $objetPDF $x $y retour boolean pdf_lineTo(resource $objetPDF, double $x, double $y) Identifiant tel que retourn par pdf_new(). Abscisse de la fin du segment. Ordonne de la fin du segment. TRUE.

Les rectangles

pdf_rect()
Permet de dessiner un rectangle (le pointeur graphique prend alors la position du coin infrieur gauche du rectangle). Syntaxe $objetPDF $x $y $largeur $hauteur retour boolean pdf_rect(resource $objetPDF, double $x, double $y, double $largeur, double $hauteur) Identifiant tel que retourn par pdf_new(). Abscisse du bord gauche du rectangle. Ordonne du bord infrieur du rectangle. Largeur du rectangle. Hauteur du rectangle. TRUE.

14. La cration de documents PDF

Les cercles et arcs de cercle

pdf_circle()
Dessine un cercle (le pointeur graphique prend alors la position de lextrmit droite du cercle). Syntaxe $objetPDF $x $y boolean pdf_circle(resource $objetPDF, double $x, double $y, double $rayon) Identifiant tel que retourn par pdf_new(). Abscisse du centre de larc. Ordonne du centre de larc.

1153

Chapitre 14

La cration de documents PDF

$rayon retour

Rayon de larc. TRUE.

pdf_arc()
Dessine un arc de cercle dans le sens trigonomtrique (un segment reliera la position courante du pointeur la premire extrmit de larc, et le pointeur graphique sera dplac la seconde extrmit de larc). Syntaxe $objetPDF $x $y $rayon $angle1 $angle2 retour boolean pdf_arc(resource $objetPDF, double $x, double $y, double $rayon, double $angle1, double $angle2) Identifiant tel que retourn par pdf_new(). Abscisse du centre de larc. Ordonne du centre de larc. Rayon de larc. Angle de dpart (en degrs). Angle de fin (en degrs). TRUE.

14. La cration de documents PDF

pdf_arcn()
Dessine un arc de cercle dans le sens horaire (un segment reliera la position courante du pointeur la premire extrmit de larc, et le pointeur graphique sera dplac la seconde extrmit de larc). Syntaxe $objetPDF $x $y $rayon $angle1 $angle2 retour void pdf_arcn(resource $objetPDF, double $x, double $y, double $rayon, double $angle1, double $angle2) Identifiant tel que retourn par pdf_new(). Abscisse du centre de larc. Ordonne du centre de larc. Rayon de larc. Angle de dpart (en degrs). Angle de fin (en degrs). TRUE.

1154

Dessiner des formes gomtriques

Les courbes de Bzier

pdf_curveTo()
Permet de tracer une courbe de Bzier cubique entre la position courante du pointeur graphique et les coordonnes du dernier point prcis (qui deviendra la nouvelle position du pointeur) en sappuyant sur deux autres points. Syntaxe $objetPDF $x1 $y1 $x2 $y2 $x3 $y3 retour boolean pdf_curveto(resource $objetPDF, double $x1, double $y1, double $x2, double $y2, double $x3, double $y3) Identifiant tel que retourn par pdf_new(). Abscisse du premier point dappui Ordonne du premier point dappui. Abscisse du deuxime point dappui. Ordonne du deuxime point dappui. Abscisse du point darrive. Ordonne du point darrive. TRUE.

Clture et validation du trac


14. La cration de documents PDF
Si vous souhaitez fermer la figure que vous venez de dessiner, sans avoir prciser les coordonnes du point initial du trac, vous devez faire appel pdf_closePath().

pdf_closePath()
Permet de clore un trac. Syntaxe $objetPDF retour boolean pdf_closePath(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

Toutefois, un appel pdf_closePath() ne valide pas le trac du contour (opration qui doit ncessairement tre faite avant lappel pdf_end_page()), contrairement aux fonctions qui suivent.

1155

Chapitre 14

La cration de documents PDF

pdf_closepath_stroke()
Permet de clore un trac et dafficher le contour. Syntaxe $objetPDF retour boolean pdf_closepath_stroke(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

pdf_closePath_ll_stroke()
Permet de clore un trac, de le remplir et dafficher le contour (les couleurs du remplissage et du contour tant dfinies par pdf_selColor()). Syntaxe $objetPDF retour boolean pdf_closePath_fill_stroke(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

Si, toutefois, vous considrez que votre trac est ferm, vous pouvez appeler les fonctions suivantes :

14. La cration de documents PDF

pdf_stroke()
Permet dafficher le trac. Syntaxe $objetPDF retour boolean pdf_stroke(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

pdf_ll()
Permet de remplir un trac. Syntaxe $objetPDF retour boolean pdf_fill(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

1156

Modifier les paramtres du trac

pdf_ll_stroke()
Permet de remplir un trac et den afficher le contour (les couleurs du remplissage et du contour tant dfinies par pdf_selColor()). Syntaxe $objetPDF retour boolean pdf_fill_stroke(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

14.7. Modier les paramtres du trac


Il est, bien entendu, possible de jouer sur les paramtres du trac (comme la couleur, la largeur du trac, etc.). Mais attention, ceci ne peut se faire que si le trac na pas t commenc (i.e. juste aprs avoir valid le trac prcdent).

La couleur

pdf_setColor()
Dfinit la couleur de trait et/ou de remplissage.

14. La cration de documents PDF

Syntaxe $objetPDF $type

boolean pdf_setColor(resource $objetPDF, string $type, string $palette, numeric $c1, double $c2, double $c3, double $c4) Identifiant tel que retourn par pdf_new(). lment dont vous souhaitez changer la couleur : "fill" pour changer la couleur de remplissage. "stroke" pour changer la couleur du trait. "both" pour changer les deux (et leur donner la mme couleur). Prcise comment vous souhaitez identifier la couleur : "gray" si vous souhaitez indiquer un niveau de gris. "rgb" si vous souhaitez prciser les composantes rouge, verte et bleue de la couleur. "cmyk" si vous souhaitez prciser les composantes cyan, magenta, jaune et noire de la couleur. "spot" si vous souhaitez prciser lidentifiant de la couleur (dans le cas dune couleur dfinie par pdf_makeSpotColor() dcrite ci-aprs). "pattern". Selon les cas : Niveau de gris (0 = noir, 1 = blanc) dans le cas "gray". Composante rouge (entre 0 et 1) dans le cas "rgb". Composante cyan (entre 0 et 1) dans le cas "cmyk".

$palette

$c1

1157

Chapitre 14

La cration de documents PDF

Identifiant de la couleur dans le cas "spot". Indice dans la palette dans le cas "pattern". $c2 Selon les cas : (Ce paramtre est optionnel avec PHP4) Coefficient appliquer la couleur (entre 0 = noir et 1 = couleur sauvegarde) dans le cas "spot". Composante verte (entre 0 et 1) dans le cas "rgb". Composante magenta (entre 0 et 1) dans le cas "cmyk" Selon les cas : (Ce paramtre est optionnel avec PHP4) Composante bleue (entre 0 et 1) dans le cas "rgb". Composante jaune (entre 0 et 1) dans le cas "cmyk" Composante noire (entre 0 et 1, uniquement dans le cas "cmyk"). Ce paramtre est optionnel avec PHP4. TRUE.

$c3

$c4 retour Quelques exemples :

// Dfinit la couleur de remplissage bleu pdf_setColor($pdf, "fill", "rgb", 0, 0, 1); // Dfinit la couleur de trait gris clair pdf_setColor($pdf, "stroke", "gray", 0.8); // Dfinit la couleur de trait et de remplissage rouge pdf_setColor($pdf, "both", "cmyk", 1, 0, 0, 0.7);

Comme cela a t voqu au cours de la description de la fonction prcdente, il est possible dattribuer un identifiant une couleur (ce qui est plus simple dutilisation). Pour cela, il faut utiliser la fonction pdf_makeSpotColor().

14. La cration de documents PDF

pdf_makeSpotColor()
Retourne un identifiant pour la couleur de remplissage courante. Syntaxe $objetPDF $nom retour int pdf_makespotcolor(resource $objetPDF, string $nom) Identifiant tel que retourn par pdf_new(). Nom donner la couleur. Identifiant de la couleur.

La largeur, les extrmits et les bords

pdf_setLineWidth()
Permet de modifier lpaisseur du trait. Syntaxe boolean pdf_setLineWidth(resource $objetPDF, double $largeur)

1158

Modifier les paramtres du trac

$objetPDF $largeur retour

Identifiant tel que retourn par pdf_new(). Largeur du trait (en points). TRUE.
Figure 14.3 : Largeur du trait

pdf_setLineJoin()
Dfinit la forme du coin form par deux segments dont on a demand tracer le contour. Syntaxe $objetPDF $formeCoin boolean pdf_setLineJoin(resource $objetPDF, int $formeCoin) Identifiant tel que retourn par pdf_new(). Au choix : 0 pour un coin obtus. 1 pour un coin arrondi. 2 pour un coin plat. TRUE.
Figure 14.4 : Diffrents codes pour diffrents coins

retour

14. La cration de documents PDF

pdf_setLineCap()
Dfinit la faon dont doivent tre affiches les extrmits des segments. Syntaxe $objetPDF $style boolean pdf_setLineCap(resource $objetPDF, int $style) Identifiant tel que retourn par pdf_new(). Au choix : 0 pour une extrmit plate. 1 pour une extrmit arrondie. 2 pour une extrmit carre. TRUE.
Figure 14.5 : Diffrents codes pour diffrents bouts

retour

1159

Chapitre 14

La cration de documents PDF

pdf_setMiterLimit()
Dfinit la hauteur du coin (cf. dessin). Syntaxe $objetPDF $hauteur retour boolean pdf_setmiterlimit(resource $objetPDF, double $hauteur) Identifiant tel que retourn par pdf_new(). Hauteur maximale du coin. TRUE.
Figure 14.6 : Hauteur dun coin (miter)

Il est grand temps prsent de mettre en pratique certaines des fonctions vues jusque-l.

Listing 14.2 : pdf2.php


<?php // Creation dun pdf $pdf = pdf_new(); // Ouverture dun fichier en ecriture le nom // du fichier est un chemin absolu. pdf_open_file($pdf, ""); pdf_begin_page($pdf, 595, 842); // Deplacement du curseur en (50, 740) pdf_moveto($pdf, 50, 740); // Definit un trait jusquen (315, 740) pdf_lineto($pdf, 340, 740); // Definition dun arc de cercle dans le sens trigonometrique pdf_arc ($pdf, 340, 700, 40, 90, 270); // Definition dun arc de cercle dans le sens horaire pdf_arcn($pdf, 340, 620, 40, 90, 180); // Deplacement du curseur en (50, 740) pdf_moveto($pdf, 50, 740); // Definition dun cercle de centre (30, 740) et de rayon 20 pdf_circle($pdf, 30, 740, 20); // Dessine le circuit trace precedemment et le remplit pdf_fill($pdf); //Modification de lepaisseur du trait pour le trace suivant pdf_setlinewidth($pdf, 10); // Deplacement du curseur en (50, 400) pdf_moveto($pdf, 50, 400); // Definition dun rectangle en (50, 600) de largeur 20 // et de hauteur 40 pdf_rect($pdf, 50, 600, 20, 40); // Dessin du rectangle pdf_stroke($pdf); // Termine la page

14. La cration de documents PDF 1160

Modifier les paramtres du trac

pdf_end_page($pdf); // Ferme le document PDF pdf_close($pdf); // Rcupre les donnes du document PDF $donnees = pdf_get_buffer($pdf); // Efface lobjet PDF de la memoire et les ressources associes pdf_delete($pdf); /*************************************/ /* Cette partie concerne laffichage */ /* du document, les donnes sont */ /* prtes, il suffit de les envoyer. */ /*************************************/ header("Content-type: application/pdf"); header("Content-Length: ".strlen($donnees)); header("Content-Disposition: inline; filename=test.pdf"); echo $donnees; ?>

Voici ce qui doit tre obtenu :


Figure 14.7 :

Dessiner un PDF en PHP

14. La cration de documents PDF

Les pointills
Il est possible de dfinir des pointills simples...

1161

Chapitre 14

La cration de documents PDF

pdf_setDash()
Permet de dfinir le type de pointills. Syntaxe $objetPDF $trace $nonTrace retour void pdf_setDash(resource $objetPDF, double $trace, double $nonTrace) Identifiant tel que retourn par pdf_new(). Nombre de points tracer avant de suspendre le trac. Nombre de points ne pas tracer avant de reprendre le trac. TRUE.

... comme de plus complexes.

pdf_setPolyDash()
Permet de dfinir un type de pointills complexe. Syntaxe $objetPDF $tableauPoints boolean pdf_setPolyDash(resource $objetPDF, array $tableauPoints) Identifiant tel que retourn par pdf_new(). Tableau de points (nombre de points tracer, puis nombre de points ne pas tracer, puis nombre de points tracer, etc). TRUE.
Figure 14.8 : Les pointills

14. La cration de documents PDF

retour

Rinitialiser les paramtres


Il est possible de rtablir les valeurs par dfaut de ces paramtres avec la fonction suivante :

pdf_initGraphics()
Rinitialise les paramtres graphiques (couleurs, tracs, axes) leurs valeurs par dfaut. Syntaxe $objetPDF retour boolean pdf_initGraphics(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

1162

Inclure une image

Comme indiqu, cette fonction rtablit les axes de coordonnes leur position initiale, car (nous le verrons plus loin dans ce chapitre) il est possible de les modifier.

14.8. Inclure une image


Pour inclure une image, vous devez au pralable ouvrir un fichier image, ce qui peut se faire avec pdf_open_image_file(). Les ressources ainsi alloues devront plus tard tre libres par un appel pdf_close_image().

pdf_open_image_le()
Lit une image depuis un fichier. Syntaxe int pdf_open_image_file(resource $objetPDF, string $typeImage, string $nomFichier, string $parametreChaine, string $parametreEntier) Identifiant tel que retourn par pdf_new(). Type de limage, au choix "jpeg", "tiff", "gif" ou "png". Nom et chemin du fichier. Au choix : NULL, mask, masked, ignoremask, invert, page ou colorize. Ce paramtre est optionnel avec PHP4. 0, lidentifiant de limage du masque ou numro de page. Ce paramtre est optionnel avec PHP4. Identifiant de limage.

$objetPDF $typeImage $nomFichier $parametreChaine $parametreEntier retour

14. La cration de documents PDF

pdf_close_image()
Libre les ressources alloues par une image. Syntaxe $objetPDF $idImage void pdf_close_image(resource $objetPDF, int $idImage) Identifiant tel que retourn par pdf_new(). Identifiant dimage tel que retourn par pdf_open_image_file().

Pour ajouter limage la page, vous disposez de pdf_place_image().

1163

Chapitre 14

La cration de documents PDF

pdf_place_image()
Place une image dans la page. Syntaxe $objetPDF $idImage boolean pdf_place_image(resource $objetPDF, int $idImage, double $x, double $y, double $echelle) Identifiant tel que retourn par pdf_new(). Identifiant dimage tel que retourn par pdf_open_image_file() ou pdf_open_memory_image() (ou identifiant de modle tel que retourn par pdf_begin_template()). Abscisse du bord gauche de limage. Ordonne du bord infrieur de limage. chelle pour agrandir ou rtrcir limage. TRUE.

$x $y $echelle retour

Le script suivant ouvre une image dans une page PDF de 100 sur 100.

Listing 14.3 : imagefile.php


<?php // Creation dun pdf $pdf = pdf_new(); pdf_open_file($pdf, ""); pdf_begin_page($pdf, 100, 100);

14. La cration de documents PDF

$logopdf = pdf_open_image_file($pdf, "png", "logo.png", "", 0); pdf_place_image($pdf, $logopdf, 0, 0, 1); pdf_close_image($pdf, $logopdf); // Termine la page pdf_end_page($pdf); // Ferme le document PDF pdf_close($pdf); // Lit les donnes du document PDF $donnees = pdf_get_buffer($pdf); // Efface lobjet PDF de la memoire et les ressources associees pdf_delete($pdf); /*************************************/ /* Cette partie concerne laffichage */ /* du document, les donnes sont */ /* prtes, il suffit de les envoyer. */ /*************************************/ header("Content-type: application/pdf"); header("Content-Length: ".strlen($donnees)); header("Content-Disposition: inline; filename=test.pdf"); echo $donnees; ?>

1164

Inclure une image

dont le rsultat est :


Figure 14.9 : Insrer une image dans un document PDF

Il est galement possible dutiliser des images ouvertes ou cres avec GD.

pdf_open_memory_image()
Ouvre une image obtenue par la librairie GD. Syntaxe $objetPDF $idImageGD retour int pdf_open_memory_image(resource $objetPDF, resource $idImageGD) Identifiant tel que retourn par pdf_new(). Identifiant dimage tel que retourn par les fonctions imageCreate() ou imageCreateFromXXX() de la bibliothque GD. Identifiant de limage (PDF).

14. La cration de documents PDF

Dcoupe dune image


Il est assez simple de ne reprsenter quune partie de limage, ou de lui donner des contours ayant une forme un peu particulire. Cest ce que permet la fonction pdf_clip().

pdf_clip()
Permet de dcouper une partie de limage dfinie prcdemment par un trac. Syntaxe boolean pdf_clip(int $objetPDF)

1165

Chapitre 14

La cration de documents PDF

$objetPDF retour

Identifiant tel que retourn par pdf_new(). TRUE.

<?php // (...) Initialisation $img = pdf_open_image_file($pdf, "png", "logo.png", NULL, 0); pdf_circle($pdf, 50, 50, 50); pdf_clip($pdf); pdf_place_image($pdf, $img, 0, 0, 1); pdf_close_image($pdf, $img); // (...) Cloture ?> Figure 14.10 : Utilisation de clip

14.9. Ajouter des liens et des annotations


Liens PDF
Il vous est possible dinsrer un lien vers une autre page du document...

14. La cration de documents PDF

pdf_add_locallink()
Ajoute un lien vers une autre page du mme fichier PDF. Syntaxe $objetPDF $x1 $y1 $x2 $y2 $noPage $zoom boolean pdf_add_locallink(resource $objetPDF, double $x1, double $y1, double $x2, double $y2, int $noPage, string $zoom) Identifiant tel que retourn par pdf_new(). Abscisse du point infrieur gauche. Ordonne du point infrieur gauche. Abscisse du point suprieur droit. Ordonne du point suprieur droit. Page de destination. Au choix : "retain" pour conserver le facteur de zoom actuel louverture du document li. "fitpage" pour adapter le zoom de faon ce que le document li tienne dans la fentre.

1166

Ajouter des liens et des annotations

"fitwith" pour adapter le zoom de faon ce que la largeur du document li tienne dans la fentre. "fitheight pour adapter le zoom de faon ce que la hauteur du document li tienne dans la fentre. "fitbbox" pour adapter le zoom de faon ce que le contenu du document (donc sans tenir compte des marges) tienne dans la fentre. retour TRUE.

... ou vers celle dun autre document.

pdf_add_pdink()
Ajoute un lien vers un fichier PDF. Syntaxe boolean pdf_add_pdflink(int $objetPDF, double $x1, double $y1, double $x2, double $y2, string $nomFichier, int $noPage, string $zoom) Identifiant tel que retourn par pdf_new(). Abscisse du point infrieur gauche. Ordonne du point infrieur gauche. Abscisse du point suprieur droit. Ordonne du point suprieur droit. Nom du fichier vers lequel faire un lien. Numro de la page ouvrir. Au choix : "retain" pour conserver le facteur de zoom actuel louverture du document li. "fitpage" pour adapter le zoom de faon ce que le document li tienne dans la fentre. "fitwith" pour adapter le zoom de faon ce que la largeur du document li tienne dans la fentre. "fitheight pour adapter le zoom de faon ce que la hauteur du document li tienne dans la fentre. "fitbbox" pour adapter le zoom de faon ce que le contenu du document (donc sans tenir compte des marges) tienne dans la fentre. TRUE.

$objetPDF $x1 $y1 $x2 $y2 $nomFichier $noPage $zoom

14. La cration de documents PDF

retour

1167

Chapitre 14

La cration de documents PDF

Liens Internet

pdf_add_weblink()
Ajoute un lien vers une adresse Internet. Syntaxe $objetPDF $x1 $y1 $x2 $y2 $url retour boolean pdf_add_weblink(resource $objetPDF, double $x1, double $y1, double $x2, double $y2, string $url) Identifiant tel que retourn par pdf_new(). Abscisse du point infrieur gauche. Ordonne du point infrieur gauche. Abscisse du point suprieur droit. Ordonne du point suprieur droit. Adresse du site web de destination. TRUE.

Liens vers un chier

pdf_add_launchlink()
Ajoute un lien vers un fichier.

14. La cration de documents PDF

Syntaxe $objetPDF $x1 $y1 $x2 $y2 retour

int pdf_add_launchlink(resource $objetPDF, double $x1, double $y1, double $x2, double $y2, string $nomFichier); Identifiant tel que retourn par pdf_new(). Abscisse du point infrieur gauche. Ordonne du point infrieur gauche. Abscisse du point suprieur droit. Ordonne du point suprieur droit. TRUE.

Annotations

pdf_add_note()
Ajoute une annotation pour la page courante. Syntaxe boolean pdf_add_note(resource $objetPDF, double $x1, double $y1, double $x2, double $y2, string $contenu, string $titre, string $icone, boolean $ouvrir)

1168

Ajouter des liens et des annotations

$objetPDF $x1 $y1 $x2 $y2 $contenu $titre $icone $ouvrir retour

Identifiant tel que retourn par pdf_new(). Abscisse du point infrieur gauche de la zone de dploiement de lannotation. Ordonne du point infrieur gauche de la zone de dploiement de lannotation. Abscisse du point suprieur droit de la zone de dploiement de lannotation. Ordonne du point suprieur droit de la zone de dploiement de lannotation. Texte de lannotation. Titre de lannotation. Icne a afficher, au choix : "comment", "insert", "note", "paragraph", "newparagraph", "key" ou "help". TRUE si le commentaire doit tre visible par dfaut, FALSE sinon. TRUE.

Icne Sous Windows XP et Acrobat Reader 5.0, licne affiche est toujours note. Il semblerait que ce soit le cas pour toutes les versions 3 dAcrobat Reader et au moins les versions 4 sous UNIX. Selon la documentation officielle, cela aurait d fonctionner sous lenvironnement de test Mais en pratique, cela ne fonctionne pas. 14. La cration de documents PDF

Modier lapparence des contours des liens et annotations


Il est possible de dfinir lapparence des contours des liens et annotations grce aux fonctions suivantes :

pfd_set_border_style()
Dfinit laspect des bordures (largeur du trait, pointills ou non) des liens et des annotations. Syntaxe $objetPDF $style boolean pdf_set_border_style(resource $objetPDF, string $style, double $epaisseur) Identifiant tel que retourn par pdf_new(). Au choix : "solid" pour un trait continu. "dashed" pour des pointills. paisseur du trait. TRUE.

$epaisseur retour

La nature des pointills peut videmment tre prcise.

1169

Chapitre 14

La cration de documents PDF

pdf_set_border_dash()
Permet de dfinir le type des pointills appliqus aux contours des liens et des annotations. Syntaxe $objetPDF $trace $nonTrace retour boolean pdf_set_border_dash(resource $objetPDF, double $trace, double $nonTrace) Identifiant tel que retourn par pdf_new(). Nombre de points tracer avant de suspendre le trac. Nombre de points ne pas tracer avant de reprendre le trac. TRUE.

pdf_set_border_color()
Dfinit la couleur des contours des liens et annotations. Syntaxe $objetPDF $rouge $vert $bleu boolean pdf_set_border_color(resource $objetPDF, double $rouge, $vert, $bleu) Identifiant tel que retourn par pdf_new(). Composante rouge de la couleur du contour (entre 0 et 1). Composante verte de la couleur du contour (entre 0 et 1). Composante bleue de la couleur du contour (entre 0 et 1). TRUE.

14. La cration de documents PDF

retour

14.10. Ajouter des chiers attachs et aperus (thumbnails) pdf_add_thumbnail()


Ajoute une petite image (thumbnail) pour la page courante. Syntaxe $objetPDF $idImage retour boolean pdf_add_thumbnail(resource $objetPDF, int $idImage) Identifiant tel que retourn par pdf_new(). Identifiant dimage tel que retourn par pdf_open_image_file() ou pdf_open_memory_image(). TRUE.

1170

Modifier le systme de coordonnes

pdf_attach_le()
Ajoute un fichier attach pour la page courante. Syntaxe boolean pdf_attach_file(int $objetPDF, double $x1, double $y1, double $x2, double $y2, string $nomFichier, string $description, string $auteur, string $mimetype, string $icone) Identifiant tel que retourn par pdf_new(). Abscisse du point infrieur gauche. Ordonne du point infrieur gauche. Abscisse du point suprieur droit. Ordonne du point suprieur droit. Nom du fichier attacher. Description du fichier attach. Auteur du fichier attach. Type MIME du fichier (ex: "text/plain"). Icne associe, au choix : "graph" graphique. "paperclip" trombone. "pushpin" punaise. "tag" tiquette. TRUE.

$objetPDF $x1 $y1 $x2 $y2 $nomFichier $description $auteur $mimetype $icone

retour

14. La cration de documents PDF

14.11. Modier le systme de coordonnes pdf_translate()


Redfinit lorigine du systme. Syntaxe $objetPDF $x $y retour boolean pdf_translate(resource $objetPDF, double $x, double $y) Identifiant tel que retourn par pdf_new(). Abscisse du nouveau centre. Ordonne du nouveau centre. TRUE.

1171

Chapitre 14

La cration de documents PDF

pdf_rotate()
Permet de tourner le systme de coordonnes. Syntaxe $objetPDF $angle retour boolean pdf_rotate(resource $objetPDF, double $angle) Identifiant tel que retourn par pdf_new(). Angle de rotation (en degrs) par rapport au systme de coordonnes actuel. TRUE.

pdf_skew()
Modifie les axes du systme de coordonnes (permet davoir un repre non orthonorm). Syntaxe $objetPDF $angle1 $angle2 boolean pdf_skew(resource $objetPDF, double angle1, double angle2) Identifiant tel que retourn par pdf_new(). Angle de rotation (en degrs) de laxe des abscisses par rapport au systme de coordonnes actuel. Angle de rotation (en degrs) de laxe des ordonnes par rapport au systme de coordonnes actuel. TRUE.

14. La cration de documents PDF

retour

pdf_scale()
Redfinit lchelle. Syntaxe $objetPDF $echelleX $echelleY retour boolean pdf_scale(resource $objetPDF, double $echelleX, double $echelleY) Identifiant tel que retourn par pdf_new(). Coefficient appliquer sur lchelle des abscisses. Coefficient appliquer sur lchelle des ordonnes. TRUE.

Si par hasard vous ne trouviez pas votre bonheur avec les fonctions prcdentes, vous pouvez encore prciser votre propre matrice de transformation (i.e. combiner les appels prcdents en un appel unique).

1172

Lire, sauvegarder et restaurer les paramtres courants

pdf_setMatrix()
Remplace la matrice de transformation courante par une autre. Syntaxe $objetPDF boolean pdf_setMatrix(resource $objetPDF, double $m11, double $m21, double $m12, double $m22, double $m13, double $m23) Identifiant tel que retourn par pdf_new().

$m11, $m21, $m12, $m22, $m13, $m23 Les lments de la matrice de transformation (3x2) [[$m11, $m12, $m13][$m21, $m22, $m23]]. retour TRUE.

pdf_concat()
Concatne une matrice la matrice courante de transformation. Syntaxe $objetPDF boolean pdf_concat(resource $objetPDF, double $m11, double $m21, double $m12, double $m22, double $m13, double $m23) Identifiant tel que retourn par pdf_new().

$m11, $m21, $m12, $m22, $m13, $m23 Les lments de la matrice de transformation (3x2) [[$m11, $m12, $m13][$m21, $m22, $m23]]. retour TRUE.

14. La cration de documents PDF

14.12. Lire, sauvegarder et restaurer les paramtres courants pdf_get_value()


Rcupre la valeur dun paramtre (certains peuvent tre modifis par pdf_set_value()). Syntaxe $objetPDF $cle $valeur retour double pdf_get_value(int $objetPDF, string $cle, double $valeur) Identifiant tel que retourn par pdf_new(). Nom de la valeur rcuprer. Nouvelle valeur. Ce paramtre est optionnel avec PHP4. La valeur recherche.

Voici un tableau de diffrentes valeurs pouvant tre obtenues :

1173

Chapitre 14

La cration de documents PDF

Tableau 14.4 : Valeurs pouvant tre obtenues par pdf_get_value()


Cl major minor revision version Description Rcupre le numro principal de version de PDFLib. Rcupre le numro secondaire de version de PDFLib. Rcupre le numro de rvision de PDFLib. Rcupre le numro de version complet sous la forme major.minor.revision suivi ventuellement de chanes telles que beta, rc Rcupre le nom de ltendue courante. Largeur de la page courante en points. Hauteur de la page courante en points. Change les tailles des botes de la page courante. Le nom de la cl doit tre suivi dun slash / puis de llx (abscisse du point infrieur gauche), lly (ordonne du point infrieur gauche), urx (abscisse du point suprieur gauche), ury (ordonne du point suprieur droit). Par exemple Cropbox/llx permettra de modifier labscisse infrieure gauche de la Cropbox. Retourne lidentifiant de la police dcriture qui doit avoir t dfinie par pdf_setfont(). Retourne la taille de la police dcriture prcdemment dfinie par pdf_setfont(). Retourne les valeurs des tailles pour laffichage de caractres en fraction de taille de police. Capheight est la taille dune majuscule. Ascender est la taille dune lettre haute telle que l, f, k, t Capheight est juste la taille de la partie basse dune lettre descendante comme j, p, q Aprs ce tableau se trouve une image expliquant ces trois valeurs. Modifie lespace entre deux lignes de base de deux lignes conscutives. Modifie lespace entre la position dsire du texte et la ligne de base. 0 pour du texte plein. 1 pour navoir que le contour du texte. 2 pour du texte plein et le contour. 3 pour ne pas afficher le texte mais lajouter au chemin. Pourcentage pour largir ou rtrcir le texte. Espace entre deux caractres ajouter lespacement par dfaut. Espace ajouter la taille du caractre despacement. Retourne labscisse courante du pointeur de texte. Retourne lordonne courante du pointeur de texte. Labscisse du point graphique courant. Lordonne du point graphique courant.

scope pagewidth pageheight Cropbox BleedBox ArtBox TrimBox

font fontsize capheight ascender descender

14. La cration de documents PDF

leading textrise textrendering

horizscaling charspacing wordspacing textx texty currentx currenty

1174

Lire, sauvegarder et restaurer les paramtres courants

Cl Imagewidth imageheight resx resy

Description Retourne la largeur et la hauteur dune image en pixel. Il faut passer en paramtre lidentifiant de limage. Retourne les rsolutions horizontales et verticales dune image. Il faut passer en paramtre lidentifiant de limage. Si la valeur est positive, la valeur retourne est exprime en points par pouce ; sinon la valeur na pas de sens, mais permet de dterminer le rapport entre la largeur et la hauteur dun point. Si la valeur est nulle, alors linformation sur la rsolution nest pas accessible.
Figure 14.11 : capheight, ascender et descender en images

pdf_set_parameter()
Permet de dfinir un paramtre. Syntaxe $objetPDF $cle $valeur void pdf_set_parameter(resource $objetPDF, string $cle, string $valeur) Identifiant tel que retourn par pdf_new(). Nom du paramtre.

14. La cration de documents PDF

Valeur du paramtre.

Voici un tableau des diffrents paramtres attribuables :

Tableau 14.5 : Paramtres attribuables par pdf_set_parameter()


Cl compatibility Description Permet de dfinir la compatibilit. Elle peut tre dfinie en 1.3, 1.4 ou 1.5 pour Acrobat 3, Acrobat 4 ou Acrobat 5. Ce changement de paramtre doit tre effectu avant tout appel pdf_open_*(). Prfixe utilis dans un fichier UPR. Nom du fichier de configuration UPR. Dfinit le numro de srie de la bibliothque PDFLib ; il ne peut tre modifi quune seule fois avant le premier appel pdf_begin_page(). Permet ou supprime les messages dalerte. Peut tre mis "true" ou "false". (Par dfaut, les messages sont apparents.) "true" Dfaut 1.3

Prefix Resourcefile Serial

Warning

1175

Chapitre 14

La cration de documents PDF

Cl FontAFM FontPFM FontOutline Encoding fontwarning

Description Les fichiers de ressources tels quils doivent apparatre dans un fichier UPR. Pour en ajouter plusieurs, il suffit dappeler plusieurs fois la fonction. SI cette valeur est mise "false" alors, pdf_findfont() renverra 0 au lieu dun message derreur. Permet de dfinir laspect dune chane de caractres ("true" ou "false") : Underline pour le soulignement. Overline pour le surlignage. Strikeout pour du texte barr. Si la valeur est mise "true" alors le texte Unicode natif est permis. Change la rgle de remplissage courante. Cette rgle est utilise par les visionneurs de fichier PDF, mais conduisent au mme rsultat. Les valeurs permises sont "winding" ou "evendd".

Dfaut

"true"

underline overline strikeout

"false"

nativeunicode Fillrule

"false" "winding"

Imagewarning

Ce paramtre peut servir savoir pourquoi une image "false" na pas pu tre ouverte correctement. Si ce paramtre est mis "true" alors un message derreur est gnr, sinon aucun message derreur nest gnr. Contrle de limportation des attributs graphiques avec les pages et mises en page. "true", les attributs graphiques seront imports. "false", les attributs graphiques ne seront pas imports. Dfinit laction douverture ou encore le grossissement de la premire page du document. Les diffrentes valeurs possibles sont : "retain" pour conserver la valeur actuelle. "fitpage" pour que le zoom fasse en sorte que la page tienne lcran. "fitwidth" pour que la largeur tienne lcran. "fitheight" pour que la hauteur tienne lcran. "fitbbox" pour que le contenu de la page (sans tenir compte des bords) tienne lcran. "true"

14. La cration de documents PDF

openaction

"retain"

1176

Lire, sauvegarder et restaurer les paramtres courants

Cl openmode

Description Dfinit lapparence quand le document est ouvert. "none", ni les signets ni les imagettes ne sont visibles. "bookmarks", les signets safficheront louverture du document. "thumbnails", les imagettes safficheront. "fullscreen", le document souvrira sur tout lcran si celui-ci nest pas dans un navigateur Internet. Dfinit le zoom pour laffichage des signets. Les diffrentes valeurs possibles sont : "retain" pour conserver la valeur actuelle. "fitpage" pour que le zoom fasse en sorte que la page tienne lcran. "fitwidth" pour que la largeur tienne lcran. "fitheight" pour que la hauteur tienne lcran. "fitbbox" pour que le contenu de la page (sans tenir compte des bords) tienne lcran. Dfinit la transition dune page une autre. Les diffrentes valeurs possibles sont : "split", "blinds", "box", "wipe", "dissolve", "glitter", "replace".

Dfaut "bookmarks" si le document contient des signets. "none" sinon.

bookmarkdest

"retain"

transition

"replace"

Sauvegarder et restaurer
Il est galement possible de sauvegarder lenvironnement courant pour le rutiliser plus tard. Les axes de coordonnes, couleurs, paisseurs de traits peuvent ainsi tre changs aprs avoir sauvegard lenvironnement, pour ensuite recharger les mmes paramtres de dpart.

14. La cration de documents PDF

pdf_save()
Enregistre lenvironnement courant. Syntaxe $objetPDF retour boolean pdf_save(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

1177

Chapitre 14

La cration de documents PDF

pdf_restore()
Redfinit lenvironnement graphique avec les informations stockes lors de lappel pdf_save(). Syntaxe $objetPDF retour boolean pdf_restore(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

14.13. Crer un modle


Il est possible de crer un modle de page qui servira de base pour la cration de pages. Lavantage principal rside dans le fait quune modification apporte ce modle sappliquera toutes les pages y faisant rfrence. Aprs avoir cr un modle, il suffit, pour lutiliser,il de le considrer comme une image. Ainsi, pour lajouter la page, vous naurez qu appeler la fonction pdf_place_image(). Un modle de page doit tre dfini en dehors de toute section page (pdf_begin_page() ...pdf_end_page()). Un modle de page peut faire appel un autre modle de page, mais pas lui-mme. Toutes les fonctions agissant sur le texte, les graphiques et les couleurs peuvent tre utilises, exception faite des fonctions douverture et de fermeture dimages et des lments hypertextes.

14. La cration de documents PDF

Introduire des images Il nest pas possible douvrir des images dans les modles, mais il est possible de les placer. Il suffit donc de les ouvrir avant de dfinir le modle.

pdf_begin_template()
Dbute la description dun modle. Syntaxe $objetPDF $largeur $hauteur retour int pdf_begin_template(resource $objetPDF, double $largeur, double $hauteur) Identifiant tel que retourn par pdf_new(). Largeur du modle. Hauteur du modle. Un identifiant de modle.

1178

Crer un modle

pdf_end_template()
Termine la description dun modle. Syntaxe $objetPDF retour boolean pdf_end_template(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.

Lexemple qui suit utilise ces deux fonctions.

Un exemple de script
Lexemple que nous avons choisi de dtailler est un fax de facture avec une page de garde. Les renseignements ncessaires la facture sont rcuprs depuis un formulaire HTML. Voici le script HTML du formulaire que nous ne dtaillerons pas (il ne sagit ni plus ni mois que dune page HTML) :

Listing 14.4 : facture.html


<html> <head><title>Facture></title></head> <body> <center><h1> <font color="#0000FF">Creation de facture en fichier PDF</font> </h1></center> <form method="post" action="facture.php"> <h2>Informations sur le destinataire</h2> <table align="center"> <tr> <td>Nom:</td> <td><input type="text" name="nom" /></td> </tr> <tr> <td>Prenom:</td> <td><input type="text" name="prenom" /></td> </tr> <tr> <td>Numero de fax:</td> <td><input type="text" name="fax" /></td> </tr> </table> <h2>Informations sur la facture</h2> <table align="center"> <tr> <td>Numero de facture:</td> <td><input type="text" name="no" /></td> </tr> <tr>

14. La cration de documents PDF 1179

Chapitre 14

La cration de documents PDF

<td>Montant:</td> <td><input type="text" name="montant" /></td> </tr> <tr> <td>Prestation:</td> <td><textarea name="prestation"></textarea></td> </tr> </table> <center><input type="submit" /></center> </form> </body> </html>

14. La cration de documents PDF

Figure 14.12 : Exemple de formulaire rempli

La page dappel facture.php traite toute la partie crant le fichier PDF.

Listing 14.5 : facture.php


<?php // Largeur de la page $largeur=495; // Hauteur de la page $hauteur=742; // Creation dun pdf $pdf = pdf_new(); // Allocation de memoire pdf_open_file($pdf, "");

1180

Crer un modle

// Ouverture de limage de logo $logopdf = pdf_open_image_file($pdf, "png", "logo.png", "", 0); // Definition dun nouveau modele de taille inferieure a la page $miseEnPage = pdf_begin_template($pdf, $largeur-100, $hauteur-100); // Choisir la police Courier de taille 15 $font = pdf_findfont($pdf, "Courier", "host", FALSE); if ($font) { pdf_setfont($pdf, $font, 15); } else { die ("Police decriture introuvable"); } // Demande dafficher que le contour du texte pdf_set_value($pdf, "textrendering", 1); // Affichage de "Bible PHP" pdf_show_xy($pdf, "Bible PHP" , 175, $hauteur-125); // Choisir la police Courier de taille 8 pdf_setfont($pdf, $font, 8); // Demande dafficher du texte plein pdf_set_value($pdf, "textrendering", 0); // Affichage de ladresse de lexpediteur dans un rectangle // en justifiant le texte pdf_show_boxed($pdf, "Bible PHP\r\nChemin des acacias\r\n20876 Germantown\r\n". "Tel: 02 00 00 00 00", 0, $hauteur-100-100, 100, 100, "fulljustify"); // Placement du logo sur le modele pdf_place_image($pdf, $logopdf, $largeur-100-50, $hauteur-100-50, 0.5); //Changement de la taille du texte 8 points pdf_setfont($pdf, $font, 8); // Affiche un texte centre en bas de page pdf_show_boxed($pdf, "Copyright. SARL Capital 0 Euros", 0, 0, $largeur-100, 15, "center"); //Fin de la definition du modle pdf_end_template($pdf); // Fermeture de limage ouverte avant la declaration du modle pdf_close_image($pdf, $logopdf);

14. La cration de documents PDF

// Creer une nouvelle page: la page de garde pdf_begin_page($pdf, $largeur, $hauteur); // Placement du modele sur la page

1181

Chapitre 14

La cration de documents PDF

pdf_place_image($pdf, $miseEnPage, 50, 50, 1); // Choisir la police Courier de taille 10 $font = pdf_findfont($pdf, "Courier", "host", FALSE); if ($font) { pdf_setfont($pdf, $font, 10); } else { die("Police decriture introuvable"); } // Demande dafficher du texte plein pdf_set_value($pdf, "textrendering", 0); // Affichage du nom et du numero de fax du destinataire pdf_show_boxed($pdf, "Pour: ".$_POST["nom"]." ".$_POST["prenom"]. "\r\nFax: ".$_POST["fax"], $largeur-200, $hauteur-300, 150, 100, "right", ""); // Changement de la taille du texte 14 points pdf_setfont($pdf, $font, 14); // Demande dafficher du texte plein pdf_set_value($pdf, "textrendering", 0); // Texte afficher $texte = "Monsieur,\r\n\r\n". " Vous trouverez dans ce fac-simile, une facture comme". " nous avions convenu. Le montant de cette facture est". " hors taxes et". " payable a lordre de \"Monsieur Bible PHP\".\r\n". " Nous venons de modifier notre systeme de gestion de factures". " et nous serons heureux de vous envoyer cette facture par ". " courrier electronique dans un format". " lisible par tous, le PDF.\r\n\r\nRecevez Monsieur, mes meilleures". " salutations.\r\n\r\n ". " Le president."; // Affichage du texte precedent sur la page pdf_show_boxed($pdf, $texte , 50, 100, $largeur-100, 400, "justify", ""); // Termine la page pdf_end_page($pdf); // Creer une nouvelle page: la facture pdf_begin_page($pdf, $largeur, $hauteur); // Placement du modele sur la page pdf_place_image($pdf, $miseEnPage, 50, 50, 1); // Choisir la police Courier de taille 10 $font = pdf_findfont($pdf, "Courier", "host", FALSE); if ($font) { pdf_setfont($pdf, $font, 10); } else { die("Police decriture introuvable"); }

14. La cration de documents PDF 1182

Crer un modle

// Demande dafficher du texte plein pdf_set_value($pdf, "textrendering", 0); // Affichage du nom et du numero de fax du destinataire pdf_show_boxed($pdf, "Pour: ".$_POST["nom"]." ".$_POST["prenom"]. "\r\nFax: ".$_POST["fax"], $largeur-200, $hauteur-300, 150, 100, "right", ""); //Changement de la taille du texte a 35 points pdf_setfont($pdf, $font, 35); // Affichage du titre "Facture" pdf_show_xy($pdf, "Facture" , 150, $hauteur-100-50); //Changement de la taille du texte a 15 points pdf_setfont($pdf, $font, 15); // Texte afficher $texte="Facture No: ".$_POST["no"]."\r\nMontant: ".$_POST["montant"]. " Euros H.T.\r\n". "Objet de prestation: ".stripslashes($_POST["prestation"])."\r\n". "TVA non applicable, article 293B du CGI"; // Affiche le texte aligne gauche pdf_show_boxed($pdf, $texte, 50, 100, $largeur-100, 300, "left", ""); // Termine la page pdf_end_page($pdf); // Ferme le document PDF pdf_close($pdf); // Rcupre les donnes du document $donnees = pdf_get_buffer($pdf); // Efface lobjet PDF de la memoire et les ressources associees pdf_delete($pdf); /*************************************/ /* Cette partie concerne laffichage */ /* du document, les donnes sont */ /* prtes, il suffit de les envoyer. */ /*************************************/ header("Content-type: application/pdf"); header("Content-Length: ".strlen($donnees)); header("Content-Disposition: inline; filename=test.pdf"); echo $donnees; ?>

14. La cration de documents PDF

Ce script cre un fichier PDF de deux pages ; la premire est la page de garde dun fax :

1183

Chapitre 14

La cration de documents PDF

Figure 14.13 : Page de garde

La seconde page est la page de facture :

14. La cration de documents PDF

Figure 14.14 : Page de facture

1184

Chapitre 15

Lutilisation de XML
15.1 15.2 15.3 15.4 15.5 Introduction . . . . . . . . . . . Installation . . . . . . . . . . . Les parseurs . . . . . . . . . . . XSLT . . . . . . . . . . . . . . . . Gnration de messages XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1187 .1192 .1192 .1241 .1254

Introduction

15.1. Introduction
Prsentation du langage XML
Ces dernires annes, vous avez certainement beaucoup entendu parler du langage XML. La plupart en disent le plus grand bien, et il est de plus en plus utilis dans lindustrie. Toutefois, beaucoup nont encore quune vague ide de ce quil est, tandis que dautres pensent ( tort) quil sagit dune volution du langage HTML. En fait, XML dfinit avant tout des rgles trs simples de description dinformations (gnralement stockes dans des fichiers). En quelques mots, respecter le standard XML, cest stocker linformation sous forme de balises et dattributs (un peu comme avec HTML). En revanche, en aucun cas XML ne sattache dcrire la faon dont les informations seront prsentes. Il se peut dailleurs que les informations ne soient jamais affiches ou imprimes, mais seulement stockes et changes entre serveurs et applications. Le traitement de linformation (y compris affichage ou impression) est laiss la charge du parseur (ou analyseur) XML (logiciel pouvant tre crit en nimporte quel langage, y compris PHP, et qui pourra ventuellement sappuyer sur le langage XSL). Contrairement au langage HTML, XML ne dfinit ni balises ni attributs. Cest lutilisateur, selon son corps de mtier et ses besoins, de les dfinir. La bibliothque libXml a fait sont entre avec PHP5. Elle remplace avantageusement les autres prcdemment utilises tout en gardant les mmes signatures de fonctions. Ainsi une application utilisant XML crite pour PHP4 doit continuer fonctionner sans problme en passant PHP5 mme si derrire il ne se passe pas exactement la mme chose. Lavantage de libXML est quelle supporte lanalyse SAX et DOM, de plus il se trouve que cette bibliothque est trs performante.

Comparatif A titre dinformation voici une adresse o vous pouvez comparer les diffrents analyseurs syntaxiques, vous verrez que libXml est trs bien place.
http://xmlbench.sourceforge.net/index.php?page=results.php

15. Lutilisation de XML

Spcifications Les langages XML et XSL sont dcrits par le W3C.

Le format XML
Un chier bien form
Un fichier XML :
j

Commence par un en-tte <?xml version="1.0" encoding="UTF8"?> prcisant quil sagit dun document XML respectant la norme de la version 1.0, et utilisant des caractres cods en "UTF-8" (il est possible de prciser un autre encodage).

1187

Chapitre 15

Lutilisation de XML

Ne possde quune balise racine (autrement dit, lensemble des balises du document XML, hormis len-tte doit tre compris entre <baliseracine> et </baliseracine>). Peu importe le nom de cette balise. Toute balise ouverte doit tre referme (si il ny a pas de balise ou de texte entre les balises ouvrante et fermante, <balise></balise> peut tre remplac par <balise />). Les noms des balises doivent commencer par une lettre ou un underscore (_). Les caractres suivants peuvent tre des chiffres, des lettres, un underscore, un point ou un tiret. Un nom de balise ne peut pas commencer par "xml".
</balise1></balise2>).

j j j j

Les balises ne peuvent se chevaucher (il ne peut y avoir <balise1><balise2>

Les noms des balises sont gnralement en minuscules. Un document respectant ces rgles est dit bien form.

Un chier valide (DTD)


Bien quil suffise quun document soit bien form pour quil sagisse dun document XML, ce ne sont gnralement pas des conditions suffisantes pour assurer son bon traitement par un analyseur. En effet, selon le corps de mtier, nous nous attendrons avoir un document XML contenant telle ou telle balise. Les contraintes seront certainement mme plus fortes, puisquune balise donne devra contenir un certain type dattributs et de balises. Pour assurer quun document respecte ces contraintes supplmentaires, ces dernires seront exprimes sous la forme dun document appel DTD, dont voici un exemple :
<?xml version="1.0" encoding="UTF-8" ?> <!ELEMENT annuaire (personne*)> <!ELEMENT personne (nom, personne, email+)> <!ATTLIST personne profession (etudiant | professeur | chanteur | musicien) "etudiant"> <!ELEMENT nom (#PCDATA)> <!ELEMENT prenom (#PCDATA)> <!ELEMENT email (#PCDATA)>

15. Lutilisation de XML

Un tel document prcise que la balise "annuaire" doit comporter entre zro et plusieurs balises "personne" (ceci est indiqu par le caractre *). La balise "personne" doit contenir, dans cet ordre, exactement une balise "nom", une balise "personne" et une ou plusieurs balises "email" (ceci est indiqu par le caractre +). La balise "personne" possde un attribut "profession" qui pourra prendre une des valeurs parmi "etudiant", "professeur", "chanteur", "musicien". Si cet attribut nest pas prcis, il prendra pour valeur "etudiant". Les balises "nom", "prenom" et "email" contiendront simplement du texte. Nous nirons pas plus loin dans la description de la DTD. Un fichier DTD prsente tout de mme un gros dfaut. En effet, il ne sagit pas dun document XML (bien form). Ainsi, petit petit, lutilisation de la DTD devrait laisser place son quivalent XML : "XML Schema" que nous naborderons pas ici.

1188

Introduction

XML, XML Schema et DTD Vous trouverez plus dinformations sur XML, XML Schema et la DTD, sur les sites :
http://www.xmlfacile.com http://www.xmlfr.org/documentations/

Sans oublier la rfrence (en anglais) :


http://www.w3.org/XML/

et sa traduction :
http://babel.alis.com/web_ml/xml/REC-xml.fr.html

Exemple de document XML


Comme nous lavons vu, XML impose trs peu de rgles. Il peut donc convenir tous les domaines dapplications. Prenons lexemple dune mdiathque dsireuse de dcrire sa liste de CD audio dans un document XML. Un tel fichier pourra ressembler :

Listing 15.1 : mediatheque_01.xml


<?xml version="1.0" encoding="ISO-8859-1" ?> <mediatheque> <cdaudio interprete="Noir Dsir" titre="des Visages des Figures"> <chanson> <titre>Lenfant roi</titre> <duree>6:03</duree> </chanson> <chanson> <titre>Le grand incendie</titre> <duree>4:37</duree> </chanson> <chanson> <titre>Le vent nous portera</titre> <duree>4:48</duree> </chanson> </cdaudio> <cdaudio interprete="Placebo" titre="Without You Im Nothing"> <chanson> <titre>Pure Morning</titre> <duree>4:15</duree> </chanson> <chanson> <titre>Without You Im Nothing</titre> <duree>4:30</duree> </chanson> <chanson> <titre>Every You, Every Me</titre> <duree>5:00</duree> </chanson> </cdaudio> </mediatheque>

15. Lutilisation de XML 1189

Chapitre 15

Lutilisation de XML

Mais, encore une fois, le choix ntant pas impos, il est fait de faon totalement arbitraire. Par exemple : nous aurions pu choisir de crer une balise "interprete" plutt que den faire un attribut de la balise "cdaudio". Tout comme nous aurions pu avoir un attribut "titre" pour "chanson" plutt que den faire une balise (ce qui aurait certainement t plus judicieux, mais aurait constitu un exemple moins intressant). Quoi quil en soit, nous avons (pour les parties renseignes) toutes les informations ncessaires au bon droulement des oprations. Peut-tre mme que certaines de ces informations ne seront finalement pas utilises (ou seulement dans certains cas). Vous remarquerez quil est souhaitable dindiquer que le document est un document XML rpondant la norme tablie dans la version 1.0. Il est galement prfrable de prciser quel type dencodage est utilis : ISO-8859-1, UTF-8 (i.e. comment sont cods les caractres accentus ou les caractres non europens).

Exemples dencodage UTF-8 : est destin supporter tous les styles de caractres. US-ASCII : correspond aux caractres anglais. ISO-8859-1 : correspond aux caractres utiliss en Europe de lOuest. ISO-8859-2 : correspond aux caractres utiliss en Europe centrale. ISO-8859-9 : correspond aux caractres turcs. EUC-JP : correspond aux caractres japonais (sous UNIX). etc. Bref, il existe un grand nombre dencodages. Mais, heureusement, un effort dharmonisation a t entrepris et lencodage UTF-8 (ou lUTF-16) devrait, terme, simposer.
Toutefois, les fichiers XML peuvent tre un poil plus complexes sils utilisent, par exemple, des dclarations de type de documents <!DOCTYPE ...> incluant (pourquoi pas) des <!ENTITY ...> avec des rfrences internes et externes. Le but tant dutiliser des alias afin de remplacer, par exemple, un mot-cl par une longue chane de caractres ou par un fichier complet.

15. Lutilisation de XML

Listing 15.2 : mediatheque_01b.xml


<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE mediatheque [ <!ENTITY OKComputer SYSTEM "mediatheque_02.xml"> <!ENTITY nc "Non communiqu"> ]> <mediatheque> <cdaudio interprete="Noir Dsir" titre="des Visages des Figures"> <chanson> <titre>Lenfant roi</titre> <duree>6:03</duree> </chanson> <chanson> <titre>Le grand incendie</titre> <duree>4:37</duree> </chanson> <chanson>

1190

Introduction

<titre>Le vent nous portera</titre> <duree>4:48</duree> </chanson> </cdaudio> <cdaudio interprete="Placebo" titre="Without You Im Nothing"> <chanson> <titre>Pure Morning</titre> <duree>4:15</duree> </chanson> <chanson> <titre>Without You Im Nothing</titre> <duree>4:30</duree> </chanson> <chanson> <titre>Every You, Every Me</titre> <duree>5:00</duree> </chanson> </cdaudio> &OKComputer; <cdaudio interprete="Muse" titre="Showbiz"> <chanson> <titre>Feeling Good</titre> <duree>&nc;</duree> </chanson> </cdaudio> </mediatheque>

Listing 15.3 : mediatheque_02.xml


<?xml version="1.0" encoding="ISO-8859-1" ?> <cdaudio interprete="Radiohead" titre="OK Computer"> <chanson> <titre>Karma Police</titre> <duree>4:23</duree> </chanson> </cdaudio>

15. Lutilisation de XML

Mais, mme ce genre de fichier XML (faisant appel un autre fichier XML) pourra tre analys par PHP, comme nous allons trs bientt le voir

Utilisation des documents XML


Les documents XML pourront tre lus par un analyseur XML (parseur), transforms par un analyseur XSL, ou pourront simplement servir de support dchange (comme WDDX).

1191

Chapitre 15

Lutilisation de XML

15.2. Installation
Depuis PHP 4, le support de XML est activ par dfaut (mais peut tre dsactiv par loption de compilation disablexml). Vous naurez donc, a priori, rien faire de spcial pour pouvoir profiter des fonctions dcrites dans ces chapitres. Depuis PHP5, une seule bibliothque (libXml) permet de soccuper des diffrentes mthodes danalyse syntaxique et de transformation, il est cependant possible de dsactiver certaines parties. Vous pouvez vous assurer du support de libXML en appelant un script contenant uniquement <?php phpinfo(); ?>, qui devra alors afficher :
Figure 15.1 :

phpinfo()

15.3. Les parseurs


Dans PHP4, le parseur appel expat tait intgr par dfaut et il ny avait rien faire pour profiter de ses fonctions. Depuis PHP5, expat a t remplac par libXml qui est galement intgre et qui offre en outre la mme API. Ainsi les fonctions dcrites ci-dessous pour libXML (PHP5) sont valides pour expat (PHP4) et inversement Un autre parseur appel SimpleXML est disponible depuis PHP5, comme son nom lindique son utilisation est trs simple.

Le parseur SAX
Cette analyse de document est une analyse par vnement. Cest--dire qu chaque fois quune situation particulire est rencontre (ouverture dune balise, fermeture dune balise, texte contenu dans une balise, etc.), une fonction donne est appele.

15. Lutilisation de XML

Notre script PHP devra donc comporter :


j

Les dclarations des fonctions devant tre appeles pour les vnements nous intressant.

et les tapes suivantes :


j j j j

Cration du parseur XML ; Pour chaque type dvnement, dclaration des fonctions auprs du parseur ; Lancement de lanalyse proprement dite ; Libration des ressources monopolises par le parseur.

xml_parser_create
La cration du parseur XML se fait par simple appel la fonction xml_parser_create().

1192

Les parseurs

xml_parser_create()
Initialisation dun parseur XML. Syntaxe $encodage resource xml_parser_create([string $encodage]) Argument optionnel (insensible la casse) prcisant le type dencodage de la source parmi : ISO-8859-1 (par dfaut). US-ASCII. UTF-8. En cas de succs, une rfrence de parseur est retourne, FALSE sinon.

retour

La rfrence retourne sera alors utilise dans tous les appels aux fonctions XML (nous aurions prfr un bel objet avec une srie de mthodes mais bon...).

Gestion des balises ouvrantes et fermantes avec xml_set_element_handler


Dans une version minimaliste (pour commencer) de lanalyseur, nous ne nous intresserons quaux balises ouvrantes ou fermantes. Lorsque de tels lments sont rencontrs, le parseur fait appel aux fonctions qui ont t pralablement rfrences par xml_set_element_handler().

xml_set_element_handler()
Dclare auprs du parseur les fonctions appeler lorsquune balise ouvrante ou fermante est rencontre. Syntaxe $parseur $fonctionBalise Ouvrante $fonctionBalise Fermante retour boolean xml_set_element_handler(resource $parseur, string $fonctionBaliseOuvrante, string $fonctionBaliseFermante) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

15. Lutilisation de XML

Nom de la fonction en charge des balises ouvrantes. Nom de la fonction en charge des balises fermantes. TRUE si lopration sest droule correctement, NULL sinon.

Fonction balise ouvrante


La fonction (dont le nom sera prcis par $fonctionBaliseOuvrante) devant traiter les balises ouvrantes aura linterface suivante : Syntaxe [boolean] maFonction(resource $parseur, string $nomBalise, array $tableauAttributs)

1193

Chapitre 15

Lutilisation de XML

$parseur $nomBalise

Rfrence du parseur telle xml_parser_create(). Nom de la balise ouvrante.

que

retourne

par

la

fonction

$tableauAttributs Tableau associatif ayant pour cls les noms des attributs (en majuscules) contenus dans la balise et pour valeurs les valeurs des attributs. retour TRUE en cas de succs, FALSE sinon. (Ceci nest pas requis ni pris en compte ce jour par le parseur, mais cest conseill puisque cet tat de fait peut voluer).

Lensemble des paramtres tant fourni par le parseur, la fonction aura accs toutes les informations ncessaires au bon traitement des donnes du fichier XML.

Fonction balise fermante


La fonction (dont le nom sera prcis par $fonctionBaliseFermante) devant traiter les balises fermantes aura linterface suivante : Syntaxe $parseur $nomBalise retour [boolean] maFonction(resource $parseur, string $nomBalise) Rfrence du parseur telle xml_parser_create(). Nom de la balise fermante. TRUE en cas de succs, FALSE sinon. (Ceci nest pas requis ni pris en compte ce jour par le parseur, mais cest conseill puisque cet tat de fait peut voluer). que retourne par la fonction

Lensemble des paramtres tant fourni par le parseur, la fonction aura accs toutes les informations ncessaires au bon traitement des donnes du fichier XML.

xml_parse
15. Lutilisation de XML
Lanalyse dun document XML consiste gnralement lire un fichier ligne par ligne et, pour chacune des lignes, appeler xml_parse(), en prcisant sil sagit ou non de la dernire ligne.

xml_parse()
Analyse une chane de caractres avec un parseur XML. Syntaxe $parseur $ligne $derniereLigne boolean xml_parse(resource $parseur, string $ligne [, boolean $derniereLigne]) Rfrence du parseur telle xml_parser_create(). Chane de caractres analyser. TRUE sil sagit des dernires donnes traiter, FALSE (par dfaut) sinon. que retourne par la fonction

1194

Les parseurs

retour

1 (mais pas strictement TRUE) si lopration sest droule correctement, 0 (mais pas strictement FALSE) en cas dchec. Pour certaines fonctions de gestion des vnements (xml_set_external_entity _ref_handler()), lopration sera considre en chec si elles ne retournent pas TRUE. Ce nest en revanche pas le cas des fonctions xml_set_element_handler() et xml_set_character_data _handler().

Selon les lments rencontrs, les diffrentes fonctions charges des vnements seront appeles.

xml_parser_free
la fin de lanalyse, il est bon de librer les ressources qui ont t alloues par le parseur. Pour cela, il suffit dun simple appel xml_parser_free().

xml_parser_free()
Libre les ressources alloues au parseur. Syntaxe $parseur retour boolean xml_parser_free(resource $parseur) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

TRUE en cas de succs, NULL en cas dchec.

Premier exemple dapplication


Ceci nous permet donc de crer notre premier script danalyse de document XML (qui, pour linstant, reste basique et ne gre pas les erreurs).

15. Lutilisation de XML

Listing 15.4 : expat_01.xml


<?php $fichier = "../src_xml/mediatheque_01.xml"; // Exemple de fonction grant // les balises ouvrantes function fonctionBaliseOuvrante($parseur, $nomBalise, $tableauAttributs) { echo "La balise ouvrante : $nomBalise<br />\n"; if ( count($tableauAttributs) > 0 ) { echo "...avec les attributs:<br />\n"; while ( list($attribut, $valeur) = each($tableauAttributs) ) { echo "&nbsp;&nbsp;&nbsp;$attribut = $valeur<br />\n"; } }

1195

Chapitre 15

Lutilisation de XML

return TRUE; } // Exemple de fonction grant // les balises fermantes function fonctionBaliseFermante($parseur, $nomBalise) { echo "La balise fermante: $nomBalise<br />\n"; return TRUE; } // Creation du parseur XML $parseurXML = xml_parser_create(); // Association des fonctions // de traitement des balises ouvrantes et fermantes xml_set_element_handler($parseurXML, "fonctionBaliseOuvrante", "fonctionBaliseFermante"); // Ouverture du fichier ( $fp = fopen($fichier, "r") ) or die("Impossible douvrir le fichier XML"); // Lecture du fichier ligne par ligne echo "Lors du parcours du fichier XML. Jai rencontr:<br />"; while ( $ligneXML = fgets($fp, 1024) ) { xml_parse($parseurXML, $ligneXML, feof($fp) ) or die("Erreur XML"); } // Libration des ressources xml_parser_free($parseurXML); fclose($fp); ?>

15. Lutilisation de XML

Ceci aura pour effet dafficher :


Lors du parcours du fichier XML. Jai rencontr: La balise ouvrante : MEDIATHEQUE La balise ouvrante : CDAUDIO ...avec les attributs: INTERPRETE = Noir Dsir TITRE = des Visages des Figures La balise ouvrante : CHANSON La balise ouvrante : TITRE La balise fermante: TITRE La balise ouvrante : DUREE La balise fermante: DUREE La balise fermante: CHANSON La balise ouvrante : CHANSON La balise ouvrante : TITRE

1196

Les parseurs

La balise fermante: TITRE La balise ouvrante : DUREE La balise fermante: DUREE La balise fermante: CHANSON La balise ouvrante : CHANSON La balise ouvrante : TITRE La balise fermante: TITRE La balise ouvrante : DUREE La balise fermante: DUREE La balise fermante: CHANSON La balise fermante: CDAUDIO La balise ouvrante : CDAUDIO ...avec les attributs: INTERPRETE = Placebo TITRE = Without You Im Nothing La balise ouvrante : CHANSON La balise ouvrante : TITRE La balise fermante: TITRE La balise ouvrante : DUREE La balise fermante: DUREE La balise fermante: CHANSON La balise ouvrante : CHANSON La balise ouvrante : TITRE La balise fermante: TITRE La balise ouvrante : DUREE La balise fermante: DUREE La balise fermante: CHANSON La balise ouvrante : CHANSON La balise ouvrante : TITRE La balise fermante: TITRE La balise ouvrante : DUREE La balise fermante: DUREE La balise fermante: CHANSON La balise fermante: CDAUDIO La balise fermante: MEDIATHEQUE

15. Lutilisation de XML

Premire constatation : le document a t correctement analys (on retrouve tous les attributs et balises contenus dans le fichier XML). Et cest plutt une bonne nouvelle ! Seconde constatation : tous les noms de balises et attributs ont t passs en majuscules. Enfin, dans cet exemple, le contenu des balises na pas t trait. Ceci na rien dtonnant, puisque nous nous sommes contents de dfinir les fonctions des vnements balises ouvrantes et balises fermantes. La transformation ou non des noms des balises et des attributs est une option du parseur qui peut tre fixe par la fonction xml_parser_set_option().

1197

Chapitre 15

Lutilisation de XML

xml_parser_set_option()
Fixe les options du parseur (respect de la casse, encodage de sortie). Syntaxe $parseur $option boolean xml_parser_set_option(resource $parseur, int $option, mixed $valeur) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

Au choix, une valeur parmi : XML_OPTION_CASE_FOLDING : force le passage en majuscules (par dfaut TRUE). XML_OPTION_TARGET_ENCODING : dtermine lencodage de sortie (par dfaut, celui prcis du document en entre). Valeur donner loption. TRUE en cas de succs, rien (mais pas strictement FALSE) sinon.

$valeur retour

Il est possible de vrifier la valeur dune option avec xml_parser_get_option().

xml_parser_get_option()
Retourne les options du parseur. Syntaxe $parseur $option mixed xml_parser_get_option(resource $parseur, int $option) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

15. Lutilisation de XML

Au choix, une valeur parmi : XML_OPTION_CASE_FOLDING indiquant si les noms sont convertis en majuscules. XML_OPTION_TARGET_ENCODING indiquant lencodage de sortie. Valeur de loption.

retour

Ce premier exemple nous a permis de bien comprendre comment se droule lanalyse. Voici maintenant un exemple dutilisation un peu plus concret, destin afficher la liste des interprtes et titres.

Listing 15.5 : expat_02.php


<?php $fichier = "../src_xml/mediatheque_01.xml"; // Exemple de fonction grant // les balises ouvrantes function fonctionBaliseOuvrante($parseur, $nomBalise, $tableauAttributs) {

1198

Les parseurs

switch ($nomBalise) { case "cdaudio" : echo $tableauAttributs["interprete"]; echo " : "; echo $tableauAttributs["titre"]; echo "<br />"; break; } return TRUE; } // Exemple de fonction grant // les balises fermantes function fonctionBaliseFermante($parseur, $nomBalise) { // Dans ce cas, je nai rien faire.. return TRUE; } // Creation du parseur XML $parseurXML = xml_parser_create(); // Force le parseur respecter la casse xml_parser_set_option($parseurXML, XML_OPTION_CASE_FOLDING, FALSE); // Dclaration des fonctions de traitement // des balises ouvrantes et fermantes xml_set_element_handler($parseurXML, "fonctionBaliseOuvrante", "fonctionBaliseFermante"); // Ouverture du fichier ( $fp = fopen($fichier, "r") ) or die("Impossible douvrir le fichier XML"); // Lecture du fichier ligne par ligne while ( $ligneXML = fgets($fp, 1024) ) { xml_parse($parseurXML, $ligneXML, feof($fp) ) or die("Erreur XML"); } // Libration des ressources xml_parser_free($parseurXML); fclose($fp); ?>

15. Lutilisation de XML

donnera effectivement :
Noir Dsir : des Visages des Figures Placebo : Without You Im Nothing

1199

Chapitre 15

Lutilisation de XML

Voyons maintenant le moyen de traiter les autres vnements.

Gestion du texte contenu dans les balises avec xml_set_character_data_handler


La fonction xml_set_character_data_handler() vous permet de prciser quelle fonction doit traiter le texte contenu entre les balises ouvrante et fermante.

xml_set_character_data_handler()
Dclare auprs du parseur la fonction appeler lorsque du texte est rencontr. Syntaxe $parseur $fonctionTexte retour boolean xml_set_character_data_handler(resource $parseur, string $fonctionTexte) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

Nom de la fonction en charge du traitement du texte. TRUE si lopration sest droule correctement, NULL sinon.

Fonction texte des balises


La fonction (dont le nom sera prcis par $fonctionTexte) devant traiter le texte contenu entre les balises aura linterface suivante : Syntaxe $parseur $texte [boolean] maFonction(resource $parseur, string $texte) Rfrence du parseur telle xml_parser_create(). Le texte rencontr. TRUE en cas de succs, FALSE sinon. (Ceci nest pas requis ni pris en compte ce jour par le parseur, mais cest conseill puisque cet tat de fait peut voluer). que retourne par la fonction

15. Lutilisation de XML

retour

Lensemble des paramtres tant fourni par le parseur, la fonction aura accs toutes les informations ncessaires au bon traitement des donnes.

Gestion du caractre & Lorsquune chane de caractres contient un & (indicateur de rfrence interne ou externe) celle-ci est scinde en plusieurs morceaux. Il y a donc dans ce cas plusieurs appels la fonction dcrite ici.
Nous allons donc pouvoir complter notre exemple afin dafficher les noms et dures des chansons disponibles sur les albums.

1200

Les parseurs

Listing 15.6 : expat_03.php


<?php $fichier = "../src_xml/mediatheque_01.xml"; // Exemple de fonction grant // les balises ouvrantes function fonctionBaliseOuvrante($parseur, $nomBalise, $tableauAttributs) { // Pour les besoins de la fonction // fonctionTexte nous devons mmoriser // les noms des balises rencontres // dans une variable globale global $balises; $balises[] = $nomBalise; switch ($nomBalise) { case "cdaudio" : echo "<b>"; echo $tableauAttributs["interprete"]; echo " : "; echo $tableauAttributs["titre"]; echo "</b><br />"; break; } return TRUE; } // Exemple de fonction grant // les balises fermantes function fonctionBaliseFermante($parseur, $nomBalise) { // Une fois sorti de la balise // il faut mettre jour la variable // globale mmorisant les noms de balises // rencontres, en supprimant le dernier nom global $balises; array_pop($balises); return TRUE; } function fonctionTexte($parseur, $texte) { // Pour savoir a quelle balise se rapporte // ce texte, il faut avoir au pralable // mmoris les balises rencontres // dans une variable globale global $balises;

15. Lutilisation de XML 1201

Chapitre 15

Lutilisation de XML

// Toutefois, dans notre cas, // Nous ne nous interessons qu la dernire // balise rencontre (sans tenir compte // des balises parentes) $derniereBalise = $balises[count($balises)-1]; switch ($derniereBalise) { case "titre" : echo "- $texte"; break; case "duree": echo " $texte<br />"; break; } return TRUE; } // Creation du parseur XML $parseurXML = xml_parser_create(); // Force le parseur a respecter la casse xml_parser_set_option($parseurXML, XML_OPTION_CASE_FOLDING, FALSE); // Dclaration des fonctions de traitement // des balises ouvrantes et fermantes xml_set_element_handler($parseurXML, "fonctionBaliseOuvrante", "fonctionBaliseFermante"); // Dclaration de la fonction de traitement // du texte entre les balises xml_set_character_data_handler($parseurXML, "fonctionTexte");

15. Lutilisation de XML

// Ouverture du fichier ( $fp = fopen($fichier, "r") ) or die("Impossible douvrir le fichier XML"); // Lecture du fichier ligne par ligne while ( $ligneXML = fgets($fp, 1024) ) { xml_parse($parseurXML, $ligneXML, feof($fp) ) or die("Erreur XML"); } // Libration des ressources xml_parser_free($parseurXML); fclose($fp); ?>

Comme vous pouvez le constater, le rsultat obtenu est :


Noir Dsir : des Visages des Figures - Lenfant roi 6:03

1202

Les parseurs

- Le grand incendie 4:37 - Le vent nous portera 4:48 Placebo : Without You Im Nothing - Pure Morning 4:15 - Without You Im Nothing 4:30 - Every You, Every Me 5:00

Mais, surtout, la lecture du code, vous constatez que la principale difficult (notamment pour ceux qui nont jamais utilis ce genre de parseur) vient du fait quau niveau de la fonction charge du traitement du texte, nous navons, a priori, aucune information sur la balise laquelle le texte se rapporte. Il convient donc de mmoriser, par nos propres moyens, "lhistorique" des balises rencontres. Avant de passer la suite, afin de prparer le terrain pour une utilisation plus complexe, nous vous proposons de lgrement remanier ce script pour en faire un objet. Mais voil ! pour utiliser le parseur XML dans un objet, il faut faire appel la fonction xml_set_object().

xml_set_object()
Permet lutilisation du parseur XML dans un objet. Syntaxe $parseur $objet void xml_set_object(resource $parseur, object &$objet) Rfrence du parseur telle xml_parser_create(). Rfrence sur lobjet. que retourne par la fonction

Attention !... suspense... et voil !

Listing 15.7 : expat_03b.php


<?php class XML_Parseur { var $parseurXML; function XML_Parseur() { } function init() { $this->parseurXML = xml_parser_create(); // Dfinit lobjet courant comme tant lobjet // qui "hberge" les fonctions de gestion des vnements xml_set_object($this->parseurXML, &$this);

15. Lutilisation de XML 1203

Chapitre 15

Lutilisation de XML

xml_parser_set_option($this->parseurXML, XML_OPTION_CASE_FOLDING, FALSE); xml_set_element_handler($this->parseurXML, "fonctionBaliseOuvrante", "fonctionBaliseFermante"); xml_set_character_data_handler($this->parseurXML, "fonctionTexte"); }

function parse($fichier) { ( $fp = fopen($fichier, "r") ) or die("Impossible douvrir le fichier XML"); while ( $ligneXML = fgets($fp, 1024) ) { xml_parse($this->parseurXML, $ligneXML, feof($fp) ) or die("Erreur XML"); } fclose($fp); } function free() { xml_parser_free($this->parseurXML); } // // Mthodes prives // function fonctionBaliseOuvrante($parseur, $nomBalise, $tableauAttributs) { global $balises; $balises[] = $nomBalise; switch ($nomBalise) { case "cdaudio" : echo "<b>"; echo $tableauAttributs["interprete"]; echo " : "; echo $tableauAttributs["titre"]; echo "</b><br />"; break; } return TRUE; } function fonctionBaliseFermante($parseur, $nomBalise) { global $balises; array_pop($balises);

15. Lutilisation de XML 1204

Les parseurs

return TRUE; } function fonctionTexte($parseur, $texte) { global $balises; $derniereBalise = $balises[count($balises)-1]; switch ($derniereBalise) { case "titre" : echo "- $texte"; break; case "duree": echo " $texte<br />"; break; } return TRUE; } } $fichierXML = "../src_xml/mediatheque_01.xml"; $parseur = new XML_Parseur(); $parseur->init(); $parseur->parse($fichierXML); $parseur->free(); ?>

Nous voil prts pour aborder la suite.

Gestion des entits externes avec xml_set_external_entity_ref_handler


La fonction xml_set_external_entity_ref_handler() vous permet de prciser quelle fonction doit traiter les rfrences aux entits externes. Les entits externes apparaissent dans les documents XML sous la forme &nomEntite; et sont dclares sous la forme <!ENTITY nomEntite SYSTEM "fichier.xml">.

15. Lutilisation de XML

xml_set_external_entity_ref_handler()
Dclare auprs du parseur la fonction appeler lorsque des rfrences des entits externes sont rencontres (&nomEntite; avec <!ENTITY nomEntite SYSTEM "fichier.xml">). Syntaxe boolean xml_set_external_entity_ref_handler(resource $parseur, string $fonctionRefEntiteExterne)

1205

Chapitre 15

Lutilisation de XML

$parseur $fonctionRef EntiteExterne retour

Rfrence du parseur telle xml_parser_create().

que

retourne

par

la

fonction

Nom de la fonction en charge du traitement des rfrences des entits externes. TRUE si lopration sest droule correctement, NULL sinon.

Fonction rfrence des entits externes


La fonction (dont le nom sera prcis par $fonctionRefEntiteExterne) devant traiter les instructions de traitement aura linterface suivante : Syntaxe $parseur $nomEntite $base $idSysteme boolean maFonction(resource $parseur, string $nomEntite, string $base, string $idSysteme, $idPublic) Rfrence du parseur telle xml_parser_create(). Nom de lentit. Non renseign. Lidentifiant systme de lentit (en dautres termes, valeur du champ "SYSTEM" ou celui suivant la valeur du champ "PUBLIC", cest--dire le document externe point). Lidentifiant public de lentit (concrtement, la valeur du champ "PUBLIC", cest--dire le document externe point servant de rfrence). TRUE si lopration a t ralise avec succs, FALSE sinon. que retourne par la fonction

$idPublic retour

Lensemble des paramtres tant fourni par le parseur, la fonction aura accs toutes les informations ncessaires au bon traitement des donnes. Cependant, il est noter que la prsence de cette fonction sous-entend que la lecture et linclusion du document externe sont votre charge.

15. Lutilisation de XML

Listing 15.8 : expat_04.php


<?php class XML_Parseur { var $parseurXML; var $fichierXML;

// Fichier sur lequel sest appliqu // le dernier traitement

function XML_Parseur() { } function init() { $this->parseurXML = xml_parser_create(); // Dfinit lobjet courant comme tant lobjet

1206

Les parseurs

// qui "hberge" les fonctions de gestion des vnements xml_set_object($this->parseurXML, &$this); xml_parser_set_option($this->parseurXML, XML_OPTION_CASE_FOLDING, FALSE); xml_set_element_handler($this->parseurXML, "fonctionBaliseOuvrante", "fonctionBaliseFermante"); xml_set_character_data_handler($this->parseurXML, "fonctionTexte"); // Dclaration de la fonction de traitement // des references aux entits externes xml_set_external_entity_ref_handler($this->parseurXML, "fonctionRefEntiteExterne"); }

function parse($fichier) { // Pour le traitement des references aux entits externes // nous avons besoin de mmoriser quel fichier est appliqu // le traitement $this->fichierXML = $fichier; ( $fp = fopen($fichier, "r") ) or die("Impossible douvrir le fichier XML"); while ( $ligneXML = fgets($fp, 1024) ) { xml_parse($this->parseurXML, $ligneXML, feof($fp) ) or die("Erreur XML". xml_error_string(xml_get_error_code($this->parseurXML))); } fclose($fp); } function free() { xml_parser_free($this->parseurXML); } // // Mthodes prives // function fonctionBaliseOuvrante($parseur, $nomBalise, $tableauAttributs) { global $balises; $balises[] = $nomBalise; switch ($nomBalise) { case "cdaudio" : echo "<b>";

15. Lutilisation de XML 1207

Chapitre 15

Lutilisation de XML

echo $tableauAttributs["interprete"]; echo " : "; echo $tableauAttributs["titre"]; echo "</b><br />"; break; } return TRUE; } function fonctionBaliseFermante($parseur, $nomBalise) { global $balises; array_pop($balises); return TRUE; } function fonctionTexte($parseur, $texte) { global $balises; $derniereBalise = $balises[count($balises)-1]; switch ($derniereBalise) { case "titre" : echo "- $texte"; break; case "duree": echo " $texte<br />"; break; } return TRUE;

15. Lutilisation de XML

} // Exemple de fonction grant // les rfrences aux entits externes function fonctionRefEntiteExterne($parseur, $nomEntite, $base, $idSysteme, $idPublic) { // Il est ici, fait rfrence // $idSysteme (et eventuellement $idPublic) // nous ne nous interesserons ici // qua $idSysteme. // // // // Attention: Petite subtilit le chemin du fichier externe est relatif au fichier XML et non au script PHP (REM: Ici, on suppose que le chemin est relatif

1208

Les parseurs

// et non absolu) $fichierExterne = dirname($this->fichierXML)."/".$idSysteme; // Nous instancions un nouveau parseur // (cela pourrait par exemple permettre de grer // des fichiers externes possdant un encodage diffrent) $tmpParseur = new XML_Parseur(); $tmpParseur->parse($fichierExterne); $tmpParseur->free(); // Ne pas oublier de retourner TRUE en cas // de succs des oprations. return TRUE; } } $fichierXML = "../src_xml/mediatheque_01b.xml"; $parseur = new XML_Parseur(); $parseur->init(); $parseur->parse($fichierXML); $parseur->free(); ?>

Appliqu au fichier mediatheque_01b.xml cela donne le sobre rsultat suivant ( vous de lenrichir) :
Figure 15.2 : Rsultat de transformation expat

15. Lutilisation de XML

Rfrence une entit interne Les rfrences internes sont, quant elles, automatiquement remplaces par leurs valeurs (comme le prouve lexemple prcdent).

Gestion des instructions de traitement <? ... ?> avec xml_set_processing_instruction_handler


La fonction xml_set_processing_instruction_handler() vous permet de prciser quelle fonction doit traiter les instructions de traitement prcises entre <? et ?>. noter que cela ne concerne pas les instructions de traitement XML (<?xml ?>).

1209

Chapitre 15

Lutilisation de XML

xml_set_processing_instruction_handler()
Dclare auprs du parseur la fonction appeler lorsque des instructions de traitement (entre <? et ?>) sont rencontres. Syntaxe $parseur boolean xml_set_processing_instruction_handler(resource $parseur, string $fonctionInstructionTraitement) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

$fonctionInstruction Traitement Nom de la fonction en charge du traitement des instructions de traitement. retour TRUE si lopration sest droule correctement, NULL sinon.

Fonction instruction de traitement


La fonction (dont le nom sera prcis par $fonctionInstructionTraitement) devant traiter les instructions de traitement aura linterface suivante : Syntaxe $parseur $cible $code retour [boolean] maFonction(resource $parseur, string $cible, string $code) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

Indique qui est destine linstruction (il sagit de lidentifiant que lon trouve juste aprs "<?". Ce peut tre par exemple "php"). Le code ou tout au moins les instructions. TRUE en cas de succs, FALSE sinon. (Ceci nest pas requis ni pris en compte ce jour par le parseur, mais cest conseill puisque cet tat de fait peut voluer).

15. Lutilisation de XML

Lensemble des paramtres tant fourni par le parseur, la fonction aura accs toutes les informations ncessaires au bon traitement des donnes.

Gestion des dclarations de notation <!NOTATION ... > avec xml_set_notation_decl_handler

xml_set_notation_decl_handler()
Dclare auprs du parseur la fonction appeler lorsque des dclarations de notation (<!NOTATION ...>) sont rencontres. Syntaxe $parseur boolean xml_set_notation_decl_handler(resource $parseur, string $fonctionDeclarationNotation) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

1210

Les parseurs

$fonction DeclarationNotation Nom de la fonction en charge du traitement des dclarations de notation. retour TRUE si lopration sest droule correctement, NULL sinon.

Fonction dclaration de notation


La fonction (dont le nom sera prcis par $fonctionDeclarationNotation) devant traiter les instructions de traitement aura linterface suivante : Syntaxe $parseur $nomNotation $base $idSysteme [boolean] maFonction(resource $parseur, string $nomNotation, string $base, string $idSysteme, string $idPublic) Rfrence du parseur telle xml_parser_create(). Nom de la notation. Non renseign. Lidentifiant systme de lentit (en dautres termes la valeur du champ "SYSTEM" ou celui suivant la valeur du champ "PUBLIC". Cest--dire la dclaration de type ou lapplication de traitement pointe). Lidentifiant public de lentit (concrtement, la valeur du champ "PUBLIC". Cest--dire la dclaration de type ou lapplication de traitement pointe servant de rfrence). TRUE en cas de succs, FALSE sinon. (Ceci nest pas requis ni pris en compte ce jour par le parseur, mais cest conseill puisque cet tat de fait peut voluer). que retourne par la fonction

$idPublic

retour

Gestion des dclarations dentits non analysables <!ENTITY ...NDATA... > avec xml_set_unparsed_entity_decl_handler
15. Lutilisation de XML

xml_set_unparsed_entity_decl_handler()
Dclare auprs du parseur la fonction appeler lorsque des dclarations dentits non analysables (<!ENTITY ... NDATA ...>) sont rencontres. Syntaxe $parseur boolean xml_set_unparsed_entity_decl_handler(resource $parseur, string $fonctionDeclarationEntiteNonAnalysable) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

$fonctionDeclaration EntiteNonAnalysable Nom de la fonction en charge du traitement des dclarations dentits non analysables. retour TRUE si lopration sest droule correctement, NULL sinon.

1211

Chapitre 15

Lutilisation de XML

Fonction dclaration dentit non analysable


La fonction (dont le nom sera prcis par $fonctionDeclarationEntiteNonAnalysable) devant traiter les instructions de traitement aura linterface suivante : Syntaxe [boolean] maFonction(resource $parseur, string $nomEntite, string $base, string $idSysteme, string $idPublic, string $nomNotation) Rfrence du parseur telle xml_parser_create(). Nom de lentit. Non renseign. Lidentifiant systme de lentit (en dautres termes la valeur du champ "SYSTEM" ou celui suivant la valeur du champ "PUBLIC". Cest--dire la dclaration de type ou lapplication de traitement pointe). Lidentifiant public de lentit (concrtement, la valeur du champ "PUBLIC". Cest--dire la dclaration de type ou lapplication de traitement pointe servant de rfrence). Nom de la notation. TRUE en cas de succs, FALSE sinon. (Ceci nest pas requis ni pris en compte ce jour par le parseur, mais cest conseill puisque cet tat de fait peut voluer). que retourne par la fonction

$parseur $nomEntite $base $idSysteme

$idPublic

$nomNotation retour

Gestion par dfaut avec xml_set_default_handler


La fonction xml_set_default_handler() vous permet de prciser quelle fonction doit tre appele par dfaut (cela concerne aussi bien les vnements pour lesquels il nexiste pas de fonction xml_..._handler associe que les vnements ayant leur propre fonction xml_ ..._handler, mais pour lesquels vous navez pas dfini de fonction de traitement).

15. Lutilisation de XML

xml_set_default_handler()
Dclare auprs du parseur la fonction appeler pour le traitement par dfaut. Syntaxe $parseur boolean xml_set_default_handler(resource $parseur, string $fonctionParDefaut) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

$fonctionParDefaut Nom de la fonction en charge du traitement par dfaut.

Fonction par dfaut


La fonction (dont le nom sera prcis par $fonctionParDefaut) devant traiter les instructions de traitement aura linterface suivante :

1212

Les parseurs

Syntaxe $parseur $chaine

void maFonction(resource $parseur, string $chaine) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

Chane de caractres contenant la chane non reconnue comme vnement prdfini.

Lensemble des paramtres tant fourni par le parseur, la fonction aura accs toutes les informations ncessaires au bon traitement des informations.

Gestion des erreurs


Jusque-l, afin de garder une certaine continuit dans le raisonnement, nous avons pass sous silence les fonctions de gestion des erreurs. Pourtant, elles sont souvent indispensables pour dterminer les causes des problmes danalyse des documents. tout moment, il est possible de rcuprer le dernier code derreur rencontr par un parseur lors de lanalyse. Pour cela, il y a la fonction xml_get_error_code().

xml_get_error_code()
Retourne le dernier code derreur rencontr par le parseur. Syntaxe $parseur retour int xml_get_error_code(resource $parseur) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

Code derreur pouvant prendre les valeurs : XML_ERROR_NONE : pas derreur. XML_ERROR_NO_MEMORY : plus de mmoire disponible. XML_ERROR_SYNTAX : erreur de syntaxe. XML_ERROR_NO_ELEMENTS : aucune balise na t rencontre. XML_ERROR_INVALID_TOKEN : document non "bien form". XML_ERROR_UNCLOSED_TOKEN. XML_ERROR_PARTIAL_CHAR. XML_ERROR_TAG_MISMATCH : prsence de balises non fermes ou se chevauchant (ex. : <a><b></a></b>). XML_ERROR_DUPLICATE_ATTRIBUTE : prsence multiple du mme attribut dans une mme balise. XML_ERROR_JUNK_AFTER_DOC_ELEMENT : prsence de balises aprs la balise racine fermante. XML_ERROR_PARAM_ENTITY_REF. XML_ERROR_UNDEFINED_ENTITY : entit non dfinie. XML_ERROR_RECURSIVE_ENTITY_REF : rfrence dentit rcursive. XML_ERROR_ASYNC_ENTITY. XML_ERROR_BAD_CHAR_REF. XML_ERROR_BINARY_ENTITY_REF : rfrence une entit binaire (entit non analysable non texte).

15. Lutilisation de XML 1213

Chapitre 15

Lutilisation de XML

XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF. XML_ERROR_MISPLACED_XML_PI. XML_ERROR_UNKNOWN_ENCODING : encodage inconnu. XML_ERROR_INCORRECT_ENCODING : encodage ne correspondant pas au document. XML_ERROR_UNCLOSED_CDATA_SECTION. XML_ERROR_EXTERNAL_ENTITY_HANDLING : la fonction de gestion des entits externes na pas retourn TRUE (laissant supposer quune erreur est intervenue), ou NULL si le parseur nexiste pas. Il est galement possible davoir linformation sous forme de texte (en anglais) via
xml_error_string().

xml_error_string()
Retourne le message derreur (en anglais) correspondant au code derreur fourni. Syntaxe $codeErreur retour string xml_error_string(int $codeErreur) Code derreur tel que retourn par xml_error_code(). Le message derreur, ou NULL si le code derreur nexiste pas.

Pour aider lanalyse du problme, il est souvent galement ncessaire de connatre la position estime de lerreur. Heureusement, il est tout moment (donc pas uniquement en cas derreur) possible de connatre la position du parseur. Pour cela, vous disposez de xml_get_current_line_number() et xml_get_current_column_number().

15. Lutilisation de XML

xml_get_current_line_number()
Retourne le numro de la ligne en cours danalyse par le parseur. Syntaxe $parseur retour int xml_get_current_line_number(resource $parseur) Rfrence du parseur telle xml_parser_create(). que retourne par la fonction

Numro de ligne, ou NULL si le parseur nexiste pas.

xml_get_current_column_number()
Retourne le numro de la colonne en cours danalyse par le parseur. Syntaxe int xml_get_current_column_number(resource $parseur)

1214

Les parseurs

$parseur retour

Rfrence du parseur telle xml_parser_create().

que

retourne

par

la

fonction

Numro de colonne, ou NULL si le parseur nexiste pas.

Et, pour ceux que cela intresse, il est galement possible davoir la position en octets depuis le dbut du document avec xml_get_current_byte_index().

Le parseur DOM
Si libXML est install, alors le parseur DOM est probablement activ. Vous pouvez le vrifier en jetant un il aux informations affiches par phpinfo().
Figure 15.3 : phpinfo() DOM

Parfois, il est prfrable daccder aux parties dun fichier XML dans un ordre diffrent de celui impos par SAX. Lavantage de lanalyse par DOM est que lon peut accder tout lment de larbre trs facilement et mme faire des retours en arrire. Linconvnient (et cest probablement pourquoi SAX et DOM coexistent) cest que larbre entier est mis en mmoire, ainsi pour un gros fichier XML, DOM nest pas adapt. La bibliothque DOM tant imposante, nous nous limiterons exceptionnellement aux fonctionnalits les plus utilises.

Constantes
Voici lensemble des constantes dfinies:

15. Lutilisation de XML

Tableau 15.1 : Constantes XML


Nom de variable XML_ELEMENT_NODE XML_ATTRIBUTE_NODE XML_TEXT_NODE XML_CDATA_SECTION_NODE XML_ENTITY_REF_NODE XML_ENTITY_NODE XML_PI_NODE XML_COMMENT_NODE Nud de type Commentaire Nud de type Entit (comme &eacute; ) Dfinition Nud de type Elment. Nud de type Attribut. Nud de type Text. Nud de type section CData (non traite)

1215

Chapitre 15

Lutilisation de XML

Nom de variable XML_DOCUMENT_NODE XML_DOCUMENT_TYPE_NODE XML_DOCUMENT_FRAG_NODE XML_NOTATION_NODE XML_HTML_DOCUMENT_NODE XML_DTD_NODE XML_ELEMENT_DECL_NODE XML_ATTRIBUTE_DECL_NODE XML_ENTITY_DECL_NODE XML_NAMESPACE_DECL_NODE XML_ATTRIBUTE_CDATA XML_ATTRIBUTE_ID XML_ATTRIBUTE_IDREF XML_ATTRIBUTE_IDREFS XML_ATTRIBUTE_ENTITY XML_ATTRIBUTE_NMTOKEN XML_ATTRIBUTE_NMTOKENS XML_ATTRIBUTE_ENUMERATION XML_ATTRIBUTE_NOTATION

Dfinition Noeud de type Document

Nud dun document HTML Nud dune DTD

Tableau 15.2 : Constantes DOM

15. Lutilisation de XML

Nom de variable DOM_INDEX_SIZE_ERR DOMSTRING_SIZE_ERR DOM_HIERARCHY_REQUEST_ERR DOM_WRONG_DOCUMENT_ERR DOM_INVALID_CHARACTER_ERR DOM_NO_DATA_ALLOWED_ERR DOM_NO_MODIFICATION_ALLOWED_ERR

Dfinition Lindex ou la taille est ngative ou plus grande que la valeur accepte. Un nud est insr un endroit o il ne devrait pas. Un nud est utilis dans un autre document que celui o il a t cr. Un caractre invalide a t insr. Des donnes sont spcifies pour un nud qui nen accepte pas. Il y a eu tentative de modification un endroit interdit.

1216

Les parseurs

Nom de variable DOM_NOT_FOUND_ERR DOM_NOT_SUPPORTED_ERR DOM_INUSE_ATTRIBUTE_ERR DOM_INVALID_STATE_ERR DOM_SYNTAX_ERR DOM_INVALID_MODIFICATION_ERR DOM_NAMESPACE_ERR DOM_INVALID_ACCESS_ERR DOM_VALIDATION_ERR

Dfinition Il y a eu tentative de rfrencer un nud dans un contexte o il nexiste pas. Le type dobjet demand nest pas support. Il y a eu tentative dajouter un attribut qui est dj utilis un autre endroit.

Les diffrentes classes principales


Voici quelques unes des classes les plus utilises avec leurs attributs et leurs fonctions brivement prsentes. Les fonctions les plus importantes sont par ailleurs dcrites en dtails la suite de ces tableaux succincts.

Tableau 15.3 : Classe DOMDocument


Attribut doctype implementation documentElement actualEncoding encoding standalone version strictErrorChecking documentURI config formatOutput validateOnParse resolveExternals preserveWhiteSpace substituteEntities Type String DOMImplemenation DOMElement String String Boolean String Boolean String String String Boolean Boolean Boolean Boolean Version XML utilise. Elment racine de larbre. Dfinition

15. Lutilisation de XML

Encodage utilis.

1217

Chapitre 15

Lutilisation de XML

Attribut

Type DOMAttr DOMCDATASection DOMComment

Dfinition Cre un nouvel attribut. Cre un nouvel attribut avec espace de nom. Cre une nouvelle section CDATA. Cre un nouveau commentaire. Cre un nouveau fragment.

createAttribute(String $nom) DOMAttr createAttributeNS(String $espaceNom, String $nom) createCDATASection(String $donnees) createComment(String $commentaire) createDocumentFragment() createElement(String $nom [, String $valeur]) createElementNS(String $espaceNom, String $nom) DOMElement DOMElement

Cre un nouvel lment. Cre un nouvel lment avec espace de noms. Cre une nouvelle entit.

createEntityReference(String DOMEntityReference $nom) createProcessingInstruction (String $cible [, String $donnees]) createTextNode(String $texte) getElementById(String $idElement)

DOMProcessingInstruction Cre un nud de type PI.

DOMText DOMElement

Cre un nud de type texte. Fait une recherche sur lidentifiant de llment. Selon le standard DOM cette fonction require quun attribut ID de type ID soit dfini dans la DTD. Retourne les nuds ayant $nom comme nom. Idem mais avec espace de noms. Importe un nud dans le document courrant Charge et cre larbre DOM partir du nom de fichier dun document XML. Charge et cre larbre DOM partir de la chane de caractres $HTML.

15. Lutilisation de XML

getElementByTagName(String $nom)

DOMNodeList

getElementByTagNameNS(String DOMNodeList $espaceNom, String $nom) importNode(DOMNode $noeudImporte [, boolean $copieProfonde]) load(String $nomFichier) DOMNode

DOMDocument

loadHTML(String $HTML)

DOMDocument

1218

Les parseurs

Attribut loadHTMLFile(String $NomFichierHTML)

Type DOMDocument

Dfinition Charge et cre larbre DOM partir du nom de fichier dun document HTML. Charge et cre larbre DOM partir de la chane de caractres $XML. Normalise le document. Vrifie la validit dun document selon le fichier relaxNG pass en paramtre. Vrifie la validit dun document selon relaxNG pass en paramtre. Cre et stocke dans un fichier le code XML correspondant au document DOM. Cre le HTML correspondant au document DOM. Cre et stocke dans un fichier le code HTML correspondant au document DOM. Cre le XML correspondant au document DOM. Vrifie la validit dun document selon le fichier Schema pass en paramtre. Vrifie la validit dun document selon un Schema pass en paramtre. Vrifie si un le document est valide selon sa DTD. Remplace les xinclude dans un document DOM.

loadXML(String $XML)

DOMDocument

normalize() relaxNGValidate(String $nomFichier)

void boolean

relaxNGValidateSource(String boolean $relaxNG) save(String $nomFichier) integer

saveHTML()

String

saveHTMLFile(String $nomFichier)

String

saveXML([DOMNode $noeud])

String

15. Lutilisation de XML

schemaValidate(String $nomFichierSchema)

boolean

schemaValidateSource(String $schema)

boolean

validate() xinclude()

boolean int

1219

Chapitre 15

Lutilisation de XML

Tableau 15.4 : Classe DOMNode


Attribut nodeName nodeValue nodeType parentNode childNodes firstChild lastChild previousSibling nextSibling attributes ownerDocument namespaceURI prefix Type String String Integer DOMElement DOMNodeList DOMNode DOMNode DOMNode DOMNode DOMNamedNodeMap DOMDocument String String Dfinition Nom du nud. Valeur du nud (contenu). Code type du Nud. Nud parent. Nuds enfants. Premier enfant. Dernier enfant. Nud prcdant de mme hirarchie. Enfant suivant de mme hirarchie. Attributs du nud. Document auquel appartient le nud. Espace de noms (nom complet). Espace de noms (nom rduit prfix du nud) si utilis. Nom du nud sans le prfix despace de nom si le prfix est utilis. Contenu du nud. Ajoute un fils la suite des autres fils du mme lment. Fait une copie du nud courant. Vrifie si le nud a des attributs. Vrifie si le nud a des enfants. Insert le nud $noeudAInserer juste avant $noeudReference. Renvoi TRUE si les deux nuds sont les mmes. (pas au niveau du contenu)

localName

String

baseURI

String String DOMNode

15. Lutilisation de XML

textContent appendChild(DOMNode $noeud) cloneNode([boolean $enProfondeur]) hasAttributes() hasChildNodes() insertBefore(DOMNode $noeudAInserer[, DOMNode $noeudReference]) isSameNode($DOMNode $noeudAComparer)

DOMNode boolean DOMNode DOMNode

boolean

1220

Les parseurs

Attribut isSupported(string $option, String $version) lookupNamespaceURI(String $prefix) lookupPrefix(String $espaceNoms) normalize() removeChild(DOMNode $fils) replaceChild(DOMNode $ancienNoeud, DOMNode $nouveauNoeud)

Type boolean

Dfinition Renvoi TRUE si loption est disponible dans la version prcise. Retourne luri du prfix pass en paramtre. Retourne le prefix de luri pass en paramtre. Normalise le nud. Retire le fils pass en paramtre du nud courant. Remplace lancien nud par le nouveau nud.

String String void DOMNode DOMNode

Tableau 15.5 : Classe DOMElement hritante de DOMNode


Attribut tagName schemaTypeInfo getAttribute(String $nom) getAttributeNode(String $nom) getAttributeNodeNS(String $espaceNoms, String $nom) getAttributeNS(String $espaceNoms, String $nom) getElementByTagName(String $nom) Type String String String DOMAttr DOMAttr Retourne la valeur dun attribut. Retourne le nud dun attribut. Retourne le nud dun attribut dans un espace de noms. Retourne la valeur dun attribut en spcifiant lespace de noms. Retourne les lments de nom $nom. Idem mais avec espace de noms. Retourne TRUE si lattribut de nom $nom existe. Retourne TRUE si lattribut de nom $nom existe dans lespace de nom spcifi. Retire lattribut de nom $nom. Dfinition Nom de la balise

15. Lutilisation de XML

String

DOMNodeList

getElementByTagNameNS(String DOMNodeList $espaceNom, String $nom) hasAttribute(String $nom) hasAttributeNS(String $espaceNoms, String $nom) boolean boolean

removeAttribute(String $nom) boolean

1221

Chapitre 15

Lutilisation de XML

Attribut removeAttributeNode(DOMNode $nom) removeAttributeNS(String $espaceNoms, String $nom) setAttribute(String $nom, String $valeur) setAttributeNode(DOMAttr $attribut) setAttributeNodeNS(DOMAttr $attribut) setAttributeNS(String $espaceNoms, String $nom, String $valeur)

Type boolean boolean

Dfinition Retire lattribut de nom $nom. Retire lattribut de nom $nom dans lespace de noms. Cre ou met jour lattribut $nom avec la valeur $valeur. Ajoute lattribut $attribut. Ajoute lattribut $attribut. Cre ou met jour lattribut $nom avec la valeur $valeur dans lespace de noms spcifi.

boolean

boolean boolean void

Tableau 15.6 : Classe DOMAttr


Attribut name specified value ownerElement Type String Boolean String DOMElement String boolean Renvoi TRUE si lattribut est un identifiant selon les spcifications DOM. (Dfini en tant que tel dans la DTD) Valeur de lattribut. Elment auquel est rattach lattribut. Dfinition Nom de lattribut.

15. Lutilisation de XML

schemaTypeInfo isId()

Tableau 15.7 : Classe DOMText hritante de DOMNode


Attribut wholeText isWhitespaceInElement Content() Type String boolean Renvoi TRUE si les espaces font parti du contenu. Dfinition

1222

Les parseurs

Attribut splitText(integer $index)

Type DOMText

Dfinition "Casse" le nud en deux lindice spcifi le nud sur lequel est appel cette fonction contient alors la premire partie tandis que la seconde partie est retourne.

Crer ou modier un arbre DOM


Pour crer un arbre il faut dabord crer un objet de type DOMDocument. (par exemple: $document = new DOMDocument())

DOMDocument()
Constructeur dobjet de type DOMDocument. Syntaxe $versionXML retour DOMDocument DOMDocument([String $versionXML]) Version XML du document. Objet de type DOMDocument.

A partir dun document existant, il va falloir le charger en mmoire, pour cela on utilise DOMDocument>load().

DOMDocument->load()
Permet de charger un fichier XML en mmoire. Cette fonction peut aussi sappeler statiquement. Syntaxe $nomFichier retour DOMDocument load(String $nomFichier) Nom du fichier charger. Un nouveau DOMDocument si la fonction a t appele de manire statique.

15. Lutilisation de XML

Pour charger une chane de caractre XML, autrement que dans un fichier, il faut faire appel DOMDocument>loadxml().

1223

Chapitre 15

Lutilisation de XML

DOMDocument->loadXml()
Permet de charger une chane de caractres XML en mmoire. Cette fonction peut aussi sappeler statiquement. Syntaxe $chaineXML retour DOMDocument loadXml(String $chaineXML) Chane de caractres charger. Un nouveau DOMDocument si la fonction a t appele de manire statique.

Un fichier HTML est trs souvent mal form, par exemple on y trouve des balises <br> (si ce nest pas de lXHTML) pour charger du HTML on utilise donc DOMDocument>loadhtmlfile() et DOMDocument>loadhtml().

DOMDocument->loadHTMLFile()
Permet de charger un fichier HTML en mmoire. Cette fonction peut aussi sappeler statiquement. Syntaxe $nomFichierHTML retour DOMDocument loadHTMLFile(String $nomFichierHTML) Nom du fichier HTML charger. Un nouveau DOMDocument si la fonction a t appele de manire statique.

15. Lutilisation de XML

DOMDocument->loadHTML()
Permet de charger une chane de caractres HTML en mmoire. Cette fonction peut aussi sappeler statiquement. Syntaxe $chaineHTML retour DOMDocument loadHTML(String $chaineHTML) Chane de caractres HTML charger. Un nouveau DOMDocument si la fonction a t appele de manire statique.

Les quatre fonctions suivantes permettent la cration du XML (ou HTML) partir de larbre DOM:

1224

Les parseurs

DOMDocument->save()
Permet de sauvegarder larbre DOM dans un fichier. Syntaxe $nomFichier retour int save(String $nomFichier) Nom du fichier o enregistrer larbre DOM. La taille en octets du fichier.

DOMDocument->saveXML()
Permet de crer la chane XML correspondante larbre DOM en mmoire. Syntaxe $noeud retour String saveXML([DOMNode $noeud]) Nud parent du XML extraire si lon ne veut pas larbre entier. Chane de caractres XML.

DOMDocument->saveHTMLFile()
Permet de sauvegarder larbre DOM dans un fichier. Syntaxe $nomFichier retour String saveHTMLFile(String $nomFichier) Nom du fichier o enregistrer larbre DOM. Chane de caractres HTML.

15. Lutilisation de XML

DOMDocument->saveHTML()
Permet de crer la chane HTML correspondante larbre DOM en mmoire. Syntaxe retour String saveHTML() Chane de caractres HTML.

A partir dun tel document, il est possible de crer des instances dobjets constituant larbre. En voici les principales fonctions:

1225

Chapitre 15

Lutilisation de XML

DOMDocument->createAttribute()
Permet de crer un attribut. Il faudra attacher cet attribut un nud en utilisant DOMNode>appendchild(). Syntaxe $nomAttribut retour DOMAttr createAttribute(String $nomAttribut) Nom de lattribut. Un nouveau objet de type DOMAttr. FALSE en cas derreur

DOMDocument->createAttributeNS()
Permet de crer un attribut avec espace de noms. Il faudra attacher cet attribut un nud en utilisant DOMNode>appendchild(). Syntaxe $espaceNoms $nomAttribut retour DOMAttr createAttributeNS(String $espaceNoms, String $nomAttribut) Espace de noms Nom de lattribut. Un nouveau objet de type DOMAttr. FALSE en cas derreur

DOMDocument->createCDATASection ()
15. Lutilisation de XML
Permet de crer une section CDATA, ce type de section peut servir pour inclure des donnes XML encodes (Base64 est souvent utilis) ou simplement du texte qui pourrait nuire au fichier XML (car contenant des balises par exemple). Il faudra attacher cet attribut un nud en utilisant DOMNode>appendchild(). Syntaxe $donnees retour DOMCDataSection createCDATASection(String $donnees) Donnes mettre dans la section. Un nouveau objet de type DOMCDataSection. FALSE en cas derreur

DOMDocument->createComment()
Permet de crer une balise de commentaires (entre <!-- et ->. Il faudra attacher cet attribut un nud en utilisant DOMNode>appendchild(). Syntaxe DOMComment createComment(String $commentaires)

1226

Les parseurs

$commentaires retour

Commentaires ajouter. Un nouveau objet de type DOMComment. FALSE en cas derreur

DOMDocument->createElement()
Permet de crer un nouvel lment. Il faudra attacher cet attribut un nud en utilisant DOMNode>appendchild(). Syntaxe $nomElement $valeur retour DOMElement createElement(String $nomElement [, String $valeur]) Nom de la balise. Valeur de la balise Un nouveau objet de type DOMElement. FALSE en cas derreur

DOMDocument->createElementNS()
Permet de crer un nouvel lment avec espace de noms. Il faudra attacher cet attribut un nud en utilisant DOMNode>appendchild(). Syntaxe $espaceNoms $nomElement retour DOMElement createElementNS(String $espaceNoms, String $nomElement) Espace de noms Nom de la balise. Un nouveau objet de type DOMElement. FALSE en cas derreur

15. Lutilisation de XML

DOMDocument->createTextNode()
Permet de crer un nouvel nud texte. Il faudra attacher cet attribut un nud en utilisant DOMNode>appendchild(). Syntaxe $texte retour DOMText createTextNode(String $texte) Texte du nud. Un nouveau objet de type DOMText. FALSE en cas derreur

Voici un exemple darbre DOM construit puis affich:

1227

Chapitre 15

Lutilisation de XML

Listing 15.9 : dom_exemple_01.php


<?php $doc = new DOMDocument(); $html = $doc->createElement("HTML"); $html = $doc->appendChild($html); $head = $doc->createElement("HEAD"); $head = $html->appendChild($head); $title = $doc->createElement("TITLE"); $title = $head->appendChild($title); $titre = $doc->createTextNode("Titre du document HTML"); $titre = $title->appendChild($titre); $body = $doc->createElement("BODY"); $body = $doc->appendChild($body); $comment = $doc->createComment("Comme en terre"); $comment = $body->appendChild($comment); echo $doc->saveHTML(); ?>

Dont le rsultat est:


<HTML><HEAD><TITLE>Titre du document HTML</TITLE></HEAD></HTML> <BODY><!--Comme en terre--></BODY>

Le script est extrmement simple comprendre mme si nous navons pas encore vu la fonction appendChild() qui ne fait quajouter un nud un autre, ce nud devenant donc le fils du second. Les nuds du document HTML sont crs un un comme tout document HTML. La premire balise est donc <HTML> laquelle on ajoute les balises <HEAD> puis <BODY>, la balise <HEAD> on ajoute la balise <TITLE> et cette dernire on ajoute un nud de type texte pour dfinir son contenu. Enfin on ajoute un commentaire la balise <BODY>.

15. Lutilisation de XML

Rien fermer Pour les personnes qui ne sont pas habitues manipuler des arbres DOM, vous remarquerez quil ny a pas "fermer" quoi que ce soit comme cest le cas pour les balises. Ici, tout fonctionne selon le principe dimbrication dlments.
Nous venons de voir les principales fonctions relatives lobjet DOMDocument, voici celles de DOMNode en dbutant par celle certainement la plus usite: DOMNode>appendChild().

DOMNode->appendChild()
Ajoute un nud enfant un nud existant. Syntaxe $noeudEnfant retour DOMNode appendChild(DOMNode $noeudEnfant) Nud ajouter au parent. Lobjet parent modifi.

1228

Les parseurs

Pour, au contraire, retirer un nud, on utilise DOMNode>removeChild() et pour remplacer par un autre: DOMNode>replaceChild().

DOMNode->removeChild()
Retire un nud de son parent. Syntaxe $noeudEnfant retour DOMNode removeChild(DOMNode $noeudEnfant) Nud retirer du parent. Lancien fils ou une erreur de type DOMException.

DOMNode->replaceChild()
Remplace un nud fils par un autre. Syntaxe $ancienNoeud $nouveauNoeud retour DOMNode replaceChild(DOMNode $ancienNoeud, DOMNode $nouveauNoeud) Nud remplacer. Nud remplaant. Lancien fils ou une erreur de type DOMException.

Cela peut servir de dupliquer un nud pour cela il suffit dutiliser DOMNode>cloneNode().

DOMNode->cloneNode()
Ajoute un nud enfant un nud existant. Syntaxe $copieProfondeur retour DOMNode cloneNode([boolean $copieProfondeur]) Indique si le nud doit tre copi avec ses enfants. (Non par dfaut) Le nud copi.

15. Lutilisation de XML

Rcuprer des donnes dun arbre existant


Rcuprer des donnes dun arbre DOM est bien plus simple que dutiliser SAX. La fonction DOMElement>getElementsByTagName() permet de retourner tous les nud ayant le nom spcifi. Lobjet retourn est de type DOMNodeList qui est un objet trs simple avec length comme attribut qui retourne le nombre dlment et DOMNodeList>item(integer $i) comme fonction qui permet de retourner le i-me lment.

1229

Chapitre 15

Lutilisation de XML

DOMElement->getElementsByTagName()
Retourne une liste de nud dont le nom est la chane de caractres passe en paramtre cette fonction. Syntaxe $nom retour DOMNodeList getElementsByTagName(String $nom) Nom des nuds retourner. Une liste de nuds ayant $nom comme nom.

Afin de rcuprer lattribut dun lment, il existe la fonction DOMElement>getAttribute() dtaille ci-dessous.

DOMElement->getAttribute()
Permet de rcuprer la valeur dun attribut. Syntaxe : $nom retour String getAttribute(String $nom) Nom de lattribut retourner Valeur de lattribut.

Pour rcuprer une valeur on peut aussi utiliser son chemin XPath.

DOMXPath->query()
15. Lutilisation de XML
Retourne la liste des nuds correspondants lexpression XPath fournie. Syntaxe : $xpath $noeudRelatif retour DOMNodelist query(String $xpath [, DOMNode $noeudRelatif]) Expression Xpath Nud de rfrence pour une expression XPath relative. Liste des nuds

XPath XPath est trs riche et nest pas prsent ici, mais si vous ne connaissez pas ces expressions utiles pour faire des recherches dans un document, je vous conseille vivement de jeter un il :

1230

Les parseurs

http://xmlfr.org/w3c/TR/xpath/

pour la documentation de rfrence traduite en franais.


http://www.zvon.org/xxl/XPathTutorial/General_fre/examples.html

pour une aide rapide par lexemple, ou encore le lien suivant qui met en parallle requtes SQL et leur quivalent utilisant XPATH.
http://www.fragbase.com/sql2xpath.php

Il y a bien dautres fonctions comme prsentes dans les tableaux succincts au dbut de ce chapitre. Et comme un exemple vaut des pages dexplications, en voici un qui montre comment manipuler du XML grce DOM.

Exemples
Reprenons lexemple de la mdiathque du chapitre prcdent dont le fichier sappelait mediathque_01.xml.

Listing 15.10 : dom_exemple_02.php


<?php $doc = DomDocument::load("mediatheque_01.xml"); $listeCD = $doc->getElementsByTagName("cdaudio"); foreach($listeCD as $cdAudio) { $interprete = $cdAudio->getAttribute("interprete"); $listeChansons = $cdAudio->getElementsByTagName("chanson"); echo "** $interprete\n"; for ($i=0; $i<$listeChansons->length; $i++) { $chanson = $listeChansons->item($i); $titre = $chanson->getElementsByTagName("titre")->item(0)->nodeValue; echo " - $titre\n"; } } ?>

15. Lutilisation de XML

Dont le rsultat attendu serait:


** Noir Dsir - Lenfant roi - Le grand incendie - Le vent nous portera ** Placebo - Pure Morning - Without You Im Nothing - Every You, Every Me

Quelques explications de cet exemple: tout dabord on rcupre lobjet DOMDocument correspondant au fichier XML stock sur le disque dur par un appel la mthode statique load(). Ensuite getElementsByTagName("cdaudio") permet de rcuprer lensemble des balises "cdaudio" puis on boucle sur cette liste. Rcuprer le nom de linterprte revient rcuprer la valeur de lattribut "interprete" de la balise "cdaudio". La liste des chansons du CD

1231

Chapitre 15

Lutilisation de XML

est ensuite rcupre et ici jai volontairement chang la faon ditrer sur les chansons pour utiliser les mthodes de DOMNodeList. Voici maintenant un court exemple de lutilisation de XPath:

Listing 15.11 : dom_exemple_03.php


<?php $doc = DomDocument::load("mediatheque_01.xml"); $xpath = new DOMXpath($doc); $liste = $xpath->query("//titre"); foreach ($liste as $title) { echo $title->nodeValue."\n"; } ?>

Dont le rsultat attendu serait:


Lenfant roi Le grand incendie Le vent nous portera Pure Morning Without You Im Nothing Every You, Every Me

Voil pour lanalyse syntaxique utilisant DOM. Ci-aprs est dcrit en dtail la toute nouvelle librairie de PHP5 appele SimpleXML, elle permet de simplifier lanalyse syntaxique dun document XML. Jetez-y au moins un il et vous vous rappellerez pourquoi vous aimez autant le PHP.

Le parseur SimpleXML
15. Lutilisation de XML
Si libXML est install alors le parseur SimpleXML est probablement activ, vous pouvez le vrifier en jetant un il aux informations affiches par phpinfo().
Figure 15.4 : phpinfo()SimpleXML

SimpleXML est intgr PHP depuis la version 5, cette librairie base sur libxml pour objectif de simplifier lanalyse syntaxique dun document XML. Il est ainsi possible en quelques lignes daccder tout lment dun document XML. SimpleXML nest ni plus ni moins quun analyseur DOM simplifi.

1232

Les parseurs

Exemples
Voici tout dabord quelques exemples pour voir le fonctionnement de cette bibliothque. Le document analyser sera le suivant pour tous les exemples qui suivent et est reprsentatif de ce que lon pourrait avoir pour une vidothque :

Listing 15.12 : videotheque.xml


<?xml version="1.0" standalone="yes" ?> <videotheque> <film imdb="0378194"> <titre>Kill Bill: Vol. 2</titre> <realisateur>Quentin Tarantino</realisateur> <genres> <genre>action</genre> <genre>drama</genre> <genre>thriller</genre> </genres> <acteurs> <acteur> <nom>Uma Thurman</nom> <role>The Bride (Black Mamba)</role> </acteur> <acteur> <nom>David Carradine</nom> <role>Bill (Snake Charmer)</role> </acteur> </acteurs> </film> <film imdb="0070356"> <titre>Mais ou est donc passee la septieme compagnie ?</titre> <realisateur>Robert Lamoureux</realisateur> <genres> <genre>war</genre> <genre>action</genre> <genre>comedy</genre> </genres> <acteurs> <acteur> <nom>Jean Lefebvre</nom> <role>Pitivier</role> </acteur> <acteur> <nom>Pierre Mondy</nom> <role>Sergent Chaudard</role> </acteur> </acteurs> </film> </videotheque>

15. Lutilisation de XML

Le premier exemple montre comment rcuprer un lment du document XML, ici le titre du premier film, le titre du second film et le nom du deuxime acteur du second film. Plusieurs

1233

Chapitre 15

Lutilisation de XML

faons daccder ses donnes sont prsentes, en effet, lindice du tableau nest pas obligatoire quand on veut accder au premier lment, cest particulirement utile lorsquil ny a quun lment comme "titre", "realisateur", "genres"

Listing 15.13 : parse_videotheque_1.php


<?php $xml = simplexml_load_file("videotheque.xml"); echo $xml->film[0]->titre[0]."\n<br />"; echo $xml->film->titre."\n<br />"; echo $xml->film[1]->titre."\n<br />"; echo $xml->film[1]->acteurs[0]->acteur[1]->nom."\n<br />"; echo $xml->film[1]->acteurs->acteur[1]->nom."\n<br />"; ?>

En sortie nous avons donc:


Kill Bill: Vol. 2 Kill Bill: Vol. 2 Mais ou est donc passee la septieme compagnie ? Pierre Mondy Pierre Mondy

En fait, pour bien comprendre la structure de lobjet $xml, faisons le afficher:

Listing 15.14 : parse_videotheque_2.php


<?php $xml = simplexml_load_file("videotheque.xml"); print_r($xml); ?>

Et le rsultat:

15. Lutilisation de XML

SimpleXMLElement Object ( [film] => Array ( [0] => SimpleXMLElement Object ( [titre] => Kill Bill: Vol. 2 [realisateur] => Quentin Tarantino [genres] => SimpleXMLElement Object ( [genre] => Array ( [0] => action [1] => drama [2] => thriller ) )

1234

Les parseurs

[acteurs] => SimpleXMLElement Object ( [acteur] => Array ( [0] => SimpleXMLElement Object ( [nom] => Uma Thurman [role] => The Bride (Black Mamba) ) [1] => SimpleXMLElement Object ( [nom] => David Carradine [role] => Bill (Snake Charmer) ) ) ) ) [1] => SimpleXMLElement Object ( [titre] => Mais ou est donc passee la septieme compagnie ? [realisateur] => Robert Lamoureux [genres] => SimpleXMLElement Object ( [genre] => Array ( [0] => war [1] => action [2] => comedy ) ) [acteurs] => SimpleXMLElement Object ( [acteur] => Array ( [0] => SimpleXMLElement Object ( [nom] => Jean Lefebvre [role] => Pitivier ) [1] => SimpleXMLElement Object ( [nom] => Pierre Mondy [role] => Sergent Chaudard ) ) ) ) ) )

15. Lutilisation de XML

Ce rsultat nous apprend deux choses, dune part, quil est facile daccder nimporte quelle entit car la structure nest ni plus moins quun tableau, et dautre part, on apprend que dans le

1235

Chapitre 15

Lutilisation de XML

cas dun document XML imposant que la place mmoire occupe par ce tableau sera immense et donc simpleXML ne sera pas adapt pour de larges fichiers XML (De mme que DOM). Connaissant la structure de lobjet $xml, toute folie est dsormais possible, par exemple lister les films ou les acteurs dun film et dsormais trs facile, la preuve ci-aprs.

Listing 15.15 : parse_videotheque_3.php


<?php $xml = simplexml_load_file("videotheque.xml"); foreach ($xml->film as $film) { echo "* ".$film->titre."\n<br />"; foreach ($film->acteurs->acteur as $acteur) { echo " - ".$acteur->nom." joue dans le role de ".$acteur->role."\n<br />"; } } ?>

qui a pour rsultat:


* Kill Bill: Vol. 2 - Uma Thurman joue dans le role de The Bride (Black Mamba) - David Carradine joue dans le role de Bill (Snake Charmer) * Mais ou est donc passee la septieme compagnie ? - Jean Lefebvre joue dans le role de Pitivier - Pierre Mondy joue dans le role de Sergent Chaudard

Simple mais nous navons pas vu comment rcuprer un attribut. imdb est le numro de film sachant que chaque film possde un numro unique attribu par un organisme. On peut vouloir rcuprer le numro imdb du premier film, ou mieux encore, rcuprer le titre du film dont on connat le numro. Voici comment il est possible de procder :

Listing 15.16 : parse_videotheque_4.php

15. Lutilisation de XML

<?php $xml = simplexml_load_file("videotheque.xml"); echo "Numero imdb du premier film: ".$xml->film[0][imdb]."\n<br />"; echo "Numero imdb du second film: ".$xml->film[1][imdb]."\n<br />"; foreach ($xml->film as $film) { if ((string)($film[imdb])=="0378194") echo "Titre du film ayant 0378194 comme numero: ".$film->titre."\n<br />"; } ?>

Le rsultat obtenu :
Numero imdb du premier film: 0378194 Numero imdb du second film: 0070356 Titre du film ayant 0378194 comme numero: Kill Bill: Vol. 2

En conclusion, rcuprer un attribut nest pas plus compliqu.

1236

Les parseurs

SimpleXML ne manque pas de gne et se permet mme dutiliser les expressions XPath pour faire des recherches dans le document, pour cela il faut faire appel la fonction xpath() de lobjet SimpleXML. XPath est un ensemble de commandes de recherche trs complet quoique rebutant au premier abord.

XPath Prsenter XPath ici serait trop long mais si vous ne connaissez pas ces expressions utiles pour faire des recherches dans un document, je vous conseille vivement de jeter un il :
http://xmlfr.org/w3c/TR/xpath/

pour la documentation de rfrence traduite en franais


http://www.zvon.org/xxl/XPathTutorial/General_fre/examples.html

pour une aide rapide par lexemple, ou encore le lien suivant qui met en parallle requtes SQL et leur quivalent utilisant XPATH.
http://www.fragbase.com/sql2xpath.php

Lexemple que nous avons pris tant simple, il ne va pas tre facile de montrer les capacits de Xpath. Rcuprer la liste des acteurs se fait trs facilement en crivant:

Listing 15.17 : parse_videotheque_5.php


<?php $xml = simplexml_load_file("videotheque.xml"); foreach ($xml->xpath(//acteur) as $acteur) { echo $acteur->nom."\n<br />"; } ?>

Qui donne:

15. Lutilisation de XML

Uma Thurman David Carradine Jean Lefebvre Pierre Mondy

Rcuprer le film dont limdb est 0378194 se fait facilement galement:

Listing 15.18 : parse_videotheque_6.php


<?php $xml = simplexml_load_file("videotheque.xml"); $film = $xml->xpath(//film[@imdb=0378194]); echo $film[0]->titre; ?>

1237

Chapitre 15

Lutilisation de XML

Qui donne:
Kill Bill: Vol. 2

API
Nous avons vu trs peu de fonctions dans les exemples prcdents (deux pour tre exact) mais nous pouvons dj faire beaucoup. Il est possible danalyser un fichier XML ou une chane de caractres XML avec simplexml_load_file() et simplexml_load_string() respectivement.

simplexml_load_le()
Transforme le fichier XML en objet facilement manipulable. Syntaxe $nomFichier retour SimpleXMLElement simplexml_load_file(string $nomFichier) Nom du fichier charger. Objet de type SimpleXMLElement facilement manipulable.

simplexml_load_string()
Transforme la chane de caractres XML en objet facilement manipulable. Syntaxe $chaineXML retour SimpleXMLElement simplexml_load_file(string $chaineXML) Chane de caractres XML charger. Objet de type SimpleXMLElement facilement manipulable.

15. Lutilisation de XML

Il est galement possible de rcuprer un objet SimpleXMLElement partir dun arbre DOM.

simplexml_import_dom()
Retourne un objet SimpleXMLElement partir dun arbre DOM. Syntaxe $noeudDOM retour SimpleXMLElement simplexml_import_dom(domNode $noeudDOM) Nud rcupr par la mthode danalyse syntaxique DOM. Objet de type SimpleXMLElement facilement manipulable.

Comme vu dans les exemples, xpath() est une fonction qui sapplique un objet de type SimpleXMLElement obtenu par une des trois fonctions prcdentes.

1238

Les parseurs

SimpleXMLElement->xpath()
Retourne un tableau dobjet de type SimpleXMLElement correspondant la recherche XPath. Syntaxe $requete retour array[SimpleXMLElement] xpath(string $xpath) Requte XPath. Tableau dobjets SimpleXMLElement.

SimpleXMLElement->children()
Retourne un objet de type SimpleXMLElement correspondant aux enfants du nud courant. Syntaxe retour SimpleXMLElement children() Un objet de type SimpleXMLElement.

Cette dernire fonction permet de rcuprer les "enfants" dun nud, voici un exemple dutilisation:

Listing 15.19 : parse_videotheque_7.php


<?php $xml = simplexml_load_file("videotheque.xml"); foreach ($xml -> children() as $test) { echo $test->titre."\n<br />"; } ?>

Dont le rsultat attendu est bien videment:


Kill Bill: Vol. 2 Mais ou est donc passee la septieme compagnie ?

15. Lutilisation de XML

SimpleXMLElement->attributes()
Retourne un objet de type SimpleXMLElement correspondant aux attributs du nud courant. Syntaxe retour SimpleXMLElement attributes() Un objet de type SimpleXMLElement.

Voici un court exemple dutilisation:

1239

Chapitre 15

Lutilisation de XML

Listing 15.20 : parse_videotheque_8.php


<?php $xml = simplexml_load_file("videotheque.xml"); foreach ($xml->film[0]->attributes() as $attribut => $valeur) { echo $attribut."=".$valeur."\n<br />"; } ?>

Dont le rsultat attendu est:


imdb=0378194

Bien entendu, rien nempche de modifier les objets SimpleXMLElement. Mais une fois modifis, on peut vouloir rcuprer le contenu de ces objets en format XML pour lcrire par exemple dans un fichier. Pour cela, il suffira alors dutiliser la fonction asXML() qui sapplique un objet de type simpleXMLElement.

SimpleXMLElement->asXML()
Retourne une chane de caractres XML valide reprsentant lobjet SimpleXMLElement. Syntaxe retour string asXML() Une chane XML

Listing 15.21 : parse_videotheque_9.php


<?php $xml = simplexml_load_file("videotheque.xml"); $xml->film[0]->titre = "Kill Bill Volume 2"; echo $xml->asXML(); ?>

15. Lutilisation de XML

Et en retour on a le XML modifi (le titre de Kill Bill: Vol. 2 a t subtilement modifi)"
<?xml version="1.0" standalone="yes"?> <videotheque> <film imdb="0378194"> <titre>TITRE</titre> <realisateur>Quentin Tarantino</realisateur> <genres> <genre>action</genre> <genre>drama</genre> <genre>thriller</genre> </genres> <acteurs> <acteur> <nom>Uma Thurman</nom>

1240

XSLT

<role>The Bride (Black Mamba)</role> </acteur> <acteur> <nom>David Carradine</nom> <role>Bill (Snake Charmer)</role> </acteur> </acteurs> </film> <film imdb="0070356"> <titre>Mais ou est donc passee la septieme compagnie ?</titre> <realisateur>Robert Lamoureux</realisateur> <genres> <genre>war</genre> <genre>action</genre> <genre>comedy</genre> </genres> <acteurs> <acteur> <nom>Jean Lefebvre</nom> <role>Pitivier</role> </acteur> <acteur> <nom>Pierre Mondy</nom> <role>Sergent Chaudard</role> </acteur> </acteurs> </film> </videotheque>

Et voil pour la bibliothque simpleXML, en tout et pour tout il y a sept fonctions utiles vous permettant de lire/modifier de petits documents XML trs simplement !

15.4. XSLT
Prsentation
La transformation XSL sappuie sur un fichier dcrivant ce que la transformation doit retourner lorsque telle ou telle balise est rencontre. Nous supposerons ici que vous tes familier avec ce genre de transformation.

15. Lutilisation de XML

XML, XSL Vous trouverez plus dinformations sur XML et la XSL, sur le site :
http://www.xmlfacile.com

sans oublier la rfrence (en anglais) :


http://www.w3.org/Style/XSL/

et sa traduction :
http://www.xmlfr.org/w3c/TR/xslt/

1241

Chapitre 15

Lutilisation de XML

Par la suite, titre dexemple, nous utiliserons la feuille de styles suivante :

Listing 15.22 : mediatheque_01.xsl


<?xml version="1.0" encoding="ISO-8859-1" ?> <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html" /> <xsl:template match="/"> <html> <body> <xsl:apply-templates /> </body> </html> </xsl:template> <xsl:template match="mediatheque"> <h1>Contenu de la mdiathque</h1> <table border="1"> <xsl:apply-templates select="cdaudio" /> </table> </xsl:template> <xsl:template match="cdaudio"> <tr><td colspan="2" bgcolor="#BBBBFF"> <b><xsl:value-of select="@interprete" /></b> </td></tr> <tr><td colspan="2" bgcolor="#DDDDFF"> <b><i><xsl:value-of select="@titre" /></i></b> </td></tr> <xsl:apply-templates select="chanson" /> </xsl:template>

15. Lutilisation de XML

<xsl:template match="chanson"> <tr> <td><xsl:apply-templates select="titre" /></td> <td><xsl:apply-templates select="duree" /></td> </tr> </xsl:template> <xsl:template match="titre"> <xsl:value-of select="text()" /> </xsl:template> <xsl:template match="duree"> <xsl:value-of select="text()" /> </xsl:template> <xsl:template match="*"> </xsl:template> </xsl:transform>

1242

XSLT

Les transformations de documents XML


La bibliothque XSL
PHP 4 Cette bibliothque a t introduite dans la version 5 de PHP, elle nest donc pas disponible pour PHP4. Vous devrez donc dans ce cas utiliser la bibliothque XSLT dcrite plus loin. Erreur de jeunesse ? Cette bibliothque PHP tant rcente, elle peut tre amene voluer et est donc marque comme tant exprimentale.

Installation
Sous Windows
Que ce soit avec larchive de PHP Group ou avec EasyPHP, vous devrez vous assurer que vous possdez bien un fichier php_xsl.dll dans le rpertoire des extensions PHP. Il vous suffit alors dajouter au fichier php.ini ou de dcommenter une ligne
extension=php_xsl.dll

Sous Linux
Il vous faut dabord rcuprer et installer la bibliothque libxslt disponible ladresse ftp://xmlsoft.org comme indiqu sur http://xmlsoft.org/XSLT. en tapant les commandes dsormais habituelles:

15. Lutilisation de XML

# # # #

tar zxvf libxslt-1.1.10.tar.gz ./configure --prefix=/usr/local make make install

Problme de compilateur (fails sanity check) Il se trouve que lopration configure ne sest pas droul correctement dans notre environnement. Celui-ci nacceptant pas apparemment pas notre compilateur. Nous ne nous sommes alors pas attards sur le problme et nous nous en sommes remis aux "packages" de notre Debian. Nous avons donc remplac linstallation prcdente par
# apt-get install libxslt1-dev

Une fois libxslt install, il suffit de recompiler PHP avec loption de configuration "withxsl=/usr/local".

1243

Chapitre 15

Lutilisation de XML

Vous pouvez vous reporter au chapitre "Installation" pour plus de dtails sur la compilation de PHP.

Vrication
Comme vous en avez pris lhabitude, vous pouvez vrifier que linstallation sest droule correctement en appelant un script contenant <?php phpinfo(); ?> qui doit afficher :

Figure 15.5 : phpinfo()

Utilisation
La transformation dun document XML via XSLT est trs simple. Il suffit de charger les documents XML et XSL dans des objets DOMDocument, dinstancier un objet XSLTProcessor, de charger le document XSL et dappeler la mthode de transformation.

Vous pouvez vous reporter au chapitre "Le parseur DOM" pour plus de dtails sur lobjet DOMDocument.

XSLTProcessor();
15. Lutilisation de XML
Objet permettant les transformations XSLT Syntaxe : XSLTProcessor()

XSLTProcessor->importStyleSheet()
Dfinit la feuille de style utiliser pour les prochaines transformations XSL. Syntaxe : $documentXSL retour boolean importStyleSheet(DOMDocument $documentXSL) Document DOM contenant la feuille de style FALSE en cas dchec, NULL sinon

1244

XSLT

XSLTProcessor->transformToXML()
Retourne, sous forme dune chane de caractres, le rsultat de lapplication de la feuille de style prcdemment slectionne sur le document XML indiqu. Syntaxe : $documentXML retour string transformToXML(DOMDocument $documentXML) Document DOM contenant le document XML transformer. Rsultat de la transformation ou FALSE en cas derreur.

XSLTProcessor->transformToDoc()
Retourne, sous forme dun DOMDocument, le rsultat de lapplication de la feuille de style prcdemment slectionne sur le document XML indiqu. Syntaxe : $documentXML retour DOMDocument transformToDoc(DOMDocument $documentXML) Document DOM contenant le document XML transformer. Rsultat de la transformation sous forme de DOMDocument ou FALSE en cas derreur.

Listing 15.23 : xsl_01.php


<?php $cheminAbsolu = dirname(__FILE__); // Chargement du document XML $xmlDoc = new DOMDocument(); $xmlDoc->load("$cheminAbsolu/../src_xml/mediatheque_01b.xml"); $xslDoc = new DOMDocument(); $xslDoc->load("$cheminAbsolu/../src_xml/mediatheque_01.xsl"); // Chargement de la feuille de style $xslt = new XSLTProcessor(); $xslt->importStyleSheet($xslDoc); // Transformation du fichier XML via XSLT // et envoi du rsultat directement lcran echo $xslt->transformToXML($xmlDoc);

15. Lutilisation de XML

?>

Le rsultat obtenu sera alors :

1245

Chapitre 15

Lutilisation de XML

Figure 15.6 : Exemple de transformation XSL

Dans lensemble la transformation sest relativement correctement bien passe. Nanmoins les entits externes nont pas t prises en compte (&nc; na par exemple pas t remplac par "Non Communiqu". Il est trop tt pour dire sil sagit dun bug ou bien sil faut attendre que cette bibliothque volue encore un peu pour rpondre totalement nos besoins.

La bibliothque XSLT/Sablotron
PHP 5 Cette bibliothque nest pas disponible avec PHP 5.X. Elle a t remplace par la bibliothque XSL sappuyant sur libxslt.

15. Lutilisation de XML

Installation
Sous Windows
Que ce soit avec larchive de PHP Group ou avec EasyPHP, vous devrez vous assurer que vous possdez bien un fichier php_xslt.dll dans le rpertoire des extensions PHP. Il vous suffit alors dajouter au fichier php.ini ou de dcommenter une ligne
extension=php_xslt.dll

Sous Linux
Pour pouvoir utiliser la bibliothque XSLT avec Sablotron, vous devez au pralable rcuprer la bibliothque Sablotron. Celle-ci est disponible sur le site http://www.gingerall.com/ ainsi que sur le CD-ROM fourni (sous le nom Sablot-1.0.tar.gz). Cette bibliothque ncessite galement la bibliothque expat. Cette dernire est disponible ladresse http://sourceforge.net/projects/expat/ ainsi que sur le CD-ROM fourni (sous le nom expat-1.95.6.tar.gz).

1246

XSLT

Installation dexpat Copiez le fichier expat-1.95.6.tar.gz sous le rpertoire /usr/local/src/lib (par exemple), puis saisissez les commandes :
# gunzip expat-1.95.6.tar.gz # tar xvf expat-1.95.6

Le fichier est prsent dcompress.


# # # # cd expat-1.95.6 ./configure make make install

La bibliothque expat est maintenant disponible sous /usr/local/lib (fichiers libexpat*). Installation de Sablotron Avant dinstaller Sablotron vous aurez besoin de patcher un des fichiers installs par expat (si comme indiqu vous utilisez la version 1.95.6). Pour cela, allez dans le rpertoire /usr/local/ include et ditez le fichier expat.h. Recherchez le bout de code suivant:
enum XML_Status { XML_STATUS_ERROR = 0, #define XML_STATUS_ERROR XML_STATUS_ERROR XML_STATUS_OK = 1 #define XML_STATUS_OK XML_STATUS_OK };

et dplacez le en dbut de fichier (avant le bloc "enum XML_Error {" par exemple) Maintenant vous pouvez copier le fichier Sablot-1.0.tar.gz sous le rpertoire /usr/local/src/lib (par exemple), puis saisir les commandes :
# gunzip Sablot-1.0.tar.gz # tar xvf Sablot-1.0.tar # cd Sablot-1.0

15. Lutilisation de XML

Le fichier est prsent dcompress.


# # # # # cd Sablot-1.0 export SABLOT_GPL=1 ./configure make make install

SABLOT_GPL La commande export SABLOT_GPL=1 est ncessaire si vous souhaitez utiliser la fonction xslt_set_encoding().

1247

Chapitre 15

Lutilisation de XML

La bibliothque Sablotron est dsormais disponible sous /usr/local/lib (fichiers libsab*) ainsi que le fichier /usr/local/bin/sabcmd. Maintenant que Sablotron est install, il suffit de lintgrer PHP, en le recompilant avec loption de configuration "enablexslt withxsltsablot". Mais attention! Avec la version 3 de gcc, vous risquez davoir des petits problmes. Pour y palier, vous devrez lancer la commande suivante avant lappel la commande ./configure.
# export LDFLAGS="-lstdc++"

Vous pouvez vous reporter au chapitre "Installation" pour plus de dtails sur la compilation de PHP. Apache Le serveur Apache intgre sa propre version dexpat qui peut entrer en conflit avec celle qui vient dtre installe. Cependant, depuis la version 1.3.21 dApache, il suffit de recompiler Apache pour quil intgre la version dexpat qui vient dtre installe. Si vous disposez dune version plus ancienne dApache pensez la mettre jour.

Vrication
Comme vous en avez pris lhabitude, vous pouvez vrifier que linstallation sest droule correctement en appelant un script contenant <?php phpinfo(); ?> qui doit afficher :
Figure 15.7 :

phpinfo()

15. Lutilisation de XML

Utilisation
La transformation dun document XML via XSLT se ralise en trois tapes :
j j j

Cration dun analyseur XSLT ; Transformation du document ; Libration des ressources occupes par lanalyseur.

Ceci se traduit par lappel aux fonctions :


j j j
xslt_create() ; xslt_process() ; xslt_free().

1248

XSLT

xslt_create()
Cre un nouvel analyseur XSLT. Syntaxe retour resource xslt_create(void) Rfrence sur un analyseur XSLT.

xslt_process()
Applique une transformation XSL sur un document XML. Syntaxe mixed xslt_process(resource $analyseurXSLT, string $uriXML, string $uriXSL [, string $uriResultat, [array $parametresAnalyseur, [array $parametresXSL]]]) Rfrence sur un analyseur XSLT tel que retourn par la fonction xslt_create(). URI (adresse) du fichier XSL. Ce doit tre soit un chemin relatif au serveur (et non pas relatif au script PHP !) soit un chemin absolu prcd de "file://", "http://", etc. selon la localisation du fichier. URI (adresse) du fichier XSL. Ce doit tre soit un chemin relatif au serveur (et non pas relatif au script PHP !) soit un chemin absolu prcd de "file://", "http://", etc. selon la localisation du fichier. URI (adresse) o doit tre crit le fichier rsultat. Ce doit tre soit un chemin relatif au serveur (et non pas relatif au script PHP !) soit un chemin absolu prcd de "file://" selon la localisation du fichier. Si ce paramtre nest pas spcifi, alors le rsultat est donn dans la valeur retour de la fonction.

$analyseurXSLT $uriXML

$uriXSL

$uriResultat

15. Lutilisation de XML

$parametresXSLT

Qui doit contenir un tableau associatif avec pour cls les paramtres utiliss par la feuille XSLT et pour valeurs les valeurs de ces diffrents paramtres.

$parametresAnalyseur Qui doit contenir un tableau prsentant les paramtres passer lanalyseur Sablotron. retour Chane de caractres contenant le rsultat de la transformation si aucun nom de fichier nest prcis, TRUE si le rsultat a t sauvegard dans un fichier avec succs, FALSE sinon.

Les encodages supports en entre Avec la bibliothque Sablotron, les fichiers XML peuvent tre encods en "UTF-8", "UTF-16", "ASCII", "ISO-8859-1", "ISO-8859-2" et "Windows-1250". Mais cette liste est plus importante si la bibliothque iconv est disponible dans lenvironnement de lanalyseur XSLT.

1249

Chapitre 15

Lutilisation de XML

xslt_free()
Libre les ressources occupes par lanalyseur. Syntaxe $analyseurXSLT void xslt_free(resource $analyseurXSLT) Rfrence sur un analyseur XSLT tel que retourn par la fonction xslt_create().

Listing 15.24 : xslt_01.php


<?php // Cration dun nouvel analyseur XSLT $xslt = xslt_create(); // Transformation du fichier XML via XSLT // et envoi du rsultat directement lcran $cheminAbsolu = "file://".dirname(__FILE__); echo xslt_process($xslt, "$cheminAbsolu/../src_xml/mediatheque_01b.xml", "$cheminAbsolu/../src_xml/mediatheque_01.xsl"); // Libration des ressources xslt_free($xslt); ?>

Le rsultat obtenu sera alors :


Figure 15.8 :

Exemple de transformation XSL

15. Lutilisation de XML

Vous constaterez que, dans ce cas, les rfrences externes sont prises en compte automatiquement (ce qui nest pas le cas avec le parseur expat).

1250

XSLT

Le rsultat est encod en UTF-8 (ce qui fait que les caractres accentus pourraient avoir une allure trange selon la configuration de votre navigateur). Si vous souhaitez un rsultat en ISO-8859-1 (ou autre) vous devez, au pralable, configurer lanalyseur.

Conguration de lanalyseur
Par dfaut, le document cr est cod en UTF-8, mais il est possible de choisir un type dencodage alternatif avec xslt_set_encoding().

xslt_set_encoding()
Prcise lencodage du document gnr (cette fonction nest pas disponible dans les versions Windows de PHP sorties jusque-l, savoir 4.2.1). Syntaxe $analyseurXSLT $encodage void xslt_set_encoding(resource $analyseurXSLT, string $encodage) Rfrence sur un analyseur XSLT tel que retourn par la fonction xslt_create(). Encodage choisi (ex. : "ISO-8859-1", "UTF-8", ...).

Encodages supports en sortie La liste des encodages supports dpend de lenvironnement. Si la bibliothque iconv est prsente alors Sablotron supporte tous les encodages que supporte iconv.

xslt_set_base()
Prcise lURI de base des documents prciss par un chemin relatif. Syntaxe $analyseurXSLT $baseURI void xslt_set_base(resource $analyseurXSLT, string $baseURI) Rfrence sur un analyseur XSLT tel que retourn par la fonction xslt_create(). URI de base pour les chemins relatifs.

15. Lutilisation de XML

Listing 15.25 : xslt_02.php


<?php // Cration dun nouvel analyseur XSLT $xslt=xslt_create(); // Selection dun encodage de sortie ISO-8859-1 $status = xslt_set_encoding($xslt, "ISO-8859-1");

1251

Chapitre 15

Lutilisation de XML

// Prcision du chemin du repertoire de base $cheminAbsolu="file://".dirname(__FILE__); xslt_set_base($xslt, "$cheminAbsolu/../src_xml/"); echo xslt_process($xslt, "mediatheque_01b.xml", "mediatheque_01.xsl"); // Libration des ressources xslt_free($xslt); ?>

Gestion des erreurs


Il est videmment possible tout moment de connatre quelle a t la dernire erreur rencontre, soit sous la forme dun code avec xslt_errno(), soit sous la forme dun message derreur en anglais avec xslt_error().

xslt_errno()
Retourne le code de la dernire erreur rencontre par lanalyseur XSLT. Syntaxe $analyseurXSLT retour int xslt_errno(resource $analyseurXSLT) Rfrence sur un analyseur XSLT tel que retourn par la fonction xslt_create(). Code derreur.

15. Lutilisation de XML

xslt_error()
Retourne le message derreur correspondant la dernire erreur rencontre par lanalyseur XSLT. Syntaxe $analyseurXSLT retour string sxlt_error(resource $analyseurXSLT) Rfrence sur un analyseur XSLT tel que retourn par la fonction xslt_create(). Message derreur.

Il est galement (en thorie) possible de faire excuter sa propre fonction lorsquune erreur est rencontre. Pour cela, il faut, au pralable, dclarer la fonction auprs de lanalyseur XSLT avec la fonction xslt_set_error_handler().

1252

XSLT

xslt_set_error_handler()
Dclare auprs de lanalyseur XSLT une fonction de gestion des erreurs. Syntaxe $analyseurXSLT $fonctionErreur void xslt_error_handler(resource $analyseurXSLT, string $fonctionErreur) Rfrence sur un analyseur XSLT tel que retourn par la fonction xslt_create(). Nom de la fonction devant grer les erreurs.

La fonction de gestion des erreurs ($fonctionErreur) aura la syntaxe suivante : Syntaxe $analyseurXSLT $niveauErreur $erreur $info void maFonction(resource $analyseurXSLT, int $niveauErreur, int $erreur, array $info) Rfrence sur un analyseur XSLT telle que retourne par la fonction xslt_create(). Le niveau derreur (les niveaux PHP ?). On croirait le code derreur prcdent. Tableau associatif contenant diverses informations sur lerreur. Vous trouverez parmi les cls : "msgtype" associ la valeur "error". "code" : le code derreur. "module" : le module ayant dtect lerreur (i.e. "Sablotron"). "URI" : lURI du document en cause. "line" : la ligne laquelle lerreur a t dtecte. "msg" : le message derreur.

Bug Dans une prcdente version teste (PHP 4.2.1 + Sablot-0.90 + Expat 1.95.2) les noms des cls taient souvent "complts" par des signes cabalistiques. Cela semble dsormais corrig (PHP 4.3.2 + Sablot-1.0 + Expat 1.95.6).

15. Lutilisation de XML

Gestion des traces


Il est possible de suivre la trace le travail de lanalyseur XSLT grce la fonction xslt_set_log(). La mise en uvre de ce mcanisme de trace se droule en deux temps. Premier temps : autoriser les traces, et second temps : indiquer dans quel fichier stocker les traces (par dfaut les traces vont sur la sortie stderr).

xslt_set_log()
Demande lactivation/larrt des traces. Indique quel fichier utiliser pour les traces.

1253

Chapitre 15

Lutilisation de XML

Syntaxe $analyseurXSLT $onOffNomFichier

void xslt_set_log(resource analyseurXSLT, mixed $onOffNomFichier) Rfrence sur un analyseur XSLT telle que retourne par la fonction xslt_create(). TRUE si vous souhaitez activer les traces, FALSE si vous souhaitez stopper les traces, ou bien encore nom de fichier (il ne sagit pas ici dune URI, donc pas besoin de le faire prcder de "file://") vers lequel vous souhaitez que les traces soient rediriges.

15.5. Gnration de messages XML


Depuis son arrive, XML est utilis dans de nombreux domaines. Cela devient llment de base du stockage et de lchange de linformation. Pas tonnant de voir de nouvelles normes apparatre pour lchange de messages entre serveurs. Parmi elles, lon trouve la norme WDDX (Web Distributed Data Exchange, cest--dire la norme dchange de donnes sur le Web). Celle-ci est destine changer des structures de donnes complexes entre les langages de programmation.

Web services Le langage XML est galement la base de lchange dinformations des "Web services".

Les messages WDDX


Installation
15. Lutilisation de XML

Sous Windows
Que ce soit avec larchive du PHP Group ou EasyPHP, le support de WDDX est activ doffice.

Sous Linux
Il suffit de recompiler PHP avec loption de configuration "enablewddx".

Vous pouvez vous reporter au chapitre "Installation" pour plus de dtails sur la compilation de PHP.

Vrication
L encore, vous pouvez vrifier que WDDX est bien activ en appelant un script contenant <?php phpinfo(); ?> et qui devra cette fois afficher :

1254

Gnration de messages XML

Figure 15.9 : phpinfo()

Utilisation
Lutilisation de la bibliothque WDDX est trs simple. Crer un paquet WDDX dcrivant le contenu dune variable consiste appeler la fonction wddx_serialize_value().

wddx_serialize_value()
Cre un paquet WDDX dcrivant le contenu dune variable unique. Syntaxe $variable $commentaire retour string wddx_serialize_value(mixed $variable [, string $commentaire]) Variable dcrire dans le paquet WDDX. Commentaire inclure dans lattribut "comment" de la balise "header" du paquet WDDX. La chane de caractres contenant le paquet WDDX.

Exemple dutilisation :

Listing 15.26 : wddx_01.php


<?php include("wddx2html_inc.php");

15. Lutilisation de XML

$variable1 = "Du Texte"; $paquetWDDX = wddx_serialize_value($variable1, "Test avec chane de caractres"); echo wddx2html($paquetWDDX); echo "<br />"; $tab = array ("Test", 2, array("Cle"=>"Valeur")); $paquetWDDX = wddx_serialize_value($tab, "Test avec tableau"); echo wddx2html($paquetWDDX); ?>

Ce script utilise une fonction (faite maison) afin de rendre laffichage du rsultat plus lisible depuis un navigateur.

1255

Chapitre 15

Lutilisation de XML

Listing 15.27 : wddx2html_inc.php


<?php // Retourne un paquetWDDX avec une forme // permettant une meilleure lecture en HTML. function wddx2html($paquetWDDX) { $resultat = ""; $tab = ""; $balises = explode("<", $paquetWDDX); for ($i=0; $i<count($balises); $i++) { if ($balises[$i]!="") { // Sil sagit dune balise fermante // indenter un peu moins la ligne if (eregi("^/",$balises[$i])) $tab = substr($tab, 0, -12); $resultat .= $tab . htmlspecialchars("<".$balises[$i])."<br />"; // // // if Sil sagit dune balise ouvrante indenter un peu plus la ligne suivante ((!eregi("^/",$balises[$i]))&& (!eregi("/>$",$balises[$i]))) $tab .= "&nbsp;&nbsp;";

} } return $resultat; } ?>

15. Lutilisation de XML

dont voici le rsultat : <wddxPacket version=1.0> <header> <comment>Test avec chane de caractres </comment> </header> <data> <string>Du Texte </string> </data> </wddxPacket>
<wddxPacket version=1.0> <header> <comment>Test avec tableau </comment> </header>

1256

Gnration de messages XML

<data> <array length=3> <string>Test </string> <number>2 </number> <struct> <var name=Cle> <string>Valeur </string> </var> </struct> </array> </data> </wddxPacket>

Pour crer un paquet WDDX dcrivant plusieurs variables, il faut faire appel wddx_serialize_vars().

wddx_serialize_vars()
Cre un paquet WDDX dcrivant plusieurs variables. Syntaxe $nomVariable string wddx_serialize_vars(mixed $nomVariable [, mixed $nomVariable...]) Nom de la variable ou tableau de noms de variables.

Listing 15.28 : wddx_02.php


<?php include("wddx2html_inc.php"); $tableau = array ("Test", 2, array("Cle"=>"Valeur")); $variable1 = "Variable1"; $variable2 = "Variable2"; $tableauNom = array ("variable1", "variable2"); $paquetWDDX = wddx_serialize_vars("variable1", "tableau", $tableauNom); echo wddx2html($paquetWDDX); ?>

15. Lutilisation de XML

affichera : <wddxPacket version=1.0> <header/>

1257

Chapitre 15

Lutilisation de XML

<data> <struct> <var name=variable1> <string>Variable1 </string> </var> <var name=tableau> <array length=3> <string>Test </string> <number>2 </number> <struct> <var name=Cle> <string>Valeur </string> </var> </struct> </array> </var> <var name=variable1> <string>Variable1 </string> </var> <var name=variable2> <string>Variable2 </string> </var> </struct> </data> </wddxPacket> Dans ce cas, il nest pas possible de spcifier un attribut "comment".

15. Lutilisation de XML

Si vous souhaitez spcifier un attribut "comment", et surtout si vous souhaitez crer un packet WDDX en ajoutant les variables les unes aprs les autres, vous pouvez utiliser les fonctions wddx_packet_start(), wddx_add_vars() et wddx_packet_end().

wddx_packet_start()
Commence un paquet WDDX. Syntaxe $comment retour int wddx_packet_start([string $comment]) Commentaire inclure dans lattribut "comment" de la balise "header". Rfrence sur un paquet WDDX.

1258

Gnration de messages XML

wddx_add_vars()
Ajoute des variables un paquet WDDX. Syntaxe $paquetWDDX $nomVariable void wddx_add_vars(resource $paquetWDDX, mixed $nomVariable [,mixed $nomVariable ...]) Rfrence sur un paquet wddx_packet_start(). WDDX telle que retourne par

Nom de la variable, tableau de noms de variables.

wddx_packet_end()
Clt et retourne le paquet WDDX. Syntaxe $paquetWDDX retour string wddx_packet_end(int $paquetWDDX) Rfrence sur un paquet wddx_packet_start(). WDDX telle que retourne par

La chane de caractres contenant le paquet WDDX.

Listing 15.29 : wddx_03.php


<?php include("wddx2html_inc.php"); $tableau = array ("Test", 2, array("Cle"=>"Valeur")); $variable1 = "Variable1"; $variable2 = "Variable2"; $tableauNom = array ("variable1", "variable2"); $refWDDX = wddx_packet_start("Mon commentaire"); wddx_add_vars($refWDDX, "variable1", "tableau"); wddx_add_vars($refWDDX, $tableauNom); $paquetWDDX = wddx_packet_end($refWDDX); echo wddx2html($paquetWDDX); ?>

15. Lutilisation de XML

Enfin, fort heureusement, la bibliothque WDDX ne permet pas seulement de gnrer des paquets WDDX ; elle permet aussi de les lire. Pour cela, vous disposez de la fonction wddx_deserialize().

1259

Chapitre 15

Lutilisation de XML

wddx_deserialize()
Lit un paquet WDDX. Syntaxe $paquetWDDX retour mixed wddx_deserialize(string $paquetWDDX) Paquet WDDX lire. Retourne, selon les cas, un nombre, une chane de caractres, un tableau associatif ayant pour cl le nom de la variable et pour valeur la valeur de la variable. Ce tableau pourra tre trs simplement converti en une srie de variables grce la fonction extract() prsente dans le chapitre concernant les tableaux.

Listing 15.30 : wddx_04.php


<?php echo "<b>Dsrialisation dun paquet WDDX de type tableau "; echo "(issu des exemples prcdents)</b>"; echo "<br />"; $paquetWDDX $paquetWDDX $paquetWDDX $paquetWDDX $paquetWDDX $paquetWDDX $paquetWDDX $paquetWDDX $paquetWDDX $paquetWDDX $paquetWDDX $paquetWDDX $paquetWDDX = .= .= .= .= .= .= .= .= .= .= .= .= "<wddxPacket version=1.0>"; "<header><comment>Mon commentaire</comment></header>"; "<data><struct>"; "<var name=variable1><string>Variable1</string></var>"; "<var name=tableau><array length=3>"; "<string>Test</string><number>2</number>"; "<struct>"; "<var name=Cle><string>Valeur</string></var>"; "</struct>"; "</array></var>"; "<var name=variable1><string>Variable1</string></var>"; "<var name=variable2><string>Variable2</string></var>"; "</struct></data></wddxPacket>";

15. Lutilisation de XML

$tableauWDDX = wddx_deserialize($paquetWDDX); if (is_array($tableauWDDX)) extract($tableauWDDX); echo "variable1 = $variable1<br />"; echo "tableau = "; print_r($tableau); echo "<br/>"; echo "variable2 = $variable2<br />"; echo "<b>Cas dune variable de type chane de caractres</b><br />"; $paquetWDDX = wddx_serialize_value("Texte"); echo wddx_deserialize($paquetWDDX)."<br />"; echo "<b>Cas dune variable de type nombre</b><br />";

1260

Gnration de messages XML

$paquetWDDX = wddx_serialize_value(12); echo wddx_deserialize($paquetWDDX)."<br />"; ?>

aura bien leffet attendu, en retournant : Dsrialisation dun paquet WDDX de type tableau (issu des exemples prcdents) variable1 = Variable1 tableau = Array ( [0] => Test [1] => 2 [2] => Array ( [Cle] => Valeur ) ) variable2 = Variable2 Cas dune variable de type chane de caractres Texte Cas dune variable de type nombre 12

15. Lutilisation de XML 1261

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.


16.1 16.2 16.3 16.4 16.5 16.6 Fonctions rseau (de base) Rseau . . . . . . . . . . . . . Les sockets . . . . . . . . . . FTP . . . . . . . . . . . . . . . cURL (client URL Library) . SOAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1265 .1265 .1270 .1275 .1288 .1299

Rseau

16.1. Fonctions rseau (de base) 16.2. Rseau


Les fonctions prsentes dans ce chapitre ne permettent pas de rels dveloppements, mais constituent une "trousse outils" parfois ncessaire dans la manipulation dinformations rseau (comme ce peut tre le cas, par exemple, avec lutilisation des sockets). Elles ne ncessitent aucune installation particulire.

Adresses IP et DNS
Lopration la plus souvent sollicite est certainement celle qui consiste dterminer ladresse IP dune machine lorsque lon ne connat que son nom. Pour cela, vous disposez de la fonction getHostByName().

getHostByName()
Retourne ladresse IP de la machine prcise par son nom. Syntaxe $nomMachine retour string getHostByName(string $nomMachine) Nom de la machine. Adresse IP de la machine, ou $nomMachine si aucune adresse IP na pu tre trouve.

Ainsi, le code suivant :


<?php echo getHostByName("localhost"); ?>

retournera trs probablement :


127.0.0.1

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Alors que :
<?php echo getHostByName("www.php.net"); ?>

retournera une adresse IP publique comme, par exemple,


208.210.50.161

1265

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Il est galement possible de raliser lopration inverse, savoir rcuprer un nom de machine partir de son adresse IP grce getHostByAddr().

getHostByAddr()
Retourne un nom de machine associ ladresse IP prcise (tel quon le trouve dans le fichier /etc/hosts des sytmes UNIX/Linux). Syntaxe $adresseIP retour string getHostByAddr(string $adresseIP) Adresse IP de la machine. Nom associ la machine, ou $adresseIP si aucun nom na pu tre trouv.

Le code suivant :
<?php echo getHostByAddr("127.0.0.1"); ?>

pourra retourner :
localdomain.localhost

On

notera

au

passage

que

lopration

nest

pas

ncessairement

rversible.

Si

getHostByName("localhost") retourne "127.0.0.1" cela nimplique pas que getHostByAddr("127.0.0.1") retourne "localhost". En effet, une machine peut avoir

plusieurs noms (via des alias), et cest donc le nom principal qui est retourn par getHostByAddr(). De mme, une unique machine peut possder plusieurs adresses IP. Pour en dterminer la liste, vous pouvez faire appel getHostByNameL().

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

getHostByNameL()
Retourne la liste des adresses IP de la machine prcise par son nom. Syntaxe $nomMachine retour array getHostByNameL($nomMachine) Nom de la machine. Tableau index des adresses IP de la machine, ou FALSE si aucune adresse IP na pu tre trouve.

PHP dispose de fonctions permettant de convertir des adresses IP prcises sous la forme "classique" xxx.xxx.xxx.xxx en adresses sous la forme dentiers, et rciproquement.

1266

Rseau

ip2long()
Convertit une adresse IP du format "xxx.xxx.xxx.xxx" en un entier. Syntaxe : $adresseIP retour int ip2long(string $adresseIP) Adresse IP au format "xxx.xxx.xxx.xxx". Adresse IP sous forme dun entier.

Entier sign ou non Un simple echo du rsultat fourni par ip2long peut conduire laffichage dun entier ngatif. Or celui-ci est thoriquement non sign. Il est donc prfrable de faire appel printf("%u", ip2long($adresseIP)).

long2ip()
Convertit une adresse IP dentier au format "xxx.xxx.xxx.xxx". Syntaxe $adresseIP retour int ip2long(string $adresseIP) Adresse IP sous forme dun entier. Adresse IP au format "xxx.xxx.xxx.xxx".

Dans certaines circonstances, comme par exemple pour dterminer si une adresse e-mail a des chances dtre valide, il peut tre utile de dterminer si le nom de domaine indiqu existe, ou, plus prcisment, vrifier si ce nom est connu du DNS.

DNS DNS sont les initiales anglaises de "Domain Name Server", autrement dit "Serveur de nom de domaine". En deux mots, ce serveur contient les tables de correspondances qui permettent de retrouver une machine (ou son adresse IP) partir de son nom. Vous trouverez plus dinformations sur le site Internet : http://www.nic.fr/guides/dns-intro.
Pour tester la prsence dun nom de machine auprs du DNS vous ferez appel checkDNSRR().

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

checkDNSRR() (non disponible sous Windows)


Teste la prsence dun nom de machine ou dune adresse IP auprs du DNS. Notez que dans la version 5 de PHP, cette fonction est baptise DNS_check_record() (tout en assurant la compatibilit).

1267

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Syntaxe $nomMachine $type

boolean checkDNSRR(string $nomMachine [, string $type]) Nom de la machine ou adresse IP. Prcise le type dentre recherche (par dfaut MX) : A (Address = Adresse) : une simple adresse. CNAME (Cannonical Name = Nom canonique) : un alias. MX (Mail eXchanger = Distributeur de courrier) : machine permettant la rception de mails. NS (Name Server = Serveur de nom) : un serveur de nom. PTR (Pointer = Pointeur) : un renvoi sur une autre machine. SOA (Start Of Authority) : une zone. ANY : lensemble des options prcdentes. TRUE si la machine est connue du DNS (pour le type prcis), FALSE sinon.

retour

Voici donc une petite fonction permettant non pas de vrifier la validit dune adresse e-mail, mais de dbusquer certaines adresses manifestement non valides.
<?php function testEmail($email) { $domaine = strstr($email, @); return checkdnsrr($domaine, MX); } $email = "damien@toutestfacile.com"; if (testEmail($email)) { echo "Je ne peux pas assurer que cette adresse email est valide ". "mais elle nest pas totalement farfelue"; } else { echo "Pfuuu... Cest nimporte quoi cet email, ". "jamais je ne pourrai envoyer demail cette adresse"; } ?>

Pour ce qui concerne les entres MX du fichier de configuration du DNS, il est possible den savoir un peu plus grce la fonction getMXRR().

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

getMXRR() (Non disponible sous Windows)


Retourne la liste des machines enregistres auprs du DNS pour la gestion des mails. Notez que dans la version 5 de PHP, cette fonction est baptise DNS_get_mx() (tout en assurant la compatibilit). Syntaxe $nomMachine $machines boolean getMXRR(string $nomMachine, array &$machines [, array &$poids]) Nom de la machine. Rfrence sur une variable dans laquelle sera copi un tableau index contenant les noms des machines devant "router" les mails.

1268

Rseau

$poids

Rfrence sur une variable dans laquelle sera copi un tableau index contenant les poids associs aux machines. Les mails seront prioritairement "routs" par la machine de plus faible poids. TRUE si la machine est connue du DNS, FALSE sinon.

retour

Protocoles et services
PHP propose galement des fonctions permettant de rcuprer des informations plus intimement lies au serveur. Il est, par exemple, possible de connatre le port associ un service ou, inversement, de retrouver le nom dun service partir de son numro de port.

getServByName()
Retourne le port associ au service donn. Syntaxe $service $protocole retour int getServByName(string $service, string $protocole) Nom du service (ex. : "ftp", "http", ...) Nom du protocole ("tcp" ou "udp"). Numro de port, ou FALSE en cas dchec.

getServByPort()
Retourne le nom du service associ au port donn. Syntaxe $port $protocole retour int getServByPort(string $port, string $protocole) Numro du port. Nom du protocole ("tcp" ou "udp"). Nom du service, ou FALSE en cas dchec.

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Ainsi, pour connatre le port associ au service FTP, ou le nom du service associ au port 80, lon pourra utiliser le script suivant :
<?php echo getServByName("ftp", "tcp")."<br />"; echo getServByPort(80, "tcp"); ?>

ce qui retournera (probablement) :


21 http

1269

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Il est galement possible de connatre le numro associ un protocole ou, inversement, de retrouver le nom dun protocole partir de son numro.

getProtoByName()
Retourne le numro associ un nom de protocole (tel quon le trouve dans le fichier /etc/protocols des systmes UNIX/Linux). Syntaxe $nomProtocole retour int getProtoByName(string $nomProtocole) Nom du protocole. Numro du protocole, ou 1 sil nexiste pas.

getProtoByNumber()
Retourne le nom associ un numro de protocole (tel quon le trouve dans le fichier /etc/protocols des systmes UNIX/Linux). Syntaxe $numeroProtocole retour int getProtoByNumber(string $numeroProtocole) Numro du protocole. Nom du protocole, ou FALSE sil nexiste pas.

Voici un exemple dutilisation. Le script suivant :


<?php echo getProtoByName("tcp")."<br />"; echo getProtoByNumber(62)."<br />"; ?>

pourra retourner :

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

6 cftp

16.3. Les sockets


Pour communiquer directement avec un service dune machine donne, vous serez peut-tre amen utiliser les sockets. Vous pouvez ainsi communiquer directement avec un serveur FTP, HTTP, NNTP (newsgroup), etc , et matriser plus finement les oprations que si vous utilisiez les commandes de plus haut niveau (plus couramment utilises). Le principe dutilisation est simple et se droule en quatre grandes tapes :

1270

Les sockets

j j j j

Ouverture de la connexion ; Configuration de la connexion ; Lecture/criture sur la socket ; Fermeture de la connexion.

Un exemple dapplication est donn la fin de ce sous-chapitre.

Ouverture de la connexion
Louverture dune connexion se fait via la fonction fSockOpen().

fSockOpen()
Ouvre une connexion sur une socket. Syntaxe resource fSockOpen(string $serveur, int $port [, int &$codeErreur [, string &$msgErreur [, double $delaiExpiration]]]) Nom du serveur sur lequel doit se porter la connexion (ventuellement prcd de "udp://" pour une connexion UDP). Numro du port sur lequel tablir la connexion. Rfrence sur une variable dans laquelle sera copi le code derreur lev. Rfrence sur une variable dans laquelle sera copi le message derreur lev. Dlai (en secondes) au-del duquel la tentative de connexion doit tre abandonne (par dfaut 60 secondes). Identifiant de connexion la socket, ou FALSE en cas derreur.

$serveur $port $codeErreur $msgErreur $delaiExpiration retour

La fonction fSockOpen() possde un quivalent permettant louverture dune connexion persistante (nous navons pas vrifi le caractre persistant et rutilisable de la connexion). Il sagit de la fonction pFSockOpen(), qui possde exactement la mme syntaxe que fSockOpen().

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Conguration de la connexion
Il est possible de jouer sur deux paramtres de connexion :
j j

Le mode de lecture bloquant ou non ; Le dlai dexpiration (timeout) de la socket.

La lecture est dite en mode bloquant si la fonction de lecture doit attendre quun message lui soit adress pour "rendre la main" au programme. Dans le cas contraire, elle est dite non bloquante, et la fonction de lecture retourne simplement le contenu de la mmoire tampon

1271

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

(espace stockant les messages nouvellement reus) qui pourra ventuellement tre vide (si le message nest pas encore arriv). Par dfaut, en labsence dappel la fonction socket_set_blocking(), le mode de lecture est bloquant.

socket_set_blocking()
Dtermine si le mode de lecture de la socket doit tre ou non bloquant. Syntaxe $idSocket $modeLecture retour boolean socket_set_blocking(resource $idSocket, boolean $modeLecture) Identifiant de la socket tel que retourn par fsockopen(). TRUE si le mode de lecture doit tre bloquant, FALSE sinon. FALSE en cas dchec, TRUE sinon.

La dure de vie de la connexion la socket peut tre limite par la fonction socket_set_timeout().

socket_set_timeout()
Dtermine la dure de vie maximale de la socket. Syntaxe $idSocket $secondes $microsecondes boolean socket_set_timeout(resource $idSocket, int $secondes, int $microsecondes) Identifiant de la socket tel que retourn par fsockopen(). Partie "secondes" de la dure de vie de la socket exprime en "secondes:microsecondes". Partie "microsecondes" de la dure de vie de la socket exprime en "secondes:microsecondes". FALSE en cas dchec, TRUE sinon.

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

retour

Lecture/criture sur la socket


La lecture et lcriture sur la socket seffectuent laide des fonctions qui ont dj t vues dans le chapitre relatif aux fichiers. Vous pourrez ainsi utiliser fGets($idSocket, $nbOctets); pour lire jusqu $nbOctets octets sur la socket, fPuts($idSocket, $chaine); pour envoyer au serveur une chane de caractres via la socket, ou encore fEOF($idSocket); pour tester si la fin de fichier (fin dmission) a t atteinte.

1272

Les sockets

Fermeture de la connexion
Le fermeture de la connexion sopre exactement de la mme faon que celle dun fichier, cest--dire par la commande fClose($idSocket).

Informations sur la connexion


Pour connatre ltat dune socket, vous pouvez faire appel la fonction
socket_get_status().

socket_get_status()
Retourne quelques informations sur ltat de la socket. Syntaxe $idSocket retour array socket_get_status(resource $idSocket) Identifiant de la socket tel que retourn par fsockopen(). Tableau associatif possdant les cls : "time_out" associe une valeur de type boolen prcisant si la dure de vie de la socket a expir ou non. "blocked" associe une valeur de type boolen prcisant si la lecture sur la socket se fait en mode bloquant ou non. "eof" associe une valeur de type boolen prcisant si un indicateur de fin de fichier a t dtect ou non. "unread_bytes" associe une valeur de type entier prcisant le nombre doctets actuellement dans la mmoire tampon de lecture de la socket.

Application
Pour mettre en place une communication via une socket, lessentiel est de bien connatre le langage de communication avec le serveur. Si vous avez conu votre propre serveur, vous savez certainement comment il fonctionne autrement, il faut se rfrer aux spcifications. Dans le cas dun serveur HTTP, le principe est assez simple et a t voqu dans le chapitre En-ttes.

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Vous pouvez vous reporter l annexe "Les en-ttes" pour plus de dtails.
Pour rcuprer un document via la mthode GET, il suffit de lui envoyer les instructions "GET <nom du document> HTTP/<norme HTTP>", et, dans le cas de la norme 1.1, il faut au minimum communiquer len-tte Host. Pour rcuprer la page daccueil dun site, il faudra donc, par exemple, envoyer les instructions suivantes :
GET / HTTP/1.1 Host: localhost

1273

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

ce qui nous donne le script suivant :

Listing 16.1 : socket_01.php


<?php // Exemple de rcupration dun document via HTTP // en utilisant directement les sockets. $serveur = "www.gnu.org"; $document = "/"; echo "<b>Lecture de $serveur$document</b><br />"; $idSocket = fSockOpen($serveur, 80, $codeErreur, $msgErreur); if (!$idSocket) { echo "La connexion via la socket a choue.<br />"; echo "Code derreur: $codeErreur<br />"; echo "Message derreur: $msgErreur<br />"; die(); } // Configuration de la connexion // en mode bloquant // et avec un timeout de 5 minutes socket_set_blocking($idSocket, TRUE); socket_set_timeout($idSocket, 5, 0);

// Envoi de donnes au serveur fputs($idSocket, "GET $document HTTP/1.1\r\n"); fputs($idSocket, "Host: localhost\r\n"); fputs($idSocket, "\r\n"); // Marque la fin de len-tte // Lecture de la rponse while (!feof($idSocket)) { $donnees = fgets($idSocket, 512); echo "<xmp>$donnees</xmp>"; } ?>

// Affichage du code source

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

qui fournira, par exemple, le rsultat suivant (dbut de la rponse uniquement) :


Lecture de www.gnu.org/ HTTP/1.1 200 OK Date: Tue, 28 May 2002 15:39:34 GMT Server: Apache/1.3.24 (Unix) Debian GNU/Linux mod_python/2.7.8 Python/1.5.2 Last-Modified: Fri, 24 May 2002 17:51:38 GMT ETag: "1088107-2e6e-3cee7daa" Accept-Ranges: bytes Content-Length: 11886 Content-Type: text/html

1274

FTP

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD> <TITLE>GNUs Not Unix! - the GNU Project and the Free Software Foundation (FSF)</title> <META HTTP-EQUIV="Keywords" CONTENT="GNU, FSF, Free Software Foundation, Linux, Emacs, GCC, Unix, Free Software, Operating System, GNU Kernel, HURD, GNU HURD"> <META HTTP-EQUIV="Description" CONTENT="Since 1983, developing the free Unix-like operating system GNU,

Comme vous pouvez le constater, nous rcuprons ainsi non seulement le code source HTML de la page, mais galement len-tte retourn par le serveur (le dbut du code source se trouvant juste aprs la premire ligne laisse vide). Lutilisation des sockets permet ici de rcuprer len-tte retourn par le serveur (et ainsi, par exemple, de vrifier le "Content-type"), mais aussi de prciser notre propre en-tte de requte (en utilisant par exemple le "User-agent" dInternet Explorer ou de Mozilla, et en testant diffrentes valeurs pour "Accept-Language", etc.).

16.4. FTP
Les fonctions de la bibliothque FTP permettent daccder en tant que client un serveur FTP.

Installation
Sous Windows
Que ce soit avec larchive du PHP Group ou avec EasyPHP, les fonctions FTP sont intgres PHP.

Sous Linux
Vous devrez recompiler PHP avec loption enableftp (avec les versions 3 de PHP, il sagissait de loption withftp).

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Vous pouvez vous reporter au chapitre "Prise en main" pour plus de dtails sur la faon de compiler PHP.

Vrication
Pour vrifier que le support FTP est activ, appelez un script contenant <?php phpinfo(); ?>. Celui-ci doit alors laisser apparatre :

1275

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Figure 16.1 : phpinfo() FTP

Les fonctions de base


Connexion/dconnexion
La premire tape consiste, comme toujours, se connecter au serveur.

ftp_connect()
Permet de se connecter un serveur FTP. Syntaxe $serveur $port $delaiExpiration retour resource ftp_connect(string $serveur [, int $port [, int $delaiExpiration]]) Adresse du site FTP. Port du serveur FTP si celui-ci est diffrent du port usuel 21. Temps en secondes pour toute commande avant abandon ; par dfaut cette valeur vaut 90 secondes. Un identifiant de connexion ou FALSE en cas derreur.

Une fois connect, il faut sidentifier (sans quoi rien nest possible).

ftp_login()
Identification auprs du serveur. Syntaxe boolean ftp_login(resource $idConnexion, string $identifiant, string $motDePasse) Identifiant de connexion obtenu par ftp_connect(). Identifiant (login) de lutilisateur. Mot de passe utilisateur. TRUE si la connexion a pu se faire, FALSE sinon.

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

$idConnexion $identifiant $motDePasse retour

La dconnexion seffectuera, quant elle, grce la fonction ftp_close().

1276

FTP

ftp_close()
Permet de clore la connexion FTP. Syntaxe $idConnexion retour boolean ftp_close(resource $idConnexion) Identifiant de connexion obtenu par ftp_connect(). TRUE en cas de succs.

ftp_close() possde un alias appel ftp_quit().

Dplacement dans larborescence


Une fois que lon est identifi, il est possible deffectuer toutes les oprations courantes en ligne, comme, par exemple, changer de rpertoire :

ftp_chdir()
Permet de changer de rpertoire. Syntaxe $idConnexion $repertoire retour boolean ftp_chdir(resource $idConnexion, string $repertoire) Identifiant de connexion obtenu par ftp_connect(). Rpertoire de destination. TRUE en cas de succs, FALSE sinon.

De son ct, ftp_cdup() permet de monter dun niveau dans la hirarchie des rpertoires.

ftp_cdup()
16. La gestion des protocoles HTTP, FTP, SOAP, etc.
Change de rpertoire pour monter dun niveau. Syntaxe $idConnexion retour boolean ftp_cdup(resource $idConnexion) Identifiant de connexion obtenu par ftp_connect(). TRUE en cas de succs, FALSE sinon.

Liste du contenu dun rpertoire


Il est possible galement de voir le contenu dun rpertoire :

1277

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

ftp_rawlist()
Permet dobtenir une liste dtaille des fichiers dun rpertoire (et ventuellement de ses sous-rpertoires). Le rsultat est identique ls l. Syntaxe $idConnexion $repertoire $recursif retour array ftp_rawlist(resource $idConnexion, string $repertoire [, boolean $recursif]) Identifiant de connexion obtenu par ftp_connect(). Rpertoire lister. TRUE si le contenu des sous-rpertoires doit galement tre retourn, FALSE (valeur par dfaut) sinon. (Option disponible depuis PHP 4.3.0) Tableau index des diffrents fichiers du rpertoire avec leur dtail (droits, taille, date).

ftp_nlist()
Permet dobtenir une liste des fichiers dun rpertoire. Le rsultat est identique ls. Syntaxe $idConnexion $repertoire retour array ftp_nlist(resource $idConnexion, string $repertoire) Identifiant de connexion obtenu par ftp_connect(). Rpertoire lister. Tableau des diffrents fichiers du rpertoire.

Cration, suppression, renommage

ftp_mkdir()
16. La gestion des protocoles HTTP, FTP, SOAP, etc.
Cration dun nouveau rpertoire. Syntaxe $idConnexion $repertoire retour boolean ftp_mkdir(resource $idConnexion, string $repertoire) Identifiant de connexion obtenu par ftp_connect(). Nom du rpertoire crer avec, ventuellement, son chemin. TRUE si le rpertoire a pu tre cr, FALSE sinon.

1278

FTP

ftp_rmdir()
Permet deffacer un rpertoire vide. Syntaxe $idConnexion $chemin retour boolean ftp_rmdir(resource $idConnexion, string $chemin) Identifiant de connexion obtenu par ftp_connect(). Rpertoire effacer avec, ventuellement, son chemin. TRUE si le rpertoire a t effac, FALSE sinon.

ftp_delete()
Permet deffacer un fichier. Syntaxe $idConnexion $chemin retour boolean ftp_delete(resource $idConnexion, string $chemin) Identifiant de connexion obtenu par ftp_connect(). Chemin du fichier effacer avec, ventuellement, son chemin. TRUE si le fichier a t effac, FALSE sinon.

ftp_rename()
Permet de renommer un fichier ou un rpertoire. Syntaxe $idConnexion $ancienNom $ancienNom retour boolean ftp_rename(resource $idConnexion, string $ancienNom, $nouveauNom) Identifiant de connexion obtenu par ftp_connect(). Ancien nom du fichier ou rpertoire. Nouveau nom du fichier ou rpertoire.

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

TRUE si le fichier ou rpertoire a pu tre renomm, FALSE sinon.

Transfert de chiers
Les fonctions de transfert de fichiers sont galement disponibles. Il est ainsi possible de copier un fichier du serveur FTP vers le serveur web (ftp_get()) ou le contraire (ftp_put()).

ftp_get()
Permet de rcuprer un fichier dun serveur FTP.

1279

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Syntaxe

boolean ftp_get(resource $idConnexion, string $cheminFichierLocal, string $cheminFichierDistant, int $mode [, int $offset]) Identifiant de connexion obtenu par ftp_connect().

$idConnexion

$cheminFichierLocal Chemin avec le nom du fichier o enregistrer le fichier. $cheminFichierDistant Chemin avec le nom du fichier rcuprer. $mode $offset retour FTP_ASCII (pour les fichiers textes) ou FTP_BINARY (pour les fichiers binaires). Position dans le fichier distant du premier octet transfrer. (Paramtre ajout depuis PHP 4.3.0) TRUE si le fichier a pu tre copi, FALSE sinon.

ftp_put()
Tlcharge un fichier du serveur web vers le serveur FTP. Syntaxe $idConnexion $fichierDistant $fichierLocal $mode $offset retour boolean ftp_put(resource $idConnexion, string $fichierDistant, string $fichierLocal, int $mode [, int $offset]) Identifiant de connexion obtenu par ftp_connect(). Destination sur le serveur web. Chemin sur le serveur web local. FTP_ASCII (pour les fichiers textes) ou FTP_BINARY (pour les fichiers binaires). Position dans le fichier local du premier octet transfrer. (Paramtre ajout depuis PHP 4.3.0) TRUE si le fichier a pu tre copi, FALSE sinon.

Les fonctions ftp_get() et ftp_put() possdent des variantes permettant dutiliser un pointeur vers un fichier. Cela permet de garder le fichier accessible en lecture ou criture une fois copi.

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

ftp_fget()
Permet de tlcharger un fichier dun serveur FTP dans un fichier (ou plus gnralement un stream) ouvert. Syntaxe $idConnexion $idFichier boolean ftp_fget(resource $idConnexion, resource $idFichier, string $fichierDistant, int $mode [, int $offset]) Identifiant de connexion obtenu par ftp_connect(). Identifiant (obtenu par fopen()) du fichier remplir.

1280

FTP

$fichierDistant $mode $offset retour

Nom du fichier distant rcuprer. FTP_ASCII (pour les fichiers textes) ou FTP_BINARY (pour les fichiers binaires). Position dans le fichier distant du premier octet transfrer. (Paramtre ajout depuis PHP 4.3.0) TRUE si le fichier a pu tre rcupr, FALSE sinon.

ftp_fput()
Permet de dposer le contenu dun fichier ouvert (ou plus gnralement un stream) sur un serveur FTP. Syntaxe boolean ftp_fput(resource $idConnexion, string $fichierDistant, resource $idFichier, int $mode [, int $offset]) Identifiant de connexion obtenu par ftp_connect(). Nom quaura le fichier sur le serveur FTP. Identifiant (obtenu par fopen()) du fichier copier. FTP_ASCII (pour les fichiers textes) ou FTP_BINARY (pour les fichiers binaires). Position dans le fichier local du premier octet transfrer. (Paramtre ajout depuis PHP 4.3.0) TRUE si le fichier a pu tre mis sur le serveur FTP, FALSE sinon.

$idConnexion $fichierDistant $idFichier $mode $offset retour

Exemple dapplication
Les fonctions vues jusque-l sont les fonctions les plus couramment utilises, et nous permettent de raliser un script de client FTP. Dans le script prsent, lutilisateur pourra naviguer sur le compte FTP, ajouter des fichiers, en supprimer, en renommer, ajouter et supprimer des rpertoires, uploader ou tlcharger des fichiers.

1281

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Figure 16.2 : Client FTP en PHP

Voici le script en question :

Listing 16.2 : ftp.php


<html> <head> <title>Client FTP</title> <link rel="stylesheet" type="text/css" href="style.css" /> </head> <body> <center><font color="blue"><h1>Client FTP 12.9</h1></font></center> <font color="red"> <?php // On augmente le temps de vie du script 100 secondes set_time_limit(100); // Parametres de connexion $serveur = "ftp.monsite.com"; $utilisateur = "utilisateur"; $motdepasse = "motdepasse"; // Connexion au serveur FTP $connexion = ftp_connect($serveur) or die("Serveur FTP inexistant"); // Identifiaction sur le serveur FTP ftp_login($connexion, $utilisateur, $motdepasse) or die("Utilisateur inconnu ou mauvais mot de passe"); $repertoire = $_GET["repertoire"]!="" ? $_GET["repertoire"] : "/";

16. La gestion des protocoles HTTP, FTP, SOAP, etc. 1282

FTP

// Verifie si "effacer" est pass en parametre if ($_GET["effacer"]!="") { effacer($_GET["effacer"], $repertoire); } // Verifie si "effacerrep" est pass en parametre if ($_GET["effacerrep"]!="") { effacerRep($_GET["effacerrep"], $repertoire); } // Verifie si "telecharger" est pass en parametre if ($_GET["telecharger"]!="") { telecharger($_GET["telecharger"], $repertoire); } // Verifie si "nouveaurep" est pass en parametre if ($_POST["nouveaurep"]!="") { nouveauRep($_POST["nouveaurep"], $repertoire); } // Verifie si "ajouterfichier" est pass en parametre if ($_POST["ajouterfichier"]!="") { ajouterFichier($_POST["ajouterfichier"], $repertoire); } // Verifie si "nouveaunom" est passe en parametre if ($_POST["nouveaunom"]!="") { nouveauNom($_POST["nouveaunom"], $_POST["fichier"], $repertoire); } </font> <form method="post"> Nouveau Repertoire:<input type="text" name="nouveaurep" /><br /> <form> <form method="post"> Ajouter fichier:<input type="text" name="ajouterfichier" /> <font size="1">Le chemin doit etre absolou ou relatif a lendroit ou est place ce script.</font><br /> <form> <?php // Changement de repertoire ftp_chdir($connexion, $repertoire); // Affichage du contenu du repertoire listerRepertoire($repertoire); ftp_close($connexion); ?> </body> </html> <?php function listerRepertoire($repertoire) { global $connexion; echo "<h2><font color=\"green\">".$repertoire."</font></h2>\n"; // Affichage du lien vers le repertoire superieur if ($repertoire!="/") { echo "<a href=\"ftp1.php?repertoire=". ?>

1283

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

substr(substr($repertoire, 0, -1), 0, 1+strrpos(substr($repertoire, 0, -1), "/"))."\"> <h2><font color=\"green\">". substr(substr($repertoire, 0, -1), 0, 1+strrpos(substr($repertoire, 0, -1), "/")). "</font></h2></a>\n"; } // Recuperation de la liste des fichiers $liste = ftp_rawlist($connexion, $repertoire); echo "<table>"; foreach($liste as $fichier) { echo "<tr>"; if (substr($fichier,0,1)=="d") { echo "<td>"; echo "<a href=\"ftp1.php?repertoire=$repertoire". substr($fichier,56)."/\">". "<b>".substr($fichier,56)."/</b></a><br />\n"; echo "</td><td>"; echo "<a href=\"ftp1.php?repertoire=$repertoire&effacerrep=". substr($fichier,56)."\">Effacer ce repertoire</a><br />\n"; } else { echo "<td>"; echo "<a href=\"ftp1.php?repertoire=$repertoire&telecharger=". substr($fichier,56)."\"><b>".substr($fichier,56)."</b>\n"; echo "</td><td>"; echo "<a href=\"ftp1.php?repertoire=$repertoire&effacer=". substr($fichier,56)."\">Effacer</a><br />\n"; echo "</td>"; echo "</tr><tr><td>&nbsp;</td><td>"; echo "<form method=\"post\">". "<input type=\"hidden\" name=\"fichier\" value=\"$repertoire\"".substr($fichier,56)."\"/> <input type=\"text\" name=\"nouveaunom\" /> <input type=\"submit\" value=\"Renommer\"/></form>"; echo "</td>"; } echo "</tr>"; } echo "</table>"; } // Efface un fichier function effacer($fichier, $repertoire) { global $connexion; if (@ftp_delete($connexion, $repertoire.$fichier)) echo "Le fichier $fichier a ete supprime"; else echo "Impossible deffacer le fichier $fichier"; } // Efface un repertoire vide function effacerRep($fichier, $repertoire) { global $connexion;

16. La gestion des protocoles HTTP, FTP, SOAP, etc. 1284

FTP

if (@ftp_rmdir($connexion, $repertoire.$fichier)) echo "Le repertoire $fichier a ete supprime"; else echo "Impossible deffacer le repertoire $fichier assurez vous " ."quil est vide"; } // Telecharge un fichier depuis le site FTP function telecharger($fichier, $repertoire) { global $connexion; if (@ftp_get($connexion, $fichier, $repertoire.$fichier, FTP_BINARY)) echo "Le fichier $fichier devrait etre telecharge dans le repertoire". " ou se trouve ce script"; else echo "Impossible douvrir le fichier $fichier"; } // Cree un repertoire function nouveauRep($fichier, $repertoire) { global $connexion; if (@ftp_mkdir($connexion, $repertoire.$fichier)) echo "Le nouveau repertoire $fichier a ete cree"; else echo "Impossible de creer le repertoire $fichier"; } // Renomme un fichier function nouveauNom($nouveaunom, $fichier, $repertoire) { global $connexion; if (@ftp_rename($connexion, $fichier, $repertoire.$nouveaunom)) echo "Le fichier $fichier a ete renomme"; else echo "Impossible de renommer $fichier"; } // Ajoute un fichier function ajouterFichier($fichier, $repertoire) { global $connexion; $nomFichier = (strrchr($fichier, "/")) ? $repertoire.substr(strrchr($fichier, "/"), 1) : $repertoire.$fichier; if (@ftp_put($connexion, $nomFichier, $fichier, $FTP_BINARY)) echo "Le fichier $fichier a ete ajoute"; else echo "Impossible dajouter $fichier"; } ?>

1285

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Transfert de chiers en mode asynchrone


Les fonctions ftp_put(), ftp_get(), ftp_fput() et ftp_fget() sont des fonctions synchrones. Cest dire que lorsque le script PHP traite ces fonctions il ne fait plus rien dautre en attendant le transfert complet des donnes. Depuis, PHP 4.3.0, ces fonctions ont leur quivalent en mode asynchrone. Il sagit des fonctions ftp_nb_put(), ftp_nb_get(), ftp_nb_fput(), ftp_nb_fget(). Leur syntaxe est tout fait identique si ce nest quelles ne retournent pas un boolen mais un entier dont les valeurs possibles sont les mmes que celles retournes par la fonction dcrite ci-aprs. Une fois lances, ces fonctions transfrent bien les fichiers mais le script, lui, continue pour traiter les instructions suivantes. Pour savoir si la prcdente opration est termine vous devrez faire appel la fonction ftp_nb_continue().

ftp_nb_continue
Teste si la dernire opration FTP asynchrone lance est termine ou non. Syntaxe : $idConnexion retour int ftp_nb_continue(resource $idConnexion) Identifiant de connexion obtenu par ftp_connect(). FTP_MOREDATA si le transfert est en cours, FTP_FINISHED sil est termin ou FTP_FAILED sil a chou.

Autres fonctions

ftp_exec()
Permet dexcuter une commande sur le serveur FTP si celui-ci lautorise. Syntaxe $idConnexion $commande retour boolean ftp_exec(resource $idConnexion, string $commande) Identifiant de connexion obtenu par ftp_connect(). Commande excuter sur le serveur. TRUE en cas de succs, FALSE sinon.

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

ftp_site()
Envoie une commande un serveur FTP de type SITE xxxx. Syntaxe $idConnexion $commande retour boolean ftp_site(resource $IdConnexion, string $commande) Identifiant de connexion obtenu par ftp_connect(). Commande excuter. TRUE en cas de succs, FALSE sinon.

1286

FTP

Paramtres de connexion

ftp_get_option()
Retourne certains paramtres de la connexion FTP courante. Syntaxe $idConnexion option mixed ftp_get_option(resource $idConnexion, int $option) Identifiant de connexion obtenu par ftp_connect(). Option dont on veut connatre la valeur. Seul le temps avant abandon dune commande est disponible ; la constante est FTP_TIMEOUT_SEC, la fonction retourne alors le temps en secondes. Dpend de loption.

retour

ftp_set_option()
Dfinit certains paramtres de la connexion FTP courante. Syntaxe $idConnexion option $valeur retour boolean ftp_set_option(resource $idConnexion, int $option, mixed $valeur) Identifiant de connexion obtenu par ftp_connect(). Option dont on veut dfinir la valeur. Seul le temps avant abandon dune commande est disponible ; la constante est FTP_TIMEOUT_SEC. Valeur du paramtre dfinir. Pour FTP_TIMEOUT_SEC, la valeur est donner en secondes. TRUE si le paramtre a pu tre modifi.

ftp_pasv()
Permet de passer en mode passif. Cela peut servir pour passer outre un firewall un peu exigeant. Syntaxe $idConnexion $pasv retour boolean ftp_pasv(resource $idConnection, boolean $pasv) Identifiant de connexion obtenu par ftp_connect(). TRUE pour activer le mode passif, FALSE sinon. TRUE si le changement de mode a pu seffectuer, FALSE sinon.

1287

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Information sur les chiers

ftp_mdtm()
Retourne la date de dernire modification dun fichier. Syntaxe : $idConnexion $fichierDistant retour int ftp_mdtm(resource $idConnexion, string $fichierDistant) Identifiant de connexion obtenu par ftp_connect(). Fichier dont on veut connatre la date de dernire modification. La date de dernire modification au format timestamp dUNIX.

ftp_size()
Retourne la taille dun fichier. Syntaxe $idConnexion $fichierDistant retour int ftp_size(resource $idConnexion, string $fichierDistant) Identifiant de connexion obtenu par ftp_connect(). Fichier dont on veut connatre la taille. Taille du fichier en octets, 1 si le fichier nexiste pas.

Informations sur le serveur

ftp_systype()
Retourne le type du systme dexploitation du serveur FTP (UNIX par exemple). Syntaxe $idConnexion retour string ftp_systype(resource $idConnexion) Identifiant de connexion obtenu par ftp_connect(). Le nom du systme dexploitation (attention, cela nest absolument pas prcis. Un serveur sous Linux renverra UNIX, mais cela permet de diffrencier les systmes de fichiers de type UNIX et Windows.)

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

16.5. cURL (client URL Library)


La bibliothque cURL a t dveloppe afin de permettre le dveloppement dapplications devant effectuer des oprations sur le rseau. Elle est disponible sur de nombreux systmes : Linux, Windows, HPUnix, Solaris, Amiga, OS/2, MacOS X et dautres encore.
cURL supporte diffrents protocoles parmi lesquels :

j j

FTP et FTPS ; HTTP et HTTPS ;

1288

cURL (client URL Library)

j j j j

GOPHER ; TELNET ; LDAP(v2) ; Le transfert de fichiers.

Vous pouvez retrouver tous les protocoles supports par cURL sur cette page : http://curl.haxx.se/docs/features.html. Elle gre les HTTP POST, HTTP PUT, lupload de fichiers par FTP ou HTTP et passe les proxys. De plus, cURL sait manipuler les cookies et effectuer lauthentification HTTP.

Installation
Installation sous Linux
Si vous utilisez Linux, il est probable que vous ayez les librairies cURL installes sur votre machine. Si ce nest pas le cas, vous pouvez toujours les tlcharger sur le site web ladresse http://curl.haxx.se/download.html (ou utiliser la version disponible sur le CD-ROM). Si vous souhaitez utiliser SSL, vous devrez galement linstaller (ce qui est gnralement dj fait par dfaut). OpenSSL est disponible ladresse http://www.openssl.org/. Nous supposerons ici quil a t install sous /usr/local/ssl. Si vous avez rcupr les sources de cURL, commencez par dcompresser larchive en tapant :
# tar -zxvf curl-7.10.7.tar.gz # cd curl 7.10.7

Ensuite, compilez cURL de la faon suivante :


# ./configure --disable-ipv6 --with-ssl=/usr/local/ssl # make # make install

Recompilez PHP en ajoutant loption withcurl=/usr/local/lib et puis relancez le serveur web.

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Vrication
Appelez un simple script contenant <?php phpinfo(); ?>, vous devriez avoir un rsultat similaire :
Figure 16.3 : Vrifions que le module est activ

Nous pouvons prsent nous concentrer sur la manipulation de ce module avec le langage PHP.

1289

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Utilisation
Initialiser une session cURL
Afin dexploiter les diffrentes fonctions cURL, vous devez, dans un premier temps, crer une session avec linstruction curl_init().

curl_init()
Initialise une session cURL. Syntaxe $adresse resource curl_init([string $adresse]) Adresse utilise par les diffrentes fonctions cURL. Ce paramtre est optionnel, et peut tre fix ou modifi plus tard laide de la fonction curl_setopt(). Ressource vers la session cURL initialise.

retour

Fermer une session cURL


La fermeture de la session est ralise par lappel linstruction curl_close().

curl_close()
Ferme une session cURL. Syntaxe $curlId void curl_close(resource $curlId) Pointeur sur la ressource tel que retourn par curl_init().

Prparer une requte


16. La gestion des protocoles HTTP, FTP, SOAP, etc.
Avant deffectuer votre requte, quelle quelle soit, vous devez spcifier certaines options PHP. Pour cela, vous utiliserez la fonction curl_setopt().

curl_setopt()
Permet de spcifier les options ncessaires votre transfert cURL. Syntaxe $curlId boolean curl_setopt (resource $curlId, string $option, mixed $valeur) Pointeur sur la ressource tel que retourn par curl_init().

1290

cURL (client URL Library)

$option $valeur retour

Option modifier. Voyez le tableau ci-aprs pour connatre les diffrents paramtres configurables. Nouvelle valeur donner loption. TRUE si la modification de loption a t effectue avec succs, FALSE dans le cas contraire.

Tableau 16.1 : Les diffrentes options configurables avec linstruction curl_setopt()


Option CURLOPT_COOKIEJAR CURLOPT_COOKIEFILE Description Indique PHP/cURL le fichier o doivent tre stocks les diffrents cookies. Indique le fichier contenant les diffrents cookies et leurs valeurs. Le fichier peut tre dans mme format que celui dun en-tte HTTP : SetCookie: cookie1=premier+cookie SetCookie: cookie2=deuxieme+cookie SetCookie: cookie3=troisieme+cookie SetCookie: cookie4=quatrieme+cookie Permet dindiquer une mthode particulire envoyer au serveur : PUT, DELETE, etc. Indique PHP/cURL de retourner les erreurs HTTP 300 et plus. Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon). Par dfaut, cette option est desactive. Spcifie le pointeur du fichier devant contenir les donnes de votre transfert. Ce fichier doit avoir t ouvert en criture par linstruction fopen(). Indique PHP/cURL de suivre toutes les redirections HTTP envoyes par le serveur distant. Pour activer cette option vous devez indiquer TRUE (ou FALSE sinon). Par dfaut, loption est active. Indique PHP/cURL de ne pas craser les fichiers distants. la place, le contenu du fichier est ajout la suite de celui existant. Pour activer cette option vous devez indiquer TRUE (ou FALSE sinon).

CURLOPT_CUSTOMREQUEST CURLOPT_FAILONERROR

CURLOPT_FILE

CURLOPT_FOLLOWLOCATION

CURLOPT_FTPAPPEND

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

CURLOPT_FTPLISTONLY

Indique PHP/cURL de neffectuer quun listing des noms des fichiers sur un serveur FTP. Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon). Par dfaut PHP retourne la liste complte des fichiers. Spcifie au serveur distant ladresse utilise par PHP/cURL pour la connexion par FTP. Cette adresse est indique lors dune connexion par FTP par la commande "PORT" envoye au serveur. Indique PHP/cURL de retourner len-tte dans la rponse. Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon). Par dfaut, PHP renvoie uniquement le corps du document.

CURLOPT_FTPPORT

CURLOPT_HEADER

1291

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Option CURLOPT_INFILE

Description Spcifie le pointeur de fichier contenant les donnes que vous expdiez lors dun transfert. Ce fichier doit avoir t ouvert en lecture par linstruction fopen(). Cette option sert fixer la taille maximale des donnes transmettre un serveur distant.

CURLOPT_INFILESIZE

CURLOPT_LOW_SPEED_LIMIT Indique le nombre doctets par secondes qui doivent circuler de faon valider laction de cURL. Si la vitesse indique nest pas atteinte, PHP annulera lexcution de laction. Cette vitesse est calcule pendant une dure fixe par CURLOPT_LOW_SPEED_TIME. CURLOPT_LOW_SPEED_TIME Indique le temps en secondes qui est considr pour vrifier le taux de transfert fix par loption CURLOPT_LOW_SPEED_LIMIT. Indique PHP/cURL de ne pas retourner les messages retourns par les diffrentes actions de cURL. Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon). Indique PHP/cURL dutiliser le compte utilisateur et le mot de passe de lutilisateur courant (tel que dfini dans le fichier ./netrc sous Linux) pour effectuer la connexion distance. Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon). Indique PHP/cURL de ne pas retourner le corps du document. Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon). Par dfaut, loption est desactive. Indique PHP/cURL de retourner ltat des transferts avec le serveur distant. Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon). Par dfaut, loption est desactive. Indique PHP/cURL de prparer une action de type HTTP POST (identique lenvoie dun formulaire HTML par mthode POST). Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon). Indique PHP/cURL les diffrentes donnes passer lors dun transfert HTTP par mthode POST. La chane doit tre passe dans ce format : var1=valeur1&var2=valeur2&var(n)=valeur(n). Nom de lutilisateur et mot de passe utiliser lors de la connexion un proxy HTTP. La chane indique est de la forme nomUtilisateur:motPasse. Indique PHP/cURL de prparer une action HTTP de type PUT. Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon). Permet de spcifier la plage de valeurs dsire. Vous devez la spcifier de la faon suivante : val1val2. Vous pouvez prciser plusieurs plages diffrentes en les sparant par une virgule de la faon suivante : val1val2, val3val4.

CURLOPT_MUTE

CURLOPT_NETRC

CURLOPT_NOBODY

CURLOPT_NOPROGRESS

CURLOPT_POST

CURLOPT_POSTFIELDS

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

CURLOPT_PROXYUSERPWD

CURLOPT_PUT

CURLOPT_RANGE

1292

cURL (client URL Library)

Option CURLOPT_REFERER CURLOPT_RESUME_FROM CURLOPT_RETURNTRANSFER

Description Permet de spcifier len-tte REFERER envoye lors dune requte au serveur distant. Indique PHP/cURL le dbut du transfert. La valeur est fixe en octets. Option permettant de rcuprer le rsultat dans une variable lexcution de la session : $resultat = curl_exec($curlId). Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon). Par dfaut, la fonction curl_exec() retourne un boolen. Indique le fichier contenant le certificat SSL passer au serveur. Ce certificat doit tre au format PEM. Indique le mot de passe utilis avec le certificat spcifi par loption CURLOPT_SSLCERT. Indique la version de SSL utilise pour les oprations avec cURL. La valeur peut tre de 2 ou 3. Par dfaut, PHP la dterminera automatiquement. Spcifie le pointeur du fichier devant contenir les erreurs pouvant survenir lors dun transfert. Ce fichier doit avoir t ouvert en criture par linstruction fopen(). Indique PHP/cURL comment utiliser loption CURLOPT_TIMEVALUE. Les valeurs possibles sont TIMECOND_IFMODSINCE ou TIMECOND_ISUNMODSINCE. Par dfaut, loption est TIMECOND_IFMODSINCE. Indique, en secondes, le temps maximum accord lexcution dune action par cURL. Temps en secondes depuis le 1er janvier 1970. Indique PHP/cURL de prparer un transfert de fichier. Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon). URL indiquant PHP/cURL la page et le serveur distant. Cette URL dsigne la page qui doit tre rcupre. Cette option peut tre fixe ds lappel linstruction curl_init(). Permet de spcifier len-tte USER-AGENT envoy lors dune requte au serveur distant. Nom de lutilisateur et mot de passe de lutilisateur qui doivent tre utiliss lors de la connexion distante. La chane indique est de la forme nomUtilisateur:motPasse. Indique PHP/cURL dafficher tous les vnements. Pour activer cette option, vous devez indiquer TRUE (ou FALSE sinon).

CURLOPT_SSLCERT CURLOPT_SSLCERTPASSWD CURLOPT_SSLVERSION

CURLOPT_STDERR

CURLOPT_TIMECONDITION

CURLOPT_TIMEOUT CURLOPT_TIMEVALUE CURLOPT_UPLOAD

CURLOPT_URL

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

CURLOPT_USERAGENT CURLOPT_USERPWD

CURLOPT_VERBOSE

1293

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Option CURLOPT_WRITEHEADER

Description Spcifie le pointeur du fichier devant contenir len-tte de sortie de votre transfert. Ce fichier doit avoir t ouvert en criture par linstruction fopen().

De nombreux paramtres ont un lien troit avec les en-ttes HTTP ; nhsitez pas consulter lannexe "Les en-ttes" pour plus dinformations.

Rcuprer les informations dune option


Il est possible de rcuprer les valeurs que contient une option en utilisant la fonction curl_getinfo().

curl_getinfo()
Retourne la valeur dune option. Syntaxe $curlId $option retour string curl_getinfo(resource $curlId, int $option) Pointeur sur la ressource tel que retourn par curl_init(). Option rcuprer. Chane de caractres indiquant la valeur de loption qui y est associe.

Excuter une session


Afin dexcuter la session, il faut appeler la fonction curl_exec().

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

curl_exec()
Excute une session cURL. Syntaxe $curlId retour mixed curl_exec(resource $curlId) Pointeur sur la ressource tel que retourn par curl_init(). Par dfaut, lexcution de la fonction retourne TRUE si lexcution de la session a t ralise avec succs, FALSE dans le cas contraire. Suivant lactivation de certaines options, linstruction peut retourner un entier ou une chane de caractres. Ainsi, loption CURLOPT_RETURNTRANSFER indique PHP de retourner le rsultat plutt que de lafficher sur la sortie standard.

1294

cURL (client URL Library)

Gestion des erreurs


La gestion des erreurs est ralise par lappel deux instructions : curl_errno() et curl_error(). La fonction curl_errno() retourne le numro du code de lerreur.

curl_errno()
Permet de rcuprer le code de la dernire erreur rencontre pour une session cURL. Syntaxe $curlId retour int curl_errno(resource $curlId) Pointeur sur la ressource tel que retourn par curl_init(). Code de lerreur cURL.

La fonction curl_error() permet de rcuprer lerreur dans une chane de caractres.

curl_error()
Retourne le dernier message derreur rencontr dans une session cURL. Syntaxe $curlId retour string curl_error(resource $curlId) Pointeur sur la ressource tel que retourn par curl_init(). Message derreur cURL.

Vrier la version de cURL


Linstruction curl_version() permet de rcuprer la version de votre librairie cURL.

curl_version()
Retourne la version de la bibliothque cURL. Syntaxe retour string curl_version(void) Chane de caractres indiquant la version de la bibliothque installe sur le systme.

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Exemples dapplications
prsent, nous allons voir diffrents exemples dutilisation des fonctions cURL. Ce sont des exemples simples, qui nont dautre but que de vous montrer les diverses possibilits de ce module.

1295

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

Afficher le contenu dune page web distante


Voici lutilisation la plus simple des fonctions cURL. Le script va chercher la page sur un serveur distant et laffiche sur le navigateur web.

Listing 16.3 : exemple1.php


<?php $curlId = curl_init("http://www.linux.org/"); curl_exec($curlId); curl_close($curlId); ?>

Rcuprer le contenu dune page dans un chier


Cet exemple est une variation du prcdent. Cette fois, nous spcifions simplement un fichier de sortie, ce qui permet de rcuprer le code HTML de la page plutt que de lafficher directement.

Listing 16.4 : exemple2.php


<?php // Ouverture dun fichier en criture $fp = fopen("linux.html", "w"); // Cration de la session cURL $curlId = curl_init("http://www.linux.org/"); // Fichier de sortie curl_setopt($curlId, CURLOPT_FILE, $fp); // Excution de la session curl_exec($curlId); // Fermeture de la session curl_close($curlId);

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

// Fermeture du fichier fclose($fp); // On vrifie en affichant ensuite le fichier readfile("linux.html"); ?>

Envoyer des donnes par mthode POST


Lexemple suivant montre comment cURL peut envoyer des donnes par une mthode POST, cet envoi tant alors identique celui depuis un formulaire HTML.

1296

cURL (client URL Library)

Listing 16.5 : exemple3.php


<?php // Cration de la session cURL $curlId = curl_init("http://www.monserveur.com/formulaire.php"); // Le serveur demande une authentification curl_setopt($curlId, CURLOPT_USERPWD, "utilisateur:mot2passe"); // Mthode POST curl_setopt($curlId, CURLOPT_POST, TRUE); $post = "nom=GUEDON". "&prenom=Laurent". "&mail=laurent@tild.com". "&action=valider"; curl_setopt($curlId, CURLOPT_POSTFIELDS, $post); // Indiquons galement diffrents cookies $cookies = "cookie1=premier cookie;cookie2=deuxieme cookie"; curl_setopt($curlId, CURLOPT_COOKIE, $cookies); // Execution de la session curl_exec($curlId); // Fermeture de la session curl_close($curlId); ?>

Lister le contenu dun rpertoire FTP


Cet exemple liste les noms des fichiers se trouvant dans un rpertoire. Le script rcupre les diffrents fichiers dans une variable et les affiche ensuite en ajoutant la balise <br> entre les diffrents sauts de lignes.

Listing 16.6 : exemple4.php


<?php // Cration de la session cURL $curlId = curl_init("ftp://www.monsite.org/repertoire/"); // Indiquons le login et le mot de passe de la connexion curl_setopt($curlId, CURLOPT_USERPWD, "utilisateur:mot2passe"); // Indiquons de retourner la sortie dans une variable curl_setopt($curlId, CURLOPT_RETURNTRANSFER, TRUE); // On demande dafficher uniquement les noms des fichiers curl_setopt($curlId, CURLOPT_FTPLISTONLY, TRUE); // Execution de la session $retour = curl_exec($curlId);

1297

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

// Affichons le rsultat echo nl2br($retour); // Fermeture de la session curl_close($curlId); ?>

Envoyer un chier sur un serveur FTP


Cet exemple montre de faon simple comment envoyer un fichier sur un serveur FTP.

Listing 16.7 : exemple5.php


<?php // Ouverture dun fichier en lecture $fp = fopen("monfichier.html", "r"); // Cration de la session cURL $curlId = curl_init("ftp://ftp.monserveur.com/html/monfichier.html"); // Indiquons le login et le mot de passe de la connexion curl_setopt($curlId, CURLOPT_USERPWD, "utilisateur:mot2passe"); // Prparation dun Upload de fichier curl_setopt($curlId, CURLOPT_UPLOAD, TRUE); // Taille du fichier envoyer curl_setopt($curlId, CURLOPT_INFILESIZE, filesize("monfichier.html")); // Fichier envoyer curl_setopt($curlId, CURLOPT_INFILE, $fp); // Indiquons ladresse "PORT" du client curl_setopt($curlId, CURLOPT_FTPPORT, "-"); // Execution de la session if (!$donnee = curl_exec($curlId)) { die("Problme lors de lenvoie du fichier\n". curl_error($curlId)); } else { echo "Le fichier a t envoy sur le serveur."; } // Execution de la session curl_exec($curlId); // Fermeture de la session curl_close($curlId);

16. La gestion des protocoles HTTP, FTP, SOAP, etc. 1298

SOAP

// Fermeture du fichier fclose($fp); ?>

16.6. SOAP
SOAP (Simple Object Access Protocol) permet denvoyer des messages XML des serveurs, en utilisant HTTP comme moyen de communication. Depuis peu, le clbre moteur de recherche Google permet gratuitement de faire une requte sous forme XML via SOAP, et de rcuprer le rsultat de la requte. Ce sera le sujet de notre exemple. Un message SOAP est gnralement constitu dun en-tte et dun corps. Lexemple que nous dcrivons un peu plus loin dans ce chapitre donne lieu la cration du message SOAP suivant, que lon appelle une enveloppe :
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns4="urn:GoogleSearch" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns4:doGoogleSearch> <item xsi:type="xsd:string">M4liC3nceS3cr3tE</item> <item xsi:type="xsd:string">mail site:www.toutestfacile.com</item> <item xsi:type="xsd:int">0</item> <item xsi:type="xsd:int">5</item> <item xsi:type="xsd:boolean">true</item> <item xsi:type="xsd:string"></item> <item xsi:type="xsd:boolean">true</item> <item xsi:type="xsd:string">lang_fr|lang_en</item> <item xsi:type="xsd:string">latin1</item> <item xsi:type="xsd:string">latin1</item></ns4:doGoogleSearch> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Dans lexemple prcdent, nous retrouvons, dans le corps de lenveloppe, les informations pertinentes pour la fonction doGoogleSearch du serveur SOAP de Google. Les fichiers WSDL (Web Service Definition Language) permettent de dfinir un service web ; ils sont crits au format XML. partir de ces fichiers, il est possible de savoir ce quattendent les services web comme paramtres. Voici, par exemple, un extrait du fichier WSL dcrivant le service doGoogleSearch propos par Google :
<?xml version="1.0"?>

1299

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

<!-- WSDL description of the Google Web APIs. The Google Web APIs are in beta release. All interfaces are subject to change as we refine and extend our APIs. Please see the terms of use for more information. --> <definitions name="urn:GoogleSearch" targetNamespace="urn:GoogleSearch" xmlns:typens="urn:GoogleSearch" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <!-- Types for search - result elements, directory categories --> <types> <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:GoogleSearch"> <xsd:complexType name="GoogleSearchResult"> <xsd:all> <xsd:element name="documentFiltering" type="xsd:boolean"/> <xsd:element name="searchComments" type="xsd:string"/> <xsd:element name="estimatedTotalResultsCount" type="xsd:int"/> <xsd:element name="estimateIsExact" type="xsd:boolean"/> <xsd:element name="resultElements" type="typens:ResultElementArray"/> <xsd:element name="searchQuery" type="xsd:string"/> <xsd:element name="startIndex" type="xsd:int"/> <xsd:element name="endIndex" type="xsd:int"/> <xsd:element name="searchTips" type="xsd:string"/> <xsd:element name="directoryCategories" type="typens:DirectoryCategoryArray"/> <xsd:element name="searchTime" type="xsd:double"/> </xsd:all> </xsd:complexType> <xsd:complexType <xsd:all> <xsd:element <xsd:element <xsd:element name="ResultElement"> name="summary" type="xsd:string"/> name="URL" type="xsd:string"/> name="snippet" type="xsd:string"/>

16. La gestion des protocoles HTTP, FTP, SOAP, etc. 1300

SOAP

<xsd:element name="title" type="xsd:string"/> <xsd:element name="cachedSize" type="xsd:string"/> <xsd:element name="relatedInformationPresent" type="xsd:boolean"/> <xsd:element name="hostName" type="xsd:string"/> <xsd:element name="directoryCategory" type="typens:DirectoryCategory"/> <xsd:element name="directoryTitle" type="xsd:string"/> </xsd:all> </xsd:complexType> <xsd:complexType name="ResultElementArray"> <xsd:complexContent> <xsd:restriction base="soapenc:Array"> <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="typens:ResultElement[]"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="DirectoryCategoryArray"> <xsd:complexContent> <xsd:restriction base="soapenc:Array"> <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="typens:DirectoryCategory[]"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="DirectoryCategory"> <xsd:all> <xsd:element name="fullViewableName" type="xsd:string"/> <xsd:element name="specialEncoding" type="xsd:string"/> </xsd:all> </xsd:complexType> </xsd:schema> </types>

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

<!-- Messages for Google Web APIs - cached page, search, spelling. --> <message name="doGoogleSearch"> <part name="key" type="xsd:string"/> <part name="q" type="xsd:string"/> <part name="start" type="xsd:int"/> <part name="maxResults" type="xsd:int"/> <part name="filter" type="xsd:boolean"/> <part name="restrict" type="xsd:string"/> <part name="safeSearch" type="xsd:boolean"/> <part name="lr" type="xsd:string"/> <part name="ie" type="xsd:string"/> <part name="oe" type="xsd:string"/>

1301

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

</message> <message name="doGoogleSearchResponse"> <part name="return" type="typens:GoogleSearchResult"/> </message> <!-- Port for Google Web APIs, "GoogleSearch" --> <portType name="GoogleSearchPort"> <operation name="doGoogleSearch"> <input message="typens:doGoogleSearch"/> <output message="typens:doGoogleSearchResponse"/> </operation> </portType> <!-- Binding for Google Web APIs - RPC, SOAP over HTTP --> <binding name="GoogleSearchBinding" type="typens:GoogleSearchPort"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="doGoogleSearch"> <soap:operation soapAction="urn:GoogleSearchAction"/> <input> <soap:body use="encoded" namespace="urn:GoogleSearch" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body use="encoded" namespace="urn:GoogleSearch" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> </binding> <!-- Endpoint for Google Web APIs --> <service name="GoogleSearchService"> <port name="GoogleSearchPort" binding="typens:GoogleSearchBinding"> <soap:address location="http://api.google.com/search/beta2"/> </port> </service> </definitions>

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Ce fichier, tel quil est crit, se lit de bas en haut. Tout en bas, nous trouvons ladresse du service web : http://api.google.com/search/beta2 puis, au dessus, dans la balise <binding>, nous trouvons les diffrents services (ici, il ny a que doGoogleSearch) o lentre et la sortie sont dfinies. Dans la dclaration de la balise <binding>, le lien est fait vers le type GoogleSearchPort. On retrouve un peu plus haut ce type, qui dfinit les types dentres et de sorties. Les entres seront donc de type doGoogleSearch et les sorties de type doGoogleSearchResponse. Les types doGoogleSearch et doGoogleSearchResponse sont dcrits plus haut dans le fichier.

1302

SOAP

Installation
SOAP fait partie du projet PEAR. Il dpend des paquetages PEAR suivants: Mail_Mime, Net_URL, Net_Socket, HTTP_Request, Net_DIME. Pour les installer vous pouvez, au choix, tlcharger le fichier correspondant ladresse http://pear.php.net/packages.html et le dzipper dans un espace quelconque dfini dans la variable include_path du fichier php.ini, ou bien vous pouvez utiliser les commandes PEAR. Notez toutefois, que pour les paquetages SOAP et Net_DIME qui nont pas encore le statut "stable" vous serez oblig de les tlcharger avant de les installer avec les commandes Pear.
# # # # # # pear pear pear pear pear pear upgrade upgrade upgrade upgrade install install Mail_Mime Net_URL Net_Socket HTTP_Request Net_DIME.tar.gz SOAP.tar.gz

PHP 5 SOAP PEAR nest ( lheure de lcriture de ces lignes) pas compatible avec PHP 5 (ceci cause dune mauvaise redfinition de la mthode __call dans la classe SOAP_Client). Si vous vous sentez dattaque vous pouvez tenter de le faire fonctionner sous PHP 5 en remplaant la dclaration de la mthode __call par:
function __call($method, $args)

et en remplaant return TRUE; par


return $this>call($method, $args);

Il nest toutefois pas assur que cela suffise pour un fonctionnement parfait.

Utiliser les classes PEAR


PEAR produit des classes pour les clients et serveurs SOAP, ainsi que des classes pour faire lanalyse lexicale dun message SOAP, ou encore une classe qui permet de replacer le protocole standard HTTP (par la possibilit danalyser le contenu dun e-mail et de faire les appels contenus lintrieur de celui-ci). Mais revenons la classe a priori la plus utile : la classe SOAP_Client qui permet de faire appel un serveur SOAP. Le constructeur de cette classe ncessitera ladresse du serveur SOAP.

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

SOAP_Client()
Constructeur dobjets SOAP_Client. Syntaxe SOAP_client SOAP_client(String $url [, boolean $wsdl [, string $nomPort]])

1303

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

$url $wsdl $nomPort retour

URL du serveur SOAP. TRUE si lURL est celle dun fichier WSDL. Nom du port SOAP utilis par le client. Un objet de type SOAP_Client.

SOAP_Client->setEncoding()
Dfinit lencodage des messages. Syntaxe $encodage retour mixed setEncoding(string $encodage) UTF8, US_ASCII ou ISO88591. NULL, ou une erreur de type SOAP_Fault.

SOAP_Client->addHeader()
Pour ajouter des en-ttes lenveloppe SOAP. Syntaxe $entete void addHeader(SOAP_Header $entete) En-tte ajouter de type SOAP_Header.

SOAP_Client->call()
Permet de faire un appel au serveur SOAP. Syntaxe array call(string $methode, array $parametres [, string $espaceNom, [string $actionSoap]]) Nom de la mthode appeler. Tableau des paramtres passer. Tableau des rsultats.

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

$methode $parametres retour

Interroger Google via PHP


Depuis dbut 2002, Google met disposition un serveur SOAP permettant de faire des recherches dynamiquement. Attention, lAPI fournie permettant dinterroger le moteur de recherche est susceptible dtre modifie. Pire, ce service pourrait tre supprim du jour au lendemain.

1304

SOAP

Pr-requis
Pour pouvoir utiliser le serveur SOAP de Google, vous devrez rcuprer un numro de licence sur le site web de Google en crant un nouveau compte. Ce numro de licence vous permettra de faire jusqu 1 000 requtes par jour.

Nouveau compte Pour crer un compte sur Google, ladresse est :


https://www.google.com/accounts/NewAccount?continue=http://api.google.com/ createkey &followup=http://api.google.com/createkey.

Vous serez galement intress par le tlchargement de lAPI, car cest elle qui vous dira comment effectuer vos requtes.

Tlcharger lAPI Pour tlcharger lAPI de Google, ladresse est : http://www.google.com/apis/download.html.


Notre premier script sera trs simple : il permet de faire une recherche avec des mots-cls intgrs dans le script. Les rsultats seront affichs sans mise en page, mais juste laide de la fonction print_r().

Listing 16.8 : soapgoogle.php


<?php // On utilisera les classes de projet PEAR require_once "SOAP/Client.php"; // On place ici le numero de licence obtenu sur le site de Google $numeroLicence = "MA_LICENCE, CETTE_CHAINE_DOIT_ETRE_REMPLACEE"; // Les mots cles sont stockes dans le script ici. $motsCles = "Apprendre PHP facilement"; // Creation du client SOAP et declaration du serveur SOAP. $soapClient = new SOAP_Client("http://api.google.com/search/beta2"); // Les parametres a passer tels que decrits dans lAPI de Google // (licence, // motscles, // indice du premier resultat a retourner, // nombre de resultats a retourner, // utilisation ou non du filtre cachant les resultats similaires, // restrictions a un pays ou domaine..., // filtrage des sites pour adultes, // Restriction sur la langue, // encodage dentree, // encodage de sortie) $recherche = array($numeroLicence, $motsCles, 0, 1, TRUE, "", TRUE, "", "", ""); // Appel a la methode "doGoogleSearch" du serveur SOAP,

1305

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

$result = $soapClient->call("doGoogleSearch", $recherche, "urn:GoogleSearch"); // Affichage du resultat print_r($result); ?>

Le rsultat obtenu est le suivant :


stdClass Object ( [documentFiltering] => 1 [estimatedTotalResultsCount] => 7080 [directoryCategories] => [searchTime] => 0.133035 [resultElements] => Array ( [item] => stdClass Object ( [cachedSize] => 22k [hostName] => [snippet] => Un site pour bien apprendre le PHP et SQL , les scripts comments, le forum et les tutoriaux sont l pour vous aider. [directoryCategory] => stdClass Object ( [specialEncoding] => [fullViewableName] => Top/World/Franais/ Informatique/Programmation/Langages/PHP ) [relatedInformationPresent] => 1 [directoryTitle] => <b>PHP</b> <b>Facile</b> [summary] => <b>Apprendre</b> le <b>PHP</b>. On y trouve des tutoriaux, des scripts comments et un forum. [URL] => http://www.phpfacile.com/ [title] => <b>PHP</b> <b>Facile</b> ! Le site pour <b>apprendre</b> le <b>PHP</b> simplement et <b>...</b> )

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

) [endIndex] => 1 [searchTips] => [searchComments] => [startIndex] => 1 [estimateIsExact] => [searchQuery] => Apprendre PHP facile )

Ce nest pas plus difficile que ces quelques lignes partir de l, il est facile dlaborer un moteur de recherche personnel bas sur Google.

1306

SOAP

Voici notre interface graphique : elle permet dentrer les mots-cls comme sur le site de Google, de prciser le nombre de rsultats maximum retourner, et le site sur lequel restreindre le recherche (il suffira de laisser le champ vide pour faire une recherche sur tous les sites).
Figure 16.4 : Le formulaire rempli pour notre exemple

Le script charg de traiter la requte est le suivant :

Listing 16.9 : mp_perso.php


<html> <head> <title>Moteur de recherche personnel</title> <link rel="stylesheet" type="text/css" href="style.css" /> </head> <body> <center><font color="blue"> <h1>Resultat de la recherche</h1> </font></center> <?php // On utilisera les classes de projet PEAR require_once "SOAP/Client.php"; // On place ici le numero de licence obtenu sur le site de Google $numeroLicence = " MA_LICENCE, CETTE_CHAINE_DOIT_ETRE_REMPLACEE "; // Les mots cles sont stockes dans le script ici. $motsCles = $_POST["motscles"]." site:".$_POST["site"]; $nbresultats = $_POST["nbresultats"]; // Creation du client SOAP et declaration du serveur SOAP. $soapClient = new SOAP_Client("http://api.google.com/search/beta2"); // Les parametres a passer tels que decrits dans lAPI de Google // (licence, // motscles, // indice du premier resultat retourner, // nombre de resultats retourner, // utilisation ou non du filtre cachant les resultats similaires, // restrictions un pays ou domaine..., // filtrage des sites pour adultes, // Restriction sur la langue, // encodage dentre, // encodage de sortie) $recherche = array($numeroLicence, $motsCles, 0,

1307

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Chapitre 16

La gestion des protocoles HTTP, FTP, SOAP, etc.

(int)$nbresultats, TRUE, "", TRUE, "lang_fr|lang_en", "latin1", "latin1"); // Appel a la methode "doGoogleSearch" du serveur SOAP, $result = $soapClient->call("doGoogleSearch", $recherche, "urn:GoogleSearch"); // Affichage du resultat echo "<font size=\"2\">"; echo "<br />Temps de recherche:".$result->searchTime; echo "<br />Estimation du nombre de resultats:". $result->estimatedTotalResultsCount."<br />"; echo "</font>"; $i = 0; if ($result->resultElements) { foreach ($result->resultElements as $resultat) { $i++; echo "<br />$i - <a href=\"".$resultat->URL."\">". $resultat->title."</a><br />"; echo $resultat->snippet."<br />"; echo "<font size=\"1\" color=\"#666666\">". $resultat->title."</font><br />"; echo "<br />"; } } else { echo "Pas de resultat"; } ?> </body> </html>

qui aura pour effet laffichage suivant :

16. La gestion des protocoles HTTP, FTP, SOAP, etc.

Figure 16.5 : Rsultat de la recherche

1308

Chapitre 17

Les processus et les identiants


17.1 17.2 Excution dun programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1311 POSIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1313

Excution dun programme

17.1. Excution dun programme


Les fonctions dappel aux programmes extrieurs faisant partie intgrante de PHP, aucune bibliothque nest ncessaire pour cette partie. Nous avons dj vu lutilisation des apostrophes inverses pour excuter une commande, par exemple :

17. Les processus et les identifiants

Listing 17.1 : processus_01.php


<?php echo dir c:/; ?>

pourra afficher :
Le volume dans le lecteur C na pas de nom. Le numro de srie du volume est A40D-542C Rpertoire de c:\program files\apache group\apache\htdocs\biblephpscripts\chap18 01/07/2002 01/07/2002 01/07/2002 22:25 <REP> . 22:25 <REP> .. 22:26 22 chap18-01.php 1 fichier(s) 22 octets 2 Rp(s) 1y 564y 647y 424 octets libres

Restrictions Lutilisation des apostrophes inverses pour excuter une commande nest possible que si PHP nest pas en "safe mode" (les hbergeurs sont souvent en safe mode) et si la fonction shell_exec() na pas t dsactive.
shell_exec() est identique lutilisation des apostrophes.

shell_exec()
Excute et retourne le rsultat de lexcution. Syntaxe $commande retour string shell_exec(string $commande) Commande excuter. Le rsultat de la commande.

Pour passer en argument une chane pouvant contenir des caractres problmes, la fonction escapeshellarg() permet de normaliser une chane de caractres destine tre passe en argument.

1311

Chapitre 17

Les processus et les identifiants

17. Les processus et les identifiants

escapeshellarg()
Permet de normaliser une chane de caractres destine tre passe en argument. Syntaxe $parametre retour string escapeshellarg(string $parametre) Chane normaliser. Chane normalise.

Pour normaliser une commande et empcher lexcution dune autre commande, la fonction escapeshellcmd() permet de sassurer que la chane fournie sera norme.

escapeshellcmd()
Permet de normaliser une chane. Syntaxe $commande retour stringshellcmd(string $commande) Chane normaliser. Chane normalise.

Supposons, par exemple, que nous souhaitions lister le contenu dun rpertoire en nous basant sur une chane ventuellement saisie par un utilisateur via un formulaire. Lutilisateur est alors libre de taper ce quil veut et par exemple "; rm rf /;" (sous Windows nous pourrions remplacer lexemple par "; format c:;").

Listing 17.2 : processus_02.php


<?php $chaine="; rm -rf /;"; echo "ls /tmp/".$chaine."<br />\n"; echo "ls /tmp/".escapeshellcmd($chaine)."<br />\n"; ?>

Voici le rsultat obtenu :


ls /tmp/; rm -rf /; ls /tmp/\; rm -rf /\;

Ici, nous navons affich que les commandes. Dans le cas de la premire commande, le serveur aurait perdu lensemble des fichiers sil avait t excut, cest pourquoi les hbergeurs sont peu enclins laisser leurs clients utiliser les fonctions dexcution de commandes... Pour excuter une commande, il est aussi possible dutiliser la fonction exec() :

1312

POSIX

exec()
Permet dexcuter un programme externe. En retour, on trouvera la dernire ligne du rsultat de la commande. Syntaxe $commande $sortie $variableRetour retour string exec(string $commande[, array $sortie[, int $variableRetour]]) Commande excuter. Tableau contenant toutes les lignes des sorties de la commande. Le code de retour sera inscrit dans cette variable. La dernire ligne de sortie.

17. Les processus et les identifiants

Scurit Si vous permettez aux visiteurs de passer le moindre paramtre cette fonction, noubliez pas dappliquer les fonctions escapeshellarg() et escapeshellcmd() dcrites prcdemment.

passthru()
la diffrence dexec(), passthru() excute la commande passe en paramtre et affiche la sortie du programme. Syntaxe $commande $variableRetour void passthru(string $commande [, int $variableRetour]) Commande excuter. Le code de retour sera inscrit dans cette variable.

system()
Permet dexcuter un programme externe et den afficher le rsultat. Syntaxe $commande $variableRetour retour string system(string $commande [, int $variableRetour]) Commande excuter. Le code de retour sera inscrit dans cette variable. La dernire ligne de la sortie de la commande.

17.2. POSIX
La bibliothque POSIX nest disponible que sous les systmes de type UNIX (Linux, Mac OS X...), car elle fait appel des notions de ce systme dexploitation.

1313

Chapitre 17

Les processus et les identifiants

17. Les processus et les identifiants

Un fichier appartient ncessairement un utilisateur et un groupe. Cet utilisateur est caractris par deux paramtres. Dune part, il possde un nom dutilisateur (le username ou login name) et, dautre part, tout utilisateur possde un identifiant unique de type entier appel UID (User IDentifier). Mme remarque pour le groupe qui a un nom (group name) et un identifiant unique nomm le GID (Group IDentifier). chaque fichier sont associs un UID et un GID. Cest le systme qui, ensuite, fait le rapport entre ces identifiants et leur dnomination sur ce systme. Le langage PHP possde une srie de fonctions permettant de rcuprer les UID et GID partir des identifiants et vice versa. Cest le module POSIX qui fournit au langage cette interaction entre le systme dexploitation et linterprteur PHP.

Nom dutilisateur et UID


Pour rcuprer un identifiant partir dun UID, il faut passer par linstruction posix_getpwuid().

posix_getpwuid()
Retourne les informations sur lutilisateur possdant lUID donn en paramtre (telles que dcrites dans le fichier /etc/passwd). Syntaxe $uid retour array posix_getpwuid(int $uid) UID de lutilisateur. Tableau associatif contenant les cls : "name", nom (login) de lutilisateur. "passwd", mot de passe de lutilisateur (crypt ou plus probablement x lorsquun fichier /etc/shadow est utilis). "uid", identifiant de lutilisateur. "gid", groupe de lutilisateur. "gecos", commentaire propos de lutilisateur. "dir", rpertoire racine de lutilisateur, en gnral on parle du rpertoire home de cet utilisateur. "shell", systme de commande de lutilisateur. Il sagit gnralement de bash, sh, csh ou rien comme dans notre exemple.

<?php $infoUtilisateur = posix_getpwuid(100); while (list($key, $val) = each($infoUtilisateur)) { echo "$key = $val<br />"; } ?> name = www passwd = x uid = 100 gid = 101 gecos = e-smith web server

1314

POSIX

dir = /home/e-smith shell = /bin/false

17. Les processus et les identifiants

Il est, bien entendu, possible de faire la mme chose en ne connaissant, cette fois, que le nom de lutilisateur. Ainsi, la fonction posix_getpwnam() retourne un tableau contenant les mmes informations sur lutilisateur que prcdemment.

posix_getpwnam()
Retourne les informations sur un utilisateur en fonction de son nom (telles que dcrites dans le fichier /etc/passwd). Syntaxe $nomUtilisateur retour array posix_getpwnam(string $nomUtilisateur) Nom de lutilisateur. Tableau associatif contenant les cls : "name", nom (login) de lutilisateur. "passwd", mot de passe de lutilisateur (crypt ou plus probablement x lorsquun fichier /etc/shadow est utilis). "uid", identifiant de lutilisateur. "gid", groupe de lutilisateur. "gecos", commentaire propos de lutilisateur. "dir", rpertoire racine de lutilisateur, en gnral on parle du rpertoire home de cet utilisateur. "shell", systme de commande de lutilisateur. Il sagit gnralement de bash, sh, csh ou rien comme dans notre exemple.

Pour ne rcuprer que le login de lutilisateur propritaire du processus courant, il suffit de faire appel posix_getlogin().

posix_getlogin()
Retourne le nom de login de la personne propritaire du processus courant. Syntaxe retour string posix_getlogin(void) Le login en question.

Erreur Dans nos essais nous avons eu comme retour : <b>Warning</b>: Cannot determine your login name. Something is really wrong here. in <b>{chemin du script}</b> on line <b>{no Ligne}</b><br>. Ce qui signifie que le nom de login na pas pu tre obtenu.

1315

Chapitre 17

Les processus et les identifiants

17. Les processus et les identifiants

posix_geteuid()
Retourne le numro didentifiant du propritaire effectif du processus courant. Syntaxe retour int posix_geteuid(void) Numro dutilisateur. Il est possible dobtenir plus de dtails sur ce groupe laide de posix_getpwuid().

posix_getuid()
Retourne le numro didentifiant du propritaire rel du processus courant. Syntaxe retour int posix_getuid(void) Numro dutilisateur. Il est possible dobtenir plus de dtails sur ce groupe laide de posix_getpwuid().

posix_seteuid()
Permet de dfinir lidentifiant de lutilisateur effectif du processus courant. Il faut avoir les privilges adquats pour ce type dopration (il faut gnralement tre connect en tant que root). Syntaxe $identifiant Utilisateur retour boolean posix_seteuid(int $identifiantUtilisateur) Identifiant de lutilisateur auquel le processus courant doit tre affect. TRUE en cas de succs, FALSE sinon.

posix_setuid()
Permet de dfinir lidentifiant de lutilisateur rel du processus courant. Il faut avoir les privilges adquats pour ce type dopration (il faut gnralement tre connect en tant que root). Syntaxe $identifiant Utilisateur retour boolean posix_setuid(int $identifiantUtilisateur) Identifiant de lutilisateur auquel le processus courant doit tre affect. TRUE en cas de succs, FALSE sinon.

1316

POSIX

Nom de groupe et GID


17. Les processus et les identifiants
Pour rcuprer des informations sur un groupe, le dveloppeur utilisera linstruction posix_getgrgid().

posix_getgrgid()
Retourne les informations sur le groupe possdant le GID donn en paramtre. Syntaxe $gid retour array posix_getpwuid(int $gid) GID du groupe. Tableau index et associatif. Les champs indexs contiennent les noms des diffrents utilisateurs appartenant au groupe, alors que les cls sont : "name", nom du groupe. "gid", identifiant du groupe. "members", nombre dutilisateurs appartenant au groupe.

<?php $infogroupe = posix_getgrgid(500); while (list($key, $val) = each($infogroupe)) { echo "$key = $val<br />"; } ?> name = shared gid = 500 0 = public 1 = admin 2 = www 3 = laurent 4 = kangouroo 5 = jukebox members = 6

Il est, bien entendu, possible de faire la mme chose en ne connaissant, cette fois, que le nom du groupe. Ainsi, la fonction posix_getgrnam() retourne un tableau contenant les mmes informations sur le groupe que prcdemment.

posix_getgrnam()
Retourne les informations sur un groupe en fonction de son nom. Syntaxe $nomGroupe array posix_getgrnam(string $nomGroupe) Nom du groupe.

1317

Chapitre 17

Les processus et les identifiants

retour

17. Les processus et les identifiants

Tableau index et associatif. Les champs indexs contiennent les noms des diffrents utilisateurs appartenant au groupe, alors que les cls sont : "name", nom du groupe. "gid", identifiant du groupe. "members", nombre dutilisateurs appartenant au groupe.

<?php echo "Information sur lutilisateur Laurent<br />"; $infoUtilisateur = posix_getpwnam("laurent"); while (list($key, $val) = each($infoUtilisateur)) { echo "$key = $val<br />"; } ?> <br /> <?php echo "Information sur le groupe Laurent<br />"; $infogroupe = posix_getgrnam("laurent"); while (list($key, $val) = each($infogroupe)) { echo "$key = $val<br />"; } ?> Information sur lutilisateur Laurent name = laurent passwd = x uid = 5001 gid = 5001 gecos = Laurent GUEDON dir = /home/e-smith/files/users/laurent shell = /bin/sshell Information sur le groupe Laurent name = laurent gid = 5001 members = 0

posix_getegid()
Retourne le numro du groupe effectif du processus courant. Syntaxe retour int posix_getegid(void) Numro de groupe. Il est possible dobtenir plus de dtails sur ce groupe laide de posix_getgrgid().

1318

POSIX

posix_getgid()
Retourne le numro du groupe rel du processus courant. Syntaxe retour int posix_getgid(void) Numro de groupe. Il est possible dobtenir plus de dtails sur ce groupe laide de posix_getgrgid().

17. Les processus et les identifiants

posix_getpgrp()
Retourne lidentifiant du groupe de processus courant. Syntaxe retour int posix_getpgrp(void) Un identifiant de groupe de processus.

posix_setegid()
Permet de dfinir lidentifiant du groupe effectif du processus courant. Il faut avoir les privilges adquats pour ce type dopration (il faut gnralement tre connect en tant que root). Syntaxe retour boolean posix_setegid(int $identifiantGroupe) TRUE en cas de succs, FALSE sinon.

$identifiantGroupe Identifiant du groupe auquel le processus courant doit tre affect.

posix_setgid()
Permet de dfinir lidentifiant du groupe rel du processus courant. Il faut avoir les privilges adquats pour ce type dopration (il faut gnralement tre connect en tant que root). Syntaxe retour boolean posix_setgid(int $identifiantGroupe) TRUE en cas de succs, FALSE sinon.

$identifiantGroupe Identifiant du groupe auquel le processus courant doit tre affect.

1319

Chapitre 17

Les processus et les identifiants

PID (identiant de processus)


17. Les processus et les identifiants

posix_getpid()
Retourne lidentifiant du processus courant. Syntaxe retour int posix_getpid(void) Un identifiant de processus.

posix_getppid()
Retourne lidentifiant du processus parent du processus courant. Syntaxe retour int posix_getppid(void) Un identifiant de processus.

posix_setpgid()
Permet de placer un processus dans un groupe de processus. Syntaxe $identifiant Processus $identifiant GroupeProcessus retour boolean posix_setpgid(int $IdentifiantProcessus, $identifiantGroupeProcessus) Identifiant du processus placer. Identifiant du groupe dans lequel placer le processus. TRUE en cas de succs, FALSE sinon.

Chemins

posix_getcwd()
Retourne le nom du rpertoire courant. Syntaxe retour String posix_getcwd() Le chemin complet du rpertoire courant.

1320

POSIX

posix_ctermid()
Retourne le chemin complet du terminal. Syntaxe retour string posix_ctermid(void) Le chemin complet du terminal (ex. : /dev/tty).

17. Les processus et les identifiants

Ressources systme
Lorsquune machine est partage entre plusieurs utilisateurs, il peut tre intressant de limiter les ressources par utilisateur, afin, par exemple, quun des utilisateurs ne consomme pas 90 % des ressources tandis que les 10 % restants sont partager entre une vingtaine dautres utilisateurs. La fonction posix_getrlimit() va nous permettre de connatre ces restrictions.

posix_getrlimit()
Permet de connatre les limites imposes de partage des ressources. Syntaxe retour array posix_getrlimit() Tableau associatif indiquant les diffrentes limites imposes.

<?php print_r(posix_getrlimit()); ?> Array ( [soft [hard [soft [hard [soft [hard [soft [hard [soft [hard [soft [hard [soft [hard [soft [hard [soft [hard [soft [hard )

core] => 0 core] => unlimited data] => unlimited data] => unlimited stack] => unlimited stack] => unlimited totalmem] => unlimited totalmem] => unlimited rss] => unlimited rss] => unlimited maxproc] => 2040 maxproc] => 2040 memlock] => unlimited memlock] => unlimited cpu] => unlimited cpu] => unlimited filesize] => unlimited filesize] => unlimited openfiles] => 1024 openfiles] => 1024

1321

Chapitre 17

Les processus et les identifiants

17. Les processus et les identifiants

posix_times()
Rcupre les diffrents temps du processus. Syntaxe retour array posix_times() Tableau associatif des diffrents temps : "ticks": nombre dunits de temps coul depuis le dernier redmarrage de la machine. "utime": temps utilisateur du processus courant. "stime": temps systme du processus courant. "cutime": temps utilisateur des processus enfants. "cstime": temps systme des processus enfants.

<?php print_r(posix_times()); ?> Array ( [ticks] => 144168 [utime] => 4 [stime] => 2 [cutime] => 0 [cstime] => 0 )

Envoi dun signal un processus

posix_kill()
Envoie un signal un processus dans le but de le terminer. Syntaxe $identifiant Processus $signal retour boolean posix_kill(int $identifiantProcessus, int $signal) Identifiant du processus terminer. Numro du signal envoyer (9 pour tuer le processus de manire brutale). TRUE si le signal a pu tre envoy, FALSE sinon.

Informations systme

posix_uname()
Rcupre des informations sur le systme dexploitation.

1322

POSIX

Syntaxe retour

array posix_uname()

17. Les processus et les identifiants

Tableau associatif des caractristiques du systme dexploitation.

<?php print_r(posix_uname()); ?> Array ( [sysname] => Linux [nodename] => australia [release] => 2.2.19-7.0.8 [version] => #1 Thu Jun 21 06:28:56 EDT 2001 [machine] => i686 )

domainname Il est possible de trouver en plus, sur certaines machines, la cl dommainname, qui correspond au nom de domaine du DNS. Ceci est une extension GNU qui ne fait pas partie de POSIX 1 ; cest pourquoi nous ne retrouvons pas cette information ici.

1323

Chapitre 18

Linteroprabilit avec COM


18.1 COM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1327

COM

18.1. COM
COM permet dinteragir avec la plupart des applications Microsoft courantes telles que Word,

Excel, Powerpoint, Access, Outlook ou encore MSGraph. Cette bibliothque daccs la couche COM va nous permettre de faire raliser par le serveur web toutes les oprations que nous pourrions faire manuellement en ouvrant ces mmes applications.

18. Linteroprabilit avec COM

Installation
La bibliothque COM nest disponible que sous Windows. Que ce soit avec larchive du PHP Group ou avec EasyPHP, vous naurez rien faire de particulier pour en profiter, puisquelle fait partie du noyau PHP. Toutefois, afin dutiliser les constantes de COM, il faudra dcommenter la ligne com .autoregister_typelib = true du fichier php.ini. De mme, pour des appels distants, vous devrez mettre com.allow_dcom la valeur true.

Utilisation
La manipulation des objets COM commence par linstanciation dun objet PHP par un simple appel du genre new COM("nom application");.

COM
Instancie un objet COM. Syntaxe $application $serveur $encodage COM COM(string $application [, string $serveur [, int $encodage]]) Dsignation de lapplication. Nom ou adresse du serveur DCOM (par dfaut localhost). Indique comment convertir les chanes. Au choix : CP_ACP. CP_MACCP. CP_OEMCP. CP_SYMBOL. CP_THREAD_ACP. CP_UTF7. CP_UTF8. retour Objet COM.

1327

Chapitre 18

Linteroprabilit avec COM

Voici une srie de dsignations dapplications possibles :


j j j

Access.Application ; Excel.Application ; Excel.Worksheet ; Excel.Chart ; MSGraph.Chart ; Outlook.Application ; Powerpoint.Application ; Powerpoint.Presentation ; Word.Application ; Word.Document.

18. Linteroprabilit avec COM

j j j j j j j

Il existe ensuite une srie de fonctions PHP permettant de lire ou modifier des attributs de ce composant, dappeler des mthodes, etc. Mais tout cela peut se faire en utilisant simplement la notation objet de PHP. Ainsi, pour modifier lattribut Visible dun objet Word et pour appeler la mthode close(), il suffira dcrire :
<?php $word = new COM("word.application") or die("Impossible de crer un objet Word"); $word->Visible = 1; $word->Quit(); ?>

La plus grande difficult rside donc dans le fait de connatre les proprits de ces objets. Il est probable que les adeptes de ces solutions propritaires qui pratiquent dj COM/DCOM sy retrouveront sans mal. Pour les autres, sachez quil est facile de crer des scripts intressants moindre frais. En fait, lastuce consiste (cest vrai pour Word, mais trs probablement aussi pour les autres applications) lancer lenregistrement dune macro (menu Outils/Macro/Nouvelle macro), taper ce que vous souhaitez faire faire au serveur, stopper lenregistrement de la macro et, enfin, consulter le rsultat obtenu. Cette dernire opration pouvant se raliser en allant dans le menu Outils/Macro/Macros..., en slectionnant la macro nouvellement cre, et en slectionnant loption modifier qui fera apparatre le code de la macro.

Exemple 1 : impression dune feuille de commande


Notre premier exemple permet, partir dun formulaire HTML, de gnrer automatiquement un document Word et den imprimer le contenu. Lexemple pris ici est celui de limpression dune feuille de commande. Il est alors possible dimaginer, qu chaque nouvelle commande passe par un client, une feuille est automatiquement imprime dans le bureau du magasinier, qui pourra alors se promener dans les rayons avec sa fiche. En Intranet, cela peut permettre nimporte qui (dans un grand bureau) dimprimer depuis son poste une tiquette au format

1328

COM

standard sur limprimante commune (dans ce cas, aucune installation spcifique nest ncessaire sur le poste du client, hormis le navigateur qui est gnralement prsent par dfaut ; en cas de modification du standard, seul le script du serveur sera modifier et sans aucune intervention sur les postes clients). La page dappel est un simple formulaire dont voici une capture dcran :
Figure 18.1 : Formulaire de saisie

18. Linteroprabilit avec COM

Cette page fait appel une page, appele impression.php, qui est charge douvrir un document Word, dy crire un contenu, dimprimer puis de fermer le document.

Listing 18.1 : impression.php


<?php $word = new COM("word.application") or die("Impossible de crer un objet Word"); // Juste titre de test pour voir ce quil se passe $word->Visible = 1; $word->Documents->Add(); // Cre les tabulations // Une 8 cm du bord gauche de la feuille avec alignement au centre // Une 16 cm du bord gauche de la feuille avec alignement droite $word->Selection->ParagraphFormat->TabStops->Add( $word->CentimetersToPoints(8), wdAlignTabCenter, wdTabLeaderSpaces); $word->Selection->ParagraphFormat->TabStops->Add( $word->CentimetersToPoints(16), wdAlignTabRight, wdTabLeaderSpaces); // Saisie du texte gauche $word->Selection->TypeText("Nom:"); $word->Selection->Font->Bold = wdToggle; $word->Selection->TypeText(stripSlashes($_POST["nom"]));

1329

Chapitre 18

Linteroprabilit avec COM

// Passage au texte central par tabulation $word->Selection->TypeText("\t"); // Saisie du texte central $word->Selection->Font->Name = "Times New Roman"; $word->Selection->Font->Size = 20; $word->Selection->Font->Bold = TRUE; $word->Selection->Font->Color = wdColorRed; $word->Selection->TypeText("COMMANDE"); // Passage au texte droit par tabulation $word->Selection->TypeText("\t"); // Saisie du texte droit $word->Selection->Font->Size = 12; $word->Selection->Font->Bold = wdToggle; $word->Selection->Font->Color = wdColorBlack; $word->Selection->TypeText("Date:"); $word->Selection->Font->Bold = wdToggle; $word->Selection->TypeText(strftime("%d/%m/%y")); $word->Selection->Font->Bold = wdToggle; // Passage au paragraphe suivant $word->Selection->TypeParagraph(); // Saisie du paragraphe suivant en centr et italique $word->Selection->ParagraphFormat->Alignment = wdAlignParagraphCenter; $word->Selection->Font->Italic = TRUE; $word->Selection->TypeText(stripSlashes($_POST["adresse"])); // Passage au paragraphe suivant $word->Selection->TypeParagraph(); // Saisie du paragraphe suivant en align gauche $word->Selection->ParagraphFormat->Alignment = wdAlignParagraphLeft; $word->Selection->Font->Italic = FALSE; $word->Selection->TypeText(stripSlashes($_POST["commande"])); // Slection de lensemble du texte $word->Selection->WholeStory(); // Et encadrement en prcisant les bords Haut, Bas, Gauche, Droit $word->Selection->Borders[wdBorderTop]->LineStyle = wdLineStyleDouble; $word->Selection->Borders[wdBorderTop]->LineWidth = wdLineWidth050pt; $word->Selection->Borders[wdBorderTop]->Color = wdColorAutomatic; $word->Selection->Borders[wdBorderBottom]->LineStyle = wdLineStyleDouble; $word->Selection->Borders[wdBorderBottom]->LineWidth = wdLineWidth050pt; $word->Selection->Borders[wdBorderBottom]->Color = wdColorAutomatic; $word->Selection->Borders[wdBorderLeft]->LineStyle =wdLineStyleDouble; $word->Selection->Borders[wdBorderLeft]->LineWidth = wdLineWidth050pt; $word->Selection->Borders[wdBorderLeft]->Color = wdColorAutomatic; $word->Selection->Borders[wdBorderRight]->LineStyle = wdLineStyleDouble;

18. Linteroprabilit avec COM 1330

COM

$word->Selection->Borders[wdBorderRight]->LineWidth = wdLineWidth050pt; $word->Selection->Borders[wdBorderRight]->Color = wdColorAutomatic; $word->Documents[1]->SaveAs("TestEtiquette.doc"); $word->Application->PrintOut();

18. Linteroprabilit avec COM

$word->Quit(); ?>

COM->Visible et WinNT/2000/XP Si COM->Visible est mis vrai, alors le document Word ne sera visible que par le propritaire du document. Si le serveur web que vous avez install est un service, alors le propritaire est SYSTEM, (cest--dire pas vous) et vous ne verrez donc pas le document Word. Pour le voir, il faut lancer le serveur web " la main". Pour Apache, il vous suffit darrter le serveur et de lancer C:\progra~1\apache ~1\apache\apache.exe.
Comment sommes-nous parvenus ce rsultat ? Simplement en gnrant le document, tout en enregistrant une macro.

Figure 18.2 : Ltiquette telle quelle sera imprime par Word

Ceci a eu pour effet de gnrer le code suivant pour la macro :


Sub Macro() Selection.ParagraphFormat.TabStops.ClearAll ActiveDocument.DefaultTabStop = CentimetersToPoints(1.25) Selection.ParagraphFormat.TabStops.Add Position:=CentimetersToPoints(8), _ Alignment:=wdAlignTabCenter, Leader:=wdTabLeaderSpaces Selection.ParagraphFormat.TabStops.ClearAll ActiveDocument.DefaultTabStop = CentimetersToPoints(1.25) Selection.ParagraphFormat.TabStops.Add Position:=CentimetersToPoints(8),_

1331

Chapitre 18

Linteroprabilit avec COM

Alignment:=wdAlignTabCenter, Leader:=wdTabLeaderSpaces Selection.ParagraphFormat.TabStops.Add Position:=CentimetersToPoints(16),_ Alignment:=wdAlignTabRight, Leader:=wdTabLeaderSpaces Selection.TypeText Text:="Nom: " Selection.Font.Bold = wdToggle Selection.TypeText Text:="Le Nom" & vbTab With Selection.Font .Name = "Times New Roman" .Size = 12 .Bold = True .Italic = False .Underline = wdUnderlineNone .UnderlineColor = wdColorAutomatic .StrikeThrough = False .DoubleStrikeThrough = False .Outline = False .Emboss = False .Shadow = False .Hidden = False .SmallCaps = False .AllCaps = False .Color = wdColorRed .Engrave = False .Superscript = False .Subscript = False .Spacing = 0 .Scaling = 100 .Position = 0 .Kerning = 0 .Animation = wdAnimationNone End With Selection.TypeText Text:="COMMANDE" & vbTab With Selection.Font .Name = "Times New Roman" .Size = 12 .Bold = False .Italic = False .Underline = wdUnderlineNone .UnderlineColor = wdColorAutomatic .StrikeThrough = False .DoubleStrikeThrough = False .Outline = False .Emboss = False .Shadow = False .Hidden = False .SmallCaps = False .AllCaps = False .Color = wdColorAutomatic .Engrave = False .Superscript = False .Subscript = False .Spacing = 0

18. Linteroprabilit avec COM 1332

COM

.Scaling = 100 .Position = 0 .Kerning = 0 .Animation = wdAnimationNone End With Selection.TypeText Text:="Date: " Selection.Font.Bold = wdToggle Selection.TypeText Text:="06/07/02" Selection.TypeParagraph Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter Selection.Font.Bold = wdToggle Selection.Font.Italic = wdToggle Selection.TypeText Text:="Adresse" Selection.TypeParagraph Selection.Font.Italic = wdToggle Selection.TypeText Text:="Texte de la commande" Selection.ParagraphFormat.Alignment = wdAlignParagraphLeft Selection.WholeStory With Selection.ParagraphFormat With .Borders(wdBorderLeft) .LineStyle = wdLineStyleDouble .LineWidth = wdLineWidth050pt .Color = wdColorAutomatic End With With .Borders(wdBorderRight) .LineStyle = wdLineStyleDouble .LineWidth = wdLineWidth050pt .Color = wdColorAutomatic End With With .Borders(wdBorderTop) .LineStyle = wdLineStyleDouble .LineWidth = wdLineWidth050pt .Color = wdColorAutomatic End With With .Borders(wdBorderBottom) .LineStyle = wdLineStyleDouble .LineWidth = wdLineWidth050pt .Color = wdColorAutomatic End With .Borders(wdBorderHorizontal).LineStyle = wdLineStyleNone With .Borders .DistanceFromTop = 1 .DistanceFromLeft = 4 .DistanceFromBottom = 1 .DistanceFromRight = 4 .Shadow = False End With End With With Options .DefaultBorderLineStyle = wdLineStyleDouble .DefaultBorderLineWidth = wdLineWidth050pt .DefaultBorderColor = wdColorAutomatic

18. Linteroprabilit avec COM 1333

Chapitre 18

Linteroprabilit avec COM

End With End Sub

Une analyse rapide permet de comprendre quun objet Word possde un attribut Selection, qui possde des attributs et mthodes permettant de positionner une tabulation par appel Selection>ParagraphFormat>TabStops>Add(), etc.

18. Linteroprabilit avec COM

Il suffit, pour ainsi dire, de remplacer les points . par des flches > pour passer du code de la macro celui du script PHP. Puis de convertir les passages de paramtres "faon macro" en passage de paramtres PHP. Il est facile didentifier les constantes Word (elles commencent par wd) puis de deviner leur rle. Bref, avec un peu dastuce, cela nous a permis dobtenir le rsultat escompt.

Exemple 2 : un Intranet facile !


Lide de ce deuxime script est de raliser un Intranet pour lequel on suppose que les personnes ayant du contenu y insrer ne connaissent pas lHTML, et se restreindront utiliser Word et enregistrer leurs documents au format Word. Le script que nous allons crer permettra dinsrer un document Word au sein de deux autres dfinis comme len-tte et le pied de page du document.

Listing 18.2 : intranet.php


<?php define("WDFORMATHTML", 8); $word = new COM("word.application") or die("Unable to instanciate Word"); $word->Documents->Add(); // Charge le document dentte $word->Selection->InsertFile("C:\\entete.doc"); $word->Selection->InsertFile("C:\\secretaire.doc"); $word->Selection->InsertFile("C:\\pieddepage.doc"); $word->ActiveDocument->SaveAs($_SERVER["DOCUMENT_ROOT"]. "\\TestIntranet.html", WDFORMATHTML); $word->Quit(); ?>

Ce script ne fait quaccoler les trois documents et enregistre le rsultat en tant que fichier HTML la racine du site web.

1334

COM

Voici le document Word den-tte :

18. Linteroprabilit avec COM

Figure 18.3 : entete.doc

suivi du message de la secrtaire :

Figure 18.4 : secretaire.doc

1335

Chapitre 18

Linteroprabilit avec COM

puis du pied de page :

18. Linteroprabilit avec COM

Figure 18.5 : pieddepage.doc

La page HTML produite par Word :

Figure 18.6 : TestIntranet.html

1336

COM

Comme vous pouvez le constater, len-tte est diffrent. Cela est d la faon de faire de Microsoft Word pour transformer un document Word en document HTML.

User de cette mthode peut provoquer de graves dfaillances de serveur vitez tout de mme duser des objets COM comme les applications bureautiques, car ils sont trs gourmands en ressources (chaque ouverture de lapplication ncessite dallouer beaucoup de mmoire et sollicite grandement le disque dur). Plus vous ouvrirez dobjets COM, plus la chute du serveur sera proche.

18. Linteroprabilit avec COM 1337

Chapitre 19

Loptimisation des temps de rponse


19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 19.10 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Environnement de test des solutions "bas niveau" (modules PHP) En labsence de solution doptimisation . . . . . . . . . . . . . . . . Avec Zend Optimizer . . . . . . . . . . . . . . . . . . . . . . . . . . . . Avec Alternative PHP Cache (APC) . . . . . . . . . . . . . . . . . . . . Avec PHP Accelerator (PHPA) . . . . . . . . . . . . . . . . . . . . . . Avec Zend Accelerator (Zend Performance Suite) . . . . . . . . . . Conclusion sur les solutions "bas niveau" (modules PHP) . . . . Les solutions "haut niveau" (programmation PHP) . . . . . . . . . Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . .. .. .. .. .. .. .. .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1341 .1342 .1346 .1349 .1358 .1362 .1366 .1376 .1377 .1378

Introduction

19.1. Introduction
Ds lors quun site devient populaire, et donc que le nombre quotidien des visiteurs est lev, il convient de rduire au minimum le temps de rponse du serveur. Cela na pas pour seul bnfice de rduire le temps dattente de lutilisateur, mais galement de rduire la probabilit quune ou plusieurs requtes arrivent alors que le serveur est dj en train den traiter dautres. Le nombre de requtes que doit traiter simultanment un serveur est appel "la charge". Plus le serveur sera "charg", moins il aura de ressources disponibles, et plus il mettra de temps rpondre une requte jusqu ne plus pouvoir prendre en compte les nouvelles requtes et tre contraint de les refuser. Ce temps de rponse dpend videmment dun grand nombre de paramtres :
j j j

19. Loptimisation des temps de rponse

Le matriel (la quantit de mmoire, la vitesse des disques durs, etc.) ; Le systme dexploitation (sa capacit raliser plusieurs traitements en parallle, sa vitesse dexcution) ; Le serveur web (et sa capacit doptimiser, donc de rduire le nombre doprations raliser).

Nous ne nous intresserons ici qu laspect PHP (composante du serveur web). Lexcution dun script PHP se droule en trois tapes principales : 1. 2. Ouverture du fichier et analyse syntaxique du script (parsing) qui consiste dtecter les blocs dinstructions, les dclarations de fonctions, etc. La compilation du code. Autrement dit, la transformation des lments (crits dans un langage comprhensible par lhomme) dtects dans ltape 1 en lments comprhensibles par la machine. Lexcution du code (gnralement pour gnrer un document HTML).

3.

Nous allons vite nous rendre compte quil est possible dintervenir ces trois niveaux afin de rduire le temps de rponse du serveur. La premire des choses ncessaires pour que le temps dexcution soit minimal est tout simplement que la compilation offre un code optimal (inutile de mettre deux instructions l o une seule suffit). La seconde chose est dviter de refaire pour un client une opration qui vient dtre ralise sur le mme script pour un des clients prcdents. Pour cela, il faut stocker le rsultat des oprations 1, 2, et ventuellement 3, dans une mmoire appele cache. Ce dernier point doit tre tudi avec attention. Il existe en effet deux cas de figure :
j

Cest le rsultat de la compilation (tapes 1 + 2) qui est mis en cache. Dans ce cas, le code sera r-excut chaque appel. Le document reste donc un document gnr dynamiquement. Cest le rsultat de lexcution (tapes 1 + 2 + 3) qui est mis en cache (autrement dit le code HTML). Dans ce cas, le document nest pas gnr dynamiquement chaque appel (cest le code HTML qui est rappel). Si, par exemple, ce document doit afficher lheure, cest lheure la date de mise en cache du document qui sera restitue lors des prochains appels.

1341

Chapitre 19

Loptimisation des temps de rponse

La diffrence entre ces deux solutions est donc trs importante. Alors que la premire est applicable nimporte quel type de script PHP, la seconde sera rserver pour les scripts retournant un rsultat voluant peu dans le temps, ou, en tout cas, dont la mise jour na pas besoin dtre immdiate (ceci nest donc pas applicable un forum et encore moins un systme de cotations en bourse). Dans limmdiat, nous ne nous intresserons quaux solutions (que nous appellerons solutions "bas niveau") qui ne sont pas lies une mise en cache du document gnr. Comme toujours avec les problmes doptimisation, il faut se mfier de la thorie. Les rsultats peuvent tre radicalement diffrents dun cas de figure lautre. Afin davoir tout de mme une ide de limpact de ces diffrentes mthodes doptimisation, nous avons ralis des tests sur un mini-site local cr pour loccasion. Ce site est assez fidle ce que peut contenir un vritable site web. Il contient donc des pages quasiment statiques (comme peuvent ltre les pages daccueil) ainsi que des pages totalement dynamiques (comme peuvent ltre les pages de moteurs de recherche ou de forums). Pour mettre en avant certains cas de figures, nous avons tout de mme rajout des pages considres comme non reprsentatives dun site web (comme des pages faisant appel du calcul scientifique).

19. Loptimisation des temps de rponse

19.2. Environnement de test des solutions "bas niveau" (modules PHP)


Conguration matrielle
Les tests ont t raliss partir dun poste client bas sur un Intel Pentium II (Deschutes) 400 MHz quip de 256 Mo de RAM et du systme dexploitation Linux (Mandrake 8.1) reli au serveur par une liaison BNC. Le serveur, quant lui, est quip de la manire suivante :
j j j j j j

Processeur : AMD K6-II 350 MHz ; Mmoire : 192 Mo (+136 Mo virtuelle) ; Disque dur : IBM-DTTA-351010 10 Go (IDE) (11 Mo/s) ; Systmes dexploitation : Linux (Mandrake 9.1) ; Serveur : Apache 1.3.28 avec PHP 4.3.0 ; Base de donnes : MySQL 4.

Pourquoi PHP 4.3.0 ? Cest la version 4.3.0 et non une version suprieure qui a t retenue parce qu la date o les tests ont t raliss, il sagissait de la seule version officiellement compatible avec lensemble des solutions doptimisation prsentes ici. Ceci dit, des tests complmentaires ont montr quil y a trs peu de diffrences entre les rsultats obtenus avec PHP 4.3.0 et PHP 4.3.2 mme si celle-ci est en faveur de PHP 4.3.2.

1342

Environnement de test des solutions "bas niveau" (modules PHP)

Et PHP 5 ? ce jour quasiment aucune des solutions doptimisation ne supporte officiellement (du moins) PHP 5.

Pages testes
Les tests ont port sur trois pages principales (dont les sources sont disponibles sur le CD-ROM) :
j j j

Une quasi-statique ; Une dynamique ; Une mathmatique.

19. Loptimisation des temps de rponse

La page quasi-statique
La page quasi-statique ne possde aucun lment variable. Tous les lments de la page sont figs : aucun nest dpendant de lheure, de lutilisateur ou du contenu dune base de donnes. Ce peut-tre, par exemple, une page daccueil. Bien que cette page aurait pu tre crite directement en HTML, sa constitution tire toutefois parti des avantages quoffre PHP, puisque chaque lment de la page (en-tte, menu gauche, menu droit, pied de page) est dcrit dans un fichier qui lui est propre. Le tout est assembl par de simples "include". Les menus, quant eux, sont dcrits dans des classes (ce qui offre une grande facilit de mise jour).

Figure 19.1 : La page quasi-statique

Cette page fait 1 569 octets.

1343

Chapitre 19

Loptimisation des temps de rponse

La page dynamique
La page dynamique est, quant elle, totalement dynamique et est susceptible de changer chaque appel, puisque son contenu est issu dune base de donnes pouvant tre alimente tout moment. Cest le cas, par exemple, dune page de rsultats dun moteur de recherche ou dun forum. Nous utiliserons ici le site de petites annonces dvelopp au cours du chapitre Les bases de donnes. La quantit de donnes dans la base est limite 33 enregistrements, afin que la mesure ne porte pas trop sur la capacit de rponse de la base de donnes.

19. Loptimisation des temps de rponse

Figure 19.2 : La page dynamique

Cette page fait 8 850 octets.

La page mathmatique
La page mathmatique a pour objectif de raliser un grand nombre doprations et de boucles, afin de vritablement solliciter le langage PHP lui-mme. En loccurrence, nous avons choisi de raliser une fonction exponentielle qui effectue en boucle un grand nombre dadditions et de multiplications. Ce cas nest pas vritablement reprsentatif dun site Internet.

1344

Environnement de test des solutions "bas niveau" (modules PHP)

19. Loptimisation des temps de rponse

Figure 19.3 : La page mathmatique

Cette page fait 1 082 octets.

Instrument de mesure
Les mesures ont t effectues uniquement depuis le poste client (cest donc le cycle complet requte-rponse qui a t mesur) grce la commande ab fournie avec la version UNIX dApache. Cette commande permet (entre autres) de prciser le nombre de requtes excuter ainsi que le nombre de requtes concurrentes, et retourne (entre autres) le temps global dexcution et le nombre de requtes qui nont pu tre satisfaites. Dans chacun des cas tudis, nous avons systmatiquement demand lexcution de 500 requtes, et cest donc toujours sur le temps ncessaire la ralisation de ces 500 requtes que nous avons tabli la comparaison. Les tests ont t dclins avec les niveaux de concurrence suivants : 1 (les tests sont donc excuts les uns aprs les autres), 3, 5, 10, 50 et 100. Chaque test a t renouvel plusieurs fois (au moins dix fois lors dune session) et, afin dcarter tout doute, la plupart des sessions de test ont t renouveles deux fois des dates diffrentes (avec redmarrage du systme). Il tait ainsi possible de dtecter une ventuelle perte de performance lie une forte occupation mmoire ou CPU par un programme externe lors du droulement dune des sessions.

Prsentation des mesures


Les rsultats des mesures (disponibles sur le CD-ROM) sont prsents sur un graphe accompagn dun tableau donnant les valeurs numriques.

1345

Chapitre 19

Loptimisation des temps de rponse

Chaque mesure est reprsente par un point avec, pour ordonne, la charge (le nombre daccs concurrents) et, pour abscisse, le temps de rponse (temps total dexcution des 500 requtes, en secondes). Pour chaque niveau de charge, le temps moyen dexcution a t calcul afin de tracer la courbe dvolution du temps dexcution en fonction de la charge. Le graphe intgre galement (en arrire-plan et dans une autre chelle) le nombre moyen de requtes en chec. Notez que nous avons choisi une chelle logarithmique pour laxe des abscisses (la charge).

19. Loptimisation des temps de rponse

Graphe Les graphiques ont t raliss grce la bibliothque JpGraph dcrite en annexe de ce livre.

19.3. En labsence de solution doptimisation


Mesures
Page quasi-statique
Figure 19.4 : Temps de rponse dune page quasi-statique sans optimisation

Tableau 19.1 : Temps de rponse sans optimisation dune page quasi-statique


Nombre de requtes simultanes 1 3 5 7 Temps total dexcution (en secondes) 7.96 4.97 4.88 4.84 Temps total dexcution minimum (en secondes) 5.87 4.87 4.78 4.75 Temps total dexcution maximum (en secondes) 15.23 5.10 4.98 4.9 Nombre de requtes en chec 0 0 0 0

1346

En labsence de solution doptimisation

Nombre de requtes simultanes 10 50 100

Temps total dexcution (en secondes) 4.85 4.86 4.92

Temps total dexcution minimum (en secondes) 4.78 4.81 4.85

Temps total dexcution maximum (en secondes) 4.9 4.91 5.17

Nombre de requtes en chec 0 0 0

Nous observons un dlai dexcution des 500 requtes bien plus long (+ 64 %) lorsque celles-ci sont mises les unes la suite des autres (en comparaison avec plusieurs appels simultans). Ceci na rien dtonnant, et vous comprendrez aisment quun systme conu pour traiter plusieurs tches en mme temps ne pourra optimiser son travail que si les demandes ne lui arrivent pas les unes aprs les autres. Nous constatons galement que le serveur ne souffre pas de la charge qui lui est impose. Il traite quasiment aussi rapidement les requtes quil y en ait 3 ou 100 simultanment (seule une trs lgre augmentation du temps dexcution est observable partir de 50 requtes simultanes). Et aucune requte ne tombe en erreur (elles sont toutes honores par le serveur). Les rsultats obtenus sont dune trs bonne stabilit. Hormis le cas o les requtes sont mises les unes aprs les autres, les rsultats obtenus dun test lautre sont similaires (avec des variations maximales de plus ou moins 2 %, comme le montrent les temps maximum et minimum relevs).

19. Loptimisation des temps de rponse

Comparatif avec les tests des ditions prcdentes Les tests raliss dans les mmes conditions mais avec Mandrake 8.1, Apache 1.3.24, PHP 4.2.1 et MySQL 3 (sur le serveur) donnaient des rsultats moins bons: de lordre de 5,8 secondes contre 4,8 ici. Difficile de dterminer quel est llment (PHP?) qui a permis ce gain en performance de 20% dune anne sur lautre mais il est pourtant bel et bien rel.

Page dynamique
Figure 19.5 : Temps de rponse dune page dynamique sans optimisation

1347

Chapitre 19

Loptimisation des temps de rponse

Tableau 19.2 : Temps de rponse sans optimisation dune page dynamique


Nombre de requtes simultanes 1 3 5 7 10 Temps total dexcution 74.03 71.64 72.58 73.37 73.79 79.35 81.30 Temps total dexcution minimum 73.29 70.47 71.66 72.60 73.00 78.24 78.96 Temps total dexcution maximum 75.139 72.90 73.27 74.10 74.36 80.97 84.33 Nombre de requtes en chec 0 0 0 0 0 0 moyenne 12.6 minimum 1 maximum 66

19. Loptimisation des temps de rponse

50 100

Nous pouvons faire ici la mme remarque que prcdemment concernant les requtes mises une une. L encore, sans surprise, le temps total est plus long que lorsque les requtes sont traites simultanment. Les temps dexcution sont, cette fois-ci, plus sensibles la charge. tel point que le serveur et/ou la base de donnes ne suivent plus lorsque lon atteint les 100 requtes simultanes. Bien quils soient reprsents sur le graphe, les temps mesurs ne sont alors plus vraiment reprsentatifs (il est plus rapide de dire "Non... je ne peux pas traiter ta requte" que de la traiter). Limpact de la charge se fait ressentir au-del des 10 requtes simultanes. Les mesures ne laissent apparatre quune faible variation (de lordre de 1 %) dun test lautre.

Comparatif avec les tests des ditions prcdentes Les tests prcdents donnaient galement des rsultats moins bons: de lordre de 91 secondes contre 73 ici: soit un gain de 25%.

Page mathmatique
Figure 19.6 : Temps de rponse dune page mathmatique sans optimisation

1348

Avec Zend Optimizer

Tableau 19.3 : Temps de rponse sans optimisation dune page mathmatique


Nombre de requtes simultanes 1 3 5 7 10 50 100 Temps total dexcution 52.71 47.22 47.41 47.37 47.31 49.11 49.36 Temps total dexcution minimum 49.05 46.70 46.63 46.73 46.47 48.28 48.02 Temps total dexcution maximum 55.59 47.84 47.96 47.95 47.94 50.55 51.88 Nombre de requtes en chec 0 0 0 0 0

19. Loptimisation des temps de rponse

0 0

Nous ne reviendrons plus sur lanalyse des rsultats obtenus lorsque les requtes sont mises les unes aprs les autres pour nous concentrer sur le phnomne de charge. Tout comme avec le script prcdent, ce test est sensible la charge. Ainsi, le temps de rponse augmente au fur et mesure quaugmente la charge (de 3 100 requtes par secondes) exception faite dun petit "accident" pour 5 requtes par secondes. Cependant, cette fois, mme avec 100 requtes par secondes, aucune requte ne tombe en erreur (laissant entendre que le rle de la base de donnes dans la perte de tenue en charge nest pas ngligeable). Le temps total dexcution semble mme atteindre un palier de seulement 4 % suprieur la plus petite mesure releve (pour trois accs concurrents). L encore, la stabilit des rsultats obtenus est satisfaisante (des variations de plus ou moins 2 % peine).

Comparatif avec les test des ditions prcdentes Surprise! Les tests prcdents donnaient de meilleurs rsultats: de lordre de 42 secondes contre 47 ici: soit une perte de 10%.
Reste maintenant voir ce que peuvent nous apporter les solutions doptimisation.

19.4. Avec Zend Optimizer


Entre les versions 3 et 4 de PHP, il y a, semble-t-il, eu un gros effort concernant loptimisation du compilateur PHP. Cependant, cela na pas empch la socit Zend de proposer (gratuitement) un optimisateur de code appel Zend Optimizer.

Description
Cet optimisateur a pour objectif deffectuer quelques traitements supplmentaires sur le code gnr, afin de le rendre encore plus rapide lexcution. Il va donc de soi que lutilisation de

1349

Chapitre 19

Loptimisation des temps de rponse

loptimisateur ne sera bnfique que si le temps gagn lexcution est suprieur au temps perdu effectuer le travail doptimisation. Ce code est disponible gratuitement ladresse http://www.zend.com (en anglais). pour les systmes dexploitation :
j j j j

Windows ; Linux glibc2.1 ; FreeBSD 3.4 et 4.0 ; Solaris Sparc ; IBM AIX Server. Mac OS X (pour PHP>=4.3.2)

19. Loptimisation des temps de rponse

j j

La version teste est la version 2.1.0 pour Linux compatible avec les versions de PHP>=4.0.5.

Version 2.5 La dernire version en date est la 2.5, elle supporte officiellement les versions de PHP allant de la 4.0.5 la 5.0.0RC2.

Installation
Son installation est trs simple.

Sous Windows
Aprs avoir tlcharg la version de Zend Optmizer gratuitement sur le site officiel (http://www .zend.com), il suffit de lancer son installation et de suivre les tapes dcrites ci-dessous. Tout dabord, vous serez invits lire et accepter la licence.
Figure 19.7 :

Slection du rpertoire dinstallation

1350

Avec Zend Optimizer

Puis vous pourrez slectionner le rpertoire dans lequel vous souhaitez installer le logiciel.
Figure 19.8 : Slection du rpertoire php.ini

19. Loptimisation des temps de rponse

Ensuite, vous devrez confirmer ou modifier le chemin du rpertoire contenant le fichier php.ini utilis par votre serveur. Une fentre vous prcisera alors que lancien fichier php.ini a t sauvegard sous un autre nom.
Figure 19.9 : Cest install

Et voil cest fait.

Sous Linux
Il vous suffit de copier le fichier dans un espace temporaire (ex. : /tmp) et de le dcompresser. Vous aurez certainement besoin dtre connect en tant quadministrateur (root) afin de pouvoir crer larborescence de Zend Optimizer (typiquement sous /usr/local).
# gunzip ZendOptimizer-2.1.0b-Linux_glibc21-i386.tar.gz # tar xvf ZendOptimizer-2.1.0b-Linux_glibc21-i386.tar # cd ZendOptimizer-2.1.0b-Linux_glibc21-i386

1351

Chapitre 19

Loptimisation des temps de rponse

Il suffit maintenant de lancer le script dinstallation :


# ./install.sh

et de rpondre correctement aux questions...


Figure 19.10 : Fentre daccueil

19. Loptimisation des temps de rponse

...aprs avoir dit bonjour. Vous laurez compris, vous navez qu taper [Entre]. Vous tes ensuite invits lire et accepter (ou non) la licence.
Figure 19.11 : Chemin dinstallation

Indiquez ensuite le nom du rpertoire dans lequel vous souhaitez installer Zend Optimizer. Par dfaut, le script vous propose "/usr/local/Zend". Nhsitez pas le changer pour "/usr/local/ Zend_Optimizer_2.1.0". Cest fait ? Tapez sur [Entre].
Figure 19.12 :

Chemin du fichier php.ini

Vous tes maintenant invit indiquer le chemin du rpertoire contenant votre fichier php.ini. Par dfaut, il sagit du rpertoire "/usr/local/lib". Cest bon ? Passons la suite en tapant [Entre].
Figure 19.13 : Slection du serveur web

Quelque peu indiscret, Zend Optimizer vous demandera si vous utilisez un serveur Apache ou non. Nous vous laissons rpondre en votre me et conscience. Toutefois, lhistoire ne dit pas ce quil se passe si lon rpond "No". Si vous avez la mme configuration que nous (ce qui est assez probable) vous aurez laiss la surbrillance sur "Yes" et tap [Entre].

1352

Avec Zend Optimizer

Figure 19.14 : Chemin du serveur web

Une rponse appelant une question, vous devez prsent indiquer le chemin du rpertoire bin/ dApache (peut-tre /usr/local/apache/bin). Ne faiblissons pas... et effectuons une nouvelle pression sur la touche [Entre].
Figure 19.15 : Dplacement de php.ini

19. Loptimisation des temps de rponse

Cette fois, cest pour nous signaler que le fichier php.ini a t dplac de son ancienne position (hum ! oui, dans notre cas, il tait sous /usr/local/Zend/etc/ mais, habituellement, il se trouve sous /usr/local/lib) vers la nouvelle position /usr/local/Zend_Optimizer_2.1.0/etc/, et un lien symbolique a t cr de lancienne vers la nouvelle. Une fois que vous avez pris connaissance de cette information, vous pouvez taper [Entre].
Figure 19.16 : Fentre de fin

Et voil... cest prt. Cest quasiment le dernier appui sur la touche [Entre].
Figure 19.17 : Redmarrage dApache

Vous tes maintenant invit relancer le serveur Apache puis une page vous confirme le succs (ou non) de lopration.

Vrication
Une fois lopration dinstallation effectue, vous pouvez vrifier quelle sest bien droule en appelant un script contenant simplement la ligne <?php phpinfo(); ?>. Vous devrez alors apercevoir le texte suivant :

Figure 19.18 : phpinfo()

1353

Chapitre 19

Loptimisation des temps de rponse

Lindication "with Zend Optimizer" confirme le succs de lopration dinstallation. Vous constaterez galement la prsence de six nouvelles lignes dans votre fichier php.ini.
[Zend] zend_optimizer.optimization_level=15 zend_extension=<chemin vers Zend Optimizeur>/lib/ZendOptimizer.so zend_extension_manager.optimizer=<chemin> zend_extension_manager.optimizer_ts=<chemin> zend_extension_ts=<chemin>

19. Loptimisation des temps de rponse

Si vous souhaitez dsactiver loptimisateur Zend, il vous suffira de mettre ces quelques lignes en commentaire (en les faisant prcder dun point-virgule).

Mesures
Page quasi-statique
Figure 19.19 : Temps de rponse dune page quasi-statique avec Zend Optimizer

Tableau 19.4 : Temps de rponse avec Zend Optimizer dune page quasi-statique
Nombre de requtes simultanes 1 3 5 7 10 50 100 Temps total dexcution (en secondes) 8.32 5.46 5.41 5.42 5.42 5.47 5.52 Temps total dexcution minimum (en secondes) 6.34 5.29 5.20 5.18 5.17 5.19 5.27 Temps total dexcution maximum (en secondes) 15.71 5.59 5.50 5.55 5.52 5.85 5.94 Nombre de requtes en chec 0 0 0 0 0 0 0

1354

Avec Zend Optimizer

Comme en labsence de solution doptimisation, les rsultats sont quasiment indpendants de la charge (tout juste 2 % de plus que le minimum avec 100 requtes simultanes). Les rsultats obtenus ont peu vari dun test lautre. Mais, malheureusement, le rsultat obtenu nest absolument pas celui attendu. En effet, les temps de rponse ont t augments de 12 % par rapport une solution sans cache. "Cest quoi cette histoire?" nous direz-vous. En fait, il suffit de se rappeler le principe de fonctionnement de Zend Optimizer pour bien comprendre : comme cela a t indiqu, Zend Optimizer retravaille le code gnr pour loptimiser et faire quil sexcute plus vite. Or, dans notre script de test, il y a relativement peu de code et probablement peu de solutions doptimisation. En consquence, Zend Optimizer perd du temps chercher optimiser un code qui, semble-t-il, ne peut pas ltre. Do des temps de rponses plus importants.

19. Loptimisation des temps de rponse

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1 et Zend Optimizer 1.3.1) donnaient des rsultats moins bons: de lordre de 6,6 secondes contre 5,4 ici: Le gain obtenu en un an est donc de 22%.

Page dynamique
Figure 19.20 : Temps de rponse dune page dynamique avec Zend Optimizer

Tableau 19.5 : Temps de rponse avec Zend Optimizer dune page dynamique
Nombre de requtes simultanes 1 3 5 7 10 Temps total dexcution (en secondes) 77.18 75.07 76.15 76.71 77.66 Temps total dexcution minimum (en secondes) 75.78 73.88 74.58 74.75 76.03 Temps total dexcution maximum (en secondes) 79.00 76.49 77.53 77.64 78.63 Nombre de requtes en chec 0 0 0 0 0

1355

Chapitre 19

Loptimisation des temps de rponse

Nombre de requtes simultanes 50 100

Temps total dexcution (en secondes) 83.73 85.84

Temps total dexcution minimum (en secondes) 83.23 82.48

Temps total dexcution maximum (en secondes) 84.83 88.62

Nombre de requtes en chec 0 Moyenne 14.35 Minimum 7 Maximum 69

19. Loptimisation des temps de rponse

Les temps de rponse sont, cette fois, dpendants de la charge (comme ce pouvait tre le cas sans optimisateur). Ceci est plus particulirement sensible au-del de 10 requtes par secondes. Finalement, nous avons des requtes en erreur lorsque 100 requtes sont envoyes simultanment (dans ce cas, le temps total dexcution nest plus significatif). Les rsultats obtenus restent lgrement suprieurs ceux obtenus en labsence doptimisation. Nous pouvons donc supposer que, dans ce cas, le gain en temps dexcution que procure le passage de loptimisateur Zend est totalement absorb par le temps supplmentaire ncessit pour cette opration. Les rsultats obtenus sont relativement stables dun test lautre.

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1 et Zend Optimizer 1.3.1) donnaient des rsultats moins bons: de lordre de 91 secondes contre 77 ici: Le gain obtenu en un an est donc de 18%.

Page mathmatique
Figure 19.21 :

Temps de rponse dune page mathmatique avec Zend Optimizer

1356

Avec Zend Optimizer

Tableau 19.6 : Temps de rponse avec Zend Optimizer dune page mathmatique
Nombre de requtes simultanes 1 3 5 7 10 50 100 Temps total dexcution (en secondes) 35.78 29.83 30.00 29.93 29.70 30.88 31.12 Temps total dexcution minimum (en secondes) 32.15 29.58 29.05 29.30 29.14 29.84 29.87 Temps total dexcution maximum (en secondes) 40.33 30.11 31.08 30.48 30.16 32.10 32.30 Nombre de requtes en chec 0 0 0 0

19. Loptimisation des temps de rponse

0 0 0

L encore, le temps de rponse dpend de la charge. Mais, pour autant, le temps dexcution subit peu limpact de la charge (au pire + 5 %) et, surtout, aucune requte nest rejete, mme pour 100 requtes simultanes. En revanche, pour une fois, le temps moyen dexcution est nettement infrieur ceux obtenus sans optimisation, puisque le gain est de 36 %. Ceci tend prouver queffectivement Zend Optimizer joue un rle doptimisateur (ce dont il tait possible de douter tant donn les premiers rsultats). Ce script de test incluant de nombreuses boucles et oprations, le temps pass optimiser le code a donc t utile et a largement contribu en acclrer lexcution. Cependant, les valeurs sont restes relativement stables dune srie de test lautre.

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1 et Zend Optimizer 1.3.1) donnaient des rsultats moins bons: de lordre de 36 secondes contre 30 ici: Le gain obtenu en un an est donc de 20%.

Conclusion
Si lon considre que les rsultats obtenus dans cette configuration de test sont reprsentatifs, alors nous pouvons conclure que lutilisation de Zend Optimizer ne se justifie pas (bien au contraire), except pour des sites trs particuliers sollicitant excessivement le langage PHP.

1357

Chapitre 19

Loptimisation des temps de rponse

19.5. Avec Alternative PHP Cache (APC)


Description
La solution retenue par APC consiste mettre en cache (conserver en mmoire) le rsultat de la compilation (afin de ne pas avoir renouveler les oprations danalyse et de compilation des scripts chaque fois que ceux-ci sont appels). APC est dsormais disponible gratuitement sur le site (anglais) http://pecl.php.net/apc. La dernire version disponible est la 2.0.4 qui supporte officiellement les versions de PHP 4.2.2, 4.2.3, 4.3.0 et 4.3.2. Elle a t conue pour compiler sous Linux, FreeBSD, OpenBSD et MacOS 10.2

19. Loptimisation des temps de rponse

Les tests ont t raliss avec une version de dveloppement disponible fin juillet 2003 (supportant officiellement PHP 4.2.2, 4.2.3 et 4.3.0) qui nest plus propos en tlchargement mais dont vous trouverez un exemplaire sur le CD-ROM fourni.

Installation
Sous Linux
Aprs avoir copi larchive (celle disponible sur le CDROM est baptise apc-cvs_030731.tar.gz) dans un rpertoire quelconque (disons /usr/local/src), vous devez la dcompresser :
# gunzip apc-cvs.tar.gz # tar xvf apc-cvs.tar

Puis vous devez la compiler :


# cd apc-cvs # /usr/local/bin/phpize # ./configure --with-php-config=/usr/local/bin/php-config

Prendre le bon chemin Nous supposons ici, que PHP a t install sous /usr/local/ et que par consquent, les commandes phpize et php-config se trouvent sous le rpertoire /usr/local/bin.
# make # make install

Cette dernire instruction affiche le rpertoire dans lequel vient dtre install le fichier apc.so. Modifiez votre fichier php.ini afin dajouter les lignes suivantes :
[APC] zend_extension = <chemin affich par make install>/apc.so

Il existe de nombreuses options mais, comme leur nom lindique, elles sont facultatives. Nous ne les prsenterons donc pas ici. Pour dsactiver le cache APC, vous pouvez mettre en commentaire ces lignes en les faisant prcder dun point-virgule.

1358

Avec Alternative PHP Cache (APC)

Vrication
Une fois lopration dinstallation effectue, vous pouvez vrifier quelle sest bien droule en appelant un script contenant simplement la ligne <?php phpinfo(); ?>. Vous devrez alors apercevoir le texte suivant :

Figure 19.22 : phpinfo()

Lindication "with APC Caching" confirme le succs de lopration dinstallation.

19. Loptimisation des temps de rponse

Mesures
Page quasi-statique
Figure 19.23 :

Temps de rponse dune page quasi-statique avec APC

Tableau 19.7 : Temps de rponse avec APC dune page quasi-statique


Nombre de requtes simultanes 1 Temps total dexcution (en secondes) 7.20 Temps total dexcution minimum (en secondes) 2.60 Temps total dexcution maximum (en secondes) 26.80 Nombre de requtes en chec Moyenne 49,9 Minimum 0 Maximum 499 0 0 0 0 0 0

3 5 7 10 50 100

2.21 2.19 2.16 2.13 2.11 2.13

2.10 2.06 2.05 2.05 2.03 2.09

2.39 2.54 2.32 2.21 2.22 2.23

1359

Chapitre 19

Loptimisation des temps de rponse

La premire grosse surprise la lecture de ces rsultats (et aprs une rapide analyse) cest de constater que systmatiquement la premire srie de test est tombe en erreur. Et nous navons malheureusement trouv aucune justification ce phnomne. Nous mettrons donc cela sur le fait quil sagit dune version en cours de dveloppement. Si lon fait abstraction de ce problme, nous pouvons constater que les temps de rponse sont extrmement bons. Le gain est ici de 56 % par rapport la version sans optimisation. APC dmontre ici lintrt de mettre en cache le rsultat de la compilation.

19. Loptimisation des temps de rponse

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1 et APC de juin 2002) donnaient des rsultats moins bons: de lordre de 5.1 secondes contre 2.1 ici: Le gain obtenu en un an est donc de 59%.

Page dynamique
Figure 19.24 : Temps de rponse dune page dynamique avec APC

Tableau 19.8 : Temps de rponse avec APC dune page dynamique


Nombre de requtes simultanes 1 3 5 7 10 50 100 Temps total dexcution (en secondes) 23.75 19.26 19.31 19.67 20.00 21.32 22.13 Temps total dexcution minimum (en secondes) 20.28 18.00 18.25 18.51 18.90 20.09 21.13 Temps total dexcution maximum (en secondes) 31.30 20.07 20.35 20.59 20.75 22.02 23.50 Nombre de requtes en chec 0 0 0 0 0 0 0

1360

Avec Alternative PHP Cache (APC)

Le schma est premire vue identique aux rsultats obtenus prcdemment pour lexemple dynamique. Les temps de rponse se trouvent augments au fur et mesure que la charge crot, par contre, chose importante, le serveur ne se trouve pas satur et peux rpondre toutes les requtes. L, encore, APC prouve son efficacit en rduisant le temps de rponse par rapport une solution non optimise, avec un gain de 73 % (excusez du peu).

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1 et APC de juin 2002) donnaient des rsultats moins bons: de lordre de 91 secondes contre 20 ici: Le gain obtenu en un an est donc de 78%.

19. Loptimisation des temps de rponse

Page mathmatique
Figure 19.25 :

Temps de rponse dune page mathmatique avec APC

Tableau 19.9 : Temps de rponse avec APC dune page mathmatique


Nombre de requtes simultanes 1 3 5 7 10 50 100 Temps total dexcution (en secondes) 50.23 49.63 48.35 46.69 46.39 47.43 47.47 Temps total dexcution minimum (en secondes) 47.98 47.62 47.08 45.50 45.31 46.41 45.56 Temps total dexcution maximum (en secondes) 55.43 52.40 50.45 48.30 48.62 48.41 50.73 Nombre de requtes en chec 0 0 0 0 0 0 0

1361

Chapitre 19

Loptimisation des temps de rponse

Apparemment, il nest pas facile de gagner sur tous les tableaux. Alors que sur les deux tests prcdents APC offre un gain en performance qui est loin dtre ngligeable, au cours de ce test, les temps de rponse sont sensiblement identiques ceux obtenus sans optimisation (et donc bien loin des rsultats obtenus avec Zend Optimizer). Il est possible desquisser une explication cela. APC a beau stocker en mmoire le rsultat de la compilation, il nen reste pas moins quil faut excuter ce code. Alors que Zend Optimizer rduit le temps dexcution et offre un gain intressant sur ce genre de script, il nen est rien pour APC qui excute le code obtenu par une compilation standard.

19. Loptimisation des temps de rponse

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1 et APC de juin 2002) donnaient de meilleurs rsultats: de lordre de 36 secondes contre 47 ici: Soit une perte de 30% en un an.

Conclusion
Mme sil est vrai quAPC napporte rien en ce qui concerne le script mathmatique (considr comme non reprsentatif dun site web), le gain obtenu dans les autres cas est loin dtre ngligeable et justifie pleinement lutilisation dun systme de mise en cache du code compil. Nous avons galement pu constater que globalement de gros progrs ont t raliss depuis la prcdente dition de ce livre. Ce qui fait dAPC une solution trs prometteuse.

19.6. Avec PHP Accelerator (PHPA)


Description
Tout comme APC, PHP Accelerator garde en mmoire le rsultat de la compilation. Cest donc galement une solution de cache, mais pas uniquement, puisque PHPA intgre aussi un optimisateur de code (comme peut le faire Zend Optimizer). Ce dernier aspect de PHPA est cependant considr par leurs auteurs comme tant au premier stade du dveloppement (sous-entendu : il pourrait tre amlior). PHPA, de la socit ionCube, est disponible gratuitement ladresse http://php-accelerator.co.uk (en anglais). Pour la version 4.3.0 de PHP, vous le trouverez pour les systmes dexploitation suivants : FreeBSD, Linux (glibc2 et glibc2.2.5), OpenBSD, Solaris. La version teste ici est la 1.3.3r2 pour PHP4.3.0 sous linux. Elle reste ce jour la dernire version disponible.

1362

Avec PHP Accelerator (PHPA)

Installation
Sous Linux
Aprs avoir copi le fichier dans un rpertoire donn (ex. : /tmp), il suffit tout simplement de dcompresser larchive.
# gunzip php_accelerator-1.3.3r2_php-4.3.0_linux_i686-glibc2.1.3.tgz # tar xvf php_accelerator-1.3.3r2_php-4.3.0_linux_i686-glibc2.1.3.tar

Il faut ensuite copier le module dans le rpertoire des extensions PHP :

19. Loptimisation des temps de rponse

# cp php_accelerator-1.3.3r2_php-4.3.0_linux_i686-glibc2.1.3/php_accelerator-1.3 .3r2.so /usr/local/lib/php/extensions/php_accelerator_1.3.3r2.so

puis ajouter quelques lignes au fichier php.ini.


[PHPA] zend_extension=/usr/local/lib/php/extensions/php_accelerator_1.3.3r2.so

Vrication
Une fois lopration dinstallation effectue, vous pouvez vrifier quelle sest bien droule en appelant un script contenant simplement la ligne <?php phpinfo(); ?>. Vous devriez alors apercevoir le texte suivant :
Figure 19.26 :

phpinfo()

Lindication "with PHP Accelerator" confirme le succs de lopration dinstallation.

Mesures
Page quasi-statique
Figure 19.27 :

Temps de rponse dune page quasi-statique avec PHPA

1363

Chapitre 19

Loptimisation des temps de rponse

Tableau 19.10 : Temps de rponse avec PHPA dune page quasi-statique


Nombre de requtes simultanes 1 3 5 7 Temps total dexcution (en secondes) 20.38 3.82 3.74 3.72 3.68 3.73 3.75 Temps total dexcution minimum (en secondes) 4.92 3.66 3.58 3.59 3.59 3.59 3.64 Temps total dexcution maximum (en secondes) 46.85 3.99 3.93 3.85 3.81 3.90 3.89 Nombre de requtes en chec 0 0 0 0 0 0 0

19. Loptimisation des temps de rponse

10 50 100

Les valeurs obtenues lorsque les appels se font les uns aprs les autres sont excessivement chaotiques, ce qui nest pas sans rappeler le phnomne observ avec APC, si ce nest quici, les requtes ne tombent pas en erreur. Pour le reste, les rsultats sont trs bons (gain de 24%) mais pas tout fait la hauteur de ceux offerts par APC. La diffrence mesure entre ces deux solutions tant tout de mme de 40%.

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1 et APC 1.3.1pre3) donnaient de moins bons rsultats: de lordre de 4.8 secondes contre 3.7 ici: Soit un gain de 23% dune anne lautre.

Page dynamique
Figure 19.28 : Temps de rponse dune page dynamique avec PHPA

1364

Avec PHP Accelerator (PHPA)

Tableau 19.11 : Temps de rponse avec PHPA dune page dynamique


Nombre de requtes simultanes 1 3 5 7 10 50 100 Temps total dexcution (en secondes) 32.02 19.60 19.81 20.05 20.42 21.88 22.80 Temps total dexcution minimum (en secondes) 21.12 18.54 18.88 19.10 19.74 20.97 21.45 Temps total dexcution maximum (en secondes) 57.02 20.53 20.32 20.62 20.90 23.33 23.82 Nombre de requtes en chec 0 0 0 0

19. Loptimisation des temps de rponse

0 0 0

PHPA offre cette fois ci des rsultats comparables ceux obtenus avec APC. Et dans ce cas aussi, le nombre de requtes en chec pour 100 requtes simultanes est nul.

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1 et APC 1.3.1pre3) donnaient de moins bons rsultats: de lordre de 42 secondes contre 20 ici: Soit un gain de 52% dune anne lautre.

Page mathmatique
Figure 19.29 :

Temps de rponse dune page mathmatique avec PHPA

1365

Chapitre 19

Loptimisation des temps de rponse

Tableau 19.12 : Temps de rponse avec PHPA dune page mathmatique


Nombre de requtes simultanes 1 3 5 7 Temps total dexcution (en secondes) 43.47 40.56 40.67 40.80 40.90 42.52 43.43 Temps total dexcution minimum (en secondes) 41.05 40.20 40.24 40.45 40.56 41.86 41.50 Temps total dexcution maximum (en secondes) 53.81 41.33 41.14 41.17 41.45 43.20 47.30 Nombre de requtes en chec 0 0 0 0 0 0 0

19. Loptimisation des temps de rponse

10 50 100

Sur ce test, PHPA amliore lgrement les performances obtenues avec APC sans toutefois atteindre le niveau de Zend Optimisateur. Le gain est ici de prs de 14 % par rapport une solution non optimise.

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1 et APC 1.3.1pre3) donnaient des rsultats sensiblement identiques: de lordre de 39.8 secondes contre 40.7 ici:

Conclusion
Tout comme APC, PHPA est une solution doptimisation gratuite et performante. Elle allie optimisation du code compil et mise en cache du code avec une certaine efficacit, mme si lon sent que loptimisation du code pourrait tre amliore (comme le dmontre Zend Optimizer).

19.7. Avec Zend Accelerator (Zend Performance Suite)


Description
Zend Accelerator est une solution destine aux professionnels (donc payante), qui est base sur le mme principe que PHPA. Elle est la combinaison dun optimisateur de code (Zend Optimisateur) et dun cache (la spcificit de Zend Accelerator). Elle est disponible pour les systmes dexploitation :
j j j

Linux glibc2.1 ; FreeBSD 4.3 ; Solaris Sparc.

1366

Avec Zend Accelerator (Zend Performance Suite)

Nous avons ici test la version dvaluation de Zend Accelerator 3.5.0 pour Linux, disponible sur le site (anglais) http://www.zend.com. La dernire version disponible est la 4.0, cest officiellement la seule des solutions prsentes ici, supporter PHP 5.0 (et toutes les versions de PHP partir de PHP 4.1.2)

Installation
Son installation est trs simple.

Sous Linux
Il vous suffit de copier larchive dans un espace temporaire (ex. : /tmp) et de la dcompresser. Vous aurez certainement besoin dtre connect en tant quadministrateur (root) afin de pouvoir crer larborescence de Zend Accelerator (typiquement sous /usr/local).
# gunzip ZendPerformanceSuite-3.5.0-Linux_glibc21-i386.tar.gz # tar xvf ZendPerformanceSuite-3.5.0-Linux_glibc21-i386.tar

19. Loptimisation des temps de rponse

Il vous suffit ensuite de lancer le script dinstallation :


# cd ZendPerformanceSuite-3.5.0-Linux_glibc21-i386 # ./install.sh

et de rpondre aux questions...


Figure 19.30 :

Fentre daccueil

... aprs avoir dit "bonjour". Vous pouvez taper [Entre] pour passer aux choses srieuses.
Figure 19.31 :

Licence

1367

Chapitre 19

Loptimisation des temps de rponse

Acceptez vous les termes de la licence? Nous vous laissons rpondre en votre me et conscience. Nous, nous avons opt pour loption "Yes".
Figure 19.32 :

Cl dactivation

19. Loptimisation des temps de rponse

Si le script dinstallation ne trouve pas de cl dactivation, celui-ci vous propose dindiquer o le fichier peut se trouver (il sagit dun fichier zend_accelerator.dat, habituellement sous le rpertoire data). Vous pouvez galement la tlcharger (cest ce que nous avons fait pour obtenir une licence dvaluation).

Intranet La licence doit tre tlcharge depuis le poste o doit tre install Zend Accelerator. Il nest, par exemple, pas possible de lancer le script dinstallation depuis un poste reli Internet pour utiliser la cl dactivation sur un poste en Intranet. Si votre poste nest pas reli Internet, slectionnez tout de mme loption "download a license file from www.zend.com". Un message derreur vous indiquera alors comment vous y prendre pour rcuprer manuellement un fichier de licence.
Figure 19.33 : Compte Zend

Il vous est ensuite demand si vous possdez un compte Zend. A priori la rponse est "oui" puisque pour pouvoir tlcharger Zend Accelerator, vous avez d ouvrir (gratuitement) un compte sur le site. Tapez donc [Entre].
Figure 19.34 :

Saisie de lidentifiant

Vous devez alors, ici, saisir lidentifiant de votre compte.

1368

Avec Zend Accelerator (Zend Performance Suite)

Figure 19.35 : Saisie du mot de passe

Saisissez ensuite le mot de passe.


Figure 19.36 : Type de la licence

19. Loptimisation des temps de rponse

Il vous est ensuite demand quel est le type de la licence. Dans notre cas, il sagit dune licence dvaluation.
Figure 19.37 : Tlchargement

Et voil... le fichier de licence est tlcharg. Tapez sur la touche [Entre].


Figure 19.38 :

Chemin dinstallation

Vous tes alors invit saisir le chemin du rpertoire o vous souhaitez installer Zend Accelerator. Nous vous suggrons /usr/local/Zend_Performance_Suite-3.5.0 (mme si, par dfaut, le script vous proposera /usr/local/Zend).
Figure 19.39 : Chemin du rpertoire du fichier de configuration du serveur

1369

Chapitre 19

Loptimisation des temps de rponse

Puisquil veut vraiment tout savoir, il vous faut maintenant donner le chemin du rpertoire hbergeant le fichier de configuration dApache (probablement /usr/local/apache/conf). Cest bon ? Allez zou !... [Entre].
Figure 19.40 : Rpertoire racine du serveur

19. Loptimisation des temps de rponse

Pas avare de questions, le script vous demande maintenant de prciser quel est le chemin du rpertoire constituant la racine de votre serveur web (probablement /usr/local/apache/htdocs). Ceci va lui servir pour installer les scripts dadministration de Zend Accelerator (on ne se refuse rien).
Figure 19.41 :

php.ini

Il est temps dsormais de prciser le chemin du rpertoire hbergeant le fichier php.ini (gnralement /usr/local/lib). Une nouvelle pression sur [Entre] et nous devrions tre bientt dbarrasss.
Figure 19.42 :

Mot de passe de loutil dadministration

Le script vous demande alors de saisir un mot de passe qui servira protger laccs la page dadministration de Zend Accelerator.
Figure 19.43 : Confirmation du mot de passe

Comme cest lusage, vous tes invit confirmer votre mot de passe (pour sassurer quaucune erreur de saisie nest intervenue).

1370

Avec Zend Accelerator (Zend Performance Suite)

Figure 19.44 : Confirmation de lutilisateur Apache

Puis, il vous faudra confirmer le nom dutilisateur sous lequel tourne le serveur Apache.
Figure 19.45 : Espace cache

19. Loptimisation des temps de rponse

Vous devrez galement spcifier un espace de stockage temporaire des fichiers de cache.
Figure 19.46 :

Crontab

Il vous est galement demand daccepter dajouter une entre dans la crontab afin de pouvoir effectuer un nettoyage rgulier du contenu obsolte du cache.
Figure 19.47 : Confirmation crontab

Pour ne rien vous cacher, Zend Accelerator prcise la ligne qui sera ajoute la crontab avant de vous demander confirmation.

Figure 19.48 : Lien symbolique

Il semblerait que nous en ayons fini avec les questions. Le script dinstallation vous indique alors que votre fichier php.ini a t dplac de son ancienne position (ici /usr/local/Zend/etc/

1371

Chapitre 19

Loptimisation des temps de rponse

mais, habituellement, /usr/local/lib) vers sa nouvelle : /usr/local/Zend_Accelerator_2.0.2/etc. Un lien symbolique est alors cr de lancienne position vers la nouvelle. Cest not ? [Entre].
Figure 19.49 :

Fentre de fin

Voil, cest fini... ou presque.

19. Loptimisation des temps de rponse

Figure 19.50 :

Relance du serveur

Il est temps de relancer le serveur web afin de prendre en compte les changements.
Figure 19.51 : Fentre de fin

...mais pour cela, Zend Optimizer doit connatre lemplacement du rpertoire bin/ dApache.
Figure 19.52 : Fentre de fin

Cette cest bon.

Vrication
Une fois lopration dinstallation effectue, vous pouvez vrifier quelle sest bien droule en appelant un script contenant simplement la ligne <?php phpinfo(); ?>. Vous devriez alors apercevoir le texte suivant :
Figure 19.53 :

phpinfo()

Lindication "with Zend Accelerator" (ajoute "with Zend Optimizer") confirme le succs de lopration dinstallation.

1372

Avec Zend Accelerator (Zend Performance Suite)

Vous constaterez galement la prsence de nombreuses nouvelles lignes dans votre fichier php.ini.
[Zend] zend_gui_password=<le mot de passe crypt de linterface dadministration> zend_accelerator.use_blacklist_filename=<chemin vers Zend Accelerator>/etc/user_blacklist.ZendAccelerator.txt zend_accelerator.validate_timestamps=1 zend_accelerator.use_cwd=1 zend_extension=<chemin vers Zend Accelerator>/lib/ZendExtensionManager.so ...etc...

19. Loptimisation des temps de rponse

Si vous souhaitez dsactiver loptimisateur Zend, il vous suffira de mettre ces lignes en commentaire (en les faisant prcder dun point-virgule).

Mesures
Page quasi-statique
Figure 19.54 : Temps de rponse dune page quasi-statique avec Zend Accelerator

Tableau 19.13 : Temps de rponse avec Zend Accelerator dune page quasi-statique
Nombre de requtes simultanes 1 3 5 7 10 50 100 Temps total dexcution (en secondes) 6.96 3.47 3.37 3.35 3.34 3.36 3.38 Temps total dexcution minimum (en secondes) 4.39 3.33 3.24 3.23 3.24 3.28 3.31 Temps total dexcution maximum (en secondes) 13.42 3.70 3.46 3.47 3.45 3.46 3.49 Nombre de requtes en chec 0 0 0 0 0 0 0

1373

Chapitre 19

Loptimisation des temps de rponse

Les valeurs obtenues sont du niveau de ceux de PHPA (gain de 31%) mais natteignent pas ceux dAPC. En revanche les appels qui se font les uns aprs les autres offrent des temps de rponse relativement stable (en tout cas plus quavec PHPA ou APC).

Comparatif avec les tests des ditions prcdentes Lors du test prcdent (bas sur PHP 4.2.1 et Zend Accelerator 2.0.2), tonnamment celui-ci ne fonctionnait pas.

Page dynamique
19. Loptimisation des temps de rponse
Figure 19.55 : Temps de rponse dune page dynamique avec Zend Accelerator

Tableau 19.14 : Temps de rponse avec Zend Accelerator dune page dynamique
Nombre de requtes simultanes 1 3 5 7 10 50 100 Temps total dexcution (en secondes) 25.34 21.22 21.50 21.79 22.04 23.72 24.66 Temps total dexcution minimum (en secondes) 22.44 19.64 20.00 20.10 22.38 21.93 23.11 Temps total dexcution maximum (en secondes) 35.00 22.05 22.51 22.98 22.99 25.01 26.06 Nombre de requtes en chec 0 0 0 0 0 0 0

Zend Accelerator offre une optimisation tout fait intressante (gain de 70%) mais toutefois lgrement moindre que celle de ses concurrents gratuits. Encore une fois, le gain en performance a mis un terme aux checs constat lorsque le nombre de requtes concurrentes atteint 100.

1374

Avec Zend Accelerator (Zend Performance Suite)

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1 et Zend Accelerator 2.0.2) donnaient de moins bons rsultats: de lordre de 28 secondes contre 21.5 ici: Soit un gain de 23% dune anne lautre.

Page mathmatique
Figure 19.56 : Temps de rponse dune page mathmatique avec Zend Accelerator

19. Loptimisation des temps de rponse

Tableau 19.15 : Temps de rponse avec Zend Accelerator dune page mathmatique
Nombre de requtes simultanes 1 3 5 7 10 50 100 Temps total dexcution (en secondes) 23.26 20.92 20.88 20.92 21.06 21.49 21.33 Temps total dexcution minimum (en secondes) 21.59 20.61 20.39 20.56 20.58 20.87 20.91 Temps total dexcution maximum (en secondes) 28.27 21.25 21.07 21.20 21.36 22.24 22.24 Nombre de requtes en chec 0 0 0 0 0 0 0

Les rsultats obtenus ici sont galement poustouflants, bien meilleurs que ceux de PHPA ou mme que ceux de Zend Optimizer. Le gain est ici de 55 % par rapport une solution sans optimisation. Malheureusement, rappelons-le, ce test nest pas le plus reprsentative dune page dun site web.

1375

Chapitre 19

Loptimisation des temps de rponse

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1 et Zend Accelerator 2.0.2) donnaient de moins bons rsultats: de lordre de 25 secondes contre 21 ici: Soit un gain de 16% dune anne lautre.

Conclusion
19. Loptimisation des temps de rponse
Zend Accelerator ne semble prendre lavantage sur les autres solutions testes que dans le cas du test intgrant des boucles sur des oprations mathmatiques. Ce qui semble bien maigre sachant que cette solution est payante et non les autres. Reste toutefois complter ces tests afin de mieux valuer la stabilit de ces produits et limpact dun choix dune autre machine et dun autre environnement.

19.8. Conclusion sur les solutions "bas niveau" (modules PHP)


Avant de tirer une conclusion, il convient de rappeler que les tests effectus ici nont quune reprsentativit limite. Les rsultats peuvent en effet considrablement changer dune configuration lautre. Vous nobtiendrez certainement pas les mmes rsultats sur une machine disposant dun processeur plus efficace, dune plus grande quantit de mmoire ou dun disque dur plus rapide. Mais cela dpend aussi beaucoup de larchitecture de votre systme (il nest pas vraiment conseill de faire tourner la base de donnes sur la mme machine que le serveur web) et, plus encore, du type de script utilis (comme le dmontre ces quelques tests). Les tests nont port que sur trois scripts ; les caches navaient donc grer, au plus, que trois fichiers. Nous tions donc bien loin du cas de figure dun vritable site hbergeant peut-tre des centaines de scripts. Bref, tout cela peut faire que vous puissiez tre amen constater des diffrences de performance moins grandes (ou plus grandes) dune solution doptimisation lautre, voire mme que la hirarchie sen trouve change. De plus, ces tests ont tous t raliss avec la configuration par dfaut. Il est possible (et mme probable) que certaines des solutions testes auraient pu donner des rsultats plus probants sils avaient t configurs pour rpondre au mieux aux besoins des scripts. Quoi quil en soit, la premire des constatations que lon peut faire, et ce nest pas la moindre, cest que ces tests confirment quil est possible damliorer grandement les performances dun serveur web quip de PHP. La meilleure solution consistant optimiser le code gnr et le stocker en mmoire cache. Enfin, il semblerait quil ne soit pas (sauf cas particulier) ncessaire de vider son porte monnaie pour obtenir des rsultats optimum, sachant que PHP Accelerator et APC font plus que rivaliser avec Zend Accelerator. A ce jour, notre prfrence se portera sur PHP Accelerator sachant que le version de production dAPC (pour les versions rcentes de PHP) nest pas encore sortie et que la version de dveloppement en court semble contenir quelques imperfections mais cela pourrait changer tout moment.

1376

Les solutions "haut niveau" (programmation PHP)

A contrario, Zend Optimizer ne semble pas recommander, sauf si votre site est un peu particulier. Cette remarque nest galement pas valable si vous optez pour lobfuscation de code (prsente dans le chapitre suivant).

Cache et mise jour Il y a au moins un point qui na pas t abord, mais quil faut garder lesprit. Comme toujours avec les solutions de mise en cache, la difficult consiste dterminer la limite de validit du cache, autrement dit rpondre la question "est-ce que le document source a t modifi depuis que je lai mis en cache ?". Afin de rpondre cette question, la plupart des solutions (toutes ?) contrlent tout simplement la date de dernire modification du fichier. Vous naurez donc pas arrter puis redmarrer le serveur afin de prendre en compte les corrections apportes vos scripts (et encore moins aller effacer je ne sais quel fichier temporaire). Certaines des solutions doptimisation proposent toutefois de dsactiver ce contrle afin daugmenter encore le temps de rponse.
Mme si toutes les solutions doptimisation nont pas t testes ici, sachez quil existe trs peu de logiciels de ce type pour Windows. Si malgr tout vous avez opt pour ce systme dexploitation, alors peut tre devrez vous essayer Turck MM Cache disponible ladresse http://www.turcksoft.com.

19. Loptimisation des temps de rponse

19.9. Les solutions "haut niveau" (programmation PHP)


Comme nous lavons vu dans le chapitre Optimisation des temps de rponse intgr au chapitre Les en-ttes HTTP, il est trs ais dutiliser un systme de cache de "haut niveau" consistant stocker dans un fichier le rsultat de linterprtation PHP. En effet, ce fichier peut tre rappel chaque nouvelle requte et/ou recr lorsque sa dure de vie a expir. La principale difficult avec ce genre de script est de dterminer la dure de vie que lon doit donner au fichier de cache. Mais, comme il ny a aucune rgle pour fixer ce seuil, nous vous laissons vous en remettre votre bon sens. Une autre difficult peut consister dterminer les scripts qui doivent en profiter. Pour un script qui ne dpend daucun paramtre (POST, GET, session ou cookie), ncessite un long traitement (ou une requte SQL un peu longue), et ne varie pas toutes les 10 mn (ou qui autorise un retard de mise jour de plus de 10 mn), il ny a quasiment pas de questions se poser : ce type doptimisation simpose. Si nous sommes dans les mmes conditions, mais que le script dpend dun certain nombre de paramtres, cette solution nest envisageable que si ces paramtres ne peuvent prendre quun nombre fini et rduit de valeurs. Il faudra, dans ce cas, crer un fichier de cache par ensemble de paramtres possibles. Dans tous les autres cas, nous considrons que cette solution ne doit pas tre envisage. Si lon considre les exemples qui nous ont servis comparer les solutions "bas niveau", il est vident quun cache "haut niveau" ne peut tre utilis avec lexemple dynamique, mais quen revanche, cela apporterait beaucoup lexemple mathmatique (le dlai dexpiration serait mme infini... Mais bon, dans ce cas, autant utiliser une page statique).

1377

Chapitre 19

Loptimisation des temps de rponse

En ce qui concerne lexemple quasi-statique, il est plus difficile de trancher. Il y a peu de code excuter, ce qui fait que les temps de rponse semblent bien courts. En pareil cas, lutilisation dun cache de haut niveau pourrait tre contre-productif. En effet, lorsque lon fait appel un script qui se suffit lui-mme, cela ne ncessite quun seul accs au disque, alors que, pour un script identique qui utilise un fichier de cache, il faut deux trois accs au disque (un pour charger le script, un autre pour charger le fichier de cache et il faut, de plus, vrifier la date de dernire modification du script). Multiplier ainsi les accs au disque par deux ou trois peut tre vraiment pnalisant, notamment vis--vis de la monte en charge. En fait, il savre que le script qui nous a servi pour lexemple fait une multitude dinclude, et chaque include ncessite un accs au disque. Ces accs sont donc bien plus nombreux que dans une solution faisant appel un fichier de cache.

19. Loptimisation des temps de rponse

Les performances sen ressentent, comme le montre le graphe suivant qui compare :
j j j

Lexemple prcdent quasi-statique ; Sa version lgrement modifie pour grer un fichier de cache dune dure de vie de 10 mn ; Une version statique de la page (sauvegarde au format HTML du rsultat retourn par le script PHP).
Figure 19.57 : Comparaison des versions statique, fichier de cache et quasi-statique

Alors que la version quasi-statique rpond aux 500 requtes en 4,8 secondes, la version avec un fichier cache rpond en 2,9 secondes et la version statique, elle, ne demande que 1,8 secondes.

Comparatif avec les tests des ditions prcdentes Les tests prcdents (bass sur PHP 4.2.1) donnaient de moins bons rsultats: de lordre de 5,7 secondes contre 4,8 et 3,4 contre 2, 9 ici: Soit un gain de 15% dune anne lautre.

19.10. Conclusion
Dun tout autre fonctionnement que les caches de bas niveau vus prcdemment, les caches de haut niveau peuvent eux aussi amliorer grandement les performances de votre site Internet, condition toutefois que la nature des scripts demands sy prte.

1378

Chapitre 20

Lobfuscation : Distribuer ses scripts sans dvoiler son code


20.1 20.2 20.3 20.4 20.5 20.6 Introduction . . . . . . . . . . Avec Zend Encoder . . . . . Avec ionCube PHP Encoder Avec PHP guardian . . . . . Avec POBS . . . . . . . . . . . Autres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1381 .1381 .1388 .1389 .1390 .1392

Avec Zend Encoder

20.1. Introduction
Si vous optez pour une licence GPL ou toute autre licence Open Source (ce que vous tes invit faire), la distribution de votre code ne vous causera aucun souci. Si, en revanche, vous ne souhaitez pas laisser partir votre savoir-faire dans la nature et que vous avez distribuer une application sous forme de scripts PHP, vous devrez trouver une solution pour que le code source ne soit pas lisible, et cela sans nuire son fonctionnement. La solution gnralement retenue sappelle lobfuscation (que lon traduit parfois aussi "assombrissement") de code. Cette opration consiste en plusieurs points, dont les principaux sont : 1. 2. Suppression de tous les commentaires (cest le moins que lon puisse faire) ; Masquage de tous les noms de variables et fonctions (un appel une fonction appele "a" ou "zedfrDS" sera bien plus difficile interprter quun appel une fonction appele connexionBaseDeDonnees()) ;

20. Lobfuscation : Distribuer ses scripts sans dvoiler son code

3.

Livraison du code sous sa forme compile (cest certainement la forme la plus difficilement interprtable pour nous autres, tres humains).

Il existe ce jour trs peu de solutions pour PHP. Il y a, par exemple, les solutions payantes comme Zend Encoder, la toute rcente ionCube PHP Encoder ou PHP guardian et une solution gratuite, POBS (PHP Obfuscator), chacune ayant ses propres caractristiques. Dautres solutions bases sur une autre technique existent. Ainsi Microcode et PHTML Encoder proposent des solutions consistant crypter/dcrypter les scripts PHP.

20.2. Avec Zend Encoder


Il est difficile de savoir ce que fait exactement Zend Encoder. Il nexiste en effet pas ( notre connaissance) de logiciel permettant de voir le source qui serait obtenu si lopration tait inverse. Mais lon peut affirmer sans trop de doutes que les commentaires sont supprims et le code livr sous sa forme compile. Il nest pas certain que les noms des fonctions et variables globales soient masqus, puisque les scripts ainsi obfusqus restent compatibles avec les scripts non obfusqus. Zend Encoder est dsormais intgr Zend Safe Guard qui propose galement un systme de gestion de licence baptis Zend License Manager. Une version dvaluation peut tre tlcharge sur le site (anglais) http://www.zend.com. Zend Encoder est disponible pour les systmes dexploitation :
j j j j

Windows (NT, 2000, XP) ; Linux glibc2.1 et 2.2 ; Solaris (2.6 et +) ; FreeBSD (3.4 et +).

Les scripts ainsi obfusqus ne peuvent tre lus que sur les sites web disposant de Zend Optimisateur (voir chapitre Optimisation).

1381

Chapitre 20

Lobfuscation : Distribuer ses scripts sans dvoiler son code

Version dvaluation Avec la version dvaluation les scripts gnrs ne sont valables que 3 jours.
La dernire version disponible ce jour est la 3.5 qui nest officiellement compatible quavec les versions 4.0.6 4.3 de PHP.

Installation
Linstallation est trs simple. Vous trouverez ci aprs la procdure pour la version 2.0.1

Sous Windows
20. Lobfuscation : Distribuer ses scripts sans dvoiler son code
Aprs avoir tlcharg Zend Encoder depuis le site http://www.zend.com, il suffit de lancer linstallation et de rpondre quelques questions.
Figure 20.1 : Installation de Zend Encoder sous Windows (1/2)

Si le script dinstallation ne trouve pas de cl dactivation, celui-ci vous propose dindiquer o le fichier peut se trouver. Vous pouvez galement la tlcharger (cest ce que nous avons fait pour obtenir une licence dvaluation).

Intranet La licence doit tre tlcharge depuis le poste o doit tre install Zend Accelerator. Il nest, par exemple, pas possible de lancer le script dinstallation depuis un poste reli Internet pour utiliser la cl dactivation sur un poste en Intranet. Si votre poste nest pas reli Internet, slectionnez tout de mme loption "download a license file from www.zend.com". Un message derreur vous indiquera alors comment vous y prendre pour rcuprer manuellement un fichier de licence.

1382

Avec Zend Encoder

Figure 20.2 : Installation de Zend Encoder sous Windows (2/2)

Pour pouvoir tlcharger Zend Encoder, vous avez d ouvrir (gratuitement) un compte sur le site Zend. Afin de tlcharger la cl dactivation vous devez, ici, saisir votre nom dutilisateur et votre mot de passe. Et voil ! Cest fini. Linterface obtenue est alors la suivante :

20. Lobfuscation : Distribuer ses scripts sans dvoiler son code

Figure 20.3 : Interface de Zend Encoder

Sous Linux
Vous devez copier larchive dans un espace quelconque (ex. : /tmp) et la dcompresser.
# gunzip ZendEncoder-Evaluation-2.0.1-Linux_glibc21-i386.tar.gz # tar xvf ZendEncoder-Evaluation-2.0.1-Linux_glibc21-i386.tar

Il suffit ensuite de lancer le script dinstallation :


# cd ZendEncoder-Evaluation-2.0.1-Linux_glibc21-i386 # ./install.sh

1383

Chapitre 20

Lobfuscation : Distribuer ses scripts sans dvoiler son code

Et cest parti...
Figure 20.4 : Fentre daccueil

...aprs avoir dit "bonjour". Cest fait ? Vous pouvez taper [Entre].
Figure 20.5 :

Licence

20. Lobfuscation : Distribuer ses scripts sans dvoiler son code

Vous avez maintenant la libert de lire ou non la licence. Nous vous laissons faire votre choix. Quoi quil en soit, en slectionnant "No" ou en choisissant de lire la licence puis en validant, vous vous retrouverez face la fentre suivante :
Figure 20.6 : Acceptation de la licence

Nous vous laissons choisir en votre me et conscience. En ce qui nous concerne, nous avons opt pour la rponse "Yes". Vous aussi ? Trs bien. Tapez [Entre] et passons la suite.
Figure 20.7 : Chemin du rpertoire dinstallation

Vous tes maintenant invit saisir le chemin du rpertoire devant accueillir Zend Encoder. Le chemin propos est /usr/local/Zend. Comme vous pouvez le constater, nous avons prfr choisir /usr/local/Zend_Encoder_2.0.1, ce qui, finalement, ne sest pas avr tre une trs bonne ide (Zend Encoder senttant aller chercher lencodeur sous /usr/local/Zend). Conservez donc la proposition par dfaut et pressez la touche [Entre].

1384

Avec Zend Encoder

Figure 20.8 : Cl dactivation

Si le script dinstallation ne trouve pas de cl dactivation, celui-ci vous propose dindiquer o le fichier peut se trouver (il sagit dun fichier zend_accelerator.dat, habituellement sous le rpertoire data ou sous /usr/local/Zend). Vous pouvez galement la tlcharger (cest ce que nous avons fait pour obtenir une licence dvaluation).

Intranet La licence doit tre tlcharge depuis le poste o doit tre install Zend Accelerator. Il nest, par exemple, pas possible de lancer le script dinstallation depuis un poste reli Internet pour utiliser la cl dactivation sur un poste en Intranet. Si votre poste nest pas reli Internet, slectionnez tout de mme loption "download a license file from www.zend.com". Un message derreur vous indiquera alors comment vous y prendre pour rcuprer manuellement un fichier de licence.
Figure 20.9 : Identifiant de compte

20. Lobfuscation : Distribuer ses scripts sans dvoiler son code

Pour pouvoir tlcharger Zend Encoder, vous avez d ouvrir (gratuitement) un compte sur le site Zend. Afin de tlcharger la cl dactivation, vous devez ici saisir votre nom dutilisateur
Figure 20.10 : Mot de passe

...ainsi que votre mot de passe. Et voil... Une srie de fentres souvrent et se ferment pour vous indiquer que tel ou tel fichier a t install. Et cest fini. Pour obfusquer un fichier ou toute une arborescence, vous navez qu lancer linterface graphique.

1385

Chapitre 20

Lobfuscation : Distribuer ses scripts sans dvoiler son code

# /usr/local/Zend/ZendEncoderGUI

20. Lobfuscation : Distribuer ses scripts sans dvoiler son code

Figure 20.11 : Interface graphique de Zend Encoder

Utilisation
Nous avons test la version 2.0 pour Linux. Vous devez, dans un premier temps, crer un projet depuis le menu File.
Figure 20.12 : Nouveau projet

Une fois le projet cr,

Figure 20.13 : Interface principale

1386

Avec Zend Encoder

vous devez ajouter les fichiers sources, qui constituent votre projet PHP, depuis le menu File.
Figure 20.14 : Ajout de fichiers au projet

Une fois intgrs au projet, les fichiers apparaissent dans la fentre gauche.
Figure 20.15 :

20. Lobfuscation : Distribuer ses scripts sans dvoiler son code

Rpertoire source

Vous devez galement indiquer le rpertoire dans lequel doivent tre copis les scripts obfusqus. Pour cela cliquez sur le bouton "..." de Target Directory.
Figure 20.16 : Rpertoire destination

1387

Chapitre 20

Lobfuscation : Distribuer ses scripts sans dvoiler son code

Une fois le projet totalement dfini, il ne vous reste qua cliquer sur "Encode !".

20. Lobfuscation : Distribuer ses scripts sans dvoiler son code

Figure 20.17 : Obfuscation

Et voil, cest fait. Nous ne vous montrerons pas le contenu dun fichier obfusqu. Cest tellement illisible que lon croirait voir un fichier de jurons.

Conclusion
Les fichiers assombris avec Zend Encoder sont vritablement illisibles, et ceci restera vrai tant quaucune solution (probablement pirate) ne permettra de passer du code compil au code source (a priori en grande partie masqu). Cette solution ncessite linstallation dun logiciel sur le serveur. Mais, comme il sagit de Zend Optimizer, cela ne constitue pas une grosse contrainte. Cest tout particulirement vrai si vous assurez vous-mme la configuration du serveur web, mais cela reste vrai galement si vous passez par un hbergeur, puisquil nest pas rare de voir Zend Optimizer install. Lutilisation de Zend Encoder est trs souple, puisquil est possible de ne masquer quune partie des scripts dun site (ce qui permet notamment de laisser lisibles les fichiers de configuration). En contrepartie, il est possible de douter du fait que les noms des fonctions ou variables globales soient masqus. Ce qui pourrait faciliter la lecture dun script "dsobfusqu", mais tout cela reste dmontrer.

20.3. Avec ionCube PHP Encoder


Tout comme dans le domaine de loptimisation, ionCube propose une alternative au produit de Zend baptis ionCube PHP Encoder. Le principe reste le mme: il sagit de ne fournir quun code prcompil illisible. Cette solution intgre galement la possibilit de limiter lexcution des scripts dans le temps et/ou par machine. Contrairement Zend Encoder, il ny a pas dinterface graphique permettant de slectionner les scripts obfusquer. Pour fonctionner, les scripts encods ncessitent linstallation pralable dionCube PHP Loader sur le serveur. Ce dernier est disponible gratuitement.

1388

Avec PHP guardian

ionCube PHP Encoder nest pas gratuite mais une version dvaluation peut tre tlcharge sur le site ladresse http://www.ioncube.com/. Il fonctionne sur les plateformes Linux, FreeBSD et prochainement Windows (systme dexploitation pour lequel il nexiste aujourdhui quune version beta). Nous avons bien videmment test la version Linux; la version dvaluation 3.0 pour tre prcis.

Version dvaluation La version dvaluation nest utilisable que durant 7 jours.

Installation
Il suffit de dcompresser larchive dans son rpertoire de destination (ex: /usr/local)
# tar zxvf ioncube_encoder_evaluation_3.0.tar.gz

20. Lobfuscation : Distribuer ses scripts sans dvoiler son code

Utilisation
Pour crypter un rpertoire complet (ici src/) et rcuprer le rsultat dans un rpertoire donn (ici dst/) vous devrez alors taper une commande similaire
# ./ioncube_encoder --key <votre cle de licence> src -o dst

Vous constaterez alors queffectivement le rpertoire dst/ contient des fichiers illisibles hormis leurs premires lignes. Les premires lignes de ces scripts sont en fait destines charger en mmoire le module capable dinterprter leur contenu, savoir ionCube PHP Loader. Ainsi, une des solutions possibles pour utiliser ces scripts obfusqus consiste dcompresser larchive directement dans le rpertoire contenant ces fichiers.
# tar zxvf ioncube_loaders_2.1.tar.gz

Une fois cette opration ralise vous pouvez constater quil est possible daccder ces scripts aussi simplement que leur quivalant non crypt. Il existe bien videmment, une longue liste doptions la commande ioncube_encoder, mais pour rpondre votre besoin spcifique, il vaut mieux que vous vous plongiez dans les notices dutilisation.

20.4. Avec PHP guardian


Disponible uniquement sous Windows, ce logiciel na pas t test. Il semble fonctionner sur le mme principe que Zend Encoder et ionCube PHP Encoder (et offre galement des options permettant de limiter la dure de vie du script ou de le limiter une adresse IP donne.). Il ne ncessite toutefois aucune installation sur le serveur le dcodage seffectuant par un script PHP fourni avec le logiciel. Vous le trouverez (y compris en version dvaluation) ladresse http://www.phpguardian.com/.

1389

Chapitre 20

Lobfuscation : Distribuer ses scripts sans dvoiler son code

20.5. Avec POBS


POBS est crit en PHP. Il fonctionne donc sur toute plateforme disposant dun serveur web intgrant PHP. La version teste est la version 0.99 qui reste ce jour la dernire version disponible. Celle-ci est officiellement teste avec PHP 4.0.4 (ce qui ne signifie pas pour autant quelle ne fonctionne pas avec les autres versions de PHP 4)

Installation
Il suffit de dcompresser, dans un coin de votre serveur web, larchive disponible sur le site http://pobs.mywalhalla.net/ (ou celle disponible sur le CD-ROM). Vous serez certainement amen modifier quelques paramtres du script pobs-ini.inc.php, en particulier $SourceDir et $TargetDir, qui indiquent respectivement le chemin du rpertoire contenant les sources et celui destin recevoir les versions obfusques des scripts.

20. Lobfuscation : Distribuer ses scripts sans dvoiler son code

Quoi quil en soit vous tes invit consulter le fichier documentation-fr.txt (profitez-en ! Pour une fois quil y a une notice en franais).

Utilisation
Il suffit dappeler le script principal pobs.php.

Figure 20.18 : POBS

Linterface qui soffre vous vous permet alors de modifier certains paramtrages. Vous pouvez choisir de masquer les noms des fonctions, constantes et/ou variables, et de supprimer les commentaires, indentations et/ou retours la ligne.

1390

Avec POBS

Lorsque vous lancez lobfuscation via le bouton "Start processing", les fichiers rsultats sont alors copis dans le rpertoire dsign par le fichier pobs-ini.inc.php et un bilan est affich.

20. Lobfuscation : Distribuer ses scripts sans dvoiler son code

Figure 20.19 : Bilan POBS

Dans ce bilan apparat la liste des fichiers traits, les noms des fonctions, constantes et variables, ainsi que leurs quivalents obfusqus. Ainsi, lexemple suivant :
<?php // Fonction retournant le rsultat // de laddition de operande1 avec operande2 function addition($operande1, $operande2) { $somme = $operande1 + $operande2; return $somme; } ?> <html> <body> <?php $val1 = 3; $val2 = 6; echo addition($val1, $val2); ?> </body> </html>

1391

Chapitre 20

Lobfuscation : Distribuer ses scripts sans dvoiler son code

donne le rsultat suivant (qui varie selon les options choisies) :


<?php function F2b2ae874($V275ff7ff, $Ve5f3bc4b) {$V3ce6e7f2 = $V275ff7ff + $Ve5f3bc4b;return $V3ce6e7f2;}?> <html> <body> <?php $V8de92ce2 = 3;$V38ceaa3b = 6;echo F2b2ae874($V8de92ce2, $V38ceaa3b);?> </body> </html>

Ce qui, vous en conviendrez, nest pas trs lisible (mme si ici, le code tant bien simple, il nest pas trs difficile de comprendre ce que fait ce script). Comme les noms de fonctions, constantes et variables sont modifis par POBS, les scripts obfusqus ne pourront pas tre inclus tels quels dans des scripts non obfusqus (et inversement). Si vous souhaitez conserver des scripts en clair (i.e. des fichiers de configuration), vous devrez configurer POBS (via le fichier pobs-ini.inc.php) afin de ne pas masquer tel ou tel nom de fonction, constante ou variable.

20. Lobfuscation : Distribuer ses scripts sans dvoiler son code

Conclusion
POBS a lavantage dtre une solution gratuite offrant un bon degr de camouflage et qui ne ncessite aucun logiciel sur le serveur web. Il est donc compatible avec toutes les plateformes. Bien que le rsultat de lobfuscation ne soit pas sous une forme compile, le travail de restauration des sources originales est toutefois grandement facilit (parions, cependant, que les solutions permettant de transformer le rsultat dune obfuscation telle que peut en retourner Zend Encoder en un code similaire celui que fournit POBS ne tarderont pas apparatre. Ce type de solution perdrait alors son avantage). Le mlange de codes sources obfusqus avec des codes sources non obfusqus nest pas chose aise, mais cest peut-tre l le prix payer pour un meilleur camouflage du code.

20.6. Autres
Il existe un certain nombre dautres solutions bases, pour la plupart, sur un simple cryptage des sources laide dun mot de passe. Toutes ces solutions ncessitent linstallation dun logiciel spcifique sur le serveur, et ne garantissent pas ncessairement la protection du code si le mot de passe venait tre "crack" (ou tout simplement si lanalyseur PHP tait modifi pour restituer le code source dcrypt qui lui est communiqu par la partie serveur du logiciel dobfuscation). Parmi elles, nous pouvons citer :
j j j

PHTML Encoder disponible ladresse http://www.rssoftlab.com/ ; Source Defendeur prsent ladresse http://www.sourcedefender.com/ ; PHP Screw ladresse http://sourceforge.net/projects/php-screw/.

1392

Chapitre 21

Annexe A : des exemples dapplications


21.1 21.2 21.3 21.4 21.5 21.6 21.7 Administration de bases de donnes Cration de sites . . . . . . . . . . . . Forums de discussion . . . . . . . . . Phorum : un moteur de forums . . Annuaires de liens . . . . . . . . . . . Solutions de travail collaboratif . . Graphiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1395 .1401 .1407 .1409 .1412 .1413 .1416

Administration de bases de donnes

21.1. Administration de bases de donnes


phpMyAdmin
Installation et conguration
Certains programmes dinstallation automatique de PHP/MySQL comprennent dj phpMyAdmin. En revanche, si vous avez choisi dinstaller vous-mme MySQL, il est fort probable que phpMyAdmin ne soit pas sur votre systme, ce qui est bien dommage... En effet, phpMyAdmin est un programme libre et gratuit qui facilite grandement ladministration et lutilisation dun serveur de bases de donnes MySQL. Via une interface web simple, puissante et francise, il permet de mener bien quasiment toute opration relative au serveur.

21. Annexe A : des exemples dapplications

Figure 21.1 : phpMyAdmin

Vous pourrez ainsi crer et supprimer des bases, crer, copier et effacer des tables, lancer des requtes SQL, charger des fichiers textes dans des tables, administrer plusieurs serveurs la fois, sauvegarder vos donnes, etc. Tlchargez la dernire version de phpMyAdmin ladresse www.phpmyadmin.net ou bien utilisez celle disponible sur le CD-ROM. Dcompressez le contenu de larchive, par exemple la base de votre serveur web (ou dans un rpertoire de votre machine pour pouvoir modifier certains scripts avant de les transfrer dans un espace allou par un hbergeur) ; cela aura pour effet de crer un rpertoire phpMyAdmin-2.5.7 (que vous pouvez ventuellement renommer en phpmyadmin). laide de votre diteur de texte prfr, ditez le fichier config.inc.php et recherchez la ligne :
$cfgPmaAbsoluteUri = ;

Compltez avec ladresse web laquelle sera disponible votre phpMyAdmin. Si vous avez suivi lexemple cit plus haut (phpmyadmin), vous devrez donner cette adresse :
$cfgPmaAbsoluteUri = http://www.votrenomdedomaine.com/phpmyadmin/;

1395

Chapitre 21

Annexe A : des exemples dapplications

Passons maintenant au bloc * Server(s) configuration. Il sagit de configurer la connexion au serveur de bases de donnes. Il faut, en effet, que phpMyAdmin puisse avoir accs au serveur si lon veut quil le manipule. Recherchez et compltez les lignes suivantes :
$cfgServers[1][host] = ; // MySQL hostname

Compltez avec localhost. Si vous installez phpMyAdmin chez votre hbergeur, il peut tre utile de se rfrer sa documentation, le nom de lhte pouvant varier.
$cfgServers[1][auth_type] = config; // Authentication method (config, http or cookie based)?

Compltez avec "config", "http" ou "cookie".


j
config permet nimporte quel utilisateur davoir accs phpMyAdmin sans avoir sidentifier. Ce sont, en effet, les paramtres du fichier config.inc.php qui sont utiliss. Ce choix nest pas le plus sr. Nimporte quel utilisateur qui connat ladresse de votre phpMyAdmin pourrait se connecter au serveur MySQL et supprimer bases ou tables sans problme. Les options "http" ou "cookie" requirent une authentification de la part de lutilisateur qui se connecte. http : un formulaire demande lutilisateur ses login et mot de passe, puis les enregistre dans un trousseau de cls (selon les navigateurs). Ne fonctionne quavec PHP install comme module Apache. PHP en CGI ne permet pas dutiliser ce mode de connexion. cookie : les informations de connexion seront conserves dans un cookie qui ne sera valable que le temps de la session.

21. Annexe A : des exemples dapplications

$cfgServers[1][user] = votre_pseudo_administrateur;

Compltez avec le pseudonyme de ladministrateur du serveur de bases de donnes. Gnralement, cest "root", moins que vous ne layez chang manuellement.
$cfgServers[1][password] = ; // MySQL password (only needed with config auth)

Comme vous lindique le fichier de configuration, vous navez renseigner cette ligne que si vous utilisez la mthode de connexion config ; celle qui donne accs au serveur tous les utilisateurs qui connaissent ladresse de votre phpMyAdmin.

Scuriser malgr tout Si vous tenez conserver le mode de connexion "config", vous pouvez tout de mme scuriser laccs votre serveur de bases de donnes en utilisant les restrictions daccs que propose votre serveur web (ex. : fichier .htaccess dApache).
Vous pouvez galement configurer ds prsent phpMyAdmin pour quil soit en franais. Recherchez cette ligne dans le fichier config.inc.php :
require(./libraries/select_lang.lib.php);

et modifiez-la comme suit :


require("french.inc.php3");

1396

Administration de bases de donnes

Une autre option intressante de ce fichier de configuration est la possibilit de configurer laccs pour des utilisateurs diffrents ayant des droits diffrents. Pour utiliser cette fonctionnalit de phpMyAdmin, il faut bien entendu que des utilisateurs autres que "root" aient t crs sur le serveur MySQL (voir plus loin Prise en main). Dans le fichier de configuration, vous devez trouver plusieurs fois cette suite de lignes :
$i++; $cfgServers[$i][host] $cfgServers[$i][port] $cfgServers[$i][socket] $cfgServers[$i][connect_type] $cfgServers[$i][controluser] $cfgServers[$i][controlpass] $cfgServers[$i][auth_type] $cfgServers[$i][user] $cfgServers[$i][password] $cfgServers[$i][only_db] $cfgServers[$i][verbose] $cfgServers[$i][bookmarkdb] $cfgServers[$i][bookmarktable] $cfgServers[$i][relation] = = = = = = = = = = = = = = ; ; ; tcp; ; ; config; root; ; ; ; ; ; ;

Ce sont des doublons de configuration daccs prts lemploi. Il suffit de les dupliquer et de les complter pour chacun des utilisateurs requis. Pour un phpMyAdmin qui dispose dj dun utilisateur "root", si lon veut ajouter lutilisatrice "Emma", ayant le mot de passe "youpi", il faudra avoir la configuration suivante :
$cfgServers[1][host] $cfgServers[1][port] $cfgServers[1][socket] $cfgServers[1][connect_type] $cfgServers[1][controluser] $cfgServers[1][controlpass] $cfgServers[1][auth_type] $cfgServers[1][user] $cfgServers[1][password] $cfgServers[1][only_db] $cfgServers[1][verbose] $cfgServers[1][bookmarkdb] $cfgServers[1][bookmarktable] $cfgServers[1][relation] $cfgServers[2][host] $cfgServers[2][port] $cfgServers[2][socket] $cfgServers[2][connect_type] $cfgServers[2][controluser] $cfgServers[2][controlpass] $cfgServers[2][auth_type] $cfgServers[2][user] $cfgServers[2][password] $cfgServers[2][only_db] = = = = = = = = = = = = = = = = = = = = = = = = localhost; ; ; tcp; ; ; http; root; coucou; ; ; ; ; ; localhost; ; ; tcp; ; ; http; emma; youpi; ;

1397

21. Annexe A : des exemples dapplications

Chapitre 21

Annexe A : des exemples dapplications

$cfgServers[2][verbose] $cfgServers[2][bookmarkdb] $cfgServers[2][bookmarktable] $cfgServers[2][relation]

= = = =

; ; ; ;

La ligne suivante :
$cfgServers[2][only_db] = ;

permet ensuite de spcifier les bases qui doivent tre listes pour cette utilisatrice en particulier. Cela ne remplace en rien les droits et privilges attribus dans MySQL. Il est seulement question daffichage. Une fois que votre fichier de configuration est correctement renseign, sauvegardez-le. Vous pouvez alors commencer utiliser phpMyAdmin en vous rendant ladresse : http://votrenomdedomaine/phpmyadmin/.

Prise en main
phpMyAdmin vous permet de grer au mieux vos bases MySQL. Nous allons passer en revue les fonctions les plus simples et les plus basiques.

21. Annexe A : des exemples dapplications

Aspect gnral
Dans la partie gauche de la page, vous devez trouver, sous la mention Accueil, un menu droulant des diffrentes bases de donnes prsentes sur le systme. La partie qui nous intresse se trouve sur la partie droite de la page. On peut voir deux colonnes : une premire qui propose des liens en rapport avec MySQL, et une seconde qui concerne phpMyAdmin.

Crer un utilisateur
Pour crer un utilisateur, rendez-vous sur le page principale de votre phpMyAdmin. Dans la partie droite de la page, sous MySQL cliquez sur le lien Utilisateurs et privilges. Notez au passage que vous disposez galement dun lien vers la documentation en ligne. Sur la nouvelle page qui saffiche, vous trouvez deux parties : en premier lieu, un tableau qui rsume tous les utilisateurs dj crs ainsi quun rsum de leurs privilges et, en second lieu, une srie doptions et de champs qui vont vous permettre de crer de nouveaux utilisateurs. Allez directement dans la partie Ajouter un utilisateur (voir fig. 21.2). Vous pouvez tout dabord slectionner le serveur sur lequel vous dsirez crer cet utilisateur, phpMyAdmin pouvant effectivement grer plusieurs serveurs. La ligne suivante vous demande Tout utilisateur ou Nom dutilisateur si vous souhaitez spcifier un nom dutilisateur. Cela est dailleurs trs largement prfrable. En effet, vous pourriez crer un accs sur nimporte quel nom dutilisateur sans donner de mot de passe, ce qui aurait pour effet douvrir votre serveur de bases de donnes nimporte qui...

1398

Administration de bases de donnes

Figure 21.2 : Ajouter un utilisateur dans phpMyAdmin

Donnez donc un nom dutilisateur dans le champ prvu cet effet, et donnez deux fois de suite le mot de passe sur la ligne suivante. Il faut encore indiquer les privilges qui seront attribus ce nouvel utilisateur. Cochez chacune des cases correspondantes selon les privilges que vous souhaitez allouer. Vous pouvez cliquer sur Excuter pour que la cration soit lance. Une fois ce nouvel utilisateur cr, vous pouvez lajouter votre fichier de configuration de phpMyAdmin pour quil puisse se connecter au serveur, ou lutiliser pour des applications web ncessitant une connexion au serveur de base.

21. Annexe A : des exemples dapplications

Crer une base


Pour crer une base, cliquez sur Accueil, tout en haut gauche de la page daccueil de phpMyAdmin. Une fois la page rafrachie, juste sous la petite barre MySQL, donnez le nom de table que vous voulez crer dans le champ prvu cet effet, puis cliquez sur Crer.

Supprimer une base


Pour supprimer une base, choisissez la base dans le menu droulant qui se situe juste sous la mention Accueil. La partie de droite sactualise alors pour vous prsenter un rsum de la table slectionne. Tout en bas de cette page se trouve un lien Supprimer la base ... Il suffit de cliquer sur ce lien.

Crer une table


Une fois que vous avez choisi une base, sur la partie droite de la page web, rendez-vous dans la section Crer une nouvelle table sur la base ... Donnez alors le nom de la table ainsi que le nombre de champs que vous voulez quelle comporte, puis cliquez sur Excuter. La page se rafrachit et vous prsente alors une vue en tableau de la future table. Renseignez tous les paramtres ncessaires pour chaque champ de la table, puis validez en cliquant sur le bouton Sauvegarder situ en bas de la page.

1399

Chapitre 21

Annexe A : des exemples dapplications

Supprimer une table


Choisissez dabord la base dans laquelle se trouve la table. Dans le menu situ gauche de la page, cliquez sur le nom de la table que vous voulez supprimer. Dans la partie droite de la page, cliquez sur le lien Supprimer de la ligne correspondant la table concerne.

Sauvegarder une table ou une base


Sauvegarder une base ou une table MySQL est une opration fort simple grce phpMyAdmin. Cliquez, dans la partie gauche de la page, sur une table ou une base. La partie droite se rafrachit. Rendez-vous dans la section Afficher le schma de la base (ou de la table). Si vous avez choisi une base, vous pourrez slectionner les tables sauvegarder grce une petite liste. Ensuite, dcidez de sauvegarder la structure de la base, la structure et les donnes ou seulement les donnes. Choisissez ensuite les options qui vous intressent parmi les diffrentes options offertes : ajouter des noncs, insertions compltes ou tendues, etc. Cliquez sur Transmettre. Selon les configurations de PHP, il vous sera galement possible de compacter le fichier de sauvegarde (zipp).

Restaurer une table ou une base


Le fichier gnr par la sauvegarde peut, bien sr, servir recrer une table ou une base. En fait, le fichier de sauvegarde contient des requtes SQL et des donnes variables selon les options choisies lors de la sauvegarde. Admettons que votre base portait le nom de "Emma" : il vous suffit de rcrer une base "Emma" sur le nouveau serveur. Rendez-vous dans la section Excuter une ou des requtes sur la base Emma. Dans la partie Emplacement du fichier texte , cliquez sur le bouton Parcourir, donnez lemplacement du fichier de sauvegarde puis cliquez sur Excuter.

21. Annexe A : des exemples dapplications

Autres
Il existe dautres scripts, similaires phpMyAdmin mais adapts dautres serveurs de bases de donnes. Parmi eux nous trouvons :
j j

phpPgAdmin,

destin

administrer

PostgreSQL Oracle

et et

disponible disponible

ladresse ladresse

http://sourceforge.net/projects/phpPgAdmin/ ;

phpOracleAdmin,

destin

administrer

http://phporacleadmin.org/.

1400

Cration de sites

21.2. Cration de sites


PHPNuke
Prsentation
PHPNuke est un logiciel libre et gratuit que vous pourrez modifier et adapter votre gr.

21. Annexe A : des exemples dapplications

Figure 21.3 : PHPNuke

PHPNuke est un systme qui gre compltement votre site web. Lorsque vous installez PHPNuke, vous obtenez un site qui a dj une page daccueil vous permettant de mettre en ligne des articles avec forums intgrs ; il gre linscription des utilisateurs, offre une zone de tlchargement modre, etc. Vous navez pas utiliser un diteur de pages web pour travailler avec un site qui utilise PHPNuke. Sil est possible de reprocher PHPNuke dtre une "usine gaz", il reste tout de mme une solution rapide et pratique pour mettre en place un site et diffuser des informations sans avoir passer par les tapes fastidieuses de lditeur HTML et du dveloppement en PHP. Au quotidien, deux aspects de PHPNuke seront mis face face : sa facilit de gestion et sa rigidit. Par exemple, la page daccueil dun site sous PHPNuke se prsente sous forme de

1401

Chapitre 21

Annexe A : des exemples dapplications

blocs : blocs de menus, blocs des articles, etc. Si vous voulez faire passer un bloc de liens de droite gauche, il vous suffit de cliquer sur de petites flches dans lespace dadministration du site. Si vous voulez mettre en ligne un article, vous faites un copier-coller dans un champ texte et le tour est jou. De mme, pour changer tout laspect visuel du site, il ny a qu choisir dans une liste pour que tout le look du site soit modifi. En revanche, vous risquez dtre rapidement bloqu par la rigidit de PHPNuke. Pour ne parler que dun point relativement secondaire dans un site web : la page daccueil reste dsesprment fige. Vous ne pourrez pas sortir du modle "deux petites colonnes et une grosse" sans mettre les mains dans le code. Cela risque dailleurs de faire seffondrer le chteau de cartes, tout tant trs imbriqu dans PHPNuke. la longue, cela peut lasser.

Installation
Pour installer PHPNuke, allez tout dabord crer un dossier "phpnuke" quelque part sur votre serveur web ou chez votre hbergeur. Dcompactez larchive PHPNuke disponible ladresse http://www.phpnuke.org/ (mais galement prsente sur le CD-ROM de la prsente Bible). Il faut dcompacter le contenu du dossier "/html" de larchive dans le dossier " phpnuke". Le reste se rsume une licence que vous devez dj connatre par cur (la GPL) et des fichiers README (assez classiques, mais que les anglophones auront tout de mme intrt lire pour tre tenus au courant des volutions de PHPNuke). Aprs avoir dcompact tous les fichiers, rendez-vous dans phpMyAdmin. Pour que PHPNuke fonctionne, il faut quil puisse utiliser une base de donnes MySQL. Si vous tes votre propre hbergeur, vous pouvez envisager de crer une table "nuke", sinon toute autre base devrait faire laffaire.

21. Annexe A : des exemples dapplications

Vous pouvez vous reporter la section MySQL du chapitre sur les bases de donnes ou lannexe phpMyAdmin pour voir comment crer une telle base.
Il faut maintenant crer les tables, qui sont en fait les tiroirs dans lesquels PHPNuke va venir stocker ses informations. Rassurez-vous, les dveloppeurs de PHPNuke ont pens vous. Dans le dossier qui vous a servi dcompacter PHPNuke, vous devriez trouver le fichier nuke.sql. Cest ce fichier qui contient toute la structure et la dfinition de PHPNuke utiles votre base de donnes. Si vous avez accs au client MySQL en ligne de commande (i.e. si vous installez PHPNuke sur votre propre machine), vous pouvez taper la commande mysql mabase < nuke.sql (si votre base sappelle "mabase", vous aurez peut-tre spcifier un nom dutilisateur et un mot de passe. Pour plus de dtails, tapez alors mysql h). Sinon, vous pouvez utiliser phpMyAdmin. Dans la liste des bases prsentes sur la partie gauche de la page web de phpMyAdmin, slectionnez celle qui doit hberger les tables PHPNuke. La partie droite de la page doit se rafrachir. Sur cette page, vous trouvez diffrentes options qui vont vous permettre deffectuer des requtes sur votre base. Un lien "Emplacement du fichier texte" vous offre de tlcharger un fichier qui contient toute une srie de requtes. Cest cette solution que nous allons utiliser pour crer toutes les tables dont a besoin PHPNuke. Dans la page web, cliquez sur Parcourir, allez chercher le fichier nuke.sql, puis cliquez sur le bouton Excuter pour que les informations contenues dans le fichier soient envoyes au serveur. Si jamais, comme cela a pu arriver, lopration produisait une erreur, vous pouvez essayer de

1402

Cration de sites

rentrer les requtes de cration de tables une une. Opration certes fastidieuse, mais ncessaire au bon fonctionnement de PHPNuke. Une fois que le serveur a digr toutes les requtes, vous devez avoir une belle liste de tables dans votre base (sur le ct gauche de la page). Une fois les tables cres, il faut configurer PHPNuke afin quil sache o aller chercher ces bases. laide de votre diteur de texte prfr, ouvrez le fichier config.php qui se situe la racine de votre site. lintrieur de ce fichier, recherchez les lignes suivantes (en dbut de fichier) :
$dbhost = "localhost"; $dbuname = "toto"; $dbpass = "passtoto"; $dbname = "basetoto"; $dbtype = "MySQL";

Tableau 21.1 : Un passage comment du fichier vous explique quoi correspond chacune des lignes
Paramtre $dbhost Signification Nom de lhte de la base MySQL. Gnralement, laissez "localhost". Renseignez-vous auprs de votre hbergeur pour savoir quels sont les paramtres exacts. Nom de lutilisateur de la base MySQL. Mot de passe de lutilisateur. Nom de la base MySQL.

21. Annexe A : des exemples dapplications

$dbuname $dbpass $dbname

Une fois que vous avez correctement renseign chacune de ces lignes, sauvegardez le fichier. Voil, tout est dit. Votre site avec PHPNuke est accessible en ligne, chez votre hbergeur ou sur votre serveur local. Pour le consulter, rendez-vous directement la racine du rpertoire dans lequel vous avez install PHPNuke, par exemple, http://www.votresite.com/test/. Si rien napparat, ou si vous avez des erreurs MySQL, cela provient peut-tre dune erreur lors de ldition du fichier config.php. Vrifiez bien les informations que vous avez donnes. Si tout est bon, vous devez alors voir la page daccueil de votre site. Outre le message central, les colonnes de droite et de gauche sont dj bien pleines. Vous pourrez rduire, configurer ou supprimer ces blocs latraux depuis lespace dadministration qui est accessible une adresse du type : http://www.votresite.com/test/admin.php. Rendez-vous dailleurs cette adresse pour crer votre compte dadministrateur.

1403

Chapitre 21

Annexe A : des exemples dapplications

Figure 21.4 : Cration dun compte dadministrateur

21. Annexe A : des exemples dapplications

Il vous sera demand un nom dutilisateur, une adresse email, ladresse du site de ladministrateur (vous pouvez donner ladresse de votre site) ainsi quun mot de passe. Une fois toutes les informations donnes, cliquez sur le bouton Submit. Vous arrivez alors directement sur une page qui vous permet de vous connecter en tant quadministrateur.

Figure 21.5 : Connexion ladministration

En plus du nom dutilisateur et du mot de passe que vous venez de dfinir, PHPNuke vous demander de saisir un code cinq chiffres alatore affich lcran. Cela vite les tentatives de piratage par des robots qui testent des jeux de noms dutilisateur et mot de passe.

1404

Cration de sites

SPIP
Prsentation (simple, puissant, beau)

21. Annexe A : des exemples dapplications

Figure 21.6 : SPIP

SPIP est un moteur de gestion de contenus. Il vous permet dcrire des articles et de les mettre en ligne. Entendez par "article" tout contenu que vous jugerez bon de mettre disposition des visiteurs de votre site. SPIP a t cre par lquipe du site Uzine. Par rapport PHPNuke, SPIP a quelques avantages. Il dispose notamment dun systme de cache qui vite de surcharger un serveur, alors que PHPNuke, lui, est lourd au possible. Signalons au passage que ce systme de cache a pour nom "Gargantua" voil qui ravira tous les amateurs de littrature franaise. SPIP est aussi plus simple mettre en place et grer. tant plus jeune que PHPNuke, SPIP dispose pour le moment de moins de fonctionnalits. Gageons que ses crateurs sauront lui garder cette simplicit qui en fait un excellent outil. Soulignons toutefois que SPIP dispose de petits "plus" tout fait sduisants. Par exemple, quand un auteur se cre un compte, il a la possibilit de donner sa cl publique PGP SPIP est actuellement en train de sorienter vers le travail collaboratif (systme de forum interne certains rdacteurs, messages privs, etc.). On reprochera tout de mme SPIP le manque de "une". En effet, la une dun site gr par SPIP est en constant mouvement. chaque fois que vous ajoutez un article, il vient prendre place sur la page daccueil. Mme si vous annoncez la priodicit de vos mises jours, vos visiteurs seront privs du plaisir de dcouvrir vos anciennes pages daccueil. Les articles sont bien archivs, mais la une, elle, na pas de mmoire.

1405

Chapitre 21

Annexe A : des exemples dapplications

Compatibilit PHP5 La version 1.7.2 de SPIP nest pas encore compatible avec PHP5. Les dveloppeurs de SPIP y travaillent en modifiant le code du moteur. Ainsi, SPIP devrait rapidement devenir compatible avec la version la plus rcente de PHP. Pour plus dinformations : www.spip.net/threadspip2014-7420.html.

Installation (du travail de pro)


Grossirement, le processus est le mme que pour PHPNuke. Il va sagir de mettre en place une interaction entre SPIP et la base de donnes MySQL. Crez un rpertoire spip dans le rpertoire racine de votre serveur web, ou bien l o vous jugerez utile dinstaller SPIP. Dans ce rpertoire spip, dcompactez le fichier spip1.7.2.zip disponible en tlchargement ladresse www.uzine.net/spip/ (et que vous trouverez sur le CD-ROM de la Bible). Si vous dcompactez les fichiers la racine de votre serveur web ou de votre espace dhbergement, tout sera mis en vrac la racine et, avouons-le, ce nest pas trs propre comme installation. Une fois les fichiers installs correctement, lancez un navigateur web et rendez-vous cette adresse : www.votresite .com/spip/ecrire/. L, et cest ce qui est merveilleux, lAssistant dinstallation de SPIP va vous prendre par la main. Une premire page vous demande ladresse de votre base de donnes, le nom dutilisateur utiliser (login de connexion) puis le mot de passe de cet utilisateur. Nous ne pouvons que vous conseiller dassigner un mot de passe lutilisateur que vous allez crer. Une fois tous les champs correctement remplis, cliquez sur suivant. Si la connexion choue, SPIP vous explique pourquoi, et vous invite gentiment corriger lerreur (qui, entre nous soit dit, doit tre assez bnigne). Une fois la connexion avec la base tablie, cliquez sur suivant pour passer la cration de la base de donnes qui sera utilise par SPIP. SPIP vous propose alors plusieurs choix de bases de donnes. Vous pouvez utiliser une base de donnes qui vous a t attribue par votre hbergeur (quand vous navez, par exemple, droit qu une seule base par serveur de bases de donnes), ou bien crer une nouvelle base spcialement pour SPIP. SPIP vous propose dailleurs den crer une qui portera son nom, ce qui nest pas une mauvaise ide (cest dailleurs ce que nous vous invitons faire). Ne touchez rien, et cliquez, vous vous en doutez, sur le bouton suivant. SPIP va alors crer les tables ncessaires son bon fonctionnement au sein de la nouvelle base de donnes. Une fois quil a fini son travail, il vous en informe, et vu que vous vous en tirez parfaitement bien, cliquez une nouvelle fois sur suivant. Tout le cur du systme SPIP est maintenant install. Il faut dsormais crer un premier utilisateur, un chef suprme : vous. Donnez votre signature, votre adresse e-mail puis un pseudonyme et un mot de passe qui vous serviront ladministration de votre site. Notez-les prcieusement, vous en aurez besoin par la suite. Une fois tous les champs remplis, cliquez sur suivant. SPIP vous annonce que vous avez tout gagn, que linstallation et la configuration sont termines. Vous allez pouvoir commencer travailler avec SPIP. Cliquez, et ce pour la dernire fois, sur suivant. Une petite fentre didentification apparat. Donnez le pseudo et le mot de passe que vous avez utiliss lors de linstallation. Vous arrivez alors dans le monde merveilleux de SPIP.

21. Annexe A : des exemples dapplications

Conguration
Linterface dadministration est un peu ardue comprendre, mais, rassurez-vous, une aide complte est intgre. Vous pouvez y accder en cliquant sur le bouton rouge en haut droite. Par la suite, vous pourrez accder cette page dadministration en vous rendant cette adresse : http://www.votresite.com/spip/ecrire. Vos pseudo et mot de passe vous seront redemands.

1406

Forums de discussion

Comme vous pouvez le constater, en vous rendant sur la page daccueil du site que vous avez cr avec SPIP (http://www.votresite.com/spip), vous manquez cruellement de contenu. Pour remdier cela, rendez-vous dans lespace dadministration (http://www.votresite.com/spip/ecrire). SPIP lui-mme vous lindique : avant de pouvoir crire, il faut que vous criez au moins une rubrique. Cliquez sur le lien prvu cet effet : Crer une nouvelle sous-rubrique. Vous arrivez alors sur une page o il vous est demand de donner un titre cette nouvelle rubrique et, si vous le dsirez, de lui adjoindre un descriptif. Une fois que vous tes satisfait de votre rubrique, cliquez sur le bouton valider situ en bas de la page. Vous retournez alors dans votre espace dadministration. Vous pouvez constater que la nouvelle rubrique apparat. De nouvelles icnes sont galement prsentes l o ne figurait que celle de la cration dune rubrique. Notez tout particulirement licne crire un nouvel article. Cliquez dessus. Vous arrivez alors sur une page vous offrant de rdiger un article. Une fois votre article termin, enregistrez-le dans la base. SPIP vous propose alors un aperu de votre travail et vous donne la possibilit de changer son statut. tant donn que vous tes ladministrateur du site, vous pouvez mettre directement ce travail en ligne, ce que nous vous invitons dailleurs faire. laide du menu droulant prsent tout en haut de la page, choisissez loption Publi en ligne, puis cliquez sur Modifier. Vous pouvez aller rcolter le fruit de votre dur labeur sur la page daccueil de votre site : http://www.votresite.com/spip/.

Autres
Il existe de nombreuses solutions destines faciliter la mise en place dun site. En voici quelques autres :
j j j j

21. Annexe A : des exemples dapplications

Templeet, disponible ladresse http://www.templeet.org/ ; AttilaPHP, disponible ladresse http://www.attila-php.net/ ; PHPForge, disponible ladresse http://membres.lycos.fr/phpforge/ ; postNuke (un clone de PHPNuke), disponible ladresse http://www.postnuke.com/.

21.3. Forums de discussion


PHPbb
Prsentation (cyber-agora et caf du commerce virtuel)
Plutt que de paraphraser btement, donnons la parole au site web PHPbb.biz, le site franais de rfrence en ce qui concerne PHPbb : "Phpbb est un puissant forum de discussion, convivial et agrable dutilisation. Ses fonctionnalits et sa rapidit sont semblables voire suprieures aux diffrents forums payants "haut de gamme" du march. En effet, PHPbb est libre et gratuit (sous licence GNU/GPL). Il dispose dune interface facile utiliser et dune aide en ligne sous forme de FAQ ("Frequently Asked Questions" ou questions les plus frquemment poses). Le panneau dadministration est complet et vous permettra une gestion aise de votre plateforme de communication. Un support technique en franais est disponible, il vous permettra de rpondre toutes vos questions". Vous trouverez galement sur ce site un guide dinstallation. Gardez cela en tte, cela pourra vous tre utile quand vous rechercherez des complments dinformation.

1407

Chapitre 21

Annexe A : des exemples dapplications

Figure 21.7 : PHPbb

21. Annexe A : des exemples dapplications

Installation
Installez PHPbb en lui demandant de se dcompacter directement dans un dossier que vous aurez cr pour lui. PHPbb crera lui-mme un dossier Phpbb. Vous trouverez PHPbb sur le site http://www.phpbb.com/ (ou sur le site de la communaut francophone http://www.phpbb.biz) ainsi que sur le CD-ROM de la Bible. Lancez un navigateur et rendez-vous ladresse : http://www .votresite.com/phpBB/install.php. Une fois tous les champs correctement remplis, cliquez sur next. PHPbb va alors crer les tables ncessaires son bon fonctionnement. Une page vous tient au courant de lvolution des crations. Une fois que tout est fait, cliquez une nouvelle fois sur next. Il vous faut maintenant crer ladministrateur de votre systme de forums. Cest lui qui aura droit de vie et de mort sur tout ce qui se passe dans les forums. Remplissez tous les champs en faisant particulirement attention au nom dutilisateur et au mot de passe. Une fois que vous avez rempli tous les champs, cliquez une nouvelle fois sur next. Vous arrivez alors sur la page de configuration gnrale du forum. Vous allez pouvoir, entre autres choses, choisir la langue du forum. Cliquez sur next pour enregistrer les paramtres. Voil, le forum est configur. PHPbb vous prsente une page de flicitations et vous invite aller dans lespace dadministration des forums, ce qui, avouons-le, est plutt une bonne ide. Cliquez sur le lien Administration Area. Vous arrivez alors sur une page assez laide, pleine de texte en anglais.

Conguration (la qute du Graal)


PHPbb vous prvient dune faille de scurit. Il refusera de fonctionner tant que vous naurez pas corrig ce qui le tracasse. Pour les besoins de la configuration, le fichier config.ini tait librement modifiable. Maintenant que la configuration est termine et que vous avez cr un administrateur, PHPbb vous demande de changer les attributs du fichier. Pour cela, rendez-vous dans le rpertoire "phpBB", sur votre serveur web ou chez votre hbergeur, et reprez le fichier config.ini. Dans votre explorateur de fichiers ou votre logiciel de FTP, modifiez les proprits du fichier. Il faut quil soit en lecture seule. Vous pouvez retourner dans votre navigateur et rafrachir la page sur laquelle vous avez laiss PHPbb. Vous voici dsormais

1408

Phorum : un moteur de forums

dans lespace dadministration de PHPbb. Si, de rage, vous aviez ferm votre navigateur, voici ladresse : http://www.votresite.com/phpBB/admin/. Donnez les login et mot de passe de ladministrateur et cliquez sur submit. Vous arrivez alors dans le panneau dadministration de PHPbb. Il vous faut maintenant crer une nouvelle catgorie. Cliquez sur le lien add a category, donnez un nom de catgorie, "test" par exemple pour commencer, puis cliquez sur create category. Retournez sur la page dadministration en cliquant sur le lien Panneau dadministration. Vous allez maintenant devoir crer un forum en cliquant sur le lien Add a forum. Donnez un nom au forum, donnez une description, nommez des modrateurs (pour le moment, il ny a que ladministrateur), choisissez une catgorie dans laquelle apparatra le forum (do lintrt davoir cr la catgorie avec le forum). Ne touchez pas les deux dernires options pour le moment ; vous pourrez les modifier et indiquer ainsi qui pourra crire dans le forum et si le forum lui-mme sera public ou priv. Cliquez sur Create forum. Noubliez pas de cliquer sur le nom dun modrateur avant de valider. Attention ! si vous oubliez un champ, PHPbb videra tous les autres champs lorsque vous reviendrez sur la page de configuration. Vous devrez repartir de zro dans la dfinition du forum. Lorsque la cration du forum a eu lieu, revenez sur la page daccueil de votre site avec PHPbb. Vous allez toucher du doigt une petite difficult de linstallation de PHPbb. Il vous faut cliquer sur le nom du forum que vous avez cr. Vous arrivez alors sur une nouvelle page : la page principale du forum. Vous allez devoir crer un sujet dans ce forum. Le lien se situe tout en haut droite de la page web, cest limage New Topic. Cliquez dessus. Donnez alors un titre et une description pour ce sujet. Une fois cette opration effectue, revenez sur la page principale du forum et cliquez sur le sujet que vous avez donn. Vous allez pouvoir entamer une discussion passionnante et enfivre.

21. Annexe A : des exemples dapplications

21.4. Phorum : un moteur de forums


Phorum est un moteur de forums libre et gratuit. En plus dtre lger, il sinstalle trs facilement et trs rapidement. Il dispose dune aide linstallation qui vite de passer par ldition des fichiers de configuration.

Figure 21.8 : Phorum

Phorum fonctionne avec MySQL ou PostgreSQL.

1409

Chapitre 21

Annexe A : des exemples dapplications

Tlchargez tout dabord larchive contenant Phorum directement sur le site de Phorum ladresse http://www.phorum.org, ou bien utilisez celle prsente sur le CD-ROM de la Bible. Noubliez pas de tlcharger, en plus, le fichier de francisation french.php (fichier galement disponible sur le CD-ROM). Avant de vous lancer dans la procdure dinstallation, il faut que vous criez une nouvelle base sur votre serveur de bases de donnes. Elle sera utilise par Phorum et vous devrez donner son nom lors de la procdure dinstallation. Pour commencez : dcompactez larchive de Phorum quelque part sur votre site web. Une fois les fichiers copis dans larborescence de votre site web, que ce soit en local ou chez un hbergeur, rendez-vous dans ladministration en ligne de Phorum pour paramtrer les forums. L"admin" est accessible via lURL : http://votresite/votredossierphorum/admin/index.php/. Choisissez une langue utiliser pour linstallation puis cliquez sur le bouton Next step. Grce au menu droulant, choisissez le serveur de bases de donnes avec lequel devra travailler Phorum, puis cliquez sur le bouton Submit. Vous arrivez ensuite sur une page qui vous demande les paramtres de connexion cette base.
Figure 21.9 : Configuration des paramtres de connexion

21. Annexe A : des exemples dapplications

Vous devrez donner le nom du serveur de bases de donnes, le nom de la base utiliser (noubliez pas den crer une pour loccasion), ainsi quun nom dutilisateur et un mot de passe pour se connecter cette base. Il faudra galement spcifier le nom de la table qui sera utilise par Phorum. Par dfaut, le nom forums est donn automatiquement. Une fois tous les champs renseigns, cliquez sur Submit. Maintenant que la connexion la base sest effectue et que les nouvelles tables sont ajoutes, Phorum vous invite crer un administrateur. Donnez un nom dutilisateur et un mot de passe dans les champs prvus cet effet, puis cliquez une nouvelle fois sur Submit. Il ne reste alors plus qu donner ladresse laquelle le forum sera accessible et ladresse e-mail de ladministrateur du forum. Votre Phorum est maintenant install. Mais, comme vous pouvez vous en rendre compte en allant sur sa page daccueil, il est dsesprment vide. Il faut en effet que vous amorciez la pompe en crant un premier forum. Rendez-vous dans ladmin de votre forum (http://votresite/dossierphorum/admin/index.php).

1410

Phorum : un moteur de forums

Figure 21.10 : Page dadministration de Phorum

Depuis ladmin, dans le bloc central Forum Maintenance, cliquez sur le lien New Forum. Vous arrivez alors sur une page qui permet la cration dun forum. Parmi toutes les options proposes, deux seulement sont obligatoires : le nom du nouveau forum et la table quil utilisera dans la base de donnes associe votre Phorum. Une fois le forum cr, vous pouvez dj lutiliser. Vous ntes pas oblig de prsenter vos forums directement les uns la suite des autres. Vous avez la possibilit de crer des dossiers (folders) dans lesquels il est possible de regrouper des forums. Il suffit, pour cela, depuis ladmin, de crer un nouveau folder. Ensuite, lors de la cration dun nouveau forum, vous pourrez, laide dun menu droulant, lui associer un folder particulier. Cette option est particulirement pratique quand un site commence avoir un certain nombre de forums... Noubliez pas de franciser linterface utilisateur de Phorum. Vous navez qu copier le fichier francais-3.3.2c.php dans le dossier lang de larborescence de votre installation de Phorum. Une fois le fichier copi, rendez-vous dans la page dadministration.

21. Annexe A : des exemples dapplications

Figure 21.11 : Slection de la langue

Cliquez sur le lien Global Options. la ligne Default Language, dans le menu droulant, vous pourrez alors choisir le franais.

Autres
Il existe videmment dautres forums comme :
j j j

NeoBoard, disponible ladresse http://www.neoboard.net:8080/NeoBoard/ ; electrifiedForum (eF), disponible ladresse http://www.electrifiedpenguin.com/mainindex.php ; bestweb Forum, disponible ladresse http://www.bestweb.ca/.

1411

Chapitre 21

Annexe A : des exemples dapplications

Entre portail et forum :


j

myWBBPortal, disponible ladresse http://www.wbbhacks.com/.

21.5. Annuaires de liens


Netref
Netref vous permet en quelques minutes dinstaller un annuaire de liens sur votre site. Netref est une application crite en PHP fonctionnant avec des bases de donnes MySQL, et qui se configure trs facilement. Du mme type que des annuaires tels que Yahoo ! par exemple, il vous permettra de grer diffrentes catgories et sous-catgories, des suggestions de liens faites par les internautes, un classement des liens les plus visits. Son interface dadministration est claire, et vous permet, entre autres, de vrifier les liens soumis, de visualiser linterface de votre annuaire, etc. Le programme est disponible en cinq langues : franais, anglais, italien, sudois ou hollandais.

21. Annexe A : des exemples dapplications

Figure 21.12 : Une base de liens gre avec Netref

Tout dabord, tlchargez le fichier netref.zip ladresse http://www.web-ref.net/annu/inscr/index.php. Dans larborescence de votre site, crez un rpertoire annuaire la racine de votre site, puis dcompactez le fichier dans le rpertoire annuaire. Vous devez ensuite paramtrer le fichier option.php. Indiquez les paramtres de connexion votre base de donnes.
$host="localhost";

1412

Solutions de travail collaboratif

Indiquez ici le nom dhte du serveur de bases de donnes.


$user="username";

Indiquez ici votre nom dutilisateur utilis pour votre connexion la base de donnes.
$pass="password";

Indiquez ici votre mot de passe utilis pour votre connexion la base de donnes.
$bdd="basename";

Indiquez ici le nom de la base de donnes utiliser. Passez ensuite ladministrateur de lannuaire :
$psadmin[0]="sylgil";

Donnez ici le nom dutilisateur qui doit tre utilis pour ladministrateur.
$passadmin[0]="alfred";

Donnez ici le nom dutilisateur qui sera requis pour ladministrateur. Enfin, publiez le rpertoire annuaire sur votre espace dhbergement, et rendez-vous sur la page www.votresite.net/annuaire/admin/. Entrez alors vos identifiants pour accder au menu de ladministration, puis cliquez sur Crer les tables sql. Voil, votre annuaire est prt. Vous pouvez crer les catgories et sous-catgories partir du menu dadministration.

21. Annexe A : des exemples dapplications

Autres
Quelques autres annuaires de liens :
j j j

phpMyAnnu, disponible ladresse http://www.creation-de-site.net/ ; HitWeb, disponible ladresse http://www.freesoftware.fsf.org/hitweb/ ; PHPMyLinks, disponible ladresse http://rhenriot.free.fr/phpmylinks/.

21.6. Solutions de travail collaboratif


Moregroupware
Moregroupware est un outil de groupware (travail collaboratif) trs complet. Il vous permettra de grer votre groupe de travail en toute simplicit. Vous pourrez crer diffrents groupes et utilisateurs, et leur attribuer des droits divers. Diffrents modules sont votre disposition : un calendrier pour grer plusieurs plannings, un rpertoire, un module dinformations gnrales, un webmail, etc. Il peut se mettre en relation avec diffrents types de bases de donnes (MySQL, PostgreSQL, Oracle...). Il supporte plusieurs langues, dont le franais.

1413

Chapitre 21

Annexe A : des exemples dapplications

21. Annexe A : des exemples dapplications

Figure 21.13 : Moregroupware

Compatibilit PHP5 La version 0.7.2 de Moregroupware nest pas encore compatible avec PHP5. Les dveloppeurs y travaillent en modifiant le code du moteur. Ainsi, Moregroupware devrait rapidement devenir compatible avec la version la plus rcente de PHP.

Installation
Avant tout, assurez-vous que votre php.ini est configur avec la fonction magic_quotes active. Tlchargez Moregroupware ladresse http://www.moregroupware.org/download.php, ou utilisez le fichier disponible sur le CD-ROM de la Bible. Dcompactez le fichier la racine de votre site, puis rendez-vous ladresse http://www.monsite.com/moregroupware/. Une page saffichera vous demandant de configurer votre groupware. Cliquez alors sur le lien Slectionnez le langage et entrez les donnes de connexion votre base de donnes. Choisissez alors les modules que vous souhaitez installer puis validez. Un message de confirmation de linstallation apparat. Rendezvous alors ladresse qui vous sera indique en rouge pour administrer votre groupware. Vous devrez utiliser lidentifiant et le mot de passe par dfaut : login admin et mot de passe admin.

1414

Solutions de travail collaboratif

Principales fonctions
Admin
Depuis linterface de ladministrateur, vous pouvez grer les utilisateurs, les groupes dutilisateurs, les projets, etc. Rendez-vous tout dabord sur linterface dadministration pour changer le mot de passe administrateur et crez les utilisateurs. Entrez dans Moregroupware avec les mots de passe par dfaut. Dans la partie Admin, puis dans Gestionnaire dutilisateurs, ditez la fiche de lutilisateur admin. Compltez-la, choisissez le mot de passe et le langage appropris, puis validez. La procdure de cration des autres utilisateurs est similaire. Vous pouvez ensuite attribuer les droits et les accs aux modules pour chacun des utilisateurs dans le gestionnaire des droits, et rpartir les membres dans diffrents groupes.

Calendrier
Dans ce module, chaque utilisateur pourra grer son planning, visualiser et/ou modifier celui des autres membres. Vous pourrez crer des vnements ponctuels ou rpts.

Contacts
Cette rubrique vous permet de grer des contacts aussi bien individuels que par groupe, par entreprise ou par fonction. Elle contient un moteur de recherche.

21. Annexe A : des exemples dapplications

Aperu
Laperu regroupe les vnements vous concernant qui ont t planifis : vos rendez-vous, les tches que vous devez effectuer, etc.

Projets
Administrez les projets du groupe de travail : crez des projets, dterminez les membres qui interviendront dessus, crez des fiches de travail pour suivre lvolution de chacun et obtenir un aperu gnral de lavancement du projet.

Conguration
Modifiez vos donnes personnelles, configurez votre webmail et dterminez vos prfrences quant laffichage des diverses rubriques.

Tches
Grez les tches concernant les diffrents projets : vos tches personnelles, celles qui vous ont t dlgues, celles que vous avez dlgues. Vous pourrez suivre leur progression.

Webmail
Envoyez et recevez vos e-mails. Attention, noubliez pas de bien indiquer votre adresse dans le champ adresse de retour lors de la configuration, sans quoi vos destinataires ne pourront pas rpondre automatiquement vos e-mails.

1415

Chapitre 21

Annexe A : des exemples dapplications

Autres
Quelques solutions supplmentaires :
j j j

PHPProjekt, disponible ladresse http://www.phpprojekt.com/ ; Tutos, disponible ladresse http://www.tutos.org/ ; Twig, disponible ladresse http://twig.screwdriver.net/.

Et il en existe bien dautres

21.7. Graphiques
JPGraph
Prsentation
JPGraph est une bibliothque en PHP qui permet de crer simplement et rapidement des

21. Annexe A : des exemples dapplications

graphiques en tous genres partir de diverses sources. Avant daller plus loin, rendons grce Johann Persson, crateur de cet outil quil a bien voulu mettre librement la disposition de tous les utilisateurs de PHP. La gnration dynamique de graphiques partir de donnes statiques ou de variables peut constituer un rel "plus" pour un site web. Cela offre une vision synthtique de bien des sujets, tout en agrmentant des dmonstrations qui, sinon, seraient bien austres. Les applications pratiques dun gnrateur de graphiques, tableaux et autres camemberts nont plus faire leurs preuves ; en tmoigne le large succs dun logiciel comme MS Excel. Toutes ces solutions sont maintenant la porte de votre site web grce JPGraph.
JPGraph est une librairie en PHP oriente objet. Toutes les informations ncessaires la ralisation dun graphique sont regroupes dans un seul fichier PHP.

Figure 21.14 : Un graphique gnr la vole par JPGraph

1416

Graphiques

Avant de vous lancer dans JPGraph, il faut vous assurer que vous disposez bien des outils ncessaires : un PHP version 4.02 ou ultrieure ainsi que le support de la librairie GD 1.x. Pour savoir si votre hbergeur rpond aux conditions, faites un simple phpinfo() et vous serez vite fix.

Vous pouvez consulter le chapitre "Les images et les animations Flash"

La gnration dun graphique ne demande que peu de lignes dun code qui sera vite produit. Avant cela, il faut tout de mme passer par linstallation et la configuration de JPGraph.

Compatibilit PHP5 La version 1.16 de JPGraph ne supporte pas encore PHP5. Il vous faudra conserver une version antrieure de PHP (4.x) pour utiliser JPGraph ou bien attendre que la compatibilit avec PHP5 soit annonce sur le site officiel du projet www.aditus.nu/jpgraph.

Installation
21. Annexe A : des exemples dapplications
Installez directement JPGraph depuis le fichier zipp prsent sur le CD-ROM, ou tlchargez une version plus rcente en ligne (sil en existe une) ladresse http://www.aditus.nu/jpgraph/. Dcompactez les fichiers dans un dossier spcialement prvu cet effet dans larborescence de votre serveur web. Le fichier zipp de JPGraph cre un dossier jpgraph-1.16 au sein du rpertoire dans lequel il sinstalle (vous pouvez le renommer dossier). la racine du dossier JPGraph, vous trouverez la licence de distribution du logiciel ainsi quun fichier README contenant des instructions dinstallation (mais videmment en anglais). Se trouve galement dans le rpertoire JPGraph un dossier src. Les dossiers Exemples et utils contiennent, comme leur nom lindique, des exemples dutilisation de JPGraph ainsi que divers utilitaires pour aller plus loin dans lutilisation de JPGraph. Pour que vous puissiez travailler avec JPGraph, ditez le fichier jpgraph.php situ dans le dossier src. Vous avez globalement peu de paramtres renseigner. Recherchez la ligne suivante :
DEFINE("CACHE_DIR","/tmp/jpgraph_cache/");

Vous devez donner un dossier temporaire qui sera utilis par JPGraph. Faites bien attention quApache puisse y crire. Renseignez ensuite cette ligne :
DEFINE("TTF_DIR","/usr/local/fonts/ttf/");

Donnez l le chemin qui pointe vers les polices TrueType installes sur votre systme (traditionnellement C:\WINDOWS\FONTS sous Windows). Une fois ces deux lignes compltes, vous pouvez appeler directement le fichier testsuit_jpgraph .php depuis un navigateur web, en ayant pris soin de vous assurer que votre serveur web fonctionnait bien. Vous verrez alors toutes les potentialits de JPGraph.

1417

Chapitre 21

Annexe A : des exemples dapplications

En cas de problme, appelez la police Certains des exemples donns par JPGraph peuvent manquer lappel et ne pas fonctionner correctement. Dans la majeure partie des cas, cela vient dune police utilise qui nest pas prsente sur votre systme. Deux solutions soffrent vous : modifier le fichier dexemple pour spcifier une autre police ou bien installer celle qui manque lappel.

Utilisation
JPGraph tant oriente objet, la cration dun graphique se rsume peu de choses. Voici un

exemple de script :
<?php include("local/jpgraph.php");

Vous devez faire un appel jpgraph.php dans chacun des fichiers de cration dun graphique. la place de "local", donnez le chemin vers le fichier jpgraph.php sur votre machine. Dans notre cas, nous souhaitons crer un graphique en toile daraigne ; nous devons donc galement inclure le script jpgraph_spider.php.

21. Annexe A : des exemples dapplications

include("local/jpgraph_spider.php");

Vous donnez ici le fichier de description du graphique que vous voulez crer. Vous trouverez dans le fichier README prsent la racine du dossier JPGraph une liste des fonctions utilisables. Pour savoir comment utiliser ces fonctions, les diffrents exemples inclus dans JPGraph pourront vous servir. Consultez galement laide pour obtenir dautres informations. Les donnes doivent gnralement est donnes via un tableau.
$data = array(30, 40, 50, 60, 70);

chaque type de graphique correspond un objet (ici SpiderGraph) auquel est communique la taille de limage.
$graph = new SpiderGraph(250,200,"auto"); $plot = new SpiderPlot($data);

Vous pouvez ensuite lancer la cration du graphique avec les valeurs que vous avez affectes la variable $data.
$graph->Add($plot); $graph->Stroke(); ?>

Pour utiliser une image gnre par la librairie JPGraph, appelez celle-ci directement dans une balise img, comme ceci :
<img src="graphique1.php" border=0 align=center width=300 height=200>

1418

Chapitre 22

Annexe B : les en-ttes HTTP et les variables externes

Annexe B : les en-ttes HTTP et les variables externes

Vous trouverez dans le tableau suivant une liste des en-ttes HTTP les plus courants, quils soient mis par le client destination du serveur (C->S) ou par le serveur destination du client (S->C).

Tableau 22.1 : En-ttes HTTP les plus courants


En-tte Accept Sens C->S Signification, exemples de valeurs, variable externe associe Type de contenu que le navigateur est susceptible daccepter (text/html, audio/x-aiff, image/jpeg, etc.) Il sagit dune chane de caractres construite par la concatnation des diffrents MIME-type supports, spars par une virgule. Une srie de types peut tre pondre par un coefficient (indiquant une notion de prfrence) ; la chane est alors suivie dun point-virgule puis de q= suivi du coefficient (<1).

Exemple : text/xml,text/html;q=0.9,text/plain;q=0.8, image/jpeg,q=0.2 Cette valeur est accessible depuis $_SERVER["HTTP_ACCEPT"]. AcceptCharset C->S Le type de caractre que le navigateur attend en rponse (ex. : ISO-8859-1). Il sagit dune chane de caractres construite par la concatnation des diffrents encodages supports, spars par une virgule. Une srie de types peut tre pondre par un coefficient (indiquant une notion de prfrence) ; la chane est alors suivie dun pointvirgule puis de q= suivi du coefficient (<1).

22. Annexe B : les enttes HTTP et les variables externes

Exemple : ISO88591, utf8;q=0.66,*;q=0.33 Cette valeur est accessible depuis $_SERVER["HTTP_ACCEPT_CHARSET"]. AcceptEncoding C->S Le type de compression que le navigateur est capable de supporter en rponse. Il sagit dune chane de caractres construite par la concatnation des diffrentes compressions supportes, spares par une virgule. Une srie de types peut tre pondre par un coefficient (indiquant une notion de prfrence) ; la chane est alors suivie dun point-virgule puis de q= suivi du coefficient (<1).

Exemple : Gzip, deflate, compress;q=0.9 Cette valeur est accessible depuis $_SERVER["HTTP_ACCEPT_ENCODING"].

1421

Chapitre 22

Annexe B : les en-ttes HTTP et les variables externes

En-tte AcceptLanguage

Sens C->S

Signification, exemples de valeurs, variable externe associe La langue prfre de lutilisateur. Il sagit dune chane de caractres construite par la concatnation des diffrents codes de langue supports, spars par une virgule. Une srie de types peut tre pondre par un coefficient (indiquant une notion de prfrence) ; la chane est alors suivie dun point-virgule puis de q= suivi du coefficient (<1).

Exemple : fr, en;q=0.50 Cette valeur est accessible depuis $_SERVER["HTTP_ACCEPT_LANGUAGE"]. Referer C->S Adresse de la page depuis laquelle la requte a t effectue

Exemple : http://www.unannuairedelien.com/ Cette valeur est accessible depuis $_SERVER["HTTP_REFERER"]. UserAgent C->S Chane didentification du client. Exemple : Mozilla/5.001 (windows; U; NT4.0; enus) Gecko/25250101

22. Annexe B : les enttes HTTP et les variables externes

Cette valeur est accessible depuis $_SERVER["HTTP_USER_AGENT"]. Host C->S S->C Nom de la machine cliente. Paramtrage du cache. En-ttes de gestion du cache CacheControl Exemple : maxage=60 (dure de vie du document limite 60 secondes). Expires S->C Limite de validit du document. Exemple : Sat, 27 Apr 2002 16:00:53 GMT Pragma S->C Gestion du cache. Exemple : nocache (le document ne doit pas tre mis en cache). Dclaration du contenu du document ContentType S->C Exemple : text/html MIME-type du document mis par le serveur.

1422

Annexe B : les en-ttes HTTP et les variables externes

En-tte

Sens

Signification, exemples de valeurs, variable externe associe Type de compression (ou plus gnralement codage) utilis pour le document mis par le serveur.

ContentEncoding S->C

Exemple : Compress Gzip Deflate ContentLength S->C Taille (en octets) du document mis par le serveur. Langue utilise dans le document. Indique au client de se tourner vers une autre adresse.

ContentLanguage S->C Redirection Location S->C

Exemple : http://www.autredomaine.com Informations serveur Server S->C Identifiant du serveur. Exemple : Apache/1.3.26 (Unix) PHP/4.2.2 Date S->C Date et heure du serveur. Exemple : Sat, 27 Apr 2002 15:59:53 GMT En-ttes de mails From To Cc Bcc ReplyTo Subject MIMEVersion Spcifie ladresse de lmetteur du mail. Spcifie les adresses des destinataires du mail. Spcifie les adresses des personnes mises en copie du mail. Spcifie les adresses des personnes mises en copie cache du mail. Spcifie ladresse laquelle le destinataire du mail doit rpondre. Titre du mail. Numro de version de la norme MIME utilise.

1423

22. Annexe B : les enttes HTTP et les variables externes

Chapitre 23

Annexe C : les erreurs HTTP

Annexe C : les erreurs HTTP

Tableau 23.1 : Les principaux codes derreur que peut retourner un serveur web
Code 100 - 199 200 - 299 200 204 300 - 399 300 301 302 303 400 - 499 400 401 Signification Les informations sont retournes. La requte a t traite avec succs. Aucun incident signaler. Le "document" retourn est vide. Demande de redirection. Le serveur a besoin de plus dinformations. Le document demand a t dplac dfinitivement. Le document demand a t dplac temporairement (les requtes suivantes ne ncessiteront pas forcment de redirection). Le document doit tre demand une autre adresse. La requte est incomplte. La requte nest pas valide. Lauthentification a chou. Si ce nest pas le rsultat attendu, sous Apache, vrifiez que les fichiers .htaccess et .htpasswd (le nom peut tre diffrent) contiennent bien les nom et mot de passe que vous saisissez. Accs interdit. La page demande au serveur na pu tre trouve. La mthode utilise est refuse par le serveur. Authentification proxy exige. Authentification proxy exige. Dlai dattente de la requte du client dpass. Le serveur a besoin de la longueur de la requte. La requte est trop longue. Indique une erreur du serveur HTTP. Erreur interne du serveur. Assurez-vous de ne pas avoir cr une boucle comme, par exemple, une srie infinie de redirections (ce qui peut arriver lors des traitements automatiques des erreurs). Dlai dattente dpass.

403 404 405 406 407 408 411 413 500 - 599 500

23. Annexe C : les erreurs HTTP

504

1427

Index des fonctions et mthodes


!
__clone, 244 __construct, 220 __destruct, 243 __FILE__, 118 __LINE__, 118 __sleep, 242 __wakeup, 242 array_keys, 180 array_key_exists, 182 array_map, 202 array_merge, 200 array_merge_recursive, 201 array_multisort, 196 array_pad, 183 array_pop, 190 array_push, 190 array_rand, 180 array_reduce, 203 array_reverse, 191 array_search, 181 array_shift, 191 array_slice, 183 array_splice, 184 array_sum, 198 array_unique, 179 array_unshift, 191 array_values, 179 array_walk, 204 arsort, 193 asin, 331 asinh, 334 asort, 192 atan, 332 atan2, 332 atanh, 335 binDec, 344 break, 154, 157

C
call_user_func, 172 call_user_func_array, 172 case, 156 ceil, 336 chdir, 539 checkDate, 443 checkDNSRR, 1267 chgrp, 532 chmod, 531 chop, 399 chown, 532 chr, 363 chunk_split, 401 class_exists, 239 clearStatCache, 559 closeDir, 519 compact, 186 const, 222 continue, 157 convert_cyr_string, 394 copy, 526 cos, 330 cosh, 333 count, 178-179 count_chars, 371 crc32, 407 create_function, 168 crypt, 408 curl_close, 1290 curl_errno, 1295 curl_error, 1295 curl_exec, 1294 curl_getinfo, 1294 curl_init, 1290 curl_setopt, 1290 curl_version, 1295 current, 187

A
abs, 346 acos, 330 acosh, 334 addCSlashes, 386 addSlashes, 357, 385 ArrayObject, 246 append, 246 count, 247 current, 248 getIterator, 248 key, 248 next, 249 offsetExists, 247 offsetGet, 247 offsetSet, 246 offsetUnset, 247 rewind, 249 seek, 249 valid, 248 __construct, 246 array_change_key_case, 185 array_chunk, 185 array_count_values, 198 array_diff, 199 array_fill, 183 array_filter, 201 array_flip, 179 array_intersect, 199 array_intersect_assoc, 200

B
base64_encode, 966 basename, 541 base_convert, 344 bcadd, 349 bccomp, 351 bcdiv, 350 bcmod, 350 bcmul, 350 bcpow, 350 bcscale, 349 bcsqrt, 351 bcsub, 349

1429

date

D
date, 438 DB affectedRows, 885 autoCommit, 877 commit, 878 createSequence, 886 disconnect, 875 execute, 886 executeMultiple, 886 getAll, 882 getAssoc, 882 getCol, 881 getListOf, 898 getOne, 880 getRow, 881 isError, 888 limitQuery, 874 netxId, 887 prepare, 885 provides, 899 query, 873 rollback, 878 DB_Result fetchInto, 880 fetchRow, 878 numRows, 884 decBin, 344 decHex, 345 decOct, 345 default, 156 define, 117 deg2rad, 332 dirname, 542 diskfreespace, 562 disk_free_space, 562 disk_total_space, 563 DNS_check_record, 1267 DNS_get_mx, 1268 do, 153 DOMAttr isId, 1222 DOMDocument createAttribute, 1218, 1226 createAttributeNS, 1218, 1226 createCDATASection, 1218, 1226 createComment, 1218, 1226 createDocumentFragment, 1218 createElement, 1218, 1227 createElementNS, 1218, 1227 createEntityReference, 1218 createProcessingInstruction, 1218 createTextNode, 1218, 1227

getElementById, 1218 getElementByTagName, 1218 importNode, 1218 load, 1218, 1223 loadHTML, 1218, 1224 loadHTMLFile, 1219, 1224 loadXML, 1219, 1224 normalize, 1219 relaxNGValidate, 1219 relaxNGValidateSource, 1219 save, 1219, 1225 saveHTML, 1219, 1225 saveHTMLFile, 1219, 1225 saveXML, 1219, 1225 schemaValidate, 1219 schemaValidateSource, 1219 validate, 1219 xinclude, 1219 DOMElement getAttribute, 1221, 1230 getAttributeNode, 1221 getAttributeNodeNS, 1221 getAttributeNS, 1221 getElementByTagName, 1221 getElementByTagNameNS, 1221 getElementsByTagName, 1230 hasAttribute, 1221 hasAttributeNS, 1221 removeAttribute, 1221 removeAttributeNode, 1222 removeAttributeNS, 1222 setAttribute, 1222 setAttributeNode, 1222 setAttributeNodeNS, 1222 setAttributeNS, 1222 DOMNode appendChild, 1220, 1228 cloneNode, 1220, 1229 hasAttributes, 1220 hasChildNodes, 1220 insertBefore, 1220 isSameNode, 1220 isSupported, 1221 lookupNamespaceURI, 1221 lookupPrefix, 1221 normalize, 1221 removeChild, 1221, 1229 replaceChild, 1221, 1229 DOMNodeList item, 1229 DOMText isWhitespaceInElementContent, 1222 splitText, 1223 DOMXPath query, 1230 dropSequence, 887

E
each, 189 easter_date, 444 easter_days, 445 echo, 115, 357 else, 149 elseif, 150 empty, 125 end, 189 endfor, 154 endif, 151 endwhile, 152 ereg, 428 eregi, 428 eregi_replace, 427 ereg_replace, 426 error_reporting, 146 escapeshellarg, 1312 escapeshellcmd, 1312 escapeSimple, 887 Exception __construct, 237 getCode, 237 getFile, 237 getLine, 238 getMessage, 237 getTrace, 238 exec, 1313 exif_imageType, 1079 exif_read_data, 1079 exif_thumbnail, 1082 exp, 333 explode, 403 extract, 186

F
fclose, 494, 1273 feof, 513, 1272 fflush, 517 fgetc, 497 fgetcsv, 508 fgets, 498, 1272 fgetss, 505 file, 502 fileatime, 552 filectime, 553 fileGroup, 549 fileInode, 553 filemtime, 551 fileOwner, 548 filePerms, 560 fileSize, 547

1430

imageFilledEllipse

fileType, 545 file_exists, 547 file_get_contents, 504 file_get_wrapper_data, 493 floor, 337 flush, 292 fopen, 490 for, 153 foreach, 154 fpassthru, 504 fputs, 495, 1272 fread, 497 frenchToJD, 448 fscanf, 499 fseek, 514 fSockOpen, 1271 fstat, 558 ftell, 513 ftp_cdup, 1277 ftp_chdir, 1277 ftp_close, 1277 ftp_connect, 1276 ftp_delete, 1279 ftp_exec, 1286 ftp_fget, 1280 ftp_fput, 1281 ftp_get, 1279 ftp_get_option, 1287 ftp_login, 1276 ftp_mdtm, 1288 ftp_mkdir, 1278 ftp_nb_continue, 1286 ftp_nb_fget, 1286 ftp_nb_fput, 1286 ftp_nb_get, 1286 ftp_nb_put, 1286 ftp_nlist, 1278 ftp_pasv, 1287 ftp_put, 1280 ftp_quit, 1277 ftp_rawlist, 1278 ftp_rename, 1279 ftp_rmdir, 1279 ftp_set_option, 1287 ftp_site, 1286 ftp_size, 1288 ftp_systype, 1288 ftruncate, 516 function_exists, 169 func_get_arg, 164 func_get_args, 165 func_num_args, 164 fwrite, 494

G
gd_info, 1026 getcwd, 538 getDate, 437 getElementByTagNameNS, 1218 getEnv, 132 getHostByAddr, 1266 getHostByName, 1265 getHostByNameL, 1266 getImageSize, 1078 getMXRR, 1268 getProtoByName, 1270 getProtoByNumber, 1270 getRandMax, 340 getServByName, 1269 getServByPort, 1269 getTimeOfDay, 442 getType, 122 get_cfg_var, 281 get_class, 238 get_class_methods, 239 get_class_vars, 239 get_declared_classes, 241 get_declared_interfaces, 241 get_defined_functions, 170 get_defined_vars, 131 get_html_translation_table, 390 get_included_files, 209 get_meta_tags, 396 get_object_vars, 240 get_parent_class, 240 glob, 524 global, 160 gmdate, 442 gmmktime, 442 gmstrftime, 442 gregorianToJD, 447 gzclose, 579 gzcompress, 588 gzdeflate, 590 gzencode, 591 gzeof, 586 gzfile, 583 gzgetc, 581 gzgets, 582 gzgetss, 585 gzinflate, 591 gzopen, 578 gzpassthru, 584 gzputs, 580 gzread, 581 gzrewind, 587 gzseek, 587 gztell, 586 gzuncompress, 589 gzwrite, 580

H
haltMsg, 317 header, 258 headers_sent, 259 hebrev, 395 hebrevc, 395 hexDec, 345 htmlEntities, 389 htmlSpecialChars, 357, 388

I
if, 148 image2WBMP, 1032 imageAlphaBlending, 1071 imageArc, 1054 imageChar, 1043 imageCharUp, 1043 imageColorAllocate, 1033 imageColorAt, 1065 imageColorClosest, 1036 imageColorClosestAlpha, 1037 imageColorClosestHWB, 1037 imageColorDeallocate, 1040 imageColorExact, 1035 imageColorExactAlpha, 1036 imageColorResolve, 1038 imageColorResolveAlpha, 1038 imageColorSet, 1039 imageColorsForIndex, 1039 imageColorsTotal, 1041 imageColorTransparent, 1034 imageCopy, 1065 imageCopyMerge, 1066 imageCopyMergeGray, 1068 imageCopyResampled, 1070 imageCopyResized, 1069 imageCreate, 1027 imageCreateFromGD, 1028 imageCreateFromGD2, 1028 imageCreateFromGD2part, 1030 imageCreateFromGIF, 1028 imageCreateFromJPEG, 1029 imageCreateFromPNG, 1029 imageCreateFromWBMP, 1029 imageCreateFromXBM, 1029 imageCreateFromXPM, 1030 imageCreateTrueColor, 1028 imageDashedLine, 1053 imageDestroy, 1032 imageEllipse, 1057 imageFilledArc, 1055 imageFilledEllipse, 1057

1431

imageFilledRectangle

imageFilledRectangle, 1059, 1061 imageFontHeight, 1043 imageFontWidth, 1044 imageFTBBox, 1048 imageFTText, 1048 imageGammaCorrect, 1039 imageGD, 1030 imageGD2, 1031 imageGIF, 1031 imageJPEG, 1031 imageLine, 1053 imageLoadFont, 1044 imagePolygon, 1060 imagePSBBox, 1051 imagePSEncodeFont, 1051 imagePSExtendFont, 1052 imagePSFreeFont, 1052 imagePSLoadFont, 1051 imagePSSlantFont, 1052 imagePSText, 1050 imageRectangle, 1058 imageRotate, 1071 imageSetBrush, 1063 imageSetPixel, 1053 imageSetStyle, 1063 imageSetThickness, 1064 imageSetTile, 1064 imageString, 1041 imageStringUp, 1042 imageSX, 1072 imageSY, 1072 ImageTrueColorToPalette, 1040 imageTTFBBox, 1047 imageTTFText, 1045 imageWBMP, 1032 imap_8bit, 1009 imap_alert, 1011 imap_append, 1004 imap_base64, 1010 imap_binary, 1010 imap_body, 995 imap_bodyStruct, 998 imap_check, 983 imap_clearFlag_full, 1002 imap_close, 978 imap_createMailbox, 1018 imap_delete, 1003 imap_deleteMailbox, 1019 imap_errors, 1011 imap_expunge, 1004 imap_fetchBody, 998 imap_fetchHeader, 988 imap_fetchStructure, 995 imap_fetch_overview, 987 imap_getMailboxes, 980 imap_getSubscribed, 982 imap_get_quota, 1017 imap_header, 991

imap_headerInfo, 990 imap_headers, 986 imap_last_error, 1012 imap_listMailbox, 979 imap_listSubscribed, 982 imap_mail, 1008 imap_mailboxMsgInfo, 983 imap_mail_compose, 1009 imap_mail_copy, 1005 imap_mail_move, 1005 imap_mime_header_decode, 1011 imap_msgno, 1006 imap_num_msg, 984 imap_num_recent, 985 imap_open, 977 imap_ping, 978 imap_qprint, 1009 imap_renameMailbox, 1019 imap_reopen, 979 imap_rfc822_parse_adrlist, 1007 imap_rfc822_write_address, 1007 imap_scanmailbox, 980 imap_search, 1000 imap_setFlag_full, 1002 imap_set_quota, 1018 imap_sort, 1001 imap_status, 985 imap_subscribe, 1005 imap_uid, 1006 imap_undelete, 1003 imap_unsubscribe, 1006 imap_utf7_decode, 1010 imap_utf7_encode, 1010 imap_utf8, 1011 implode, 402 include, 206 include_once, 209 instanceOf, 221 IntegratedTemplate, 320 get, 323 loadTemplateFile, 321 parse, 322 parseCurrentBlock, 322 setCurrentBloc, 321 setRoot, 322 setVariable, 321 show, 320 touchBlock, 323 in_array, 182 ip2long, 1267 isSet, 124 is_array, 128, 178 is_bool, 126 is_dir, 543 is_double, 127 is_executable, 546 is_file, 544

is_finite, 328 is_float, 127 is_infinite, 328 is_int, 126 is_integer, 127 is_link, 544 is_long, 127 is_nan, 328 is_NULL, 130 is_numeric, 127 is_object, 129 is_readable, 545 is_real, 127 is_resource, 130 is_scalar, 129 is_string, 128 is_subclass_of, 240 is_uploaded_file, 535 is_writable, 546 is_writeable, 546

J
JDDayOfWeek, 449 JDMonthName, 449 JDToFrench, 448 JDToGregorian, 446 JDToJewish, 447 JDToJulian, 448 JDToUnix, 446 jewishToJD, 447 julianToJD, 448

K
key, 187 krsort, 195 ksort, 195

L
lcg_value, 343 ldap_add, 910 ldap_bind, 909 ldap_close, 909 ldap_compare, 932 ldap_connect, 909 ldap_count_entries, 932 ldap_delete, 914 ldap_dn2ufn, 935 ldap_err2str, 934

1432

ob_end_clean

ldap_errno, 933 ldap_error, 933 ldap_explode_dn, 935 ldap_first_attribute, 928 ldap_first_entry, 926 ldap_free_result, 933 ldap_get_attributes, 926 ldap_get_dn, 934 ldap_get_entries, 923 ldap_get_option, 938 ldap_get_values, 929 ldap_get_values_len, 930 ldap_list, 919 ldap_modify, 912 ldap_mod_add, 913 ldap_mod_del, 913 ldap_mod_replace, 912 ldap_next_attribute, 928 ldap_next_entry, 926 ldap_read, 920 ldap_rename, 917 ldap_search, 919 ldap_set_option, 936 ldap_sort, 931 ldap_unbind, 909 levenshtein, 382 link, 526 linkInfo, 557 list, 185 localTime, 444 log, 333 log10, 333 long2ip, 1267 lstat, 556 ltrim, 399

M
mail, 963 max, 346 mcal_append_event, 479 mcal_close, 460 mcal_create_calendar, 484 mcal_date_compare, 454 mcal_date_valid, 452 mcal_days_in_month, 454 mcal_day_of_week, 453 mcal_day_of_year, 453 mcal_delete_calendar, 484 mcal_delete_event, 484 mcal_event_add_attribute, 470 mcal_event_init, 469 mcal_event_set_alarm, 474 mcal_event_set_category, 470 mcal_event_set_class, 469

mcal_event_set_description, 470 mcal_event_set_end, 471 mcal_event_set_recur_daily, 472 mcal_event_set_recur_monthly _mday, 472 mcal_event_set_recur_monthly _wday, 473 mcal_event_set_recur_weekly, 472 mcal_event_set_recur_yearly, 473 mcal_event_set_start, 471 mcal_event_set_title, 469 mcal_fetch_current_stream _event, 477 mcal_fetch_event, 465 mcal_is_leap_year, 454 mcal_list_alarms, 484 mcal_list_events, 460 mcal_next_recurrence, 468 mcal_open, 459 mcal_popen, 459 mcal_rename_calendar, 484 mcal_reopen, 459 mcal_snooze, 484 mcal_store_event, 478 mcal_time_valid, 452 md5, 407 md5_file, 592 metaphone, 384 method_exists, 239 microtime, 443 min, 347 mkDir, 529 mktime, 435 move_uploaded_file, 536 mssql_bind, 851 mssql_close, 846 mssql_connect, 845 mssql_execute, 852 mssql_fetch_array, 854 mssql_fetch_field, 870 mssql_fetch_row, 853 mssql_field_length, 870 mssql_field_name, 870 mssql_field_seek, 871 mssql_field_type, 871 mssql_free_result, 856 mssql_get_last_message, 858 mssql_init, 851 mssql_min_error_severity, 859 mssql_min_message_severity, 859 mssql_next_result, 855 mssql_num_fields, 869 mssql_num_rows, 857 mssql_pconnect, 845 mssql_query, 846 mssql_result, 852 mssql_rows_affected, 858

mssql_select_db, 845 mt_getRandMax, 342 mt_rand, 342 mt_srand, 341 mysql_affected_rows, 710 mysql_close, 702 mysql_connect, 699 mysql_db_names, 726 mysql_errno, 711 mysql_error, 711 mysql_fetch_array, 706 mysql_fetch_assoc, 707 mysql_fetch_row, 705 mysql_field_flags, 725 mysql_field_len, 724 mysql_field_name, 724 mysql_field_type, 724 mysql_free_result, 707 mysql_get_client_info, 729 mysql_get_host_info, 729 mysql_get_proto_info, 729 mysql_get_server_info, 729 mysql_info, 710 mysql_insert_id, 704 mysql_list_dbs, 726 mysql_list_fields, 723 mysql_list_processes, 728 mysql_list_tables, 725 mysql_num_fields, 723 mysql_num_rows, 709 mysql_pconnect, 700 mysql_ping, 727 mysql_query, 701 mysql_result, 705 mysql_select_db, 701 mysql_stat, 728 mysql_tablename, 725 mysql_thread_id, 728

N
natcasesort, 193 natsort, 192 new, 220 next, 188 nl2br, 393 number_format, 347

O
obstart, 288 ob_clean, 294 ob_end_clean, 292

1433

ob_end_flush

ob_end_flush, 288 ob_flush, 294 ob_get_contents, 290 ob_get_length, 293 ob_get_level, 294 ob_gzhandler, 289 ob_implicit_flush, 292 ociBindByName, 791 ociColumnName, 810 ociColumnSize, 811 ociColumnType, 811 ociCommit, 778 ociDefineByName, 787 ociError, 797 ociExecute, 777 ociFetch, 782 ociFetchInto, 785 ociFetchStatement, 786 OCILOB export, 793 free, 794 import, 793 load, 794 save, 793 saveFile, 794 writeToFile, 794 write_temporary, 793 ociLogoff, 779 ociLogon, 776 ociNewDescriptor, 793 ociNLogon, 776 ociNumCols, 810 ociParse, 777 ociPLogon, 776 ociResult, 782 ociRollback, 778 ociRowCount, 790 ociServerVersion, 812 oci_bind_by_name, 791 oci_close, 779 oci_commit, 778 oci_connect, 776 oci_define_by_name, 787 oci_error, 797 oci_execute, 777 oci_fetch, 782 oci_fetch_all, 786 oci_fetch_array, 784 oci_fetch_row, 783 oci_field_name, 810 oci_field_size, 811 oci_field_type, 811 oci_new_connect, 776 oci_new_descriptor, 793 oci_num_fields, 810 oci_num_rows, 790 oci_parse, 777 oci_pconnect, 776

oci_result, 782 oci_rollback, 778 oci_server_version, 812 octDec, 345 odbc_autoCommit, 736 odbc_close, 733 odbc_close_all, 733 odbc_columns, 757 odbc_commit, 736 odbc_connect, 731 odbc_do, 733 odbc_error, 744 odbc_errormsg, 744 odbc_exec, 732 odbc_execute, 743 odbc_fetch_into, 739 odbc_fetch_row, 737 odbc_field_len, 756 odbc_field_name, 755 odbc_field_num, 755 odbc_field_precision, 756 odbc_field_scale, 756 odbc_field_type, 756 odbc_free_result, 740 odbc_getTypeInfo, 760 odbc_num_fields, 755 odbc_num_rows, 742 odbc_pconnect, 732 odbc_prepare, 743 odbc_procedurecolumns, 759 odbc_procedures, 759 odbc_result, 737 odbc_rollback, 736 odbc_tables, 758 openDir, 518 ord, 363

P
parse_ini_file, 511 passthru, 1313 pathInfo, 542 pclose, 575 pdf_add_bookmark, 1146 pdf_add_launchlink, 1168 pdf_add_locallink, 1166 pdf_add_note, 1168 pdf_add_pdflink, 1167 pdf_add_thumbnail, 1170 pdf_add_weblink, 1168 pdf_arc, 1154 pdf_arcn, 1154 pdf_attach_file, 1171 pdf_begin_page, 1142 pdf_begin_template, 1178

pdf_circle, 1153 pdf_clip, 1165 pdf_close, 1141 pdf_closepath, 1155 pdf_closepath_fill_stroke, 1156 pdf_closepath_stroke, 1156 pdf_close_image, 1163 pdf_concat, 1173 pdf_continue_text, 1150 pdf_curveTo, 1155 pdf_delete, 1141 pdf_end_page, 1143 pdf_end_template, 1179 pdf_fill, 1156 pdf_fill_stroke, 1157 pdf_findFont, 1146 pdf_get_buffer, 1142 pdf_get_parameter, 1151 pdf_get_value, 1173 pdf_initGraphics, 1162 pdf_lineTo, 1153 pdf_makeSpotColor, 1158 pdf_moveTo, 1152 pdf_new, 1141 pdf_open_file, 1141 pdf_open_image_file, 1163 pdf_open_memory_image, 1165 pdf_place_image, 1164 pdf_rect, 1153 pdf_restore, 1178 pdf_rotate, 1172 pdf_save, 1177 pdf_scale, 1172 pdf_setColor, 1157 pdf_setDash, 1162 pdf_setFont, 1147 pdf_setLineCap, 1159 pdf_setLineJoin, 1159 pdf_setLineWidth, 1158 pdf_setMatrix, 1173 pdf_setMiterLimit, 1160 pdf_setPolyDash, 1162 pdf_set_border_color, 1170 pdf_set_border_dash, 1170 pdf_set_border_style, 1169 pdf_set_info, 1144 pdf_set_parameter, 1175 pdf_set_text_pos, 1149 pdf_set_value, 1145 pdf_show, 1149 pdf_show_boxed, 1150 pdf_show_xy, 1147 pdf_skew, 1172 pdf_stringWidth, 1151 pdf_stroke, 1156 pdf_translate, 1171 pFSockOpen, 1271 phpinfo, 131

1434

stream

pi, 330 popen, 574 pos, 187 posix_ctermid, 1321 posix_getcwd, 1320 posix_getegid, 1318 posix_geteuid, 1316 posix_getgid, 1319 posix_getgrgid, 1317 posix_getgrnam, 1317 posix_getlogin, 1315 posix_getpgrp, 1319 posix_getpid, 1320 posix_getppid, 1320 posix_getpwnam, 1315 posix_getpwuid, 1314 posix_getrlimit, 1321 posix_kill, 1322 posix_setegid, 1319 posix_seteuid, 1316 posix_setgid, 1319 posix_setpgid, 1320 posix_setuid, 1316 posix_times, 1322 posix_uname, 1322 pow, 335 preg_grep, 414 preg_match, 417 preg_match_all, 418 preg_quote, 421 preg_replace, 414 preg_replace_callback, 416 preg_split, 417 prev, 189 printf, 359 private, 227, 232 protected, 227, 232 putEnv, 133

rename, 528 require, 206 require_once, 209 reset, 188 return, 167 rewind, 515 rewindDir, 524 rmdir, 529 round, 338 rsort, 193 rtrim, 399

S
self, 223 serialize, 241 session_cache_expire, 286 session_cache_limiter, 286 session_decode, 284 session_destroy, 283 session_encode, 283 session_get_cookie_params, 285 session_id, 285 session_is_registered, 287 session_module_name, 284 session_name, 285 session_register, 287 session_save_path, 284 session_set_cookie_params, 286 session_set_save_handler, 279 session_unregister, 287 session_unset, 287 session_write_close, 287 setCookie, 264 setType, 122 set_file_buffer, 517 shell_exec, 1311 shuffle, 198 similar_text, 381 simpleElement_load_string, 1238 SimpleXMLElement asXML, 1240 attributes, 1239 children, 1239 xpath, 1239 simplexml_import_dom, 1238 simplexml_load_file, 1238 sin, 331 sinh, 334 sizeof, 179 SOAP_Client, 1303 addHeader, 1304 call, 1304 setEncoding, 1304 socket_get_status, 1273

Q
quoteMeta, 386

R
rad2deg, 332 rand, 340 range, 182 readDir, 519 readfile, 503 readgzfile, 583 readLink, 557 realPath, 543

socket_set_blocking, 1272 socket_set_timeout, 1272 sort, 192 soundex, 383 split, 429-430 sprintf, 359 sqlite_array_query, 815 sqlite_busy_timeout, 835 sqlite_changes, 834 sqlite_close, 816 sqlite_column, 819 sqlite_create_aggregate, 823 sqlite_create_function, 822 sqlite_current, 817 sqlite_error_string, 821 sqlite_escape_string, 836 sqlite_fetch_array, 816 sqlite_fetch_single, 818 sqlite_fetch_string, 818 sqlite_field_name, 834 sqlite_has_more, 819 sqlite_last_error, 821 sqlite_last_insert_rowid, 834 sqlite_libencoding, 836 sqlite_libversion, 836 sqlite_next, 820 sqlite_num_fields, 833 sqlite_num_rows, 833 sqlite_open, 813 sqlite_popen, 814 sqlite_query, 814 sqlite_rewind, 820 sqlite_seek, 820 sqlite_udf_decode_binary, 835 sqlite_udf_encode_binary, 835 sqlite_unbuffered_query, 815 sql_regcase, 430 sqrt, 336 srand, 340 sscanf, 362 stat, 554 static, 162 stderr, 492 stdin, 492 stdout, 492 strcasecmp, 378 strchr, 365 strcmp, 377 strcoll, 378 strcspn, 375 stream dir_closedir, 628 dir_opendir, 627 dir_readdir, 627 dir_rewinddir, 630 mkdir, 624 rename, 622 rmdir, 626

1435

stream_context_create

stream_close, 611 stream_eof, 614 stream_open, 610 stream_read, 613 stream_seek, 616 stream_stat, 619 stream_tell, 615 stream_write, 617 unlink, 620 stream_context_create, 602 stream_context_get_default, 603 stream_context_get_options, 605 stream_context_set_option, 604 stream_copy_to_stream, 607 stream_filter_append, 599 stream_filter_prepend, 599 stream_get_contents, 607 stream_get_filters, 597 stream_get_line, 608 stream_get_meta_data, 609 stream_get_wrappers, 593 stream_register_wrapper, 609 stream_set_write_buffer, 517 stream_wrapper_register, 610 strftime, 439 stripCSlashes, 387 stripSlashes, 387 stristr, 365 strlen, 370 strnatcasecmp, 380 strnatcmp, 379 strncasecmp, 379 strncmp, 377 strpos, 375 strrchr, 365 strrev, 405 strrpos, 376 strspn, 374 strstr, 364 strtok, 403 strToLower, 400 strtotime, 436 strToUpper, 399 strtr, 368-369 str_pad, 402 str_repeat, 405 str_replace, 367 substr, 363 substr_count, 370 substr_replace, 366 SWFAction, 1131 SWFBitmap, 1112 getHeight, 1114 getWidth, 1113 SWFButton, 1129 addAction, 1130 addShape, 1129 setDown, 1130

setHit, 1130 setOver, 1130 setUp, 1130 SWFDisplayItem addColor, 1107 move, 1105 moveTo, 1104 multColor, 1107 rotate, 1105 rotateTo, 1105 scale, 1106 scaleTo, 1105 setDepth, 1104 setName, 1104 setRatio, 1123 skewX, 1106 skewXTo, 1106 skewY, 1106 skewYTo, 1106 SWFFill moveTo, 1119 rotateTo, 1119 scaleTo, 1119 skewXTo, 1119 skewYTo, 1120 SWFFont, 1096 getAscent, 1097 getDescent, 1097 getLeading, 1097 getWidth, 1096 SWFGradient, 1116 addEntry, 1116 SWFMorph, 1122 getShape1, 1122 getShape2, 1123 SWFMovie, 1084 add, 1087 nextFrame, 1086 output, 1085 remove, 1108 save, 1085 setBackground, 1088 setDimension, 1087 setRate, 1088 SWFShape, 1097 addFill, 1110 drawArc, 1104 drawCircle, 1104 drawCubic, 1100 drawCubicTo, 1100 drawCurve, 1099, 1101 drawCurveTo, 1099, 1101 drawGlyph, 1101 drawLine, 1099 drawLineTo, 1098 movePen, 1098 movePenTo, 1098 setLeftFill, 1110

setLine, 1109 setRightFill, 1110 SWFSprite, 1131 add, 1132 nextFrame, 1132 remove, 1132 SWFText, 1089 addString, 1090 moveTo, 1090 setColor, 1090 setFont, 1089 setHeight, 1090 setSpacing, 1091 SWFTextField, 1093 addString, 1096 align, 1094 setBounds, 1093 setColor, 1094 setFont, 1094 setHeight, 1094 setIndentation, 1095 setLeftMargin, 1095 setLineSpacing, 1095 setMargins, 1095 setRightMargin, 1095 switch, 156 symLink, 527 system, 1313

T
tan, 331 tanh, 334 Template, 311 finish, 317 get_undefined, 317 get_vars, 317 p, 312 parse, 313 psubst, 316 set_block, 315 set_file, 313 set_root, 316 set_unknowns, 316 set_var, 312 subst, 316 tempNam, 527 time, 435 tmpfile, 493 touch, 552 trim, 397 try, 235

1436

Addition

U
uasort, 195 ucFirst, 400 ucWords, 400 uksort, 196 umask, 530 unixToJD, 446 unlink, 528 unserialize, 241 unset, 124 usort, 194

wddx_deserialize, 1259 wddx_packet_end, 1258 wddx_packet_start, 1258 wddx_serialize_value, 1255 wddx_serialize_vars, 1257 while, 152-153 wordWrap, 401

X
xml_error_string, 1214 xml_get_current_byte_index, 1215 xml_get_current_column _number, 1214 xml_get_current_line_number, 1214 xml_get_error_code, 1213 xml_parse, 1194 xml_parser_create, 1192-1193 xml_parser_free, 1195 xml_parser_get_option, 1198 xml_parser_set_option, 1197-1198

V
vPrintf, 361 vSPrintf, 362

W
wddx_add_vars, 1258

xml_set_character_data_handler, 1200 xml_set_default_handler, 1212 xml_set_element_handler, 1193 xml_set_element_handler, 1193 xml_set_external_entity_ref _handler, 1205 xml_set_notation_decl_handler, 1210 xml_set_object, 1203 xml_set_processing_instruction _handler, 1209-1210 xml_set_unparsed_entity_decl _handler, 1211 XSLTProcessor, 1244 importStyleSheet, 1244 transformToDoc, 1245 transformToXML, 1245 xslt_create, 1248 xslt_errno, 1252 xslt_error, 1252 xslt_free, 1248 xslt_process, 1248 xslt_set_base, 1251 xslt_set_encoding, 1251 xslt_set_error_handler, 1252

Index
!
%, 140-141, 144 146 &, 141, 166 &&, 145 *, 140 *=, 143 +, 140 ++, 143 +=, 143 -, 140 --, 143 -=, 143 ., 142 .=, 143 /, 140 /=, 143 <=, 144 ==, 144 ===, 144 !, 145 !=, 144 !==, 144 ?, 149 ~$, 141 $_COOKIE, 265 $_ENV, 131 $_FILES, 534 $_GET, 137 $_POST, 139 $_SERVER, 131 $_SESSION, 272 $GLOBALS, 161 $HTTP_COOKIE_VARS, 136, 265 $HTTP_ENV_VARS, 136 $HTTP_FILES_VARS, 136 $HTTP_GET_VARS, 136, 139 $HTTP_POST_FILES, 534 $HTTP_POST_VARS, 136, 139 $HTTP_RESPONSE_HEADER, 493 $HTTP_SERVER_VARS, 136 $HTTP_SESSION_VARS, 136, 272 $that, 244 $this, 222

A
Ab, 1345 Abstract, 234 Accesseur, 232 Addition, 140

1437

And

And, 145 Apache site Internet, 54 APC, 1358 Array, 121 ArrayObject, 246 Associativit, 148 Assombrissement, 1381

TRUE, 118 __FILE__, 118 __LINE__, 118 Cookie attributs, 263 limites, 263 CSV, 507

B
Balise, 113 Bibliothques BCMath, 348 Calendar, 444 GD, 1023 LDAP, 908 MCAL, 450 Ming, 1082 PDFLib, 1139 PHPDoc, 301 WDDX, 1255 Binaire, 121 Bool, 120 Boolean, 120 Boucles, 148

D
DB, 873 DB_Result, 878 Dcimal, 120 DEL, 253 Dsrialisation, 241 Diagrammes, 1023 Division, 140 DNS, 1267 Documentation, 301 DOMAttr, 1222 DOMDocument, 1217 DOMElement, 1221 DOMNode, 1220 DOMNodeList, 1229 DOMText, 1222 DOMXPath, 1230 Dossier, 519 Double, 120 DTD, 1188 Dynamique, 113

User-Agent, 254 Entre standard, 492 Epoch, 435 Erreurs masquer les messages, 146 niveaux dalerte, 146 Exception, 235 Expat, 1192 Extends, 230 E_COMPILE_ERROR, 146 E_COMPILE_WARNING, 146 E_CORE_ERROR, 146 E_CORE_WARNING, 146 E_ERROR, 146 E_NOTICE, 145 E_PARSE, 145 E_USER_ERROR, 146 E_USER_NOTICE, 146 E_USER_WARNING, 146 E_WARNING, 146

F
Fichiers cache statistiques, 559 date de modification, 550 droits utilisateurs, 488 inclure, 206 lire les permissions, 560 modifier les permissions, 531 ouverture, 490 propritaire, 548 renommer, 528 supprimer, 528 temporaires, 493 taille, 547 type, 544 upload, 533 Final, 227, 232 Float, 120 Flux, 593 Contexte de ressource, 601 file, 594 filtres, 597 FTP, 595 gestionnaires, 593, 609 HTTP, 594 PHP, 596 Fonctions rcursivit, 173 utilisateur, 171 Form, 137 Formats GD, 1023 GD2, 1023

C
Cache, 1358 Camemberts, 1023 Catch, 235 Client, 113 Client-serveur, 116 COM, 1327 Commande ab, 1345 Concatnation, 142 Const, 222 Constantes E_COMPILE_ERROR, 146 E_COMPILE_WARNING, 146 E_CORE_ERROR, 146 E_CORE_WARNING, 146 E_ERROR, 146 E_NOTICE, 145 E_PARSE, 145 E_USER_ERROR, 146 E_USER_NOTICE, 146 E_USER_WARNING, 146 E_WARNING, 146 PHP_OS, 118 PHP_VERSION, 118

E
Emails enttes, 963 fichiers attachs, 966 HTML, 965 Plusieurs destinataires, 965 Tester la validit, 1268 Enttes Accept, 254 Accept-Charset, 254 Content-Encoding, 257 Content-Language, 257 Content-Length, 257 Content-Type, 257 Date, 254, 257 Expires, 257 From, 254 Host, 254, 256 Location, 257, 260 Referer, 254 Server, 257

1438

Rpertoires

GIF, 1023 JPEG, 1023 PNG, 1023 WBMP, 1023 Formulaires magic quotes, 672 retours la ligne, 683 slection par dfaut, 682 valeurs par dfaut, 682 Function (type), 121

J
JPEG, 1023

L
Langages C, 30 Perl, 30 Langue prfre, 432 LibXML, 1187, 1192 Local, 162

G
GD, 1023 GD2, 1023 GET, 253 GID, 548, 1314 GIF, 1023

--, 143 -=, 143 ., 142 .=, 143 /, 140 /=, 143 <=, 144 ==, 144 ===, 144 |, 141, 145 !, 145 &, 141 &&, 145 and, 145 or, 145 xor, 145

M
Masque, 524 Mthodes, 216 Mixed, 121 Modles PEAR, 318 PHPLib, 309 Modules POSIX, 1314 Modulo, 140 Multiplication, 140

P
Page dynamique, 1344 mathmatique, 1344 quasi-statique, 1343 Paramtres rfrence, 166 Parent, 231 PEAR, 318 Rgles de codage, 297 PHP site internet, 54 PHP Accelerator, 1362 PHP Guardian, 1389 PHPDoc, 301 PHPLib, 309 PhpMyAdmin, 1395 PHP_OS, 118 PHP_VERSION, 118 PNG, 1023 POBS, 1390 POSIX Fichiers, 487 POST, 253 Private, 227, 232 Protected, 227, 232 Protocoles HTTP, 253 Public, 227, 232 PUT, 253

H
Head, 253 Hritage, 227, 229 Hxadcimal, 120 Histogrammes, 1023 HTML form, 137 head, 253 input, 137 HTTP, 253 HyperText Transfer Protocol, 253 mthodes, 253

N
NfosBal-, 1014 NULL, 121 Numeric, 121

I
Images, 1023 ImageTrueColorToPalette, 1040 Implements, 233 Inclure fichier, 206 Inclusion Problme de redclaration, 209 Input, 137 Instance, 222 Int, 120 Integer, 120

O
Obfuscation, 1381 Object, 121 OCILOB, 793 Octal, 120 Oprateurs %, 140, 144 !=, 144 !==, 144 *, 140 *=, 143 +, 140 ++, 143 +=, 143 -, 140

R
Real, 120 Rpertoires lister le contenu, 519

1439

Resource

modifier les permissions, 531 renommer, 528 suppression, 529 Resource, 121 Return, 167 RFC (Request For Comment), 256

S
Safe_mode, 133 Safe_mode_allowed_env_vars, 133 Safe_mode_protected_env_vars, 133 Scalar (attribut), 124 Scurit GET, 138 upload, 535 variables denvironnement, 133 Self, 223 Srialisation, 241 Serveur, 113 SGML, 30 SimpleXMLElement, 1240 SOAP_Client, 1303 Sortie derreur, 492 Sortie standard, 492 Soustraction, 140 SQL ALTER TABLE, 644 CREATE DATABASE, 640 CREATE TABLE, 643 DELETE, 647 DROP DATABASE, 640 DROP TABLE, 644 INSERT, 645 SELECT, 648, 650 SHOW COLUMNS, 652 SHOW DATABASE, 651 SHOW TABLES, 651 UPDATE, 646 Static, 222 Stderr, 492 Stdin, 492 Stdout, 492 Steam Contexte de ressource, 601

Stream filtres, 597 gestionnaires, 593, 609 Streams, 593 String, 120 SWFAction, 1131 SWFBitmap, 1112 SWFButton, 1129 SWFDisplayItem, 1104 SWFFill, 1119 SWFFont, 1096 SWFGradient, 1116 SWFMorph, 1122 SWFMovie, 1084 SWFShape, 1097 SWFSprite, 1131 SWFText, 1089 SWFTextField, 1093

U
UID, 548, 1314 Umask, 530 URL rewriting, 271

V
Variables denvironnement, 131 dynamiques, 119 externes, 130 globales, 160 locales, 160 statiques, 162 tester le type, 126 Void, 121

T
Tableaux, 121 Templates, 309 Tester le type dune variable, 126 Throw, 236 Timestamp Unix, 435 TRACE, 253 Transtypage, 123 TRUE, 118 Try, 235 Typage, 144 Type casting, 123 Types array (tableau), 121 boolean (boolen), 120 composs, 120 double (rel), 120 function, 121 int (entier), 120 mixed, 121 NULL, 121 numeric, 121 object (objet), 121 resource (ressource), 121 scalaires, 120 spciaux, 120 string (chane), 120 void, 121

W
WBMP, 1023 WSDL, 1299

X
XML, 1187 Xor, 145 XSL, 1187 XSLT, 1253 XSLTProcessor, 1244

Z
Zend Accelerator, 1366 Zend Encoder, 1381 Zend Optimizer,

Compos en France par Jouve 11, bd de Sbastopol - 75001 Paris1349

1440

You might also like