Professional Documents
Culture Documents
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.
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
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 :
Met laccent sur un point important quil ne faut ngliger aucun prix.
Renvoi un site o vous trouverez des infos complmentaires ou des outils tlcharger.
Sommaire
Chapitre 1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 quoi sert PHP ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Prsentation, rle et fonctionnement dun langage de script . . . . . . . . . . . 27
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
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
Sommaire
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
Chapitre 6 Les fonctions mathmatiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 Les fonctions mathmatiques et les constantes . . . . . . . . . . . . . . . . . . . . . 327
Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 Fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
Sommaire
Gnralits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
Afficher du texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357 Manipuler les caractres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
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
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
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
Sommaire
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
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
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
. . . . .
. . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
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
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
XSLT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1241
Prsentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1241 Les transformations de documents XML . . . . . . . . . . . . . . . . . . . . . . 1243
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
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
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
Autres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1392 Chapitre 21 Annexe A : des exemples dapplications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1393 Administration de bases de donnes . . . . . . . . . . . . . . . . . . . . . . . . . . . 1395
phpMyAdmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1395 Autres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1400
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
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.
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
1.1.
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>
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
1.2.
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
29
Chapitre 1
Introduction
30
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
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
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.
La socit Nexen :
http://www.nexen.net
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
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.
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
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
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.).
1.4.
40
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
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
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
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.
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).
Contact : Pierre Machard <pmachard@tuxfamily.org> Linuxfr, site dinformation sur Linux et les logiciels libres :
http://linuxfr.org
46
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
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 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
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
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
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
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
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>
56
Installation
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 :
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 :
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
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).
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
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
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.
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 :
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
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 :
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 !
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
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
66
Installation
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
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
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
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.
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
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
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
2. Prise en main
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
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
2. Prise en main
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
PHP sur Mac Os X, chez Apple (conseils pour la compilation, modules compatibles, etc.) :
http://developer.apple.com/internet/Mac_OS_X/php.html
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
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
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>
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.
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
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\
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>
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
83
Chapitre 2
Prise en main
2.2.
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
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
permet dutiliser le tag court douverture de script PHP < ? (plutt que < ?php ou <script>).
asp_tags = Off
Serveur
engine = 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
2. Prise en main
Indiquez la quantit maximale de ressource mmoire utilisable par les scripts (ici : 8 Mb).
Scurit
Mode scuris
safe_mode = 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
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
E_ALL
87
Chapitre 2
Prise en main
2. Prise en main
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
Avertissements (qui ne sont pas des erreurs fatales) survenant lors du dmarrage initial de PHP.
E_COMPILE_ERROR
88
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
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
Interdit linclusion de tags HTML dans les messages derreur. Nutilisez pas cette fonction sur des serveurs de production.
error_prepend_string = "<font color=ff0000>"
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
2. Prise en main
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".
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
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
90
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
91
Chapitre 2
Prise en main
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"]; ?>
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
session.name = PHPSESSID
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 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
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
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
Source
Couleurs pour la coloration syntaxique de votre code. Indiquez les codes couleurs qui vous conviennent :
highlight.string = #CC0000
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
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).
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
Sockets
sockets.use_system_read = On
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.
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
98
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
99
Chapitre 2
Prise en main
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
100
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
101
Chapitre 2
Prise en main
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
PhpCoder
2. Prise en main
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
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
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
105
Chapitre 2
Prise en main
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
Jext
2. Prise en main
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
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/
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
3.1.
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 :
113
Chapitre 3
Le langage PHP
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.
114
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
Comme nous pouvons le constater en rclamant le code source du document reu, le rsultat de linterprtation ne laisse plus apparatre de code PHP.
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 :
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.
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
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.
string
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
$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.
3. Le langage PHP
object
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
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.
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
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
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
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
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
3. Le langage PHP
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.
<?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.
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
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 denvironnement (du serveur) ; Les variables passes en paramtre lors de lappel de la page (soit via un formulaire soit via lURL).
130
Les variables
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 ?>
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
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.
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
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
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>
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).
135
Chapitre 3
Le langage PHP
iPlanet, IIS et PWS Cette variable nest pas disponible sur les serveurs iPlanet, IIS et PWS.
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,
$_ENV
sappelaient
136
Les variables
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,
Je pense que vous commencez entrevoir des possibilits dapplications. Mais vous serez plus enthousiasm encore aprs avoir vu comment utiliser des formulaires de saisie.
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
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.
3. Le langage PHP
Enfin, vous disposez galement des balises <select> (associe <option>) et <textarea>.
Application
Voici donc un petit exemple dapplication :
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
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.
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 :
3. Le langage PHP
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); ?>
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
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; ?>
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
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 :
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 :
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.
Extrmement utiles, les structures de contrle vous permettront de faire des boucles et des tests dans vos scripts PHP.
ou, sil y a plusieurs instructions (et cela reste conseill mme sil ny a quune seule instruction) :
148
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)
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
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
} ?>
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
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
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
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
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; }
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.
154
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
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"; }
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
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>
157
Chapitre 3
Le langage PHP
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().
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
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.
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(); ?>
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(); } ?>
3. Le langage PHP
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
165
Chapitre 3
Le langage PHP
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")
166
Les fonctions
3. Le langage PHP
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
create_function()
Permet de crer une fonction anonyme partir de paramtres.
168
Les fonctions
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
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
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 />"; ?>
$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
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
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).
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
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);
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;
Ce qui donnerait :
3. Le langage PHP
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.
Ordre daffectation Il nest pas ncessaire de prciser les valeurs dans lordre des indices. Ainsi
$monTableau = array(3 => "Valeur3", 1 => "Valeur1");
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";
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
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().
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
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
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
3. Le langage PHP
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.
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.
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
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
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
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.
188
Les tableaux
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
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.
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
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
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);.
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.
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
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.
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.
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.
krsort()
Trie les tableaux dans lordre dcroissant des cls, tout en conservant lassociation cl => valeur.
195
Chapitre 3
Le langage PHP
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.
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
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.
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".
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
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
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
array_lter()
Retourne un tableau filtr partir dune fonction crite par lutilisateur.
201
Chapitre 3
Le langage PHP
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
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.
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)); ?>
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.
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); ?>
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
retournera
1 - Accueil 2 - Forum 3 - A propos Array ( [0] => [Accueil] [1] => [Forum] [2] => [A propos] )
205
Chapitre 3
Le langage PHP
3.9.
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();
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).
206
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 :
207
Chapitre 3
Le langage 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.
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
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
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
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
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
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¶metre2=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"); ?>
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).
3. Le langage PHP
j j
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"
par
include(dirname(__FILE__)."/cheminRelatif/fichier.php").
212
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).
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
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>
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
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
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
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).
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
j j
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
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
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
Attributs :
j j
modele : STRING ; prix : REAL.
Fonctions:
j j
modifierModele (modele : STRING) : VOID ; modifierPrix (details : STRING) : VOID.
Classe Clavier
Constructeur :
j
Attributs :
j j
modele : STRING ; prix : REAL.
Fonctions :
j
modifierModele (modele : STRING) : VOID ;
218
Classe Souris
Constructeur :
j
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.
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 />";
220
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
<?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
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 "__".
224
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(); ?>
3. Le langage PHP
retournera
Message modifi par la fonction
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
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
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
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
// 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
} ?>
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. } } ?>
232
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
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
234
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..
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"; } ?>
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
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
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.
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
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
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
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.
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
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.
241
Chapitre 3
Le langage PHP
3. Le langage PHP
$souris = implode("", @file("sauvegarde")); //la chane stocke // est rcupre unserialize($souris); // la chane est transforme en son objet associ
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
$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.
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 />"; ?>
244
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.
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.
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.
246
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.
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.
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.
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
ArrayObject->getIterator()
Retourne un itrateur sur un objet ArrayObject.
3. Le langage PHP
Syntaxe retour
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
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
Chapitre 4
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.
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
HTTP/1.1 HTTP/1.1
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>.
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
Pour valider votre requte, finissez en tapant deux fois sur la touche [Entre].
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
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
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
Vous pouvez vous reporter lannexe "En-ttes et variables externes" pour un liste plus complte den-ttes.
257
Chapitre 4
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
Vous pouvez consulter lannexe sur "Les types MIME" pour une liste plus complte des types.
4.2.
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
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.
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
Les exemples dapplications sont nombreux ; nous en dtaillerons trois dans ce chapitre.
259
Chapitre 4
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.
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"); } ?>
260
Cookies
Vous pouvez vous reporter lannexe sur "Les types MIME" pour avoir une liste plus complte des valeurs possibles.
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
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.
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
Expires
DATE
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
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
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.
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);
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
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");
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.
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).
267
Chapitre 4
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"); ?>
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 :
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
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>
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
4.4.
Sessions
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
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.
Syntaxe retour
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]; ?>
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
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.
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.
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);
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
?>
<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>
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>
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.
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
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) );
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)
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.
279
Chapitre 4
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(),
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"); ?>
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.
281
Chapitre 4
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>
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
session_destroy()
Dtruit les variables de la session en cours. Syntaxe retour boolean session_destroy(void)
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"; ?>
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
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.
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.
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
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).
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
int session_cache_expire([int $expirationCache]) Nouvelle valeur (en secondes) dexpiration du cache. Retourne la valeur actuelle dexpiration du cache.
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.5.
287
Chapitre 4
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.
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
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
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.
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 :
290
// 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).
291
Chapitre 4
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().
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
Syntaxe retour
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,
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.
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
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)
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
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.
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
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; }
297
Chapitre 5
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; }
De ne pas mettre despace entre le nom de la fonction et la parenthse ouvrante prcdant les paramtres. Ce quil faut 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)
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; }
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).
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 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 } }
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.
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.
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
j j
j j
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).
/** * @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
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 } }
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
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
306
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.
5.2.
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.
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
Syntaxe retour
array rechercheVisiteurs(string $critere, int $debut, $nb) Tableau dobjet Visiteur, ou FALSE en cas dchec.
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
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.
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) :
309
Chapitre 5
<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>
// 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
"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");
?>
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 :
311
Chapitre 5
"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.
Syntaxe $variable
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
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)
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.
313
Chapitre 5
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.
// 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
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.
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
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).
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
Syntaxe $variable
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()
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
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.
Lexemple prsent en introduction de la bibliothque PHPLib devient alors : exemple de fichier modle (cr par le designer) :
318
?>
La base
Lutilisation des modles PEAR/IntegratedTemplate commence par linstanciation dun objet IntegratedTemplate selon la syntaxe suivante :
319
Chapitre 5
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
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 ;
Dfinition des valeurs par lesquelles les mots-cls doivent tre remplacs ; Remplacement proprement dit.
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
$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");
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.
Syntaxe retour
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
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.
Chapitre 6
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.
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.
Chapitre 6
Valeur 0.57721566490153286061
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.
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
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
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
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
sin()
Retourne la valeur du sinus de langle exprim en radians. Syntaxe $angle retour double sin(double $angle) Angle en radians. Sinus de langle.
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
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].
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
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.
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
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
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).
(-4)^0.5
En sortie, on obtiendra :
8 1 NAN
335
Chapitre 6
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.
En sortie, on obtiendra :
2 3 2.2360679774998 NAN
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
En sortie, on obtiendra :
3 4 4 4 4 4 4 4 4 4
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.
337
Chapitre 6
En sortie, on obtiendra :
3 3 3 3 3 3 3 3 3 3
round()
Arrondit selon les rgles dusage en 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.
338
echo echo echo echo echo echo echo echo echo ?>
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
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
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
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
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
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
342
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.
343
Chapitre 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.
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
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
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
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.
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
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
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.
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
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.
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
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.
Nombre de dcimales. 0 si les deux nombres sont identiques, 1 si $operande1 est plus grand que $operande2, sinon 1.
351
Chapitre 6
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.
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
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 :
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
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 :
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.
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
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.
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
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 :
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 :
caractres minimum,".
caractres minimum,".
360
Gnralits
" align gauche, complt par des -<br />"; printf(".:%--20s:.", "Salut"); echo "<br />Ecriture de %<br />"; printf("%%"); ?>
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.
361
Chapitre 7
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.
?>
362
Et le rsultat obtenu :
25 Franais 25 Franais 2 lments 25 Franais
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.2.
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
$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
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.
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.
364
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.
Dans le cas o nous avons utilis strstr(), la sous-chane de caractres "Exemple" na pas t trouve cause de la majuscule.
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
echo strrchr("Voici un exemple stupide dexemple", "exemple"); echo "\n"; echo strrchr("article 1,article 2, 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
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
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 :
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 :
367
Chapitre 7
$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 :
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
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.
Une autre syntaxe existe, qui consiste dclarer un tableau associatif. Cela permet de remplacer des chanes de caractres par dautres.
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.
369
Chapitre 7
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.
retour
Et le rsultat est :
22
substr_count()
Cette fonction compte le nombre doccurrences dune sous-chane dans une autre.
370
int substr_count(string $chaine, string $motif) Chane de caractres o retrouver le motif. Motif rechercher. Le nombre de fois o le motif apparat.
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.
retour
371
Chapitre 7
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"; ?>
[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
[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
[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]
0 0 0 0 0 0 0 0
373
Chapitre 7
[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
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.
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.
374
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 ?", ":!?"); ?>
Fonctions de position
Il est galement utile de pouvoir rcuprer lindex dun caractre dans une chane :
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
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); ?>
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.
retour
7.3.
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
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.
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"; ?>
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
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"; ?>
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().
Syntaxe
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
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.
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.
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
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.
= array (Image5.jpg, image4.jpg, Image12.jpg, image8.jpg, Image1.jpg, image43.jpg, Image14.jpg); echo "Ordre standard:\n";
380
usort($tableau1, "strcmp"); print_r($tableau1); echo "\nOrdre naturel:\n"; usort($tableau2, "strnatcasecmp"); print_r($tableau2); ?>
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
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"; ?>
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
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"; ?>
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".
383
Chapitre 7
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.
384
7.4.
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); ?>
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
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.
<?php $chaine="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; echo $chaine; echo "\n"; echo addcslashes($chaine,"A..z"); echo "\n"; echo addcslashes($chaine,"G..f"); ?>
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.
386
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)); ?>
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
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
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
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 :
et des </i>";
388
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.
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
389
Chapitre 7
et des </i>";
et des
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
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.
Chapitre 7
[] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [v U] [] [] [] ] [Y [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] []
=> => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => =>
Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô
=> => => => => => => => => => => => => =>
õ ö ÷ ø ù ú û ü ý þ & " < >
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.
393
Chapitre 7
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.
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.
394
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.
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.5.
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
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.
Amlioration depuis PHP 4.3.2 Cette fonction a t amliore et gre mieux les signes < et > qui ne sont pas des balises.
396
Le fichier de test :
Et le rsultat obtenu :
Array ( [author] => Damien , Laurent, PEM et Thomas [tags] => Livre PHP )
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.
397
Chapitre 7
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
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.
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.
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
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.
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.
Et le rsultat obtenu :
abcdef ghijkl mnopqr stuvwx yz0123 456789 a1:b2:23:3e:34:
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
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.
Et le rsultat obtenu :
7.7.
Fusion et dcoupe
implode()
Permet, partir dun tableau, de reconstituer une chane de caractres.
402
Fusion et dcoupe
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.
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.
strtok()
Permet de parcourir une chane morceau par morceau, par appels successifs la fonction.
403
Chapitre 7
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
Et voici le rsultat :
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.
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"; }
405
Chapitre 7
estUnPalindrome("ici")."<br />\n"; estUnPalindrome("chocolat")."<br />\n"; estUnPalindrome("radar")."<br />\n"; estUnPalindrome("rotor")."<br />\n"; estUnPalindrome("voiture")."<br />\n";
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.
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
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.
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.
407
Chapitre 7
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
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".
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
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 :
"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 :
a\.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
a\.+z
az
a\++
az
ab?c+d*e
Voici une nouvelle srie dexemples illustrant ce que lon peut dfinir avec ces ensembles de caractres.
411
Chapitre 7
01234 34534
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.
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
[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]
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".
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
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.
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).
415
Chapitre 7
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 :
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).
416
Expressions rgulires
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.
1 2 3 4
preg_match()
Recherche un motif dans une chane de caractres.
417
Chapitre 7
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
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.
Chapitre 7
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 ) )
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.
Posix
Les expressions rgulires de POSIX sont trs semblables celles en Perl ; elles sont utilises sous UNIX pour crer des scripts.
421
Chapitre 7
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 :
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
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
Pour affiner la recherche, il est possible de dfinir certains types de caractres, avec la notation suivante :
Voici une nouvelle srie dexemples illustrant ce que lon peut dfinir avec ces ensembles de caractres.
424
Expressions rgulires
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.
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
[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.
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".
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
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.
427
Chapitre 7
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.
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
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.
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.
429
Chapitre 7
qui produira :
Array ( [0] [1] [2] [3] [4] [5] )
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
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.
Et son rsultat :
[Cc][Ee][Ss][Tt] [Cc][Oo][Oo][Ll].
430
7.9.
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 :
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 :
431
Chapitre 7
?> <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?
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).
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
8.1.
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.
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.
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
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.
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).
436
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.
437
Chapitre 8
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.
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
t Y y L g G h
438
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
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.
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
$date retour
Date exprime en nombre de secondes depuis 1970 (par dfaut, la date courante). Chane de caractres reprsentant la date.
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
%p %Z %M %S %U %V (*)
440
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.
?>
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
?>
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
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.
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).
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 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.
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 :
Pques
Pour connatre la date correspondant Pques pour une anne donne, il suffit de faire appel la fonction easter_date().
444
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.
?>
retourne, en 2002,
445
Chapitre 8
Cette anne, Pques tombe le dimanche 31 mars En 2001, Pques tait le dimanche 15 avril En 1969, Pques cest le 6/4
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.
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
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
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".
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
$annee retour
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.3.
Jusqu larrive de PHP 5, PHP proposait des bibliothques permettant dinteragir avec des gestionnaires dvnements supportant le protocole ICAP (iCalendar Protocol).
449
Chapitre 8
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 :
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
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
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
451
Chapitre 8
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 :
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.
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
retour
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, ...).
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
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.
mcal_days_in_month()
Retourne le nombre de jours dans le mois en tenant compte des annes bissextiles.
454
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.
Une utilisation courante de ces fonctions consiste afficher un calendrier (annuel, mensuel, etc.).
455
Chapitre 8
$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> </td><td> </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);
Chapitre 8
// 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) :
<h2>Bibliothque MCAL</h2> <?php $dateCourante = getdate(); MCAL_Agenda::afficheAnnee($dateCourante["year"]); MCAL_Agenda::afficheMois($dateCourante["mon"], $dateCourante["year"]); ?> </body> </html>
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 :
459
Chapitre 8
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.
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
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 :
Chapitre 8
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; }
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> </td><td> </td></tr>"; } echo "</table>\n"; echo "</td>"; } echo "</tr>";
462
$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
Voici un exemple de rsultat obtenu (dans les cas dun vnement mensuel sur toute lanne et dun vnement hebdomadaire sur les derniers mois).
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
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
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
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.
$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;
Chapitre 8
} 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
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.
retour
468
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.
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().
mcal_event_set_title()
Associe un nom lvnement. Syntaxe boolean mcal_event_set_title(resource $idConnexion, string $nom)
469
Chapitre 8
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.
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
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.
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.
471
Chapitre 8
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.
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
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.
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
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.
474
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,
Chapitre 8
$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); }
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.
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.
Chapitre 8
$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 />";
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
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().
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.
479
Chapitre 8
* 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>";
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>"; } // (...) }
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
// 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"]);
482
$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>
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
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).
$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
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.1.
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
Les troisime et quatrime colonnes nous indiquent que le propritaire du fichier est "laurent" et que le groupe auquel appartient le fichier est "user".
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
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.
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.
489
Chapitre 9
UNIX, conforme la norme POSIX, ne fait aucune diffrence entre un fichier binaire et un fichier texte.
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.
Ouverture du fichier ; Opration sur le fichier (lecture, criture, lecture et criture) ; Fermeture du fichier.
fopen()
Ouverture dun fichier ou dune URL. Syntaxe resource fopen(string $nomFichier, string $mode [, int $cheminInclude [, resource $contexte]])
490
$nomFichier $mode
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
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
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.
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.
493
Chapitre 9
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.
fsockopen() est une fonction douverture dune socket de connexion. Rendez-vous dans le chapitre "La gestion des protocoles" pour plus dinformations sur le sujet.
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
$longueur retour
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.
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.
495
Chapitre 9
} ?>
<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=">>"> </td> </form> <td> </td> </tr> </body> </html>
496
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.
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 :
497
Chapitre 9
Ce qui donnerait :
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); ?>
fgets()
Lecture de la ligne courante du fichier. Syntaxe string fgets(resource $fp, int $nbOctet)
498
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.
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.
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
$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.
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.
500
<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=">>"> </td> </form> <td> </td> </tr> </body> </html>
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
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"
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
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
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.
retour
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.).
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
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.
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
$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.
retour
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.
505
Chapitre 9
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>"); ?>
La page retourne est ici compltement vide de balises HTML, lexception des balises <br> et <center> que nous avions choisi de conserver.
506
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
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.
508
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=">>"> </td> </form> <td> </td> </tr> </body> </html>
509
Chapitre 9
Figure 9.4 : Voici le systme de discussion quil ne vous reste plus qu perfectionner
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
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.
511
Chapitre 9
<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
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); ?>
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.
513
Chapitre 9
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.
514
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
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.
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.
516
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
$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.
retour
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.
518
closeDir()
Fermer un dossier pralablement ouvert avec la fonction openDir(). Syntaxe $repertoire void closeDir(resource $repertoire) Pointeur sur un dossier ouvert avec linstruction openDir().
<?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 :
519
Chapitre 9
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.
520
} } // 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 />"; ?>
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.
521
Chapitre 9
// 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>"; ?>
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.
523
Chapitre 9
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); ?>
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
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.
<?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]
=> *nux
525
Chapitre 9
[2] => thomas.txt ) Array ( [0] => bible [1] => php )
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.
526
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).
<?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."; } ?>
<?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
(dpend de la configuration mais, gnralement, /tmp sous Linux et C:\windows\temp\ sous Windows).
$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
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.
<?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
<?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".
<?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
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
<?php if (chown("fichier.txt", "damien")) { echo "Le changement dutilisateur est un succs."; } else { echo "Echec dans le changement dutilisateur."; } ?>
<?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
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 :
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
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
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
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.
535
Chapitre 9
"Peut-tre dpassait-il la limite des 1Ko<br />". "A moins que vous nayez essay de truander";
} } } ?> <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
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 []).
537
Chapitre 9
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 :
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
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.
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().
539
Chapitre 9
{ <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>"; }
540
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
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
<?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
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.
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
<?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
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
<?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."; } ?>
<?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
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.
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
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 !"; } ?>
546
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.
<?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).
547
Chapitre 9
// 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)
548
<?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.
549
Chapitre 9
// 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"] ); } ?>
cela pourrait donner : utilisateur = admin groupe = www Utilis dans notre gestionnaire de fichiers, cela donne :
Figure 9.9 : Gestionnaire de fichiers (version 3)
550
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).
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.
551
Chapitre 9
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
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).
<?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.
553
Chapitre 9
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 :
9 10
mtime ctime
554
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).
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
Sil faut simplement rcuprer les droits correspondant un fichier, il suffit alors dcrire le programme suivant :
<?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
<?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.
<?php if (@linkInfo("emma.png") != -1) { echo "Le lien symbolique existe bien."; } else { echo "Le lien symbolique nexiste pas."; } ?>
557
Chapitre 9
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
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
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.
"---";
"--x";
"-w-";
"-wx";
560
break; case 4: $retPerm break; case 5: $retPerm break; case 6: $retPerm break; case 7: $retPerm break; } return $retPerm; }
= "r--";
= "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
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
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.
<?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.
563
Chapitre 9
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 :
564
// 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
Chapitre 9
// 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
$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 .= " / "; $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
Chapitre 9
</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"]." "; 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>
</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> <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> <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
Chapitre 9
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> <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> <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
break; } } document.frenom.submit(); > </td> </form> </tr> <?php /* Crer un dossier */?> <tr> <form method=post name=fdossier> <td> <b>Crer un dossier</b> <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> <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
Chapitre 9
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).
572
} break;
// 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
} } /* 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(); ?>
popen()
Lance un processus et ouvre un pipe de communication. Syntaxe resource popen(string $commande, string $mode)
574
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.
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); ?>
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
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
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
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
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.
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.
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
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().
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.
580
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.
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
581
Chapitre 9
"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
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
582
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.
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
<?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.
584
Remarquez quil est inutile de fermer le fichier par linstruction gzclose(). En effet, comme pour la fonction fpassthru(), le fichier est automatiquement ferm.
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>.
585
Chapitre 9
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.
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
$gzFichier retour
Pointeur du fichier tel que retourn par gzopen(). Position courante du pointeur de lecture, et FALSE si une erreur survient.
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
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.
587
Chapitre 9
// 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
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
588
"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; } ?>
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
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
590
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
591
Chapitre 9
"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
9.3.
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.
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
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
<?php $ptFlux = fopen("http://identifiant:motdepasse@www.php.net", "r"); while ($ligne=fread($ptFlux, 8192)) { print($ligne); } fclose($ptFlux); ?>
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
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)
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; ?>
596
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().
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
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.
convert.quoted-printable-*
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..
598
readfile("php://filter/read=string.tolower/resource=compress.zlib://php.net.gz"); ?>
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
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
// 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");
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
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().
602
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
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;
603
Chapitre 9
) );
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
604
"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(); 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
605
Chapitre 9
<?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)); ?>
606
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
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
$taille
Taille en octet des donnes rcuprer. Par dfaut toutes les donnes seront intgralement retournes. Chane de caractre.
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; ?>
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; ?>
608
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.
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] => )
609
Chapitre 9
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().
$option
610
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.
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"); ?>
611
Chapitre 9
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.
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
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);
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
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
Vous pouvez remarquer que la lecture seffectue simplement, le pointeur se dplaant dun enregistrement lautre chaque appel de la fonction fread().
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.
Voici comment dans notre exemple, la mthode stream_tell() retourne la position actuelle du pointeur.
function stream_tell() { return $this->position; }
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
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
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
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
// On excute la requte de slection de la table $this->rs = mysql_query(select * from .$this->table, $this->db); $this->mode = $mode; return TRUE; }
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.
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
} }
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; }
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().
Voici un exemple expliquant la suppression dune ressource de type table laide de la fonction unlink().
620
621
Chapitre 9
$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); ?>
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).
622
623
Chapitre 9
//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
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().
624
URL possdant le filtre appliquer ainsi que les informations permettant de traiter la ressource.
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
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
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
// 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 !
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().
Nous avons galement besoin de crer une mthode dir_readdir() qui sera appel lors de chaque excution de la fonction readdir().
Noublions pas quil est ncessaire (parfois) de librer la ressource utilise. La mthode
dir_closedir() est l pour a !
627
Chapitre 9
Implmentation de ces mthodes pour rcuprer les tables contenues dans une base de donnes.
628
// 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); ?>
Enfin, il est possible de rinitialiser le pointeur du flux si vous implmenter la mthode dir_rewinddir().
629
Chapitre 9
630
// 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); ?>
631
Chapitre 9
Liste des tables (encore !): -> ex0 -> ex1 -> ex2 -> ex3 -> ex4 -> ex5 -> ex6 -> ex7 -> ex8 ->.ex9
632
Chapitre 10
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).
Interface graphique Il existe galement des clients ayant une interface graphique utilisable directement via votre navigateur. Pour MySQL, vous pourrez par exemple utiliser phpMyAdmin.
635
Chapitre 10
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).
636
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.
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 :
637
Chapitre 10
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
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.
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).
639
Chapitre 10
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.
640
Le langage SQL
Taille en octets 4
-9223372036854775808
9223372036854775807
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).
18446744073709551615
Il est noter que rares sont les bases de donnes qui proposent un type boolen.
641
Chapitre 10
CHARACTER(X) CHAR(X) CHARACTER VARYING(X) VARCHAR(X) TINYBLOB TINYTEXT BLOB TEXT (MySQL) MEDIUMBLOB MEDIUMTEXT LONGBLOB LONGTEXT TEXT (PostgreSQL)
642
Le langage SQL
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
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.
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
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
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
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
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).
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);
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;
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.
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
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
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.
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;
648
Le langage SQL
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);
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
Maintenant que nous avons dj bien progress dans la connaissance de linstruction SELECT, voici dautres options permettant, entre autres, de trier les 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).
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 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;
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;
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
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
Describe Il existe un quivalent SHOW COLUMNS FROM nomtable qui est DESCRIBE nomtable.
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
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.
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
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.
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).
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
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:
655
Chapitre 10
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:
656
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:
657
Chapitre 10
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
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:
659
Chapitre 10
{ 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; } } ?>
Nous utiliserons galement un objet Tri afin de dfinir la manire dont doivent tre tris les articles lors de laffichage.
660
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
// 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.
662
if (isset($_SESSION["tri"])) { $tri = $_SESSION["tri"]; } else { $tri = new Tri(); $tri->setChamp("titre"); $tri->setSens(1); $_SESSION["tri"] = $tri; }
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:
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:
663
Chapitre 10
Vous pouvez vous reporter la sections "Les variables" pour plus de dtails.
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.
664
// 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(); }
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.
665
Chapitre 10
// Modification de la plage de selection $plage->setPremierArticle($plage->getPremierArticle() $nbArticleMax); $_SESSION["plage"] = $plage; // Passage en mode visualisation header("Location: ?mode=visualisation"); die();
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.
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
Chapitre 10
/** * Retourne le tableau associatif des types * ou la cle est lidentifiant du type * la valeur le nom du type */ public function getTypes();
/** * 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).
668
$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());
Chapitre 10
public function getAlbumTypeId() { return $this->ressource->getAlbumTypeId(); } public function isAlbum($article) { if ($article->getTypeId() == $this->getAlbumTypeId()) return TRUE; else return FALSE; } } ?>
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
670
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
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 :
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.
671
Chapitre 10
$erreurs[] = "Larticle s&eactue;léctionné 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 ê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(); } }
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:
672
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; }
//----------------------------------------// 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
$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
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(); }
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éctionné 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 ê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
// 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.
et
include_once("pieddepage_inc.php");
676
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.
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 :
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.
677
Chapitre 10
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
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
678
</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é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"><<< Articles précédents</a> <?php } ?> </td> <td width="34%" align="center"> <?php if ($filtre->getAlbumId() != 0) { // Inserer un lien pour remonter a lalbum "pere" ?>
Chapitre 10
<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 >>></a> <?php }
?>
</td> </tr> </table> <br /> <center> <a href="?mode=ajout"> [Ajouter un article à 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.
680
<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 à votre guise ajouter dautres informations</i> </td> </tr> <tr> <td colspan="2"> <input type="submit" value="Sauver" /> </td> </tr> </table> </form>
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
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.
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.
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.
683
Chapitre 10
2.
3.
684
Access (MS)
4.
Voil, vous tes en passe de dcouvrir le panneau dadministration de "sources de donnes (ODBC)". Cliquez...
Figure 10.7 :
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 :
685
Chapitre 10
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)
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.
686
DB2 (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.
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.
Sous Linux
La premire chose faire consiste dcompresser larchive dans un rpertoire quelconque (ex. : /tmp/db2),
# tar xvf db2pelnx.tar
687
Chapitre 10
| the product. | | DB2 Product Messages [ Customize... ] | | DB2 Product Library [ Customize... ] | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | [ OK ] [ Cancel ] [ Help ] | +----------------------------------------------------------------------------+
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.
688
DB2 (IBM)
Vous devez alors avoir quatre lignes de rsultat. Vous pouvez alors vous dconnecter.
$ db2 connect reset
689
Chapitre 10
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 :
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.
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.
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).
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
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.
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
693
Chapitre 10
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.
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
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
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
Sous Linux
Le dmon mysqld doit tre actif pour pouvoir utiliser la base de donnes MySQL.
# /usr/local/mysql/bin/mysqld_safe --user=mysql &
695
Chapitre 10
Une autre faon de faire consiste excuter la commande en ligne mysql puis de taper :
CREATE DATABASE maBase;
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.
696
MySQL
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
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
697
Chapitre 10
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()
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
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.
$motDePasse $nouvelleCnx
$option
retour
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).
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.
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
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
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,
= "maBase";
702
MySQL
703
Chapitre 10
$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; } ?>
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
704
MySQL
Champ par champ ; Enregistrement par enregistrement (sous la forme dun tableau index, dun tableau associatif ou encore dun tableau la fois index et associatif).
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.
705
Chapitre 10
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 :
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; } ?>
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 />"; } ?>
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
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 :
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.
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; } ?>
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.
709
Chapitre 10
// 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 />";
Sachant quune requte SELECT * est plus longue quune requte SELECT COUNT(*), privilgiez la premire mthode si vous navez que faire du contenu des enregistrements.
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.
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
Unknown column nomchamp in field Le champ nomchamp prcis list dans la liste de champs nexiste pas
711
Chapitre 10
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
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).
712
MySQL
Et voici un script gnrant lensemble des erreurs ci-dessus, afin de bien mettre en vidence le bon fonctionnement de cette fonction personnalise :
713
Chapitre 10
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 :
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)".
Chapitre 10
" 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;
$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 :
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.
717
Chapitre 10
$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; } ?>
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:
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; }
Chapitre 10
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";
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"]; }
Chapitre 10
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()).
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.
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.
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
$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
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.
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
$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.
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 :
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"); } ?>
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
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
retour
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
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
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
?>
echo "Nous utilisons (sans le savoir) la version "; echo "<b>".mysql_get_proto_info()."</b> 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
odbc.check_persistent = On
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
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
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
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.
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
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.
734
ODBC
et ncessitera :
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
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().
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).
Champ par champ ; Enregistrement par enregistrement (sous la forme dun tableau index).
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
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.
<?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().
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).
$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).
739
Chapitre 10
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 :
740
ODBC
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.
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
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
Sachant quune requte SELECT * est plus longue quune requte SELECT COUNT(*), privilgiez la premire mthode si vous navez que faire du contenu des enregistrements.
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().
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
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.
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 :
745
Chapitre 10
/** * 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; } ?>
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 :
747
Chapitre 10
* 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.
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"; } ?>
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
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:
750
ODBC
break; case "IBMDB2" : $compteur = "INTEGER GENERATED BY DEFAULT AS IDENTITY"; break; default: $compteur = "INTEGER AUTO_INCREMENT"; }
$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
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;
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; }
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; }
753
Chapitre 10
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()).
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.
En savoir plus...
Il y a bien plus apprendre dune base de donnes...
754
ODBC
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.
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.
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
Cependant, les champs ont dautres informations nous livrer que leur nom et leur index. Pour cela, vous disposez des fonctions :
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.
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
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.
757
Chapitre 10
Identifiant de Type -4 -3 -2 -1 1 2 3 4 5 6 7 8 9 10 11 12
DB2 (IBM) LONG VARCHAR FOR BIT DATA VARCHAR () FOR BIT DATA CHARacter() FOR BIT DATA LONG VARCHAR CHARacter NUMeric DECimal
REAL DOUBLE
DATETIME VARCHAR
TIMESTAMP VARCHAR
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
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.
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
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.
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.
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
761
Chapitre 10
Pour vous viter des soucis, vous pouvez crer ds maintenant le rpertoire destin hberger la partie logicielle dOracle et celui pour les donnes.
# # # #
p p R R
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.
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 +
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
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
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 :
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
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.
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
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
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
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.
768
Oracle
Il est temps de prciser o doivent tre stockes les donnes de la base de donnes. Nous avons choisi /data/orainst. Cliquez sur Next.
769
Chapitre 10
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.
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
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
771
Chapitre 10
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)) ) ) )
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.
773
Chapitre 10
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.
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 :
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
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().
retour
776
Oracle
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.
retour
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).
777
Chapitre 10
OCI_DEFAULT : la requte devra tre ultrieurement valide par oci_commit() ou annule par oci_rollback(). retour TRUE en cas de succs, FALSE sinon.
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 :
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().
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.
779
Chapitre 10
// 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 :
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;
// 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
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.
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; } ?>
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.
783
Chapitre 10
{ // 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; } ?>
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
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
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).
$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
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.
787
Chapitre 10
// Boucle de lecture (et daffichage) des enregistrements while (oci_fetch($idRequete)) { echo "FilmId=".$filmId." Film=".$film."<br />"; } return TRUE; }
?>
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 :
788
Oracle
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.
Sachant quune requte SELECT * est plus longue quune requte SELECT COUNT(*), privilgiez la premire mthode si vous navez que faire du contenu des enregistrements.
789
Chapitre 10
Dans notre exemple, nous modifierons les enregistrements sans vritablement les modifier.
790
Oracle
retour
791
Chapitre 10
$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; // 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; } ?>
792
Oracle
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
OCILOB->load()
Retourne le contenu dun champ de type LOB. Syntaxe string load(void) Contenu du champ, ou FALSE en cas dchec.
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
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
// 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 />";
// 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.
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().
retour
797
Chapitre 10
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).
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.
// 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)); ?>
799
Chapitre 10
derniere erreur derniere erreur connexion derniere erreur requete Array( [code] => 900 [message] => ORA-00900: Requte SQL invalide )
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 :
800
Oracle
{ // Cration de la table $requete = "DROP TABLE $table"; $idRequete = oci_parse($idConnexion, $requete); @oci_execute($idRequete);
$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
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 :
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.
803
Chapitre 10
// 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 @
// 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:
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;
805
Chapitre 10
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";
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;
} 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
" 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() {
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; } } ?>
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()).
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
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).
retour
Cependant, les champs ont dautres informations nous livrer que leur nom. Pour cela, vous disposez des fonctions :
810
Oracle
retour
retour
811
Chapitre 10
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.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().
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
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.
$mode
&$messageErreur retour
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.
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
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.
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
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
sqlite_fetch_single() ou sqlite_fetch_string() qui est un alias, permet de rcuprer directement le premier champ et de passer la ligne suivante.
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.
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.
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.
819
Chapitre 10
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().
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.
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.
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.
821
Chapitre 10
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
// 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); ?>
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.
// 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
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);
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
824
SQLite
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 :
825
Chapitre 10
"urlId INTEGER ". "AUTO_INCREMENT PRIMARY KEY,". "url VARCHAR(128) NOT NULL,". "nbclic INTEGER DEFAULT 0,". "UNIQUE(url))"; if (!sqlite_query($idConnexion, $requete)) return FALSE;
// 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 :
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; }
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.
827
Chapitre 10
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:
828
SQLite
* Cette classe doit implementer toutes les methodes de linterface * RessourceInterface. * Compatibilite: PHP 5 */ class Ressource implements RessourceInterface { var $idConnexion;
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
"albumId INTEGER,". "titre VARCHAR(255),". "typeId INTEGER,". "commentaire VARCHAR(255))"; $idResultat = sqlite_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,". "".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";
Chapitre 10
$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; }
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()).
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.
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.
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
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
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.
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.
835
Chapitre 10
sqlite_escape_string()
Double les apostrophes et rend les donnes binaires Syntaxe string sqlite_escape_string(string $donnee) Donne encoder. Donne encode. $donnee retour
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).
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
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.
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
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.
838
Les options dinstallation sont ensuite configurables. Nous garderons les valeurs par dfaut :
839
Chapitre 10
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.
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.
840
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
842
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.
843
Chapitre 10
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 :
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
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.
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
$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
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
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.
847
Chapitre 10
"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); ?>
et ncessitera :
848
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 :
Assistant
Il faut ensuite dfinir sur quelle base de donnes la procdure stocke doit sappliquer.
Figure 10.50 :
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
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.
850
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); ?>
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.
retour
851
Chapitre 10
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
Champ par champ ; Enregistrement par enregistrement (sous la forme dun tableau index, associatif, ou la fois index et associatif).
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
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.
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
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.
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 :
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
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; ".
855
Chapitre 10
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.
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 :
856
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.
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
Sachant quune requte SELECT * est plus longue quune requte SELECT COUNT(*), privilgiez la premire mthode si vous navez que faire du contenu des enregistrements.
mssql_get_last_message()
Retourne le code derreur du dernier appel. Syntaxe retour string mssql_get_last_message(void) Le dernier message obtenu.
858
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
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 :
860
* la table "compteur de clics" **/ function CC_initialiseBD($idConnexion, $table) { // Cration de la table $requete = "DROP TABLE $table"; @mssql_query($requete, $idConnexion);
$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 :
861
Chapitre 10
* - "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 = 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.
862
// Cest lheure de la redirection if ($url) { header("Location: $url"); } else { echo "Dsol, nous ne pouvons vous proposer ce lien"; } ?>
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
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:
864
$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;
Chapitre 10
} 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;
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
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()).
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
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.
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.
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.
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
$resultat retour
Identifiant de rsultat tel que retourn par mssql_query(). Nombre de champs disponibles dans le rsultat.
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
$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
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.
871
Chapitre 10
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.
Utilisation
Lutilisation basique de la base de donnes sopre selon le schma suivant :
j
872
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().
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
DB->query()
Excute une requte SQL.
873
Chapitre 10
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.
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.
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
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.
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.
875
Chapitre 10
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();
?>
et ncessitera :
876
* 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; } ?>
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
retour
Si vous avez opt pour un mode de validation non automatique, vous pourrez valider ou annuler vos transactions avec les fonctions suivantes :
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.
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
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.
879
Chapitre 10
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.
$enregistrement $mode
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
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.
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
retour
Tableau index contenant les valeurs pour chaque enregistrement retourn, ou un objet DB_Error en cas derreur.
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
$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).
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 :
883
Chapitre 10
$resultat = $bd->getOne($requete); if (DB::isError($resultat)) return FALSE; echo "Il y a $resultat enregistrements dans la table.<br />"; return TRUE; } ?>
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.
884
Sachant quune requte SELECT * est plus longue quune requte SELECT COUNT(*), privilgiez la premire mthode si vous navez que faire du contenu des enregistrements.
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.
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).
885
Chapitre 10
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.
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.
retour
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
$nom retour
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").
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.
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.
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
string escapeSimple(string $nom) Chane de caractres traiter. La chane de caractres prte tre insre dans une requte SQL.
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.
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,
888
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) ;
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 :
889
Chapitre 10
/** * 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
// 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
Chapitre 10
* - "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";
// 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
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".
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:
893
Chapitre 10
} $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";
$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
$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
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;
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; }
Chapitre 10
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
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",
Chapitre 11
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.
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
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.
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/).
904
Installation
j j
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.
905
Chapitre 11
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
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
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
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
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.
907
Chapitre 11
Avec EasyPHP
Linstallation dEasyPHP possde, par dfaut, le module de connexion 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.
Connexion un serveur LDAP ; Identification sur serveur ; Oprations sur la base LDAP ; Fermeture de la connexion avec le serveur LDAP.
908
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.
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().
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
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.
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.
Ajouter une entre ; Modifier une entre ; Supprimer une entre ; Renommer une entre.
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
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; ?>
911
Chapitre 11
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
ldap_mod_add()
Ajoute un attribut une entre de lannuaire LDAP.
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); ?>
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
$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
// 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 !"; }
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.
914
* $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; } } ?>
915
Chapitre 11
// 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); ?>
916
*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
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.
917
Chapitre 11
// 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); ?>
Rechercher une correspondance sur un niveau ; Rechercher une correspondance sur plusieurs niveaux ; Rechercher une correspondance sur une entre spcifique.
918
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.
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
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
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.
$nbLimit $tempsExecution
$alias
retour
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
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
$alias
retour
Exemple de recherche
Cet exemple va vous montrer les diffrences existant entre ces trois fonctions :
921
Chapitre 11
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);
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.
922
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.
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
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.
<?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
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>
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.
Cration dun pointeur sur le premier lment de notre recherche ; Rcupration des donnes de cet lment ; Dplacement du pointeur sur llment suivant.
925
Chapitre 11
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.
retour
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.
ldap_next_entry()
Dplace le pointeur sur llment suivant de la recherche. Syntaxe resource ldap_next_entry(resource $idLdap, resource $idEntree)
926
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); }
Chapitre 11
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().
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
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.
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
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
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.
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
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.
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
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.
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
ldap_err2str()
Retourne le message associ au numro de lerreur. Syntaxe $numErreur retour string ldap_err2str(int $numErreur) Numro de lerreur. Message derreur.
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
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.
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
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
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 )
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
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
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.
Vous pouvez rcuprer les mmes options que pour la fonction ldap_set_option(), plus quelques autres en lecture seule.
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.
938
Exemple dapplication
/* / 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 :
939
Chapitre 11
$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> </p> <p> </p> <?php include("pieddepage.php"); ?>
Inclusion est un fichier qui contient tous les autres fichiers PHP inclure. Il ressemble ceci :
940
Exemple dapplication
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.
941
Chapitre 11
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"); } ?>
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.
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); } ?>
Chapitre 11
Figure 11.5 : Vous pouvez maintenant vous authentifier comme utilisateur, manager ou
anonyme.
944
Exemple dapplication
include("entete.php"); switch ($action) { case "ajouter": ajouterUtilisateur(); break; default: afficheFormulaire(); break; } ?> <p> </p> <p> </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().
945
Chapitre 11
{ 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];
$_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
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.
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().
947
Chapitre 11
$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.
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; } ?>
949
Chapitre 11
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 } ?> ?>
Exemple dapplication
Cette page lance dabord la fonction rechercheLdapPersonne(), qui lui retourne un tableau contenant la liste des attributs et leurs diffrentes valeurs.
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
$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().
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> </p> </body> </html>
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().
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
Exemple dapplication
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().
955
Chapitre 11
// 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>; } ?>
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.
956
Exemple dapplication
// On rcupere lentre $resultat = @ldap_get_entries($ldap, $recherche); // Dconnexion du serveur LDAP deconnexionLdap($ldap); return $resultat; } ?>
957
Chapitre 12
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.
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
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)
962
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).
retour
Une fois le serveur de courrier correctement configur, vous pouvez tester un script PHP trs simple :
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
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
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
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
965
Chapitre 12
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.)
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
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 :
// 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"); ?>
967
Chapitre 12
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.
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.
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".
968
//---------------------------------// 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";
//-------------------------------------------------// 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
// 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>
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
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.
$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
.= .= .= .= .=
//--------------------------------// 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";
$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.
972
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 :
$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
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";
//--------------------------------// 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>
974
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
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
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 :
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
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
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
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.
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
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.
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
979
Chapitre 12
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
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
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
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
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
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
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.
?>
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
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.
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
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.
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
retour
Un objet avec les attributs demands ainsi que lattribut "flags" contenant la valeur de $options.
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.
$identifiantBal retour
986
Il est galement possible davoir quelques informations supplmentaires sur lensemble ou un sous-ensemble de messages.
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
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.
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
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
Chapitre 12
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 @.
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
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()).
991
Chapitre 12
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>
992
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.
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
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 (???).
j j j j j j j j j j j j j j j j j j j j j j j
994
j j
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.
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
$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.
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
996
$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); ?>
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
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().
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).
998
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.
<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>
999
Chapitre 12
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.
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.
1000
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
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.
$listeMsg
$drapeau
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
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.
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 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.
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.
1004
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
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.
imap_subscribe()
Permet de sinscrire une bote lettres (pour les serveurs de "news").
1005
Chapitre 12
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.
$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.
1006
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.
retournerait :
Eh ! Mas tu vu ? <Emma@tuvu.com>
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.
1007
Chapitre 12
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 :
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.
1008
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
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
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.
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
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.
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
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.
La premire des pages permettra dentrer le nom du serveur IMAP ou POP, le login de lutilisateur et le mot de passe associ.
1012
<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>
Une fois connect, lutilisateur est en mesure davoir un aperu des messages prsents dans la bote lettres :
1013
Chapitre 12
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.
1015
Chapitre 12
} $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 />"; }
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
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.
1017
Chapitre 12
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.
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.
1018
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.
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.
1019
Chapitre 13
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.
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.
1023
Chapitre 13
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
;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
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
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.
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
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.
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
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.
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.
1027
Chapitre 13
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.
$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
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.
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
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.
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
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.
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
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.
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
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
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.
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
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);
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
$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 :
imageColorExact()
Retourne lidentifiant de la couleur si la couleur existe dans la palette.
1035
Chapitre 13
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.
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.
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
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.
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)
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
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.
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
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
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
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
$couleur retour
Identifiant de la couleur supprimer, tel que retourn par les fonctions imageColorAllocate() et imageColorResolve(). FALSE en cas dchec, TRUE sinon.
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.
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
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.
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 :
1042
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);
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
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
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).
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).
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).
1044
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
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.
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
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.
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 .
polices
dcriture
libres
de
droits
sur
1046
"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
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
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.
retour
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
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).
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
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
$y
1050
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])
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
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.
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
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
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.
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
1053
Chapitre 13
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...
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.
1054
$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);
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.
retour
1055
Chapitre 13
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
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
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.
1059
Chapitre 13
$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
1060
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
1061
Chapitre 13
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
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.
Voici un exemple traant une ligne compose de deux pixels bleus, puis deux rouges, puis deux verts, deux bleus, deux rouges, etc.
$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
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.
retour
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.
1064
Figure 13.14 :
Le rsultat
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.
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.
1065
Chapitre 13
Abscisse sur limage source. Ordonne sur limage source. Largeur du morceau dimage rcuprer. Hauteur du morceau dimage rcuprer. TRUE.
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
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.
Et voici une page HTML qui fait appel quatre fois ce script en variant le coefficient de transparence.
1067
Chapitre 13
<td>50</td> <td>100</td> </tr> </table> </body> </html> Figure 13.17 : Quelques exemples
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
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
Figure 13.19 :
Le rsultat
1069
Chapitre 13
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
Figure 13.21 :
Le rsultat
1070
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.
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
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.
imageSX()
Retourne la largeur de limage. Syntaxe int imageSX(resource $image)
1072
$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 :
Ici, nous rcuprons simplement limage fondhisto.jpg, qui sera limage de fond de lhistogramme.
Figure 13.24 :
tape 1
1073
Chapitre 13
tape 2
Nous allons maintenant ajouter un titre :
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
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
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.
1076
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.
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
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>.
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
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.
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
$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 ce qui est retourn dans le cas de cette photo (limagette a t retire) :
adrien.jpg: FILE.FileName: adrien.jpg
1080
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
Chapitre 13
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).
1082
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
Vous voil maintenant avec un fichier libming.so. Copiez libming.so sous /usr/local/lib.
# cp libming.so /usr/local/lib/.
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
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.
Figure 13.31 :
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
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.
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
?>
$anim->output();
ou
<?php $anim = new Movie(); // Construction proprement dite de lanimation header("Content-type: application/x-shockwave-flash"); $anim->output();
?>
SWFMovie()->nextFrame()
Valide la vue en cours et passe la cration de la suivante. Syntaxe void nextFrame(void)
Les textes ; Les formes "complexes" (bases sur des lignes, courbes, etc.) ; Les boutons ; Les zones de saisie de texte.
1086
Les remplissages.
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.
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
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)
// 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
// 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();
?>
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
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).
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
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 :
// 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
$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();
?>
1092
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().
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).
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
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.
Syntaxe $police
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
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.
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
SWFTextField->addString()
Prcise ou ajoute un texte au contenu du champ texte. Syntaxe $texte void addString(string $texte) Texte ajouter au champ texte.
SWFFont
Objet police de caractres. Syntaxe SWFFont SWFFont(string $fichierPolice) Chemin vers un fichier .dbf contenant les caractristiques de la police de caractres. $fichierPolice
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
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.
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 :
SWFShape
Objet forme "complexe". Syntaxe SWFShape SWFShape()
1097
Chapitre 13
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.
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
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.
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
$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.
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
$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.
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 :
1101
Chapitre 13
$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);
$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();
?>
1103
Chapitre 13
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.
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.
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
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.
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.
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
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.
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
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.
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
Figure 13.35 : Exemple dun objet cr avec le centre lorigine Figure 13.36 : puis ayant subi une translation
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
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.
1108
$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();
?>
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
$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).
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.
1110
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.
1111
Chapitre 13
?>
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
$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
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
SWFBitmap->getWidth()
Retourne la largeur, en pixels, de limage. Syntaxe int getWidth(void)
1113
Chapitre 13
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.
// // // //
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
$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();
?>
$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
$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();
?>
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
SWFGradient
Objet "dgrad" utilis comme motif de remplissage. Syntaxe SWFGradient SWFGradient(void)
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
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).
Figure 13.42 : Exemples de dgrads linaires (avec deux puis trois couleurs)
Figure 13.43 : Exemples de dgrads radiaux (avec deux puis trois couleurs)
1117
Chapitre 13
// 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);
$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
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.
$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
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 :
$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
?>
Ces mthodes sont galement indispensables pour bien matriser le rendu dun dgrad.
// 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
$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();
?>
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
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.
Lalgorithme de base dune animation de type morphing aura donc lallure suivante :
1123
Chapitre 13
// 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);
// // // // //
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
Chapitre 13
$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);
$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);
Chapitre 13
$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);
?>
SWFButton
Objet bouton. Syntaxe SWFButton SWFButton(void)
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
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.
1130
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 :
<?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
Syntaxe retour
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
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
Chapitre 13
// 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;".
"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);
Chapitre 13
$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
?>
Chapitre 14
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.
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
1139
Chapitre 14
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.
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.
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 :
1140
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.
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
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.
1142
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); ?>
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
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.
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.
$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()).
1144
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.
100 0 0 1
1145
Chapitre 14
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).
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.
Les fonctions que nous avons vues jusqu prsent nous permettent de crer le script (assez simple) suivant :
1147
Chapitre 14
// 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); ?>
Afficher du texte
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.
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
$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().
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.
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).
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
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
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.
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
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.
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
$rayon retour
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.
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
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.
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
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 :
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
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.
La couleur
pdf_setColor()
Dfinit la couleur de trait et/ou de remplissage.
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
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
// 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().
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.
pdf_setLineWidth()
Permet de modifier lpaisseur du trait. Syntaxe boolean pdf_setLineWidth(resource $objetPDF, double $largeur)
1158
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
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
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.
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; ?>
Les pointills
Il est possible de dfinir des pointills simples...
1161
Chapitre 14
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.
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
retour
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
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.
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.
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().
1163
Chapitre 14
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.
$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
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).
pdf_clip()
Permet de dcouper une partie de limage dfinie prcdemment par un trac. Syntaxe boolean pdf_clip(int $objetPDF)
1165
Chapitre 14
$objetPDF retour
<?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
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
"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.
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.
retour
1167
Chapitre 14
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.
pdf_add_launchlink()
Ajoute un lien vers un fichier.
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
$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
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
1169
Chapitre 14
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.
retour
1170
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
1171
Chapitre 14
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.
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
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.
1173
Chapitre 14
1174
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.
Valeur du paramtre.
Warning
1175
Chapitre 14
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"
"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"
openaction
"retain"
1176
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".
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.
pdf_save()
Enregistre lenvironnement courant. Syntaxe $objetPDF retour boolean pdf_save(resource $objetPDF) Identifiant tel que retourn par pdf_new(). TRUE.
1177
Chapitre 14
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.
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.
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) :
Chapitre 14
<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>
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);
// Creer une nouvelle page: la page de garde pdf_begin_page($pdf, $largeur, $hauteur); // Placement du modele sur la page
1181
Chapitre 14
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"); }
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; ?>
Ce script cre un fichier PDF de deux pages ; la premire est la page de garde dun fax :
1183
Chapitre 14
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
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 noms des balises sont gnralement en minuscules. Un document respectant ces rgles est dit bien form.
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/
et sa traduction :
http://babel.alis.com/web_ml/xml/REC-xml.fr.html
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.
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>
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
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()
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.
Les dclarations des fonctions devant tre appeles pour les vnements nous intressant.
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...).
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
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.
1193
Chapitre 15
Lutilisation de XML
$parseur $nomBalise
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.
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
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); ?>
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
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
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
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.
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); ?>
donnera effectivement :
Noir Dsir : des Visages des Figures Placebo : Without You Im Nothing
1199
Chapitre 15
Lutilisation de XML
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.
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
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");
// 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); ?>
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
Chapitre 15
Lutilisation de XML
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);
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(); ?>
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
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.
$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.
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>";
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;
} // 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
Rfrence une entit interne Les rfrences internes sont, quant elles, automatiquement remplaces par leurs valeurs (comme le prouve lexemple prcdent).
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.
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).
Lensemble des paramtres tant fourni par le parseur, la fonction aura accs toutes les informations ncessaires au bon traitement des donnes.
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.
$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
$idPublic
$nomNotation retour
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
1212
Les parseurs
void maFonction(resource $parseur, string $chaine) Rfrence du parseur telle xml_parser_create(). 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 informations.
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).
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().
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
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
que
retourne
par
la
fonction
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:
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 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.
Encodage utilis.
1217
Chapitre 15
Lutilisation de XML
Attribut
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)
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.
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
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
void boolean
saveHTML()
String
saveHTMLFile(String $nomFichier)
String
saveXML([DOMNode $noeud])
String
schemaValidate(String $nomFichierSchema)
boolean
schemaValidateSource(String $schema)
boolean
validate() xinclude()
boolean int
1219
Chapitre 15
Lutilisation de XML
localName
String
baseURI
textContent appendChild(DOMNode $noeud) cloneNode([boolean $enProfondeur]) hasAttributes() hasChildNodes() insertBefore(DOMNode $noeudAInserer[, DOMNode $noeudReference]) isSameNode($DOMNode $noeudAComparer)
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
DOMNodeList
getElementByTagNameNS(String DOMNodeList $espaceNom, String $nom) hasAttribute(String $nom) hasAttributeNS(String $espaceNoms, String $nom) boolean 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)
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
schemaTypeInfo isId()
1222
Les parseurs
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.
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.
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.
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.
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
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
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
1227
Chapitre 15
Lutilisation de XML
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>.
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.
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 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.
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:
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 :
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"
Et le rsultat:
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 ) ) ) ) ) )
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.
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 :
<?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
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 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:
Qui donne:
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.
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:
SimpleXMLElement->attributes()
Retourne un objet de type SimpleXMLElement correspondant aux attributs du nud courant. Syntaxe retour SimpleXMLElement attributes() Un objet de type SimpleXMLElement.
1239
Chapitre 15
Lutilisation de XML
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
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.
XML, XSL Vous trouverez plus dinformations sur XML et la XSL, sur le site :
http://www.xmlfacile.com
et sa traduction :
http://www.xmlfr.org/w3c/TR/xslt/
1241
Chapitre 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
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:
# # # #
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 :
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.
?>
1245
Chapitre 15
Lutilisation de XML
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.
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
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
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()
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.
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
$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().
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.
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); ?>
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.
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).
xslt_set_log()
Demande lactivation/larrt des traces. Indique quel fichier utiliser pour les traces.
1253
Chapitre 15
Lutilisation de XML
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.
Web services Le langage XML est galement la base de lchange dinformations des "Web services".
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
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 :
$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
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
<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.
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".
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
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
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
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.
$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
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
Chapitre 16
Rseau
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.
Alors que :
<?php echo getHostByName("www.php.net"); ?>
1265
Chapitre 16
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().
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().
1267
Chapitre 16
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().
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.
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"); ?>
1269
Chapitre 16
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.
pourra retourner :
6 cftp
1270
Les sockets
j j j j
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.
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().
Conguration de la connexion
Il est possible de jouer sur deux paramtres de connexion :
j j
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
(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.
retour
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).
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.
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
// 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>"; } ?>
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).
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
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.
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_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.
1277
Chapitre 16
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.
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.
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
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.
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
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.
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
Chapitre 16
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
Chapitre 16
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> </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;
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
Chapitre 16
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.
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
Chapitre 16
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.
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.)
j j
1288
j j j j
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
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
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
curl_close()
Ferme une session cURL. Syntaxe $curlId void curl_close(resource $curlId) Pointeur sur la ressource tel que retourn par curl_init().
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
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.
CURLOPT_CUSTOMREQUEST CURLOPT_FAILONERROR
CURLOPT_FILE
CURLOPT_FOLLOWLOCATION
CURLOPT_FTPAPPEND
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
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
CURLOPT_PROXYUSERPWD
CURLOPT_PUT
CURLOPT_RANGE
1292
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_STDERR
CURLOPT_TIMECONDITION
CURLOPT_URL
CURLOPT_USERAGENT CURLOPT_USERPWD
CURLOPT_VERBOSE
1293
Chapitre 16
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.
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.
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_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.
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.
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.
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
1296
1297
Chapitre 16
SOAP
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>
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
<!-- 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"/>
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>
<!-- 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
</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>
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)
Il nest toutefois pas assur que cela suffise pour un fonctionnement parfait.
SOAP_Client()
Constructeur dobjets SOAP_Client. Syntaxe SOAP_client SOAP_client(String $url [, boolean $wsdl [, string $nomPort]])
1303
Chapitre 16
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.
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.
Vous serez galement intress par le tlchargement de lAPI, car cest elle qui vous dira comment effectuer vos requtes.
1305
Chapitre 16
) [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
1307
Chapitre 16
(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>
1308
Chapitre 17
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
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:;").
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.
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
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.
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
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
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
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
retour
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().
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.
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.
1319
Chapitre 17
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).
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
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 )
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()
<?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
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.
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
Access.Application ; Excel.Application ; Excel.Worksheet ; Excel.Chart ; MSGraph.Chart ; Outlook.Application ; Powerpoint.Application ; Powerpoint.Presentation ; Word.Application ; Word.Document.
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.
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
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.
1329
Chapitre 18
// 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;
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.
1331
Chapitre 18
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
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
Chapitre 18
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.
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.
Ce script ne fait quaccoler les trois documents et enregistre le rsultat en tant que fichier HTML la racine du site web.
1334
COM
1335
Chapitre 18
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.
Chapitre 19
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
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
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).
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
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
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).
1343
Chapitre 19
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.
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
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.
1345
Chapitre 19
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).
Graphe Les graphiques ont t raliss grce la bibliothque JpGraph dcrite en annexe de ce livre.
1346
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).
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
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
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.
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
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)
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 :
1350
Puis vous pourrez slectionner le rpertoire dans lequel vous souhaitez installer le logiciel.
Figure 19.8 : Slection du rpertoire php.ini
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
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
...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 :
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
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
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 :
1353
Chapitre 19
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>
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
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.
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
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 :
1356
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
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
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
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
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 :
Mesures
Page quasi-statique
Figure 19.23 :
3 5 7 10 50 100
1359
Chapitre 19
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.
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
1360
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%.
Page mathmatique
Figure 19.25 :
1361
Chapitre 19
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.
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.
1362
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
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()
Mesures
Page quasi-statique
Figure 19.27 :
1363
Chapitre 19
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
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 :
1365
Chapitre 19
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).
1366
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
Fentre daccueil
... aprs avoir dit "bonjour". Vous pouvez taper [Entre] pour passer aux choses srieuses.
Figure 19.31 :
Licence
1367
Chapitre 19
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
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
1368
Il vous est ensuite demand quel est le type de la licence. Dans notre cas, il sagit dune licence dvaluation.
Figure 19.37 : Tlchargement
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
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
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 :
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
Puis, il vous faudra confirmer le nom dutilisateur sous lequel tourne le serveur Apache.
Figure 19.45 : Espace cache
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.
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
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
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
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
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...
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
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
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
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
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.
1376
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.
1377
Chapitre 19
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.
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
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()) ;
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.
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
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
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 :
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
1383
Chapitre 20
Et cest parti...
Figure 20.4 : Fentre daccueil
...aprs avoir dit "bonjour". Cest fait ? Vous pouvez taper [Entre].
Figure 20.5 :
Licence
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
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
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
# /usr/local/Zend/ZendEncoderGUI
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
1386
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 :
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
Une fois le projet totalement dfini, il ne vous reste qua cliquer sur "Encode !".
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.
1388
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.
Installation
Il suffit de dcompresser larchive dans son rpertoire de destination (ex: /usr/local)
# tar zxvf ioncube_encoder_evaluation_3.0.tar.gz
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.
1389
Chapitre 20
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.
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.
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.
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
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.
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
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
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)?
$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);
1396
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
Chapitre 21
= = = =
; ; ; ;
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.
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
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.
1399
Chapitre 21
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
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
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.
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.
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
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.
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)
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
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.
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
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/.
1407
Chapitre 21
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.
1408
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.
1409
Chapitre 21
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
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
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.
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
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
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.
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/.
1413
Chapitre 21
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
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.
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
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/.
21.7. Graphiques
JPGraph
Prsentation
JPGraph est une bibliothque en PHP qui permet de crer simplement et rapidement des
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.
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.
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
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.
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
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).
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).
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
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
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
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.
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
Chapitre 23
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
504
1427
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,
1440