You are on page 1of 418

Cet ouvrage a bnci des relectures attentives des zCorrecteurs.

Sauf mention contraire, le contenu de cet ouvrage est publi sous la licence : Creative Commons BY-NC-SA 2.0 La copie de cet ouvrage est autorise sous rserve du respect des conditions de la licence Texte complet de la licence disponible sur : http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ Simple IT 2010 - ISBN : 978-2-9535278-1-0

Avant-propos

l ny a pas si longtemps encore, on concevait les sites web comme de simples pages de prsentation. Ainsi, un internaute qui souhaitait se faire connatre crait sa page perso pour parler un peu de lui, tandis quune entreprise utilisait sa page web pour y prsenter ses produits et services. Finalement, les sites web ntaient pas si loigns des aches que lon pouvait rencontrer dans la rue : vous y lisez une information, puis vous passez votre chemin. partir des annes 2000, notre conception du Web a commenc changer. On a dcouvert quon pouvait en faire bien plus quune ache publicitaire, quil tait possible de le transformer en un vritable lieu dchanges o le visiteur ne serait plus seulement lecteur mais aussi acteur. Ctait en fait le dbut dune vritable rvolution du Web, que certains ont nomme Web 2.0 . Les premiers sites informatifs taient dits statiques car leur contenu ne changeait que trs rarement, au bon vouloir de leur crateur, le webmaster. Leurs successeurs, les sites web participatifs, ont t appels sites dynamiques car leur contenu pouvait tre modi tout moment par nimporte quel visiteur. Aujourdhui, on ne conoit plus le Web autrement que par ses sites dynamiques qui invitent linternaute participer : les blogs : ils sont rgulirement mis jour par leurs crateurs et les lecteurs peuvent participer en commentant les billets. Ce sont des sites dynamiques ; les forums : ce sont de vritables espaces de discussion en ligne ; les rseaux sociaux : Facebook et Twitter, pour ne citer queux, invitent les internautes changer entre eux, que ce soient des messages, des photos, des vidos... Ce sont eux aussi des sites dynamiques. En fait, la plupart des sites web que vous connaissez et que vous visitez aujourdhui sont des sites dynamiques. On pourrait ajouter de nombreux autres sites dans cette catgorie, comme les moteurs de recherche, les webmails, les wikis, etc. Ainsi, vous souhaitez vous aussi crer un site dynamique ? Vous aimeriez avoir votre blog, votre site avec un espace membres, un chat et des forums pour discuter ? Mais vous ne savez pas comment vous y prendre ni par o commencer ? Cest justement pour vous aider vous lancer que ce livre existe ! Jai souhait crire un cours destin aux dbutants, le plus progressif et pdagogique possible. Le rsultat est entre vos mains. i

CHAPITRE 0. AVANT-PROPOS

PHP et MySQL, les outils du web dynamique


PHP est un des langages les plus clbres et les plus utiliss permettant de crer des sites web dynamiques. Cest notamment lui qui se cache derrire Facebook et Wikipdia qui font partie des sites les plus frquents au monde. Pour programmer en PHP, il faut connatre les langages de base du web : HTML et CSS. Le premier chapitre vous en expliquera toutes les raisons. On associe la plupart du temps PHP une base de donnes pour concevoir des sites capables de stocker tout le ot de donnes quils reoivent. Parmi tous les systmes de bases de donnes qui existent, MySQL est un des outils que lon utilise le plus couramment. Ce nest donc pas un hasard si jai choisi de vous faire dcouvrir dans ce livre la combinaison PHP + MySQL . Cest la plus courante1 et elle a fait ses preuves depuis un certain nombre dannes maintenant. Le cours que vous allez dcouvrir a dj t lu plusieurs millions de fois en ligne sur le site que jai cr, le Site du Zro (www.siteduzero.com). Il a donc bnci de trs nombreuses relectures de la part de dbutants qui mont signal les points qui leur paraissaient obscurs, mais aussi dexperts qui mont aid en faire un cours qui enseigne les bonnes bases solides et qui vous donne les bonnes habitudes. Je lai entirement mis jour rcemment pour tenir compte des dernires techniques de dveloppement web et traiter de sujets plus avancs, comme la programmation oriente objet et larchitecture MVC2 .

Quallez-vous apprendre en lisant ce livre ?


Jai mri le plan du livre que vous allez lire pendant des annes pour mettre au point un cours progressif et concret ddi aux dbutants. Voici le plan que je vous propose de suivre tout au long de cet ouvrage. 1. Les bases de PHP : cette premire partie, spcialement ddie aux dbutants en PHP, va nous permettre de dcouvrir ensemble tous les concepts de base du langage. Nous installerons dabord les outils ncessaires pour travailler, que vous soyez sous Windows, Mac OS X ou Linux, puis nous raliserons nos toutes premires pages web en PHP en manipulant les variables, les includes, les boucles, les fonctions, les tableaux... 2. Transmettre des donnes de page en page : nous entrerons ensuite dans
1 Mais ce nest pas la seule qui existe, nous dcouvrirons dailleurs dautres langages concurrents dans le premier chapitre ! 2 Si vous ne comprenez pas ces termes barbares, pas de panique ! Ces sujets plus avancs sont expliqus vers la n du cours et vous aurez tout le temps dapprendre progressivement le PHP auparavant. ;o)

ii

COMMENT LIRE CE LIVRE ? un sujet un peu plus pointu, savoir la transmission de donnes entre des pages. De nombreux concepts essentiels de PHP seront abords : traitement des URL et des formulaires, sessions, cookies, chiers... Nous raliserons nos premiers Travaux Pratiques (TP) ensemble en apprenant protger le contenu dune page par un mot de passe. 3. Stocker des informations dans une base de donnes : nous commencerons travailler avec MySQL partir de cette partie. Nous apprendrons ce quest une base de donnes, nous dcouvrirons le clbre outil phpMyAdmin, puis nous crirons nos premires requtes en langage SQL. Votre niveau va rellement voluer tout au long de cette partie, car vous pourrez raliser un mini-chat et un systme de blog avec commentaires au cours de dirents TP ! 4. Utilisation avance de PHP : cette section est ddie ceux qui ont bien lu et assimil les parties prcdentes. Nous aborderons des notions plus avances autour de PHP qui vont considrablement augmenter vos possibilits : expressions rgulires, programmation oriente objet, architecture MVC, etc. Comme vous, je naime pas les cours thoriques qui nous noient dans de nouvelles notions sans nous proposer dapplication pratique. Jaime pouvoir raliser des petits projets concrets au fur et mesure de mon apprentissage, et cest pour cela que ce cours est ponctu de plusieurs TP. Vous pourrez ainsi vous tester rgulirement et dcouvrir ce que vous tes en mesure de faire votre niveau. :o)

Comment lire ce livre ?


Suivez lordre des chapitres
Lisez ce livre comme on lit un roman. Il a t conu de cette faon. Contrairement beaucoup de livres techniques o il est courant de lire en diagonale et de sauter certains chapitres, ici il est trs fortement recommand de suivre lordre du cours, moins que vous ne soyez dj un peu expriments.

Pratiquez en mme temps


Pratiquez rgulirement. Nattendez pas davoir ni la lecture de ce livre pour allumer votre ordinateur et faire vos propres essais.

Utilisez les codes web !


An de tirer parti du Site du Zro dont est issu ce livre, celui-ci vous propose ce quon appelle des codes web . Ce sont des codes six chires rentrer sur une page du Site du Zro pour tre automatiquement redirig vers un site web sans avoir en recopier ladresse. iii

CHAPITRE 0. AVANT-PROPOS Pour utiliser les codes web, rendez-vous sur la page suivante3 : http://www.siteduzero.com/codeweb.html Un formulaire vous invite rentrer votre code web. Faites un premier essai avec le code ci-dessous : Code web : 123456 Ces codes web ont deux intrts : vous faire tlcharger les codes source inclus dans ce livre, ce qui vous vitera davoir recopier certains codes un peu longs ; vous rediriger vers les sites web prsents tout au long du cours. Ce systme de redirection nous permet de tenir jour le livre que vous avez entre les mains sans que vous ayez besoin dacheter systmatiquement chaque nouvelle dition. Si un site web change dadresse, nous modierons la redirection mais le code web utiliser restera le mme. Si un site web disparat, nous vous redirigerons vers une page du Site du Zro expliquant ce qui sest pass et vous proposant une alternative. En clair, cest un moyen de nous assurer de la prennit de cet ouvrage sans que vous ayez faire quoi que ce soit !

Ce livre est issu du Site du Zro


Cet ouvrage reprend le cours PHP & MySQL du Site du Zro dans une dition revue et corrige, augmente de nouveaux chapitres plus avancs et de notes de bas de page. Il reprend les lments qui ont fait le succs des cours du site, cest--dire leur approche progressive et pdagogique, le ton dcontract et lger4 , ainsi que les TP qui vous invitent pratiquer vraiment. Vous verrez que je mexprime toujours la premire personne. Jai pris cette habitude an de montrer que je vous accompagne rellement dans votre dcouverte de PHP. Imaginez tout simplement que nous sommes vous et moi dans la mme salle et que je suis votre professeur.

Remerciements
Je tiens remercier un grand nombre de personnes qui mont aid et soutenu dans la ralisation de ce livre. Mes parents, qui suivent avec attention ce que jessaie de construire avec le Site du Zro et la collection Livre du Zro. lodie, qui ne manque jamais dnergie pour mencourager continuer.
pouvez aussi utiliser le formulaire de recherche du Site du Zro, section Code Web . faudrait-il forcment que la dcouverte dun langage informatique soit longue et ennuyeuse ? ;-)
4 Pourquoi 3 Vous

iv

REMERCIEMENTS Pierre Dubuc, mon associ, qui travaille darrache-pied avec moi pour faire valoir notre approche rsolument dirente des cours pour dbutants. Nos infographistes, Fan Jiyong (couverture du livre) et Yannick Piault (illustrations des chapitres) qui ont nouveau beaucoup travaill pour illustrer ce livre. Vincent Pontier, le crateur de llPHPant, pour son aimable autorisation de reproduction de la plus clbre des mascottes. Lquipe des zCorrecteurs, toujours aussi dvolue la langue franaise, qui a fait nouveau un travail formidable de relecture orthographique et damlioration du style et de la uidit des phrases. Merci tout particulirement Philippe Lutun (ptipilou), Loc Le Breton (Fihld), Martin Wetterwald (DJ Fox), Stphanie Noardo (Poulpette) et tienne de Maricourt (Xeroth). Lquipe de Simple IT et tous les visiteurs du Site du Zro qui font que cette belle aventure dure depuis plus dune dizaine dannes ! Je vous souhaite une bonne dcouverte de PHP et MySQL. Faites de beaux sites web !

CHAPITRE 0. AVANT-PROPOS

vi

Sommaire

Avant-propos PHP et MySQL, les outils du web dynamique . . . . . . . . . . . . . . . . . . Quallez-vous apprendre en lisant ce livre ? . . . . . . . . . . . . . . . . . . . Comment lire ce livre ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ce livre est issu du Site du Zro . . . . . . . . . . . . . . . . . . . . . . . . . Remerciements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

i ii ii iii iv iv

Les bases de PHP

1
3 4 5 7 10 13 14 15 20 23 26 33 vii

1 Introduction PHP Les sites statiques et dynamiques . . . . . . . . . . . . . . . . . . . . . . . . . Comment fonctionne un site web ? . . . . . . . . . . . . . . . . . . . . . . . . Les langages du Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Et la concurrence ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Prparer son ordinateur De quels programmes a-t-on besoin ? . . . . . . . . . . . . . . . . . . . . . . . Sous Windows : WAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sous Mac OS X : MAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sous Linux : XAMPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Utiliser un bon diteur de chiers . . . . . . . . . . . . . . . . . . . . . . . . . 3 Premiers pas avec PHP

SOMMAIRE Les balises PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Acher du texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Inclure des portions de page Le principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . La pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Les variables Quest-ce quune variable ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aecter une valeur une variable . . . . . . . . . . . . . . . . . . . . . . . . . Acher et concatner des variables . . . . . . . . . . . . . . . . . . . . . . . . Faire des calculs simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Les conditions La structure de base : if. . . else . . . . . . . . . . . . . . . . . . . . . . . . . . Une alternative pratique : switch . . . . . . . . . . . . . . . . . . . . . . . . . Les ternaires : des conditions condenses . . . . . . . . . . . . . . . . . . . . . 7 Les boucles Une boucle simple : while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Une boucle plus complexe : for . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Les fonctions Quest-ce quune fonction ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les fonctions prtes lemploi de PHP . . . . . . . . . . . . . . . . . . . . . . Crer ses propres fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Les tableaux Les deux types de tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . Parcourir un tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rechercher dans un tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 37 41 43 44 46 49 50 52 55 57 61 62 68 71 73 74 76 79 80 83 87 91 92 95 98

II

Transmettre des donnes de page en page

103
105

10 Transmettre des donnes avec lURL viii

SOMMAIRE Envoyer des paramtres dans lURL . . . . . . . . . . . . . . . . . . . . . . . 106 Rcuprer les paramtres en PHP . . . . . . . . . . . . . . . . . . . . . . . . 107 Ne faites jamais conance aux donnes reues ! . . . . . . . . . . . . . . . . . 108 11 Transmettre des donnes avec les formulaires 117

Crer la base du formulaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Les lments du formulaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 Ne faites jamais conance aux donnes reues : la faille XSS . . . . . . . . . . 125 Lenvoi de chiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 137

12 TP : page protge par mot de passe

Instructions pour raliser le TP . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 Aller plus loin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 13 Variables superglobales, sessions et cookies 145

Les variables superglobales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Les sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 Les cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 14 Lire et crire dans un chier 157

Autoriser lcriture de chiers (chmod) . . . . . . . . . . . . . . . . . . . . . . 158 Ouvrir et fermer un chier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 Lire et crire dans un chier . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161

III

Stocker des informations dans une base de donnes

165
167

15 Prsentation des bases de donnes

Le langage SQL et les bases de donnes . . . . . . . . . . . . . . . . . . . . . 168 Structure dune base de donnes . . . . . . . . . . . . . . . . . . . . . . . . . 170 Mais o sont enregistres les donnes ? . . . . . . . . . . . . . . . . . . . . . . 172 16 phpMyAdmin 173

Crer une table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Modier une table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Autres oprations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 ix

SOMMAIRE 17 Lire des donnes 187

Se connecter la base de donnes en PHP . . . . . . . . . . . . . . . . . . . . 188 Rcuprer les donnes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 Les critres de slection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 Construire des requtes en fonction de variables . . . . . . . . . . . . . . . . . 202 Traquer les erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 18 crire des donnes 209

INSERT : ajouter des donnes . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 UPDATE : modier des donnes . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 DELETE : supprimer des donnes . . . . . . . . . . . . . . . . . . . . . . . . . . 215 19 TP : un mini-chat 217

Instructions pour raliser le TP . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Aller plus loin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 20 Les fonctions SQL 225

Les fonctions scalaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Les fonctions dagrgat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 GROUP BY et HAVING : le groupement de donnes . . . . . . . . . . . . . . . . 234 21 Les dates en SQL 237

Les champs de type date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 Les fonctions de gestion des dates . . . . . . . . . . . . . . . . . . . . . . . . . 240 22 TP : un blog avec des commentaires 243

Instructions pour raliser le TP . . . . . . . . . . . . . . . . . . . . . . . . . . 244 Correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 Aller plus loin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 23 Les jointures entre tables 257

Modlisation dune relation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Quest-ce quune jointure ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 Les jointures internes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 Les jointures externes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 x

SOMMAIRE

IV

Utilisation avance de PHP

269
271

24 Crer des images en PHP

Activer la bibliothque GD . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 Les bases de la cration dimage . . . . . . . . . . . . . . . . . . . . . . . . . 272 Texte et couleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Dessiner une forme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 Des fonctions encore plus puissantes . . . . . . . . . . . . . . . . . . . . . . . 283 25 Les expressions rgulires (partie 1/2) 291

O utiliser une regex ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292 Des recherches simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 Les classes de caractres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 Les quanticateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 26 Les expressions rgulires (partie 2/2) 303

Une histoire de mtacaractres . . . . . . . . . . . . . . . . . . . . . . . . . . 304 Les classes abrges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305 Construire une regex complte . . . . . . . . . . . . . . . . . . . . . . . . . . 306 Capture et remplacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312 27 La programmation oriente objet Crer une classe 319

Quest-ce quun objet ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 Crer un objet partir de la classe . . . . . . . . . . . . . . . . . . . . . . . . 329 Constructeur, destructeur et autres fonctions spciales . . . . . . . . . . . . . 331 Lhritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 Les droits daccs et lencapsulation . . . . . . . . . . . . . . . . . . . . . . . 336 28 Organiser son code selon larchitecture MVC 339

Quest-ce que larchitecture MVC ? . . . . . . . . . . . . . . . . . . . . . . . . 340 Le code du TP blog et ses dfauts . . . . . . . . . . . . . . . . . . . . . . . . 342 Amlioration du TP blog en respectant larchitecture MVC . . . . . . . . . . 344 Aller plus loin : les frameworks MVC . . . . . . . . . . . . . . . . . . . . . . . 349 29 TP : crer un espace membres 351 xi

SOMMAIRE Conception de lespace membres . . . . . . . . . . . . . . . . . . . . . . . . . 352 Ralisation des pages principales de lespace membres . . . . . . . . . . . . . 355 Aller plus loin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360

Annexes

361
363

A Codez proprement

Des noms clairs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364 Indentez votre code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366 Un code correctement comment . . . . . . . . . . . . . . . . . . . . . . . . . 367 B Utilisez la documentation PHP ! 371

Accder la doc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372 Prsentation dune fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 C Au secours ! Mon script plante ! 379

Les erreurs les plus courantes . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 Traiter les erreurs SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382 Quelques erreurs plus rares . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383 D Protger un dossier avec un .htaccess 387

Crer le .htaccess . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 Crer le .htpasswd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 Envoyer les chiers sur le serveur . . . . . . . . . . . . . . . . . . . . . . . . . 391 E Mmento des expressions rgulires 393

Structure dune regex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 Classes de caractres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 Quanticateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 Mtacaractres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 Classes abrges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 Capture et remplacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396 Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396

xii

Premire partie

Les bases de PHP

Chapitre

1
Dicult :

Introduction PHP

e qui fait le succs du Web aujourdhui, cest la fois sa simplicit et sa facilit daccs. Un internaute lambda na pas besoin de savoir comment a fonctionne derrire . Et heureusement pour lui.

En revanche, un apprenti webmaster tel que vous doit, avant toute chose, connatre les bases du fonctionnement dun site web. Quest-ce quun serveur et un client ? Comment rend-on son site dynamique ? Que signient PHP et MySQL ? Ce premier chapitre est l pour rpondre toutes ces questions et vous montrer que vous tes capables dapprendre crer des sites web dynamiques. Tous les lecteurs seront la n rassurs de savoir quils commencent au mme niveau !

CHAPITRE 1. INTRODUCTION PHP

Les sites statiques et dynamiques


On considre quil existe deux types de sites web : les sites statiques et les sites dynamiques. Les sites statiques : ce sont des sites raliss uniquement laide des langages HTML et CSS. Ils fonctionnent trs bien mais leur contenu ne peut pas tre mis jour automatiquement : il faut que le propritaire du site (le webmaster) modie le code source pour y ajouter des nouveauts. Ce nest pas trs pratique quand on doit mettre jour son site plusieurs fois dans la mme journe ! Les sites statiques sont donc bien adapts pour raliser des sites vitrine , pour prsenter par exemple son entreprise, mais sans aller plus loin. Ce type de site se fait de plus en plus rare aujourdhui, car ds que lon rajoute un lment dinteraction (comme un formulaire de contact), on ne parle plus de site statique mais de site dynamique. Les sites dynamiques : plus complexes, ils utilisent dautres langages en plus de HTML et CSS, tels que PHP et MySQL. Le contenu de ces sites web est dit dynamique parce quil peut changer sans lintervention du webmaster ! La plupart des sites web que vous visitez aujourdhui, y compris le Site du Zro, sont des sites dynamiques. Le seul prrequis pour apprendre crer ce type de sites est de dj savoir raliser des sites statiques en HTML et CSS1 .

Fig. 1.1 LlPHPant, la mascotte de PHP Lobjectif de ce cours est de vous rendre capables de raliser des sites web dynamiques entirement par vous-mmes, pas pas. En eet, ceux-ci peuvent proposer des fonctionnalits bien plus excitantes que les sites statiques. Voici quelques lments que vous serez en mesure de raliser : un espace membres : vos visiteurs peuvent sinscrire sur votre site et avoir accs des sections qui leur sont rserves ; un forum : il est courant aujourdhui de voir les sites web proposer un forum de discussion pour sentraider ou simplement passer le temps ; un compteur de visiteurs : vous pouvez facilement compter le nombre de visiteurs qui se sont connects dans la journe sur votre site, ou mme connatre le nombre de visiteurs en train dy naviguer ! des actualits : vous pouvez automatiser lcriture dactualits, en orant vos visiteurs la possibilit den rdiger, de les commenter, etc. ; une newsletter : vous pouvez envoyer un e-mail tous vos membres rgulirement pour leur prsenter les nouveauts et les inciter ainsi revenir sur votre site.
1 Vous pouvez lire sur le Site du Zro le cours HTML/CSS que jai rdig pour vous mettre niveau (code web : 235029) ou bien vous procurer mon livre Russir son site web avec XHTML et CSS aux ditions Eyrolles.

COMMENT FONCTIONNE UN SITE WEB ? Bien entendu, ce ne sont l que des exemples. Il est possible daller encore plus loin, tout dpend de vos besoins. Sachez par exemple que la quasi-totalit des sites de jeux en ligne sont dynamiques. On retrouve notamment des sites dlevage virtuel danimaux, des jeux de conqute spatiale, etc. Mais. . . ne nous emportons pas. Avant de pouvoir en arriver l, vous avez de la lecture et bien des choses apprendre ! Commenons par la base : savez-vous ce qui se passe lorsque vous consultez une page web ?

Comment fonctionne un site web ?


Lorsque vous voulez visiter un site web, vous tapez son adresse dans votre navigateur web, que ce soit Mozilla Firefox, Internet Explorer, Opera, Safari ou un autre. Mais ne vous tes-vous jamais demand comment faisait la page web pour arriver jusqu vous ? Il faut savoir quInternet est un rseau compos dordinateurs. Ceux-ci peuvent tre classs en deux catgories. Les clients : ce sont les ordinateurs des internautes comme vous. Votre ordinateur fait donc partie de la catgorie des clients. Chaque client reprsente un visiteur dun site web. Dans les schmas qui vont suivre, lordinateur dun client sera reprsent par limage 1.2. Les serveurs : ce sont des ordinateurs puissants qui stockent et dlivrent des sites web aux internautes, cest--dire aux clients. La plupart des internautes nont jamais vu un serveur de leur vie. Pourtant, les serveurs sont indispensables au bon fonctionnement du Web. Sur les prochains schmas, un serveur sera reprsent par limage de la gure 1.3.

Fig. 1.2 Un client

Fig. 1.3 Un serveur

CHAPITRE 1. INTRODUCTION PHP La plupart du temps, le serveur est dpourvu dcran : il reste allum et travaille tout seul sans intervention humaine, 24 h/24, 7 j/7. Un vrai forat du travail. On rsume : votre ordinateur est appel le client, tandis que lordinateur qui dtient le site web est appel le serveur. Comment les deux communiquent-ils ? Cest justement l que se fait la dirence entre un site statique et un site dynamique. Voyons ensemble ce qui change.

Cas dun site statique


Lorsque le site est statique, le schma est trs simple. Cela se passe en deux temps, ainsi que vous le schmatise la gure 1.4 : 1. le client demande au serveur voir une page web ; 2. le serveur lui rpond en lui envoyant la page rclame.

Fig. 1.4 Transferts avec un site statique La communication est donc plutt basique : Bonjour, je suis le client, je voudrais voir cette page web. Tiens, voil la page que tu mas demande. Sur un site statique, il ne se passe rien dautre. Le serveur stocke des pages web et les envoie aux clients qui les demandent sans les modier.

Cas dun site dynamique


Lorsque le site est dynamique, il y a une tape intermdiaire : la page est gnre (g. 1.5). Le client demande au serveur voir une page web ; le serveur prpare la page spcialement pour le client ; le serveur lui envoie la page quil vient de gnrer. La page web est gnre chaque fois quun client la rclame. Cest prcisment ce qui rend les sites dynamiques vivants : le contenu dune mme page peut changer dun instant lautre. 6

LES LANGAGES DU WEB

Fig. 1.5 Transfert avec un site dynamique Cest comme cela que certains sites parviennent acher par exemple votre pseudonyme sur toutes les pages. tant donn que le serveur gnre une page chaque fois quon lui en demande une, il peut la personnaliser en fonction des gots et des prfrences du visiteur (et acher, entre autres, son pseudonyme).

Les langages du Web


Lorsquon cre un site web, on est amen manipuler non pas un mais plusieurs langages. En tant que webmaster, il faut imprativement les connatre. Certains programmes, appels WYSIWYG (What You See Is What You Get), permettent daider les plus novices crer un site web statique sans connatre les langages informatiques qui se cachent derrire. . . Mais pour raliser un site dynamique comme nous le souhaitons, nous devrons absolument mettre les mains dans le cambouis.

Pour un site statique : HTML et CSS


De nombreux langages ont t crs pour produire des sites web. Deux dentre eux constituent une base incontournable pour tous les webmasters. HTML : cest le langage la base des sites web. Simple apprendre, il fonctionne partir de balises. Voici un exemple de code HTML :
<p>Bonjour, je suis un <em>paragraphe</em> de texte !</p>

CSS : cest le langage de mise en forme des sites web. Alors que le HTML permet dcrire le contenu de vos pages web et de les structurer, le langage CSS soccupe de la mise en forme et de la mise en page. Cest en CSS que lon choisit notamment la couleur, la taille des menus et bien dautres choses encore. Voici un code CSS :
div.banner { text-align: center; font-weight: bold; font-size: 120%; }

CHAPITRE 1. INTRODUCTION PHP Ces langages sont la base de tous les sites web. Lorsque le serveur envoie la page web au client, il envoie en fait du code en langage HTML et CSS. Le problme, cest que lorsquon connat seulement HTML et CSS, on ne peut produire que des sites statiques. . . et non des sites dynamiques ! Pour ces derniers, il est ncessaire de manipuler dautres langages en plus de HTML et CSS. La question quil faut vous poser est donc : connaissez-vous HTML et CSS ? Si oui, cest parfait, vous pouvez continuer car nous en aurons besoin par la suite. Si la rponse est non, pas de panique. Ces langages ne sont pas bien diciles, ils sont la porte de tous. Vous pouvez les apprendre en lisant mon cours sur HTML et CSS2 . Sachez quapprendre ces langages nest laaire que de quelques petites semaines, voire moins si vous avez susamment de temps libre.

Fig. 1.6 Le serveur envoie du HTML et du CSS au client

Pour un site dynamique : ajoutez PHP et MySQL


Quel que soit le site web que lon souhaite crer, HTML et CSS sont donc indispensables. Cependant, ils ne susent pas pour raliser des sites dynamiques. Il faut les complter avec dautres langages. Cest justement tout lobjet de ce cours : vous allez apprendre manipuler PHP et MySQL pour raliser un site web dynamique. PHP : cest un langage que seuls les serveurs comprennent et qui permet de rendre votre site dynamique. Cest PHP qui gnre la page web comme on la vu sur un des schmas prcdents. Ce sera le premier langage que nous dcouvrirons dans ce cours. Il peut fonctionner seul, mais il ne prend vraiment de lintrt que sil est combin un outil tel que MySQL. Voici un code PHP :
<?php echo "Vous tes le visiteur n" . $nbre_visiteurs; ?>

MySQL : cest ce quon appelle un SGBD (Systme de Gestion de Base de Donnes). Pour faire simple, son rle est denregistrer des donnes de manire organise an de vous aider les retrouver facilement plus tard. Cest grce MySQL que vous pourrez enregistrer la liste des membres de votre site, les messages posts sur le forum, etc. Le langage qui permet de communiquer avec la base de donnes sappelle le SQL. Voici un code en langage SQL :
2 Disponible

sur le Site du Zro (code web : 235029).

LES LANGAGES DU WEB


SELECT id, auteur, message, datemsg FROM livreor ORDER BY datemsg DESC LIMIT 0, 10

PHP et MySQL sont ce quon appelle des logiciels libres. Entre autres choses, cela vous donne des garanties de prennit : tout le monde peut contribuer leur dveloppement, vous ne risquez donc pas de voir tous les webmasters se dsintresser de PHP et de MySQL du jour au lendemain, et a cest trs important ! Dautre part, PHP et MySQL sont disponibles gratuitement. Cela signie une chose essentielle : vous naurez pas dbourser un centime pour construire votre site web ! PHP peut fonctionner seul et sut crer un site dynamique, mais les choses deviennent rellement intressantes lorsquon le combine un SGBD tel que MySQL. Cependant pour simplier, oublions pour le moment MySQL et concentrons-nous sur PHP.

PHP gnre du HTML


Les clients sont incapables de comprendre le code PHP : ils ne connaissent que le HTML et le CSS. Seul le serveur est capable de lire du PHP. Le rle de PHP est justement de gnrer du code HTML (on peut aussi gnrer du CSS, mais cest plus rare), code qui est ensuite envoy au client de la mme manire quun site statique, comme le montre la g. 3.3.

Fig. 1.7 PHP dcide ce qui va tre ach sur la page web envoye au visiteur PHP est un langage de programmation utilis sur de nombreux serveurs pour prendre des dcisions. Cest PHP qui dcide du code HTML qui sera gnr et envoy au client chaque fois. Pour bien comprendre lintrt de tout cela, prenons un exemple. On peut crire en PHP : Si le visiteur est membre de mon site et quil sappelle Jonathan, ache Bienvenue Jonathan sur la page web. En revanche, si ce nest pas un membre de mon site, ache Bienvenue la place et propose au visiteur de sinscrire. Cest un exemple trs basique de site dynamique : selon que vous tes un membre enregistr ou non, vous ne verrez pas les mmes choses et naurez peut-tre pas accs toutes les sections. 9

CHAPITRE 1. INTRODUCTION PHP

Et la concurrence ?
HTML et CSS nont pas de concurrents car ce sont des standards. Tout le monde est cens les connatre et les utiliser sur tous les sites web. En revanche, pour ce qui est des sites dynamiques, PHP et MySQL sont loin dtre les seuls sur le coup. Je ne peux pas vous faire une liste complte de leurs concurrents, ce serait bien trop long (et ennuyeux !). Cependant, pour votre culture gnrale, il faut au moins connatre quelques autres grands noms. Tout dabord, si on a souvent tendance combiner PHP et MySQL pour raliser de puissants sites dynamiques, il ne faut pas mlanger les deux. Le premier a des concurrents dirents du second.

Les concurrents de PHP


Parmi les concurrents de PHP, on peut citer les suivants : ASP .NET : conu par Microsoft, il exploite le framework3 .NET bien connu des dveloppeurs C#. Ce langage peut tre intressant si vous avez lhabitude de dvelopper en C# .NET et que vous ne voulez pas tre dpayss. Ruby on Rails : trs actif, ce framework sutilise avec le langage Ruby et permet de raliser des sites dynamiques rapidement en suivant certaines conventions. Django : il est similaire Ruby on Rails, mais il sutilise en langage Python. Java et les JSP (Java Server Pages) : plus couramment appel JEE , il est particulirement utilis dans le monde professionnel. Il demande une certaine rigueur. La mise en place dun projet JEE est traditionnellement un peu plus longue et plus lourde mais le systme est apprci des professionnels et des institutions4 .

Fig. 1.8 Ruby on Rails Je ne peux pas prsenter ici tous les concurrents, mais cela devrait dj vous donner une bonne ide. Pour information, il est aussi possible dutiliser par exemple le langage C ou le C++, bien que ce soit plus complexe et pas forcment toujours trs adapt (en clair, je ne le recommande pas du tout).

Lequel choisir dans le lot ? Lequel est le meilleur ?

3 Un

4 Cest

framework est un ensemble de bibliothques qui fournissent des services pour les dveloppeurs. ce qui est utilis sur le site des impts franais, par exemple.

10

ET LA CONCURRENCE ? tant donn lobjet de ce cours, vous vous attendez ce que je vous rponde instantanment PHP ! . Mais non. En fait, tout dpend de vos connaissances en programmation. Si vous avez dj manipul le Java, vous serez plus rapidement laise avec les JSP. Si vous connaissez Python, Django semble tout indiqu. Quant PHP, il se dmarque de ses concurrents par une importante communaut qui peut vous aider rapidement sur Internet si vous avez des problmes. Cest un langage facile utiliser, idal pour les dbutants comme pour les professionnels : Wikipdia et Facebook sont des exemples de sites clbres et trs frquents qui fonctionnent grce PHP. Bref, il ny a pas de meilleur choix. Je vous recommande le langage pour lequel vous serez certains davoir quelquun pour vous aider. PHP en ce sens est souvent un trs bon choix.

Les concurrents de MySQL


En ce qui concerne les bases de donnes, le choix est l encore trs vaste. Cependant, alors que PHP et ses concurrents sont la plupart du temps libres et gratuits, ce nest pas le cas de la plupart des SGBD. Parmi les concurrents de MySQL, je vous conseille de connatre (au moins de nom) les suivants : Oracle : cest le SGBD le plus clbre, le plus complet et le plus puissant. Il est malheureusement payant (et cher), ce qui le rserve plutt aux entreprises qui lutilisent dj massivement. Il existe cependant des versions gratuites dOracle, notamment pour ceux qui veulent apprendre sen servir. Microsoft SQL Server : dit par Microsoft, on lutilise souvent en combinaison avec ASP .NET, bien quon puisse lutiliser avec nimporte quel autre langage. Il est payant, mais il existe des versions gratuites limites. PostgreSQL : il sagit dun SGBD libre et gratuit comme MySQL, qui propose des fonctionnalits plus avances. Parfois compar Oracle, il lui reste cependant du chemin parcourir. Il dispose dune communaut un peu moins importante que MySQL et Oracle. Le Site du Zro utilise PostgreSQL.

Fig. 1.9 Oracle L encore, cette liste est loin dtre exhaustive mais vous prsente au moins quelques grands noms. Pour information, MySQL reste de loin le SGBD libre et gratuit le plus utilis. Parmi les solutions professionnelles payantes, Oracle est le plus avanc et le plus rpandu mais son utilisation est surtout rserve aux grosses entreprises. En n de compte, si vos moyens sont limits, vous navez pas beaucoup de choix pour le SGBD. MySQL est le plus indiqu car il est libre, gratuit, performant et utilis par de nombreuses personnes qui sont susceptibles de vous aider. 11

CHAPITRE 1. INTRODUCTION PHP

Plusieurs combinaisons sont possibles


Comme vous avez pu le constater, vous avez le choix entre de nombreux outils pour raliser un site dynamique. La plupart dentre eux sont gratuits. Sachez que vous pouvez a priori combiner ces outils comme bon vous semble. Par exemple, on peut trs bien utiliser PHP avec une autre base de donnes que MySQL, telle que Oracle ou PostgreSQL. De mme, MySQL peut tre utilis avec nimporte quel autre langage : Java, Python, Ruby, etc. Cependant, la combinaison PHP + MySQL est probablement la plus courante. Ce nest pas par hasard si ce cours traite de ces deux outils qui ont fait leurs preuves.

En rsum
Il existe deux types de sites web : les sites statiques : raliss en HTML et CSS, leur contenu ne peut tre mis jour que par le webmaster ; les sites dynamiques : raliss avec dautres outils comme PHP et MySQL en plus de HTML et CSS, ils permettent aux visiteurs de participer la vie du site, de poster des messages. . . bref, de rendre le site vivant ! Les visiteurs du site sont appels les clients. Ils demandent au serveur qui hberge le site de leur transmettre les pages web. PHP est un langage excut par le serveur. Il permet de personnaliser la page en fonction du visiteur, de traiter ses messages, deectuer des calculs, etc. Il gnre une page HTML. MySQL est un systme de gestion de bases de donnes. Il se charge du stockage des informations (liste des messages, des membres. . .).

12

Chapitre

2
Dicult :

Prparer son ordinateur

ous savons dsormais que PHP sexcute sur le serveur et que son rle est de gnrer des pages web. Cependant, seul un serveur peut lire du PHP ; or votre ordinateur nest pas un serveur. Comment diable allez-vous pouvoir crer un site dynamique si PHP ne fonctionne pas chez vous ? Qu cela ne tienne : nous allons temporairement transformer votre ordinateur en serveur pour que vous puissiez excuter du PHP et travailler sur votre site dynamique. Vous serez n prts programmer aprs avoir lu ce chapitre !

13

CHAPITRE 2. PRPARER SON ORDINATEUR

De quels programmes a-t-on besoin ?


Selon que lon cre un site statique ou un site dynamique, on a besoin de logiciels dirents. En fait, faire un site dynamique ncessite malheureusement pour nous quelques logiciels supplmentaires !

Avec un site statique


Les webmasters qui crent des sites statiques avec HTML et CSS ont de la chance, ils ont en gnral dj tous les programmes dont ils ont besoin. Un diteur de texte : en thorie, un programme tel que le Bloc-notes livr avec Windows sut, bien quil soit recommand dutiliser un outil un peu plus volu comme Notepad++. Nous reparlerons du choix de lditeur la n de ce chapitre. Un navigateur web : il permet de tester la page web. Vous pouvez utiliser par exemple Mozilla Firefox, Internet Explorer, Google Chrome, Opera, Safari, ou tout autre navigateur auquel vous tes habitus pour aller sur le web. Il est conseill de tester son site rgulirement sur dirents navigateurs.

Fig. 2.1 Mozilla Firefox Cependant, pour ceux qui comme nous travaillent sur des sites dynamiques, ces outils ne susent pas. Il est ncessaire dinstaller des programmes supplmentaires.

Avec un site dynamique


Pour que votre ordinateur puisse lire du PHP, il faut quil se comporte comme un serveur. Rassurez-vous, vous navez pas besoin dacheter une machine spciale pour cela : il sut simplement dinstaller les mmes programmes que ceux que lon trouve sur les serveurs qui dlivrent les sites web aux internautes. 14

SOUS WINDOWS : WAMP Ces programmes dont nous allons avoir besoin, quels sont-ils ? Apache : cest ce quon appelle un serveur web. Il sagit du plus important de tous les programmes, car cest lui qui est charg de dlivrer les pages web aux visiteurs. Cependant, Apache ne gre que les sites web statiques 1 . Il faut donc le complter avec dautres programmes. PHP : cest un plug-in pour Apache qui le rend capable de traiter des pages web dynamiques en PHP. En clair, en combinant Apache et PHP, notre ordinateur sera capable de lire des pages web en PHP. MySQL : cest le logiciel de gestion de bases de donnes dont je vous ai parl en introduction. Il permet denregistrer des donnes de manire organise2 . Nous nen aurons pas besoin immdiatement, mais autant linstaller de suite.

Fig. 2.2 Logo dApache Tous ces lments qui vont nous aider crer notre site dynamique sont libres et gratuits. Certes, il en existe dautres (parfois payants), mais la combinaison Apache + PHP + MySQL est la plus courante sur les serveurs web, tel point quon a cr des packs tout prts qui contiennent tous ces lments. Il est possible de les installer un un mais cela prend plus de temps et vous nallez rien y gagner3 . Dans la suite de ce chapitre, nous allons voir comment installer le pack qui convient en fonction de votre systme dexploitation.

Sous Windows : WAMP


Il existe plusieurs paquetages tout prts pour Windows. Je vous propose dutiliser WAMP Server qui a lavantage dtre rgulirement mis jour et disponible en franais. Code web : 786702 Commencez par tlcharger WAMP sur son site web ociel4 . Rendez-vous sur la page Tlchargement . Vous ntes pas obligs de remplir le formulaire, il vous sut de descendre tout en bas de la page et de cliquer sur Tlcharger WampServer . Une fois tlcharg, installez-le en laissant toutes les options par dfaut. Il devrait sinstaller dans un rpertoire comme C:\wamp et crer un raccourci dans le menu Dmarrer.
ne peut traiter que des pages HTML. la liste des membres de votre site. 3 Sauf si vous tes administrateur de serveur, ce qui ne devrait pas tre votre cas. ;) 4 Utilisez pour cela le code web indiqu. Reportez-vous lavant-propos pour savoir comment utiliser ces codes web.
2 Comme 1 Il

15

CHAPITRE 2. PRPARER SON ORDINATEUR Lorsque vous lancez WAMP, une icne doit apparatre en bas droite de la barre des tches, ct de lhorloge, comme sur la gure 2.3.

Fig. 2.3 Icne de WAMP Si une fentre apparat pour vous indiquer que le pare-feu bloque Apache, cliquez sur Dbloquer (g. 2.4). Vous navez aucune raison de vous inquiter, cest parfaitement normal.

Fig. 2.4 Firewall et Apache Par dfaut, WAMP est en anglais. Vous pouvez facilement le passer en franais en faisant un clic droit sur licne de WAMP dans la barre des tches, puis en allant dans le menu Language / french (g. 2.5).

Fig. 2.5 Modication de la langue WAMP est maintenant en franais ! 16

SOUS WINDOWS : WAMP Vous pouvez alors lancer la page daccueil de WAMP. Faites un clic gauche sur licne de WAMP (attention, jai bien dit un clic gauche cette fois), puis cliquez sur Localhost, comme le montre la gure 2.6.

Fig. 2.6 Menu localhost de WAMP

Une page web similaire la capture de la gure 2.7 devrait souvrir dans votre navigateur favori (Firefox, par exemple). Si la page sache chez vous, cela signie quApache fonctionne.

Fig. 2.7 Page daccueil de WAMP 17

CHAPITRE 2. PRPARER SON ORDINATEUR La page web que vous voyez lcran vous a t envoye par votre propre serveur Apache que vous avez install en mme temps que WAMP. Vous tes en train de simuler le fonctionnement dun serveur web sur votre propre machine. Pour le moment, vous tes le seul internaute pouvoir y accder. On dit que lon travaille en local . Notez que lURL ache par le navigateur dans la barre dadresse est http://localhost/, ce qui signie que vous naviguez sur un site web situ sur votre propre ordinateur. La section Vos projets de la page daccueil de WAMP doit indiquer quaucun projet nexiste pour le moment. Considrez que chaque site web que vous entreprenez de faire est un nouveau projet. Nous allons crer un projet de test que nous appellerons tests. Pour ce faire, ouvrez lexplorateur Windows et rendez-vous dans le dossier o WAMP a t install, puis dans le sous-dossier intitul www. Par exemple : C:\wamp\www. Une fois dans ce dossier, crez un nouveau sous-dossier que vous appellerez tests, comme le suggre limage 2.8.

Fig. 2.8 Dossier cr pour WAMP Retournez sur la page daccueil de WAMP et actualisez-la (vous pouvez appuyer sur la 18

SOUS WINDOWS : WAMP touche F5). La section Vos projets devrait maintenant acher tests car WAMP a dtect que vous avez cr un nouveau dossier (g. 2.9).

Fig. 2.9 Projets dans WAMP Vous crerez l-dedans vos premires pages web en PHP. Vous pouvez cliquer sur le lien tests . Comme vous navez pas encore cr de chier PHP, vous devriez voir une page vide comme dans la gure 2.10.

Fig. 2.10 Le contenu est pour le moment vide Si vous avez le mme rsultat, cela signie que tout fonctionne. Bravo, vous avez install WAMP et il fonctionne correctement. Vous tes prts programmer en PHP ! Vous pouvez passer les sections suivantes qui ne concernent que les utilisateurs sous Mac OS X et Linux. 19

CHAPITRE 2. PRPARER SON ORDINATEUR

Sous Mac OS X : MAMP


Pour ceux qui ont un Mac sous Mac OS X, je vous conseille le programme MAMP (Mac Apache MySQL PHP). Il est vraiment trs simple installer et utiliser. Rendez-vous sur le site ociel de MAMP et cliquez sur Download Now sur la page daccueil, ainsi que le montre la gure 2.11.

Code web : 772402

Fig. 2.11 Accueil de MAMP

Si vous avez une version de Mac OS X antrieure Mac OS X 10.4, vous devrez tlcharger une ancienne version de MAMP grce aux liens prsents un peu plus bas sur la mme page. Vous devriez avoir tlcharg une archive au format .dmg qui contient le logiciel. Lorsque vous louvrez, la fentre de la gure 2.12 apparat. Vous devez tout simplement faire glisser le dossier MAMP en bas gauche vers le dossier Applications au-dessus. MAMP est maintenant install. Vous le trouverez dans votre dossier Applications . La fentre principale de MAMP indique que les serveurs Apache et MySQL ont t correctement dmarrs. Licne de chacun de ces lments doit tre verte comme sur la gure 2.13. Je vous invite congurer le rpertoire dans lequel Apache ira chercher les chiers PHP de votre site web. Pour cela, cliquez sur le bouton Prfrences de la fentre principale. Une bote de dialogue de conguration souvre (gure 2.14). Cliquez sur longlet Apache en haut. Cliquez sur le bouton Choisir pour slectionner le dossier dans lequel vous placerez les chiers de votre site web. Sous Mac OS, un dossier est dj cr : il sagit de Sites , dans votre rpertoire personnel (g. 2.15). 20

SOUS MAC OS X : MAMP

Fig. 2.12 Archive DMG de WAMP

Fig. 2.13 Fentre principale de MAMP

21

CHAPITRE 2. PRPARER SON ORDINATEUR

Fig. 2.14 Conguration de MAMP

Fig. 2.15 Le dossier Sites de Mac OS X

22

SOUS LINUX : XAMPP Slectionnez ce rpertoire5 , qui devrait tre de la forme /Users/pseudo/Sites. Validez les changements et retournez sur la fentre principale de MAMP. L, cliquez sur Ouvrir la page daccueil . Votre navigateur (Firefox ou Safari, par exemple) devrait alors souvrir et acher une page web. Pour vous prparer pour la suite, je vous invite crer un dossier tests dans votre rpertoire Sites . Nous placerons nos premiers chiers PHP de test lintrieur. Si le dossier tests a t correctement cr, vous pouvez visualiser son contenu en vous rendant ladresse http://localhost:8888/tests/. Si tout va bien, une page vide devrait sacher (gure 2.16).

Fig. 2.16 Dossier vide MAMP MAMP est correctement install et congur. Vous tes maintenant prts travailler en PHP pour le chapitre suivant !

Sous Linux : XAMPP


Sous Linux, il est courant dinstaller Apache, PHP et MySQL sparment. Toutefois, il existe aussi des packs tout prts comme XAMPP (X Apache MySQL Perl PHP), anciennement connu sous le nom de LAMPP. Ce pack est plus complet que WAMP pour Windows ou MAMP pour Mac OS X. Nous nutiliserons toutefois quune partie des lments installs. Code web : 718394 Sur le site ociel de XAMPP, recherchez le lien XAMPP pour Linux.
5 Notez que ce nest pas une obligation : vous pouvez utiliser nimporte quel autre rpertoire si vous le dsirez.

23

CHAPITRE 2. PRPARER SON ORDINATEUR

Fig. 2.17 Tlchargement de XAMPP pour Linux XAMPP est aussi disponible pour Windows et Mac OS X comme vous pourrez le constater sur le site. La mthode dinstallation est sensiblement dirente, mais vous pouvez lessayer si vous avez dj test WAMP (pour Windows) ou MAMP (pour Mac OS X) et quil ne vous convient pas. Sur la page qui sache, recherchez un peu plus bas le lien de tlchargement de XAMPP pour Linux.

Fig. 2.18 Lien de tlchargement de XAMPP Une fois le tlchargement termin, ouvrez une console. Linstallation et le lancement de XAMPP se font en eet uniquement en console6 . Rendez-vous dans le dossier dans lequel vous avez tlcharg XAMPP. Par exemple, dans mon cas, le chier se trouve sur le bureau : cd ~/Desktop Vous devez passer root pour installer et lancer XAMPP. root est le compte administrateur de la machine qui a notamment le droit dinstaller des programmes. Normalement, il sut de taper su et de rentrer le mot de passe root. Sous Ubuntu, il faudra taper sudo su et taper votre mot de passe habituel. Si comme moi vous utilisez Ubuntu, tapez donc : sudo su Vous devez maintenant extraire le dossier compress dans /opt. Pour ce faire, recopiez simplement la commande suivante : tar xvfz xampp-linux-1.6.7.tar.gz -C /opt
6 Allons, allons, pas de chichis, vous nallez pas me faire avaler que cest la premire fois que vous louvrez, la console !

24

SOUS LINUX : XAMPP Il se peut que le nom du chier soit lgrement dirent si le numro de version a chang. Adaptez le nom du chier en le compltant automatiquement laide de la touche Tabulation. Lorsque la dcompression des chiers est termine, cest fait ! XAMPP est maintenant install. Pour dmarrer XAMPP (et donc Apache, PHP et MySQL), tapez la commande suivante : /opt/lampp/lampp start Si vous dsirez plus tard arrter XAMPP, tapez : /opt/lampp/lampp stop

Noubliez pas que vous devez tre root lorsque vous dmarrez ou arrtez XAMPP. Ce nest pas bien compliqu, comme vous pouvez le voir ! Vous pouvez maintenant tester XAMPP en ouvrant votre navigateur favori et en tapant ladresse suivante : http://localhost. Vous devriez voir la page de slection de la langue de XAMPP. Cliquez sur Franais , comme la gure 2.19 vous y invite.

Fig. 2.19 Choix de la langue dans XAMPP La page principale de conguration de XAMPP sache ensuite. Elle est plus complte que ses homologues WAMP et MAMP, notamment parce que XAMPP contient plus de logiciels et propose donc plus de fonctionnalits (beaucoup plus). Vous pouvez vrier que tout fonctionne correctement en allant dans le menu Statut, comme dans la gure 2.20. Au minimum, les modules MySQL et PHP doivent tre en vert. Quant aux autres, nous ne les utiliserons pas, donc peu importe. ;-) Les chiers PHP devront tre placs dans le rpertoire /opt/lampp/htdocs. Vous pouvez y crer un sous-rpertoire tests pour vos premiers tests. 25

CHAPITRE 2. PRPARER SON ORDINATEUR

Fig. 2.20 Statut des composants de XAMPP

cd /opt/lampp/htdocs mkdir tests Une fois le dossier cr, vous pouvez y accder depuis votre navigateur ladresse suivante : http://localhost/tests. Vous devriez voir une page similaire la gure 2.21. Vous tes prts travailler en PHP !

Utiliser un bon diteur de chiers


Comme vous devez dj le savoir, pour diter le code dune page web vous avez plusieurs solutions : utiliser un diteur de texte tout simple que vous avez dj, comme Bloc-notes. Pour louvrir, faites Dmarrer / Programmes / Accessoires / Bloc-notes. Ce logiciel sut normalement crire des pages web en HTML et mme en PHP, mais. . . le mieux reste dutiliser un logiciel spcialis qui colore votre code (trs pratique) et qui numrote vos lignes (trs pratique aussi). Il existe des centaines et des centaines de logiciels gratuits faits pour les dveloppeurs comme vous. 26

UTILISER UN BON DITEUR DE FICHIERS

Fig. 2.21 Le dossier tests est actuellement vide dans XAMPP Je vous propose donc dinstaller un logiciel qui va vous permettre dditer vos chiers source de manire ecace. Vous en avez probablement dj install un si vous avez appris programmer en HTML / CSS, mais comme on nest jamais trop prudent, je vais rapidement vous en prsenter quelques-uns en fonction de votre systme dexploitation. Voici le code source HTML que nous allons utiliser pour commencer en terrain connu. Copiez-collez ce code dans lditeur de texte que je vais vous faire installer :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> <head> <title>Ceci est une page HTML de test</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <h2>Page de test</h2> <p> /> Cette page contient <strong>uniquement</strong> du code HTML.<br

Voici quelques petits tests : </p>

27

CHAPITRE 2. PRPARER SON ORDINATEUR

<ul> <li style="color: blue;">Texte en bleu</li> <li style="color: red;">Texte en rouge</li> <li style="color: green;">Texte en vert</li> </ul> </body> </html>

Code web : 589020 Il ny a pas de PHP pour linstant an de commencer en douceur. Nous allons simplement essayer denregistrer un chier HTML avec ce code pour nous chauer.

Sous Windows
Il existe beaucoup de logiciels gratuits tlcharger pour diter du texte sous Windows. Il mest impossible de tous vous les prsenter : je vais donc vous en recommander un qui est trs utilis et en lequel vous pouvez avoir conance : Notepad++. Ce logiciel est petit et rapide tlcharger. Nhsitez pas lessayer. Code web : 105790 Lorsque Notepad++ souvre, il prsente gnralement comme vous le montre la gure 2.22 un chier vide (vous pouvez en crer un nouveau au besoin en allant dans le menu Fichier / Nouveau). Copiez-collez le code HTML que je viens de vous donner dans Notepad++. Vous devriez voir lcran de la gure 2.23. Comme vous pouvez le voir, le code nest pas color. La raison vient du fait que Notepad++ ne sait pas de quel type de code source il sagit. Vous devez au pralable enregistrer le chier. Allez dans Fichier / Enregistrer, puis choisissez le dossier o vous souhaitez enregistrer le chier. Je vous conseille daller dans le dossier C:\wamp\www\tests que vous avez cr linstallation de WAMP. Choisissez le type de chier .html7 puis donnez un nom votre chier, ainsi que le montre la gure 2.24. Une fois le chier enregistr, le code source apparat color (gure 2.25). Vous pourrez suivre la mme procdure plus loin avec les chiers PHP, condition denregistrer le chier en .php. a vous entranera, vous verrez.
7 Hyper

Text Markup Language le

28

UTILISER UN BON DITEUR DE FICHIERS

Fig. 2.22 Le logiciel Notepad++

Fig. 2.23 Notepad++ : cration dun nouveau chier

29

CHAPITRE 2. PRPARER SON ORDINATEUR

Fig. 2.24 Enregistrement dun chier HTML

Fig. 2.25 Notepad++ avec la coloration syntaxique

30

UTILISER UN BON DITEUR DE FICHIERS

Sous Mac OS X
Si vous tes sous Mac, je peux vous recommander lditeur TextWrangler, qui est gratuit. Code web : 606652 Il existe aussi Smultron. Vous pouvez lessayer mais il nest malheureusement plus mis jour. Code web : 295295 Dautres diteurs de texte payants de qualit existent, notamment lexcellent TextMate. Code web : 640856

Fig. 2.26 Lditeur de texte TextWrangler sous Mac OS X

Sous Linux
Sous Linux, les bons diteurs ne manquent pas. Si vous tes des habitus de la console, vous travaillerez srement avec plaisir avec vim ou emacs. Si vous recherchez un diteur graphique plus facile utiliser, je vous recommande gedit (g. 2.27) ou tout autre logiciel install avec votre distribution Linux, cela fera laaire. Quel que soit le logiciel que vous utilisez, rassurez-vous, a ne change pas du tout la manire dont vous allez apprendre le PHP : les manipulations seront exactement les mmes pour tout le monde. 31

CHAPITRE 2. PRPARER SON ORDINATEUR

Fig. 2.27 gedit

En rsum
Pour crer des sites web dynamiques, nous devons installer des outils qui transformeront notre ordinateur en serveur an de pouvoir tester notre site. Les principaux outils dont nous avons besoin sont : Apache : le serveur web ; PHP : le programme qui permet au serveur web dexcuter des pages PHP ; MySQL : le logiciel de gestion de bases de donnes. Bien quil soit possible dinstaller ces outils sparment, il est plus simple pour nous dinstaller un paquetage tout prt : WAMP sous Windows, MAMP sous Mac OS X ou XAMPP sous Linux. Il est conseill dutiliser un diteur de texte qui colore le code source comme Notepad++ pour programmer convenablement en PHP.

32

Chapitre

3
Dicult :

Premiers pas avec PHP

ans le premier chapitre, nous avons dcouvert le principe de fonctionnement du PHP. Ici, nous allons passer au concret et raliser notre toute premire page web en PHP.

Ne vous attendez pas un rsultat extraordinaire, mais cela va nous permettre de prendre nos marques. Vous allez en particulier comprendre comment on spare le code HTML classique du code PHP. Vous tes prts ? Allons-y !

33

CHAPITRE 3. PREMIERS PAS AVEC PHP

Les balises PHP


Vous savez donc que le code source dune page HTML est constitu de balises (aussi appeles tags). Par exemple, <ul> est une balise. Le code PHP vient sinsrer au milieu du code HTML. On va progressivement placer dans nos pages web des morceaux de code PHP lintrieur du HTML. Ces bouts de code PHP seront les parties dynamiques de la page, cest--dire les parties qui peuvent changer toutes seules1 . La gure 3.1 illustre cela.

Fig. 3.1 Insertion de code PHP Comme vous pouvez le voir, on retrouve le code HTML que lon connat bien. . . et on insre en plus des donnes dynamiques au milieu. Ici, par exemple, cest le pseudonyme : il change en fonction du visiteur. La partie surligne peut donc changer selon les visiteurs. Le Site du Zro fait la mme chose pour ses membres inscrits. Votre pseudonyme est ach en haut des pages lorsque vous tes connects au Site du Zro.

La forme dune balise PHP


Si je vous parle de cela, ce nest pas par hasard. Pour utiliser du PHP, on va devoir introduire une nouvelle balise. . . et celle-ci est un peu spciale. Elle commence par < ?php et se termine par ?> ; cest lintrieur que lon mettra du code PHP, ce que je vais vous apprendre tout au long de ce cours. Voici une balise PHP vide :
<?php ?>

lintrieur, on crira donc du code source PHP :


1 Cest

pour cela quon dit quelles sont dynamiques.

34

LES BALISES PHP


<?php /* Le code PHP se met ici */ ?>

On peut sans problme crire la balise PHP sur plusieurs lignes. En fait, cest mme indispensable car la plupart du temps le code PHP fera plusieurs lignes. Cela donnera quelque chose comme :
<?php /* Le code PHP se met ici Et ici Et encore ici */ ?>

Il existe dautres balises pour utiliser du PHP, par exemple < ? ?>, <% %>, etc. Ne soyez donc pas tonns si vous en voyez. Nanmoins, < ?php ?> est la forme la plus correcte, vous apprendrez donc vous servir de cette balise et non pas des autres.

Insrer une balise PHP au milieu du code HTML


La balise PHP que nous venons de dcouvrir sinsre au milieu du code HTML comme je vous lai dit plus tt. Pour reprendre lexemple que lon a vu au chapitre prcdent :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> <head> <title>Ceci est une page de test avec des balises PHP</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <h2>Page de test</h2> <p> Cette page contient du code HTML avec des balises PHP.<br /> <?php /* Insrer du code PHP ici */ ?> Voici quelques petits tests : </p> <ul> <li style="color: blue;">Texte en bleu</li> <li style="color: red;">Texte en rouge</li> <li style="color: green;">Texte en vert</li> </ul>

35

CHAPITRE 3. PREMIERS PAS AVEC PHP


<?php /* Encore du PHP Toujours du PHP */ ?> </body> </html>

Bien entendu, cette page ne fonctionne pas vu que nous navons pas encore crit de vrai code PHP (ce sont juste des balises dexemple). Tout ce quil vous faut retenir ici, cest que ds que vous voulez mettre du code PHP, hop, vous ouvrez une balise PHP : < ?php ?>. Peut-on placer une balise PHP nimporte o dans le code ?

Oui ! Vraiment nimporte o. Pas seulement dans le corps de la page dailleurs : vous pouvez placer une balise PHP dans len-tte de la page.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> <head> <title>Ceci est une page de test <?php /* Code PHP */ ?> </title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head>

Plus fort encore, vous pouvez mme insrer une balise PHP au milieu dune balise HTML (bon, ce nest pas trs joli, je vous laccorde) :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> <head> <title>Ceci est une page de test</title> <meta http-equiv="Content-Type" <?php /* Code PHP */ ?> content="text/ht ml; charset=iso-8859-1" /> </head>

Comment a fonctionne ? quoi a peut servir ?

Il faut se rappeler que PHP gnre du code HTML. Nous allons mieux comprendre le fonctionnement en apprenant acher du texte en PHP. 36

AFFICHER DU TEXTE

Acher du texte
Bon, tout a cest bien beau, mais il serait temps de commencer crire du code PHP, non ? Grande nouvelle : cest maintenant que vous allez apprendre votre premire instruction en PHP. Ne vous attendez pas quelque chose dextraordinaire, votre PC ne va pas se mettre danser la samba tout seul. ;-) Vous allez cependant un peu mieux comprendre comment le PHP fonctionne, cest-dire comment il gnre du code HTML. Il est indispensable de bien comprendre cela, soyez donc attentifs !

Linstruction echo
Le PHP est un langage de programmation, ce qui ntait pas le cas du HTML2 . Si vous avez dj programm dans dautres langages comme le C ou le Java, cela ne devrait pas vous surprendre. Nanmoins, dans ce cours, nous partons de Zro donc je vais supposer que vous navez jamais fait de programmation auparavant. Tout langage de programmation contient ce quon appelle des instructions. On en crit une par ligne en gnral, et elles se terminent toutes par un point-virgule. Une instruction commande lordinateur deectuer une action prcise. Ici, la premire instruction que nous allons dcouvrir permet dinsrer du texte dans la page web. Il sagit de linstruction echo, la plus simple et la plus basique de toutes les instructions que vous devez connatre. Voici un exemple dutilisation de cette instruction :
<?php echo "Ceci est du texte"; ?>

Comme vous le voyez, lintrieur de la balise PHP on crit linstruction echo suivie du texte acher entre guillemets. Les guillemets permettent de dlimiter le dbut et la n du texte, ce qui aide lordinateur se reprer. Enn, linstruction se termine par un point-virgule comme je vous lavais annonc, ce qui signie Fin de linstruction. Notez quil existe une instruction identique echo appele print, qui fait la mme chose. Cependant, echo est plus couramment utilise. Il faut savoir quon a aussi le droit de demander dacher des balises. Par exemple, le code suivant fonctionne :
<?php echo "Ceci est du <strong>texte</strong>"; ?>

Le mot texte sera ach en gras grce la prsence des balises <strong> et </strong>.
2 On

parle plutt de langage de description, car il permet de dcrire une page web.

37

CHAPITRE 3. PREMIERS PAS AVEC PHP

Comment faire pour acher un guillemet ?

Bonne question. Si vous mettez un guillemet, a veut dire pour lordinateur que le texte acher sarrte l. Vous risquez au mieux de faire planter votre beau code et davoir une terrible Parse error . La solution consiste faire prcder le guillemet dun antislash \ :
<?php echo "Cette ligne a t crite \"uniquement\" en PHP."; ?>

Vous savez que le code PHP sinsre au milieu du code HTML. Alors allons-y, prenons une page basique en HTML et plaons-y du code PHP :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> <head> <title>Notre premire instruction : echo</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <h2>Affichage de texte avec PHP</h2> <p> Cette ligne a t crite entirement en HTML.<br /> <?php echo "Celle-ci a t crite entirement en PHP."; ?>

</p> </body> </html>

Code web : 475630 Je vous propose de copier-coller ce code source dans votre diteur de texte et denregistrer la page. Nous allons lessayer et voir ce quelle produit comme rsultat. Mais au fait, vous rappelez-vous comment vous devez enregistrer votre page PHP ?

Enregistrer une page PHP


Je vous ai expliqu comment faire dans le chapitre prcdent mais un petit rappel ne peut pas faire de mal. Enregistrez la page avec lextension .php, par exemple affichertexte.php, dans le dossier tests que je vous ai fait crer. Il doit se trouver dans C:\wamp\www\tests sous Windows. 38

AFFICHER DU TEXTE Lessentiel, quel que soit votre systme dexploitation, est que le chier soit enregistr dans le dossier www (ou un de ses sous-dossiers) sinon le chier PHP ne pourra pas sexcuter ! Si vous utilisez Notepad++, slectionnez PHP Hypertext Preprocessor file (*.php) dans la fentre pour enregistrer, comme le montre la gure 3.2.

Fig. 3.2 Sauvegarde dune page PHP Une fois la page enregistre, il faut maintenant la tester.

Tester la page PHP


Pour tester votre page PHP, cela dpend de votre systme dexploitation mais la manuvre est dans les grandes lignes la mme. Sous Windows, dmarrez WAMP si ce nest pas dj fait. Allez dans le menu Localhost, la page daccueil souvre. L, si vous avez bien cr le dossier tests dans le rpertoire www comme indiqu au chapitre prcdent, vous devriez voir un lien vers le dossier tests. Cliquez dessus (nous avons dj fait cela dans le chapitre prcdent). Une page web souvre indiquant tous les chiers qui se trouvent dans le dossier tests. Vous devriez avoir le chier affichertexte.php. Cliquez dessus : votre ordinateur gnre alors le code PHP puis ouvre la page. Vous avez le rsultat devant vos yeux. Le mme rsultat peut tre obtenu dans votre navigateur en allant directement ladresse http://localhost/tests/affichertexte.php. La mthode devrait tre quasiment la mme que vous soyez sous Windows, Mac OS X ou Linux. Je vous propose galement dessayer le rsultat directement sur le Site du Zro si vous 39

CHAPITRE 3. PREMIERS PAS AVEC PHP souhaitez le comparer au vtre3 . Essayez le code web ci-dessous. Code web : 960791 Alors, que voyez-vous ? Je pense que vous tes tonns et surpris de ce que je vous ai fait faire : a a lair dtre inutile, et ce nest pas tout fait faux. Le code PHP a crit une ligne lcran, tout simplement. Mais euh, cest pas plus simple de lcrire en HTML ?

Si ! Mais vous verrez bientt lintrt de cette fonction. Pour le moment, on constate juste que a crit du texte.

Comment PHP gnre du code HTML


Linstruction echo demande PHP dinsrer cet endroit le texte que vous demandez. Si on traduit linstruction en franais, a donne : Insrer le texte : Celle-ci a t crite entirement en PHP. . Il ne faut jamais oublier le point-virgule la n dune instruction. Si jamais a arrive, vous aurez le message derreur : Parse Error . Notez que a plante uniquement si votre code PHP fait plus dune ligne (a sera tout le temps le cas). Prenez donc lhabitude de toujours mettre un ; la n des instructions. Je vous ai expliqu dans le tout premier chapitre que le PHP gnrait du code HTML et renvoyait au visiteur uniquement du code HTML (accompagn ventuellement de sa feuille de style CSS), comme le montre la gure 3.3.

Fig. 3.3 Gnration de HTML par PHP Sur la gure 3.4, vous dcouvrez concrtement ce quil se passe avec notre code source. Le code PHP est excut en premier et lordinateur fait ce quon lui demande. Ici on lui a dit Ache ce texte ici . Une fois toutes les instructions PHP excutes4 , la page qui sort est une page qui ne
3 Je 4 Ici

vous conseille fortement de savoir acher la page chez vous directement. ctait simple, il ny en avait quune !

40

LES COMMENTAIRES contient que du HTML ! Cest cette page de rsultat qui est envoye au visiteur, car celui-ci ne sait lire que le HTML.

Fig. 3.4 Gnration de HTML avec echo Rappelez-vous, seul le serveur peut excuter du PHP. Le PHP nest jamais envoy au visiteur. Pour que nous puissions excuter du PHP sur notre ordinateur (an de faire nos tests), nous avons d le transformer en mini-serveur en installant un programme tel que WAMP.

Les commentaires
Bon, mine de rien je viens de vous apprendre pas mal de choses dun coup, a doit vous faire un choc. Daccord ce ntait pas extraordinaire, mais vous nallez pas tarder comprendre toute la subtilit de la chose. Avant de terminer ce chapitre, je tiens vous parler de quelque chose qui mes yeux a une trs grande importance en PHP, comme dans tout langage de programmation : les commentaires. Un commentaire est un texte que vous mettez pour vous dans le code PHP. Ce texte est ignor, cest--dire quil disparat compltement lors de la gnration de la page. Il ny a que vous qui voyez ce texte. Mais alors, quoi sert un commentaire ?

Cest pour vous. Cela permet de vous y retrouver dans votre code PHP, parce que si vous ny touchez pas pendant des semaines et que vous y revenez, vous risquez dtre un peu perdus. Vous pouvez crire tout et nimporte quoi, le tout est de sen servir bon escient. Il existe deux types de commentaires : les commentaires monolignes ; les commentaires multilignes. 41

CHAPITRE 3. PREMIERS PAS AVEC PHP Tout dpend de la longueur de votre commentaire. Je vais vous prsenter les deux.

Les commentaires monolignes


Pour indiquer que vous crivez un commentaire sur une seule ligne, vous devez taper deux slashs : // . Tapez ensuite votre commentaire. Un exemple ?
<?php echo "Jhabite en Chine."; // Cette ligne indique o jhabite // La ligne suivante indique mon ge echo "Jai 92 ans."; ?>

Je vous ai mis deux commentaires des endroits dirents : le premier est la n dune ligne ; le second est sur toute une ligne. vous de voir o vous placez vos commentaires : si vous commentez une ligne prcise, mieux vaut mettre le commentaire la n de cette ligne.

Les commentaires multilignes


Ce sont les plus pratiques si vous pensez crire un commentaire sur plusieurs lignes, mais on peut aussi sen servir pour crire des commentaires dune seule ligne. Il faut commencer par crire /* puis refermer par */ :
<?php /* La ligne suivante indique mon ge Si vous ne me croyez pas... ... vous avez raison ;o) */ echo "Jai 92 ans."; ?>

Ici, les commentaires nont pas grande utilit, mais vous verrez de quelle faon je les utilise dans les prochains chapitres pour vous dcrire le code PHP.

En rsum
Les pages web contenant du PHP ont lextension .php. Une page PHP est en fait une simple page HTML qui contient des instructions en langage PHP. Les instructions PHP sont places dans une balise < ?php ?>. Pour acher du texte en PHP, on utilise linstruction echo. Il est possible dajouter des commentaires en PHP pour dcrire le fonctionnement du code. On utilise pour cela les symboles // ou /* */. 42

Chapitre

4
Dicult :

Inclure des portions de page

ous est-il dj arriv de vouloir modier le menu de votre site et de devoir pour cela corriger le code HTML de chacune de vos pages web ? Le menu dune page web apparat en eet sur chacune des pages et vous avez trs certainement d le recopier sur chacune delles. a marche, mais ce nest pas trs pratique. . . Une des fonctionnalits les plus simples et les plus utiles de PHP est linclusion de pages. On peut trs facilement inclure toute une page ou un bout de page lintrieur dune autre. Cela va grandement vous faciliter la tche en vous vitant davoir copier le mme code HTML plusieurs fois. Au l de ce chapitre, vous allez dcouvrir un des multiples avantages que vous donne le PHP lors de la cration de votre site. Cest dailleurs ce qui ma fait instantanment aimer ce langage lorsque je lai dcouvert, alors que je venais comme vous seulement dapprendre le HTML et le CSS. :-)

43

CHAPITRE 4. INCLURE DES PORTIONS DE PAGE

Le principe
La plupart des sites web sont gnralement dcoups selon le schma 4.1.

Fig. 4.1 Dcoupage usuel dune page web

Le problme
Jusquici, vous tiez condamns copier sur chaque page lidentique : len-tte ; le menu ; le pied de page. Cela donnait du code lourd et rptitif sur toutes les pages ! Regardez le code dexemple ci-dessous qui reprsente une page web (appelons-la index.php) avec en-tte, menu et pied de page :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/ DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" > <head> <title>Mon super site</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" / > </head> <body> <!-- Len-tte -->

44

LE PRINCIPE
<div id="en_tete"> </div> <!-- Le menu --> <div id="menu"> <div class="element_menu"> <h3>Titre menu</h3> <ul> <li><a href="page1.html">Lien</a></li> <li><a href="page2.html">Lien</a></li> <li><a href="page3.html">Lien</a></li> </ul> </div> </div> <!-- Le corps --> <div id="corps"> <h1>Mon super site</h1> Bienvenue sur mon super site !<br /> Vous allez adorer ici, cest un site gnial qui va parler de... euh... Je cherche encore un peu le thme de mon site. :-D </p> </div> <!-- Le pied de page --> <div id="pied_de_page"> <p>Copyright moi, tous droits rservs</p> </div> </body> </html> <p>

Dune page lautre, ce site contiendra chaque fois le mme code pour len-tte, le menu et le pied de page ! En eet, seul le contenu du corps change en temps normal.

La solution
En PHP, nous pouvons facilement insrer dautres pages1 lintrieur dune page. Le principe de fonctionnement des inclusions en PHP est plutt simple comprendre. Vous avez un site web compos de disons vingt pages. Sur chaque page, il y a un menu,
1 On

peut aussi insrer seulement des morceaux de pages.

45

CHAPITRE 4. INCLURE DES PORTIONS DE PAGE toujours le mme. Pourquoi ne pas crire ce menu (et seulement lui) une seule fois dans une page menu.php ? En PHP, vous allez pouvoir inclure votre menu sur toutes vos pages. Lorsque vous voudrez modier votre menu, vous naurez qu modier menu.php et lensemble des pages de votre site web sera automatiquement mis jour !

La pratique
Comme je vous le disais, je vous propose de crer un nouveau chier PHP et dy insrer uniquement le code HTML correspondant votre menu, comme ceci :
<div id="menu"> <div class="element_menu"> <h3>Titre menu</h3> <ul> <li><a href="page1.html">Lien</a></li> <li><a href="page2.html">Lien</a></li> <li><a href="page3.html">Lien</a></li> </ul> </div> </div>

Faites de mme pour une page entete.php et une page pied_de_page.php en fonction des besoins de votre site. Mais. . . la page menu.php ne contiendra pas le moindre code PHP. . . cest normal ? Une page dont lextension est .php peut trs bien ne contenir aucune balise PHP (mme si cest plutt rare). Dans ce cas, cela redevient une page HTML classique qui nest pas modie avant lenvoi. En thorie, vous pourriez trs bien enregistrer votre page avec lextension .html : menu.html. Nanmoins, an dviter de mlanger des pages .php et .html sur votre site, je vous recommande de travailler uniquement avec lextension .php partir de maintenant. Maintenant que vos morceaux de pages sont prts, reprenez les pages de votre site, par exemple la page daccueil nomme index.php. Remplacez le menu par le code PHP suivant2 :
2 Vous noterez que, contrairement echo, jai ici plac des parenthses autour des guillemets. Il faut dire que echo tait un peu une exception. Dornavant vous verrez souvent des parenthses. include est en ralit une structure de langage particulire, comme echo, et peut donc sutiliser avec ou sans parenthses. Pour le moment nous dbutons, donc nous nous contenterons de faire comme cela sans trop rentrer dans les dtails pour ne pas nous brler les ailes. ;-)

46

LA PRATIQUE
<?php include("menu.php"); ?>

Cette instruction ordonne lordinateur : Insre ici le contenu de la page menu.php . Si nous reprenons le code que nous avons vu tout lheure et que nous remplaons chaque code rptitif par un include, cela donne le code source suivant :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/ DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" > <head> <title>Mon super site</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" / > </head> <body> <?php include("entete.php"); ?> <?php include("menus.php"); ?> <div id="corps"> <h1>Mon super site</h1> <p> Bienvenue sur mon super site !<br /> Vous allez adorer ici, cest un site gnial qui va parler de... euh... Je cherche encore un peu le thme de mon site. :-D </p> </div> <?php include("pied_de_page.php"); ?> </body> </html>

Ce code suppose que votre page index.php et celles qui sont incluses (comme menu.php) sont dans le mme dossier. Si le menu tait dans un sous-dossier appel includes, il aurait fallu crire :
< ?php include("includes/menu.php") ; ?>

Cest le mme principe que pour les liens relatifs, que vous connaissez dj dans le langage HTML. 47

CHAPITRE 4. INCLURE DES PORTIONS DE PAGE Nous avons vu que la page PHP tait gnre, donc la question que vous devez vous poser est : que reoit le visiteur ? Eh bien, il reoit exactement le mme code quavant ! Le schma 4.2 vous aidera comprendre comment les pages sont incluses.

Fig. 4.2 Les includes en pratique La page nale que reoit le visiteur est identique celle que je vous ai montre au dbut du chapitre. . . mais vous, vous avez normment gagn en exibilit puisque votre code nest plus recopi 150 fois inutilement. Le nombre dinclude par page nest pas limit, par consquent vous pouvez dcouper votre code en autant de sous-parties que vous le souhaitez !

En rsum
Une page PHP peut inclure une autre page (ou un morceau de page) grce linstruction include. Linstruction include sera remplace par le contenu de la page demande. Cette technique, trs simple mettre en place, permet par exemple de placer les menus de son site dans un chier menus.php que lon inclura dans toutes les pages. Cela permet de centraliser le code des menus alors quon tait auparavant oblig de le copier dans chaque page sur nos sites statiques en HTML et CSS !

48

Chapitre

5
Dicult :

Les variables

ttention, chapitre fondamental ! Les variables sont un lment indispensable dans tout langage de programmation, et en PHP on ny chappe pas. Ce nest pas un truc de programmeurs tordus, cest au contraire quelque chose qui va nous simplier la vie. Sans les variables, vous nirez pas bien loin. Les variables nous permettent de retenir temporairement des informations en mmoire. Avec elles, nous allons pouvoir par exemple retenir le pseudonyme du visiteur, eectuer des calculs et bien dautres choses !

49

CHAPITRE 5. LES VARIABLES

Quest-ce quune variable ?


Rien quavec leur nom, vous devez vous dire que cest quelque chose qui change tout le temps. En eet, le propre dune variable cest de pouvoir varier1 . Mais quest-ce que cest concrtement ? Une variable, cest une petite information stocke en mmoire temporairement. Elle na pas une grande dure de vie. En PHP, la variable (linformation) existe tant que la page est en cours de gnration. Ds que la page PHP est gnre, toutes les variables sont supprimes de la mmoire car elles ne servent plus rien. Ce nest donc pas un chier qui reste stock sur le disque dur mais une petite information temporaire prsente en mmoire vive. Cest vous de crer des variables. Vous en crez quand vous en avez besoin pour retenir des informations.

Un nom et une valeur


Une variable est toujours constitue de deux lments : son nom : pour pouvoir la reconnatre, vous devez donner un nom votre variable. Par exemple age_du_visiteur ; sa valeur : cest linformation quelle contient, et qui peut changer. Par exemple : 17. Ici, je vous ai donn lexemple dune variable appele age_du_visiteur qui a pour valeur 17. On peut modier quand on veut la valeur de cette variable, faire des oprations dessus, etc. Et quand on en a besoin, on lappelle (par son nom), et elle nous dit gentiment la valeur quelle contient. Par exemple, on peut imaginer lchange suivant : Hep ! Toi, la variable age_du_visiteur, que contiens-tu ? 17 Merci ! Vous allez voir que ces petites bbtes, mme si elles peuvent vous sembler encore un peu oues, seront vraiment indispensables pour votre site en PHP. Par exemple, vous pourrez retenir temporairement le nom du visiteur. Dans une variable nom_du_visiteur, vous stockerez son pseudo, mettons M@teo21 . Ds que vous en aurez besoin vous pourrez lutiliser, notamment pour acher un message de bienvenue personnalis : Salut M@teo21 ! Bienvenue sur mon site ! .

Les dirents types de variables


Les variables sont capables de stocker dirents types dinformations. On parle de types de donnes. Voici les principaux types connatre.
1 Belle

lapalissade, nest-ce pas ? ;-)

50

QUEST-CE QUUNE VARIABLE ? Les chanes de caractres (string) : les chanes de caractres sont le nom informatique quon donne au texte. Tout texte est appel chane de caractres. En PHP, ce type de donnes a un nom : string. On peut stocker des textes courts comme trs longs au besoin. Exemple : Je suis un texte . Une chane de caractres est habituellement crite entre guillemets ou entre apostrophes2 : Je suis un texte. Les deux fonctionnent mais il y a une petite dirence que lon va dcouvrir plus loin. Les nombres entiers (int) : ce sont les nombres du type 1, 2, 3, 4, etc. On compte aussi parmi eux les entiers relatifs : -1, -2, -3. . . Exemple : 42. Les nombres dcimaux (float) : ce sont les nombres virgule, comme 14,738. On peut stocker de nombreux chires aprs la virgule, ce qui devrait convenir pour la plupart des usages que vous en ferez. Attention, les nombres doivent tre crits avec un point au lieu de la virgule (cest la notation anglaise). Exemple : 14.738. Les boolens (bool) : cest un type trs important qui permet de stocker soit vrai soit faux. Cela permet de retenir si une information est vraie ou fausse. On les utilise trs frquemment. On crit true pour vrai, et false pour faux. Exemple : true. Rien (NULL) : aussi bizarre que cela puisse paratre, on a parfois besoin de dire quune variable ne contient rien. Rien du tout. On indique donc quelle vaut NULL. Ce nest pas vraiment un type de donnes, mais plutt labsence de type. La gure 5.1 vous rsume ce quil faut retenir des dirents types dinformations quest capable de stocker PHP dans les variables.

Fig. 5.1 Types de donnes

Cela devrait vous donner une ide de tout ce quest capable de stocker PHP en mmoire. Ces types suront pour la cration de notre site ! Maintenant, passons aux choses concrtes. Comment crer une variable et comment acher ce quelle contient ?

2 On

parle de guillemets simples.

51

CHAPITRE 5. LES VARIABLES

Aecter une valeur une variable


Premires manipulations de variables
Je vous propose de commencer par regarder ce code dexemple :
<?php $age_du_visiteur = 17; ?>

Avec ce code PHP, on vient en fait de crer une variable : son nom est age_du_visiteur ; sa valeur est 17. Notez quon ne peut pas mettre despace dans un nom de variable. la place, utilisez un underscore _ 3 . Pour le nom, vitez aussi les accents, les cdilles et tout autre symbole : PHP ne les apprcie pas trop. . . Analysons dans le dtail le code quon vient de voir. Dabord, on crit le symbole dollar ($) : il prcde toujours le nom dune variable. Cest comme un signe de reconnaissance si vous prfrez : a permet de dire PHP Jutilise une variable . Vous reconnatrez toujours quil y a une variable par la prsence du symbole dollar ($). Ensuite, il y a le signe gal (=) : celui-l cest logique, cest pour dire que $age_du_visiteur est gal . . . la suite, il y a la valeur de la variable, ici 17. Enn, il y a lincontournable point-virgule ( ;) qui permet de terminer linstruction. Concrtement, quest-ce que le code prcdent acherait ? Rien du tout ! Eh oui, tant que vous nutilisez pas echo, rien ne sache. L, le serveur a juste cr la variable temporairement en mmoire, mais il na rien fait dautre. Supposons maintenant que lon crive ceci :
<?php $age_du_visiteur = 17; // La variable est cre et vaut 17 $age_du_visiteur = 23; // La variable est modifie et vaut 23 $age_du_visiteur = 55; // La variable est modifie et vaut 55 ?>

Que se passera-t-il ? La variable $age_du_visiteur va tre cre et prendre pour valeur, dans lordre : 17, 23, puis 55. Tout cela va trs vite, lordinateur tant trs rapide vous naurez pas le temps de dire ouf que tout ce code PHP aura t excut.
3 Cest

le symbole sous le chire 8 sur un clavier AZERTY franais.

52

AFFECTER UNE VALEUR UNE VARIABLE Comme tout lheure, rien ne sache. Seulement, quelque part dans la mmoire de lordinateur, une petite zone nomme age_du_visiteur vient de prendre la valeur 17, puis 23, puis 55.

Utiliser les types de donnes


Vous vous souvenez des types de donnes dont je vous ai parl il y a quelques minutes ? Les string, int, double. . . Voici un exemple de variable pour chacun de ces types. Le type string (chane de caractres) Ce type permet de stocker du texte. Pour cela, vous devez entourer votre texte de guillemets doubles "" ou de guillemets simples 4 . Voici deux exemples, lun avec des guillemets simples et lautre avec des guillemets doubles :
<?php $nom_du_visiteur = "Mateo21"; $nom_du_visiteur = Mateo21; ?>

Attention, petit pige : si vous voulez insrer un guillemet simple alors que le texte est entour de guillemets simples, il faut lchapper comme on la vu prcdemment en insrant un antislash devant. Il en va de mme pour les guillemets doubles. Voici un exemple pour bien comprendre :
<?php $variable = "Mon \"nom\" est Mateo21"; $variable = Je m\appelle Mateo21; ?>

En eet, si vous oubliez de mettre un antislash, PHP va croire que cest la n de la chane et il ne comprendra pas le texte qui suivra5 . Vous pouvez en revanche insrer sans problme des guillemets simples au milieu de guillemets doubles et inversement :
<?php $variable = Mon "nom" est Mateo21; $variable = "Je mappelle Mateo21"; ?>

La dirence est subtile, faites attention. Il y a dailleurs une dirence plus importante entre les deux types de guillemets dont nous parlerons plus loin.
4 Attention, 5 Vous

ce sont des apostrophes. aurez en fait un message Parse error.

53

CHAPITRE 5. LES VARIABLES Le type int (nombre entier) On vient de lutiliser pour nos exemples prcdents. Il sut tout simplement dcrire le nombre que vous voulez stocker, sans guillemets.
<?php $age_du_visiteur = 17; ?>

Le type float (nombre dcimal) Vous devez crire votre nombre avec un point au lieu dune virgule. Cest la notation anglaise.
<?php $poids = 57.3; ?>

Le type bool (boolen) Pour dire si une variable vaut vrai ou faux, vous devez crire le mot true ou false sans guillemets autour (ce nest pas une chane de caractres !). Je vous conseille de bien choisir le nom de votre variable pour que lon comprenne ce que a signie. Voyez vous-mmes :
<?php $je_suis_un_zero = true; $je_suis_bon_en_php = false; ?>

Une variable vide avec NULL Si vous voulez crer une variable qui ne contient rien, vous devez lui passer le mot-cl NULL6 .
<?php $pas_de_valeur = NULL; ?>

Cela sert simplement indiquer que la variable ne contient rien, tout du moins pour le moment.
6 Vous

pouvez aussi lcrire en minuscules : null.

54

AFFICHER ET CONCATNER DES VARIABLES

Acher et concatner des variables


Nous avons appris crer des variables et stocker des informations lintrieur. Mais pour le moment, aucun de nos codes source nache quoi que ce soit.

Acher le contenu dune variable


Vous vous souvenez que lon peut acher du texte avec echo ? On peut aussi sen servir pour acher la valeur dune variable !
<?php $age_du_visiteur = 17; echo $age_du_visiteur; ?>

Comme vous le voyez, il sut dcrire le nom de la variable que vous voulez acher. Au fait, on ne doit pas mettre de guillemets aprs le echo comme tu nous as appris ? Non, quand il sagit dune variable on ne met pas de guillemets autour. Crez un chier PHP avec ce code source pour le tester. Inutile de mettre tout le code HTML autour, ce nest pas grave, ce ne sera pas une vraie page HTML valide mais cest bien susant pour nos tests. Vous devriez voir, ainsi que vous le montre la gure 5.2, le rsultat sacher sur un fond blanc dans votre navigateur.

Fig. 5.2 Achage dune variable Le nombre contenu lintrieur de la variable sache dans la page (ici 17).

La concatnation
Non, ce nest pas une insulte. Cela signie assemblage. ;-) En fait, crire 17 tout seul comme on la fait nest pas trs parlant. On aimerait crire du texte autour pour dire : Le visiteur a 17 ans . La concatnation est justement un moyen dassembler du texte et des variables. Comment faire cela ? Les petits malins auront lide dcrire trois instructions echo :
<?php $age_du_visiteur = 17;

55

CHAPITRE 5. LES VARIABLES


echo "Le visiteur a "; echo $age_du_visiteur; echo " ans"; ?>

Vous pouvez tester, a fonctionne, comme vous le montre la gure 5.3.

Fig. 5.3 Ajouter du texte autour dune variable Mais il y a plus malin. On peut tout faire sur une ligne. Pour cela, il y a deux mthodes et cest justement maintenant que le fait dutiliser des guillemets simples ou doubles va faire la dirence. Concatner avec des guillemets doubles Avec des guillemets doubles, cest le plus simple. Vous pouvez crire le nom de la variable au milieu du texte et il sera remplac par sa valeur. Concrtement, essayez ce code :
<?php $age_du_visiteur = 17; echo "Le visiteur a $age_du_visiteur ans"; ?>

a ache : Le visiteur a 17 ans. En eet, lorsque vous utilisez des guillemets doubles, les variables qui se trouvent lintrieur sont analyses et remplaces par leur vraie valeur. a a le mrite dtre une solution facile utiliser, mais je vous recommande plutt celle des guillemets simples, que nous allons voir ds prsent. Concatner avec des guillemets simples Si vous crivez le code prcdent entre guillemets simples, vous allez avoir une drle de surprise :
<?php $age_du_visiteur = 17; echo Le visiteur a $age_du_visiteur ans; // Ne marche pas ?>

a ache : Le visiteur a $age_du_visiteur ans. 56

FAIRE DES CALCULS SIMPLES

Misricorde ! On ne peut pas concatner du texte avec des guillemets simples ?

Eh bien si ! Mais cette fois, il va falloir crire la variable en dehors des guillemets et sparer les lments les uns des autres laide dun point. Regardez :
<?php $age_du_visiteur = 17; echo Le visiteur a . $age_du_visiteur . ans; ?>

Cette fois, a ache bien comme on voulait : Le visiteur a 17 ans. a a lair bien plus compliqu, mais en fait cest cette mthode quutilisent la plupart des programmeurs expriments en PHP. En eet, le code est plus lisible, on repre bien la variable alors que tout lheure elle tait comme noye dans le texte. Dautre part, votre diteur de texte devrait vous colorer la variable, ce quil ne faisait pas pour le code prcdent. Il faut noter aussi que cette mthode dcriture est un choua plus rapide car PHP voit de suite o se trouve la variable et na pas besoin de la chercher au milieu du texte. Dornavant, jcrirai toutes mes chanes de caractres entre guillemets simples ( de rares exceptions prs) et jutiliserai la seconde mthode de concatnation quon vient de voir. Prenez le temps de vous habituer lutiliser et cela nira par devenir compltement naturel pour vous.

Faire des calculs simples


On va maintenant faire travailler votre ordinateur, et vous allez voir quil encaisse les calculs sans broncher. Eh oui, PHP sait aussi faire des calculs ! Oh je vous rassure, on ne va pas faire des calculs tordus, juste des additions, des soustractions, des multiplications et des divisions. Cest du niveau de tout le monde, non ? ;-) Ici comme vous vous en doutez, on ne va travailler que sur des variables qui contiennent des nombres.

Les oprations de base : addition, soustraction. . .


Les signes connatre pour faire les quatre oprations de base7 sont reprsents par le tableau 5.1. Aprs, pour vous en servir, a coule de source. Voici quelques exemples :
7 Vous

les trouverez sur votre pav numrique, droite du clavier en principe.

57

CHAPITRE 5. LES VARIABLES Symbole + * / Signication Addition Soustraction Multiplication Division

Tab. 5.1 Oprateurs de base


<?php $nombre $nombre $nombre $nombre

= = = =

2 + 4; // $nombre prend la valeur 6 5 - 1; // $nombre prend la valeur 4 3 * 5; // $nombre prend la valeur 15 10 / 2; // $nombre prend la valeur 5

// Allez on rajoute un peu de difficult $nombre = 3 * 5 + 1; // $nombre prend la valeur 16 $nombre = (1 + 2) * 2; // $nombre prend la valeur 6 ?>

Allez quoi, boudez pas, un peu de calcul mental a na jamais fait de mal personne. Vriez mes calculs, comme vous pouvez le voir il ny a rien de bien compliqu dans tout a. Seulement, il ne faut pas avoir peur de jongler avec les variables. Voici des calculs avec plusieurs variables :
<?php $nombre = 10; $resultat = ($nombre + 5) * $nombre; // $resultat prend la valeur 150 ?>

Cest de la pure logique, je ne peux rien vous dire de plus. Si vous avez compris ces bouts de code, vous avez tout compris.

Le modulo
Il est possible de faire un autre type dopration un peu moins connu : le modulo. Cela reprsente le reste de la division entire. Par exemple, 6 / 3 = 2 et il ny a pas de reste. En revanche, 7 / 3 = 28 et il reste 1. Vous avez fait ce type de calculs lcole primaire, souvenez-vous ! Le modulo permet justement de rcuprer ce reste . Pour faire un calcul avec un modulo, on utilise le symbole %.
<?php $nombre = 10 % 5; // $nombre prend la valeur 0 car la division tombe juste
8 Car

le nombre 3 rentre 2 fois dans le nombre 7.

58

FAIRE DES CALCULS SIMPLES


$nombre = 10 % 3; // $nombre prend la valeur 1 car il reste 1 ?>

Et les autres oprations ?


Je passe sous silence les oprations plus complexes telles que la racine carre, lexponentielle, la factorielle, etc. Toutes ces oprations peuvent tre ralises en PHP mais il faudra passer par ce quon appelle des fonctions, une notion que lon dcouvrira plus tard. Les oprations basiques que lon vient de voir sont amplement susantes pour la programmation PHP de tous les jours.

En rsum
Une variable est une petite information qui reste stocke en mmoire le temps de la gnration de la page PHP. Elle a un nom et une valeur. Il existe plusieurs types de variables qui permettent de stocker dirents types dinformations : du texte (string), des nombres entiers (int), des nombres dcimaux (float), des boolens pour stocker vrai ou faux (bool), etc. En PHP, un nom de variable commence par le symbole dollar : $age par exemple. La valeur dune variable peut tre ache avec linstruction echo. Il est possible de faire des calculs mathmatiques entre plusieurs variables : addition, soustraction, multiplication. . .

59

CHAPITRE 5. LES VARIABLES

60

Chapitre

6
Dicult :

Les conditions

e chapitre est dune importance capitale. En eet, vous serez trs souvent amens employer des conditions dans vos pages web PHP.

quoi servent les conditions ? On a parfois besoin dacher des choses direntes en fonction de certaines donnes. Par exemple, si cest le matin, vous voudrez dire Bonjour votre visiteur ; si cest le soir, il vaudra mieux dire Bonsoir . Cest l quinterviennent les conditions. Elles permettent de donner des ordres dirents PHP selon le cas. Pour notre exemple, on lui dirait : Si cest le matin, ache Bonjour . Sinon, si cest le soir, ache Bonsoir . Vous allez voir que les conditions constituent vraiment la base pour rendre votre site dynamique, cest--dire pour acher des choses direntes en fonction du visiteur, de la date, de lheure de la journe, etc. Voil pourquoi ce chapitre est si important ! Allez, on y va !

61

CHAPITRE 6. LES CONDITIONS

La structure de base : if. . . else


Une condition peut tre crite en PHP sous direntes formes. On parle de structures conditionnelles. Celle que je vais vous apprendre utiliser maintenant est la principale connatre. Nous en verrons dautres un peu plus loin. Pour tudier la structure if... else, nous allons suivre le plan qui suit. 1. Les symboles connatre : il va dabord falloir retenir quelques symboles qui permettent de faire des comparaisons. Soyez attentifs car ils vous seront utiles pour les conditions. 2. La structure if. . . else : cest le gros morceau. L vous allez voir comment fonctionne une condition avec if... else. Inutile de vous dire quil est indispensable de bien comprendre cela. 3. Des conditions multiples : on compliquera un peu nos conditions. Vous allez voir en eet quon peut utiliser plusieurs conditions la fois. 4. Le cas des boolens : nous verrons ensuite quil existe une faon particulire dutiliser les conditions quand on travaille sur des boolens. Si vous ne savez pas ce que sont les boolens, revoyez le chapitre sur les variables. 5. Lastuce bonus : parce quil y a toujours un bonus pour rcompenser ceux qui ont bien suivi jusquau bout !

Les symboles connatre


Juste avant de commencer, je dois vous montrer les symboles que nous serons amens utiliser. Je vais vous faire un petit tableau avec ces symboles et leur signication. Essayez de bien les retenir, ils vous seront utiles ! Symbole == > < >= <= != Signication Est gal Est suprieur Est infrieur Est suprieur ou gal Est infrieur ou gal Est dirent de

Il y a deux symboles gal (==) sur la premire ligne, et il ne faut pas confondre a avec le simple = que je vous ai appris dans le chapitre sur les variables. Ici, le double gal sert tester lgalit, dire Si cest gal . . . . Dans les conditions, on utilisera toujours le double gal (==).

Les symboles suprieur (>) et infrieur (<) sont situs en bas gauche de votre clavier.

62

LA STRUCTURE DE BASE : IF. . . ELSE

La structure if. . . else


Voici ce quon doit crire, dans lordre, pour utiliser une condition. Pour introduire une condition, on utilise le mot if, qui en anglais signie si . On ajoute la suite entre parenthses la condition en elle-mme1 . Enn, on ouvre des accolades lintrieur desquelles on placera les instructions excuter si la condition est remplie. Puisquun exemple vaut toujours mieux quun long discours :
<?php $age = 8; if ($age <= 12) { echo "Salut gamin !"; } ?>

Ici, on demande PHP : si la variable $age est infrieure ou gale 12, ache Salut gamin ! . Vous remarquerez que dans la quasi-totalit des cas, cest sur une variable quon fait la condition. Dans notre exemple, on travaille sur la variable $age. Ce qui compte ici, cest quil y a deux possibilits : soit la condition est remplie (lge est infrieur ou gal 12 ans) et alors on ache quelque chose ; sinon, eh bien on saute les instructions entre accolades, on ne fait rien. Bon, on peut quand mme amliorer notre exemple. On va acher un autre message si lge est suprieur 12 ans :
<?php $age = 8; if ($age <= 12) // SI lge est infrieur ou gal 12 { echo "Salut gamin ! Bienvenue sur mon site !<br />"; $autorisation_entrer = "Oui"; } else // SINON { echo "Ceci est un site pour enfants, vous tes trop vieux pour pouvoir entrer. Au revoir !<br />"; $autorisation_entrer = "Non"; } echo "Avez-vous lautorisation dentrer ? La rponse est : $autorisation_entrer" ; ?>
1 Vous

allez voir que vous pouvez inventer une innit de conditions.

63

CHAPITRE 6. LES CONDITIONS Code web : 182557 Bon : comment marche ce code ? Tout dabord, jai mis plusieurs instructions entre accolades. Ensuite, vous avez remarqu que jai ajout le mot else ( sinon ). En clair, on demande : Si lge est infrieur ou gal 12 ans, fais ceci, sinon fais cela. Essayez ce bout de code chez vous, en vous amusant modier la valeur de $age (sur la premire ligne). Vous allez voir que le message qui sache change en fonction de lge que vous indiquez ! Bien entendu, vous mettez les instructions que vous voulez entre accolades. Ici par exemple, jai donn une valeur dirente la variable $autorisation_entrer aprs avoir ach un message, valeur qui pourrait nous servir par la suite :
<?php if ($autorisation_entrer == "Oui") // SI on a lautorisation dentrer { // instructions excuter quand on est autoris entrer } elseif ($autorisation_entrer == "Non") // SINON SI on na pas lautorisation dentrer { // instructions excuter quand on nest pas autoris entrer } else // SINON (la variable ne contient ni Oui ni Non, on ne peut pas agir) { echo "Euh, je ne connais pas ton ge, tu peux me le rappeler sil te plat ? "; } ?>

Ouh l, a commence se compliquer un tantinet, nest-ce pas ? La principale nouveaut ici, cest le mot-cl elseif qui signie sinon si . Dans lordre, PHP rencontre les conditions suivantes : 1. si $autorisation_entrer est gale Oui , tu excutes ces instructions. . . 2. sinon si $autorisation_entrer est gale Non , tu excutes ces autres instructions. . . 3. sinon, tu redemandes lge pour savoir si on a ou non lautorisation dentrer.

Au fait, au dpart, une variable ne contient rien. Sa valeur est vide, on dit quelle vaut NULL, cest--dire rien du tout. Pour vrier si la variable est vide, vous pouvez taper : if ($variable == NULL). . .

64

LA STRUCTURE DE BASE : IF. . . ELSE

Le cas des boolens


Si vous regardez bien le dernier code source (avec $autorisation_entrer), vous ne trouvez pas quil serait plus adapt dutiliser des boolens ? On a parl des boolens dans le chapitre sur les variables. Vous vous souvenez ? Ce sont ces variables qui valent soit true (vrai) soit false (faux). Eh bien, les boolens sont particulirement utiles avec les conditions ! Voici comment on teste une variable boolenne :
<?php if ($autorisation_entrer == true) { echo "Bienvenue petit Zro. :o)"; } elseif ($autorisation_entrer == false) { echo "Tas pas le droit dentrer !"; } ?>

Voil, jusque-l rien dextraordinaire. Vous avez vu que je nai pas mis de guillemets pour true et false, comme je vous lai dit dans le chapitre sur les variables. Mais un des avantages des boolens, cest quils sont particulirement adapts aux conditions. Pourquoi ? Parce quen fait vous ntes pas obligs dajouter le == true. Quand vous travaillez sur une variable boolenne, PHP comprend trs bien ce que vous avez voulu dire :
<?php if ($autorisation_entrer) { echo "Bienvenue petit Zro. :o)"; } else { echo "Tas pas le droit dentrer !"; } ?>

PHP comprend quil faut quil vrie si $autorisation_entrer vaut true. Avantages : cest plus rapide crire pour vous ; a se comprend bien mieux. En eet, si vous lisez la premire ligne, a donne : SI on a lautorisation dentrer. . . . Cest donc un raccourci connatre quand on travaille sur des boolens. Oui mais ta mthode courte ne marche pas si on veut vrier si le boolen vaut faux. Comment on fait avec la mthode courte, hein ? 65

CHAPITRE 6. LES CONDITIONS Il y a un symbole qui permet de vrier si la variable vaut false : le point dexclamation ( !). On crit :
<?php if (! $autorisation_entrer) { } ?>

Cest une autre faon de faire. Si vous prfrez mettre if ($autorisation_entrer == false) cest tout aussi bien, mais la mthode courte est plus lisible.

Des conditions multiples


Ce quon va essayer de faire, cest de poser plusieurs conditions la fois. Pour cela, on aura besoin de nouveaux mots-cls. Voici les principaux connatre : Mot-cl AND OR Signication Et Ou Symbole quivalent && ||

Le symbole quivalent pour OR est constitu de deux barres verticales. Pour taper une barre verticale, appuyez sur les touches Alt Gr et 6 en mme temps2 , ou Alt Gr et & 3 . La premire colonne contient le mot-cl en anglais, la troisime son quivalent en symbole. Les deux fonctionnent aussi bien, mais je vous recommande dutiliser le mot-cl de prfrence, cest plus facile lire4 . Servez-vous de ces mots-cls pour mettre plusieurs conditions entre les parenthses. Voici un premier exemple :
<?php if ($age <= 12 AND $sexe == "garon") { echo "Bienvenue sur le site de Captain Mgakill !"; } elseif ($age <= 12 AND $sexe == "fille") { echo "Cest pas un site pour les filles ici, retourne jouer la Barbie !"; } ?>
2 Sur 3 Sur

un clavier AZERTY franais. un clavier AZERTY belge. 4 Jespre que vous connaissez un peu langlais, quand mme.

66

LA STRUCTURE DE BASE : IF. . . ELSE Cest tout simple en fait et a se comprend trs bien : si lge est infrieur ou gal 12 ans et que cest un garon, on lui permet daccder au site de son super-hros prfr. Sinon, si cest une lle dont lge est infrieur ou gal 12 ans, on lenvoie gentiment balader5 . Bon allez, un dernier exemple avec OR pour que vous layez vu au moins une fois, et on arrte l.
<?php if ($sexe == "fille" OR $sexe == "garon") { echo "Salut Terrien !"; } else { echo "Euh, si tes ni une fille ni un garon, tes quoi alors ?"; } ?>

Lastuce bonus
Avec les conditions, il y a une astuce connatre. Sachez que les deux codes ci-dessous donnent exactement le mme rsultat :
<?php if ($variable == 23) { echo <strong>Bravo !</strong> Vous avez trouv le nombre mystre !; } ?> <?php if ($variable == 23) { ?> <strong>Bravo !</strong> Vous avez trouv le nombre mystre ! <?php } ?>

Comme vous le voyez, dans la seconde colonne on na pas utilis de echo. En eet, il vous sut douvrir laccolade ({), puis de fermer la balise PHP ( ?>), et vous pouvez mettre tout le texte acher que vous voulez en HTML ! Rudement pratique quand il y a de grosses quantits de texte acher, et aussi pour viter davoir se prendre la tte avec les antislashs devant les guillemets (" ou ). Il vous faudra toutefois penser refermer laccolade aprs6 .
5 Hum, 6

hum, maccusez pas de sexisme hein, ctait juste pour lexemple. lintrieur dune balise PHP, bien entendu.

67

CHAPITRE 6. LES CONDITIONS Et aprs a, ma foi, il ny a rien de particulier savoir. Vous allez rencontrer des conditions dans la quasi-totalit des exemples que je vous donnerai par la suite. Vous ne devriez pas avoir de problmes normalement pour utiliser des conditions, il ny a rien de bien dicile. Contentez-vous de reprendre le schma que je vous ai donn pour la structure if... else et de lappliquer votre cas. Nous aurons dailleurs bientt loccasion de pratiquer un peu, et vous verrez que les conditions sont souvent indispensables.

Une alternative pratique : switch


En thorie, les structures base de if... elseif... else que je viens de vous montrer susent pour traiter nimporte quelle condition. Mais alors, pourquoi se compliquer la vie avec une autre structure ?

Pour vous faire comprendre lintrt de switch, je vais vous donner un exemple un peu lourd avec les if et elseif que vous venez dapprendre :
<?php if ($note == 0) { echo "Tu es vraiment un gros Zro !!!"; } elseif ($note == 5) { echo "Tu es trs mauvais"; } elseif ($note == 7) { echo "Tu es mauvais"; } elseif ($note == 10) { echo "Tu as pile poil la moyenne, cest un peu juste..."; } elseif ($note == 12) { echo "Tu es assez bon"; } elseif ($note == 16)

68

UNE ALTERNATIVE PRATIQUE : SWITCH


{ }

echo "Tu te dbrouilles trs bien !";

elseif ($note == 20) { echo "Excellent travail, cest parfait !"; } else { echo "Dsol, je nai pas de message afficher pour cette note"; } ?>

Comme vous le voyez, cest lourd, long, et rptitif. Dans ce cas, on peut utiliser une autre structure plus souple : cest switch. Voici le mme exemple avec switch7 :
<?php $note = 10; switch ($note) // on indique sur quelle variable on travaille { case 0: // dans le cas o $note vaut 0 echo "Tu es vraiment un gros Zr0 !!!"; break; case 5: // dans le cas o $note vaut 5 echo "Tu es trs mauvais"; break; case 7: // dans le cas o $note vaut 7 echo "Tu es mauvais"; break; case 10: // etc. etc. echo "Tu as pile poil la moyenne, cest un peu juste..."; break; case 12: echo "Tu es assez bon"; break; case 16: echo "Tu te dbrouilles trs bien !"; break;
7 Le

rsultat est le mme, mais le code est plus adapt.

69

CHAPITRE 6. LES CONDITIONS


case 20: echo "Excellent travail, cest parfait !"; break; default: echo "Dsol, je nai pas de message afficher pour cette note";

} ?>

Code web : 733130 Testez donc ce code ! Essayez de changer la note (dans la premire instruction) pour voir comment PHP ragit ! Et si vous voulez apporter quelques modications ce code8 , nhsitez pas, a vous fera de lentranement ! Tout dabord, il y a beaucoup moins daccolades (elles marquent seulement le dbut et la n du switch). case signie cas . Dans le switch, on indique au dbut sur quelle variable on travaille (ici $note). On dit PHP : Je vais analyser la valeur de $note. Aprs, on utilise des case pour analyser chaque cas (case 0, case 10, etc.). Cela signie : Dans le cas o la valeur est 0. . . Dans le cas o la valeur est 10. . . Avantage : on na plus besoin de mettre le double gal ! Dfaut : a ne marche pas avec les autres symboles (< > <= >= !=). En clair, le switch ne peut tester que lgalit. Le mot-cl default la n est un peu lquivalent du else. Cest le message qui sache par dfaut quelle que soit la valeur de la variable. Il y a cependant une chose importante savoir : supposons dans notre exemple que la note soit de 10. PHP va lire : case 0 ? Non. Je saute. case 5 ? Non plus. Je saute. case 7 ? Non plus. Je saute. case 10 ? Oui, jexcute les instructions. Mais contrairement aux elseif, PHP ne sarrte pas l et continue lire les instructions des case qui suivent ! case 12, case 16, etc. Pour empcher cela, utilisez linstruction break ;. Linstruction break demande PHP de sortir du switch. Ds que PHP tombe sur break, il sort des accolades et donc il ne lit pas les case qui suivent. En pratique, on utilise trs souvent un break car sinon, PHP lit des instructions qui suivent et qui ne conviennent pas. Essayez denlever les break dans le code prcdent, vous allez comprendre pourquoi ils sont indispensables ! Quand doit-on choisir if, et quand doit-on choisir switch ?

Cest surtout un problme de prsentation et de clart. Pour une condition simple et courte, on utilise le if, et quand on a une srie de conditions analyser, on prfre
8 Vous

allez voir quil nest pas parfait.

70

LES TERNAIRES : DES CONDITIONS CONDENSES utiliser switch pour rendre le code plus clair.

Les ternaires : des conditions condenses


Il existe une autre forme de condition, beaucoup moins frquente, mais que je vous prsente quand mme car vous pourriez un jour ou lautre tomber dessus. Il sagit de ce quon appelle les ternaires. Un ternaire est une condition condense qui fait deux choses sur une seule ligne : on teste la valeur dune variable dans une condition ; on aecte une valeur une variable selon que la condition est vraie ou non. Prenons cet exemple base de if... else qui met un boolen $majeur vrai ou faux selon lge du visiteur :
<?php $age = 24; if ($age >= 18) { $majeur = true; } else { $majeur = false; } ?>

On peut faire la mme chose en une seule ligne grce une structure ternaire :
<?php $age = 24; $majeur = ($age >= 18) ? true : false; ?>

Ici, tout notre test prcdent a t fait sur une seule ligne ! La condition teste est $age >= 18. Si cest vrai, alors la valeur indique aprs le point dinterrogation (ici true) sera aecte la variable $majeur. Sinon, cest la valeur qui suit le symbole deux-points qui sera aecte $majeur. Cest un peu tordu mais a marche. Si vous nutilisez pas ce type de condition dans vos pages web, je ne vous en voudrai pas. Il faut avouer que les ternaires sont un peu diciles lire car ils sont trs condenss. Mais sachez les reconnatre et les comprendre si vous en rencontrez un jour en lisant le code source de quelquun dautre. 71

CHAPITRE 6. LES CONDITIONS

En rsum
Les conditions permettent PHP de prendre des dcisions en fonction de la valeur des variables. La forme de condition la plus courante est if. . . elseif. . . else qui signie si . . . sinon si . . . sinon . On peut combiner des conditions avec les mots-cls AND ( et ) et OR ( ou ). Si une condition comporte de nombreux elseif, il peut tre plus pratique dutiliser switch, une autre forme de condition. Les ternaires sont des conditions condenses qui font un test sur une variable, et en fonction des rsultats de ce test donnent une valeur une autre variable. Elles sont cependant plus rarement utilises.

72

Chapitre

7
Dicult :

Les boucles

ans la srie des lments de base de PHP connatre absolument, voici les boucles ! Rpter des instructions, a, lordinateur sait faire (et en plus, il ne bronche jamais) !

Imaginez que vous tes en train de crer le forum de votre site. Sur une page, on ache par exemple une trentaine de messages. Il serait bien trop long et rptitif de dire Ache le message 1 et le nom de son auteur , Ache le message 2 et le nom de son auteur , Ache le message 3 et le nom de son auteur , etc. Pour viter davoir faire cela, on peut utiliser un systme de boucle qui nous permettra de dire une seule fois : Ache 30 messages et le nom de leur auteur chaque fois . Bien entendu, nous nallons pas pouvoir apprendre crer le forum de votre site dans ce chapitre, il est encore trop tt. Nanmoins, prenez bien le temps de comprendre le fonctionnement des boucles car nous en aurons besoin tout au long de ce cours. Ce nest pas bien compliqu, vous allez voir !

73

CHAPITRE 7. LES BOUCLES

Une boucle simple : while


Quest-ce quune boucle ? Cest une structure qui fonctionne sur le mme principe que les conditions (if... else). Dailleurs, vous allez voir quil y a beaucoup de similitudes avec le chapitre sur les conditions. Concrtement, une boucle permet de rpter des instructions plusieurs fois. En clair, cest un gain de temps, cest trs pratique, et bien souvent indispensable. On peut si vous voulez prsenter le principe dans le schma 7.1.

Fig. 7.1 Principe de fonctionnement dune boucle Voil ce qui se passe dans une boucle : 1. comme dhabitude, les instructions sont dabord excutes dans lordre, de haut en bas (che rouge) ; 2. la n des instructions, on retourne la premire (che verte) ; 3. on recommence lire les instructions dans lordre (che rouge) ; 4. et on retourne la premire (che verte) ; 5. etc., etc. Le seul hic dans ce schma, cest que a ne sarrte jamais ! Les instructions seraient rexcutes linni ! Cest pour cela que, quel que soit le type de boucle (while ou for), il faut indiquer une condition. Tant que la condition est remplie, les instructions sont rexcutes. Ds que la condition nest plus remplie, on sort enn de la boucle (ouf !). Voici comment faire avec une boucle simple : while.
<?php while ($continuer_boucle == true) { // instructions excuter dans la boucle } ?>

while peut se traduire par tant que . Ici, on demande PHP : TANT QUE $continuer_boucle est vrai, excuter ces instructions. 74

UNE BOUCLE SIMPLE : WHILE Les instructions qui sont rptes en boucle se trouvent entre les accolades { et }. Mais bon l je ne vous apprends rien, vous commencez avoir lhabitude de voir des accolades de partout. ;-) Ce nest pas beaucoup plus compliqu que a, il ny a gure plus de choses savoir. Cependant, je vais quand mme vous montrer un ou deux exemples dutilisation de boucles, pour que vous voyiez quoi a peut servir. . . Pour notre premier exemple, on va supposer que vous avez t punis et que vous devez recopier 100 fois Je ne dois pas regarder les mouches voler quand japprends le PHP. . Avant, il fallait prendre son mal en patience et a prenait des heuuuures. . . Maintenant, avec PHP, on va faire a en un clin dil ! Regardez ce code :
<?php $nombre_de_lignes = 1; while ($nombre_de_lignes <= 100) { echo Je ne dois pas regarder les mouches voler quand j\apprends le PHP.<br />; $nombre_de_lignes++; // $nombre_de_lignes = $nombre_de_lignes + 1 } ?>

Code web : 389572 La boucle pose la condition : TANT QUE $nombre_de_lignes est infrieur ou gal 100. Dans cette boucle, il y a deux instructions : le echo, qui permet dacher du texte en PHP. noter quil y a une balise HTML <br /> la n : cela permet daller la ligne. Vu que vous connaissez le HTML, a na rien de surprenant : chaque phrase sera crite sur une seule ligne ; ensuite, une instruction bizarre : $nombre_de_lignes++ ; Qusaco ? Regardez mon commentaire : cest exactement la mme chose. En fait, cest une faon plus courte dajouter 1 la variable. On appelle cela lincrmentation1 . Chaque fois quon fait une boucle, la valeur de la variable augmente : 1, 2, 3, 4. . . 99, 100. . . Ds que la variable atteint 101, on arrte la boucle. Et voil, on a crit 100 lignes en un clin dil. Si la punition avait t plus grosse, pas de problme ! Il aurait su de changer la condition2 . Il faut TOUJOURS sassurer que la condition sera fausse au moins une fois. Si elle ne lest jamais, alors la boucle sexcutera linni ! PHP refuse normalement de travailler plus dune quinzaine de secondes. Il sarrtera tout seul sil voit que son travail dure trop longtemps et achera un message derreur.
1 Ce

2 Par

nom barbare signie tout simplement que lon a ajout 1 la variable. exemple, mettre TANT QUE cest infrieur ou gal 500 pour lcrire 500 fois.

75

CHAPITRE 7. LES BOUCLES Nous venons donc de voir comment acher une phrase plusieurs centaines de fois sans eort. Mais est-ce vraiment utile ? On na pas besoin de faire a sur un site web !

Pas vraiment, mais comme je vous lai dit en introduction, nous apprenons ici des techniques de base que lon va pouvoir rutiliser dans les prochains chapitres de ce cours. Imaginez la n que ce systme de boucle va vous permettre de demander PHP dacher dune seule traite tous les messages de votre forum. Bien sr, il vous faudra dautres connaissances pour y parvenir, mais sans les boucles vous nauriez rien pu faire ! Je vous demande pour le moment de pratiquer et de comprendre comment a marche. Bon, un autre exemple pour le plaisir ? On peut crire de la mme manire une centaine de lignes, mais chacune peut tre dirente3 . Cet exemple devrait vous montrer que la valeur de la variable augmente chaque passage dans la boucle :
<?php $nombre_de_lignes = 1; while ($nombre_de_lignes <= 100) { echo Ceci est la ligne n . $nombre_de_lignes . <br />; $nombre_de_lignes++; } ?>

Code web : 402888 Voil, cest tout bte, et cet exemple ressemble beaucoup au prcdent. La particularit, l, cest quon ache chaque fois la valeur de $nombre_de_lignes4 . Pour information, lastuce que je vous avais donne dans le chapitre sur les conditions marche aussi ici : vous pouvez fermer la balise PHP ?>, crire du texte en HTML, puis rouvrir la balise PHP < ?php. Cela vous vite dutiliser une ou plusieurs instructions echo au milieu. On aura loccasion dutiliser cette astuce de nombreuses fois dans la suite du cours.

Une boucle plus complexe : for


Mais non, nayez pas peur voyons. Il ne vous arrivera rien de mal : ici le mot complexe ne veut pas dire compliqu .
3 On 4 a

nest pas obligs dcrire la mme chose chaque fois. vous permet de voir que sa valeur augmente petit petit.

76

UNE BOUCLE PLUS COMPLEXE : FOR for est un autre type de boucle, dans une forme un peu plus condense et plus commode crire, ce qui fait que for est assez frquemment utilis. Cependant, sachez que for et while donnent le mme rsultat et servent la mme chose : rpter des instructions en boucle. Lune peut paratre plus adapte que lautre dans certains cas, cela dpend aussi des gots. Alors, comment a marche un for ? a ressemble beaucoup au while, mais cest la premire ligne qui est un peu particulire. Pour que vous voyiez bien la dirence avec le while, je reprends exactement lexemple prcdent, mais cette fois avec un for :
<?php for ($nombre_de_lignes = 1; $nombre_de_lignes <= 100; $nombre_de_lignes++) { echo Ceci est la ligne n . $nombre_de_lignes . <br />; } ?>

Que de choses dans une mme ligne ! Bon, vous vous en doutez, je ne vais vous expliquer que la ligne du for, le reste nayant pas chang. Aprs le mot for, il y a des parenthses qui contiennent trois lments, spars par des points-virgules ;. Dcrivons chacun de ces lments. Le premier sert linitialisation. Cest la valeur que lon donne au dpart la variable (ici, elle vaut 1). Le second, cest la condition. Comme pour le while, tant que la condition est remplie, la boucle est rexcute. Ds que la condition ne lest plus, on en sort. Enn, le troisime cest lincrmentation, qui vous permet dajouter 1 la variable chaque tour de boucle. Les deux derniers codes donnent donc exactement le mme rsultat. Le for fait la mme chose que le while, mais rassemble sur une seule ligne tout ce quil faut savoir sur le fonctionnement de la boucle. Comment savoir lequel prendre quand je dois choisir entre un while et un for ? La boucle while est plus simple et plus exible : on peut faire tous les types de boucles avec mais on peut oublier de faire certaines tapes comme lincrmentation de la variable. En revanche, for est bien adapt quand on doit compter le nombre de fois que lon rpte les instructions et il permet de ne pas oublier de faire lincrmentation pour augmenter la valeur de la variable ! Si vous hsitez entre les deux, il sut simplement de vous poser la question suivante : Est-ce que je sais davance combien de fois je veux que mes instructions soient rptes ? . Si la rponse est oui, alors la boucle for est tout indique. Sinon, 77

CHAPITRE 7. LES BOUCLES alors il vaut mieux utiliser la boucle while.

En rsum
Les boucles demandent PHP de rpter des instructions plusieurs fois. Les deux principaux types de boucles sont : while : utiliser de prfrence lorsquon ne sait pas par avance combien de fois la boucle doit tre rpte ; for : utiliser lorsquon veut rpter des instructions un nombre prcis de fois. Lincrmentation est une technique qui consiste ajouter 1 la valeur dune variable. La dcrmentation retire au contraire 1 cette variable. On trouve souvent des incrmentations au sein de boucles for.

78

Chapitre

8
Dicult :

Les fonctions

n PHP, on naime pas avoir rpter le mme code. Pour pallier ce problme, nous avons dcouvert les boucles, qui permettent dexcuter des instructions un certain nombre de fois. Ici nous allons dcouvrir un autre type de structure indispensable pour la suite : les fonctions. Comme les boucles, les fonctions permettent dviter davoir rpter du code PHP que lon utilise souvent. Mais alors que les boucles sont de btes machines tout juste capables de rpter deux cents fois la mme chose, les fonctions sont des robots intelligents qui sadaptent en fonction de ce que vous voulez faire et qui automatisent grandement la plupart des tches courantes.

79

CHAPITRE 8. LES FONCTIONS

Quest-ce quune fonction ?


Une fonction est une srie dinstructions qui eectue des actions et qui retourne une valeur. En gnral, ds que vous avez besoin deectuer des oprations un peu longues dont vous aurez nouveau besoin plus tard, il est conseill de vrier sil nexiste pas dj une fonction qui fait cela pour vous. Et si la fonction nexiste pas, vous avez la possibilit de la crer. Imaginez que les fonctions sont des robots comme dans la gure 8.1.

Fig. 8.1 Une fonction est comme un robot Vous ne savez pas ce qui se passe lintrieur de ce robot, mais vous pouvez appuyer sur un bouton pour lui demander de faire quelque chose de prcis. Avec les fonctions, cest le mme principe !

Dialogue avec une fonction


Voici le genre de dialogue quon peut avoir avec une fonction : Toi, la fonction calculCube, donne-moi le volume dun cube dont larte mesure 4 cm. La fonction eectue les calculs demands puis rpond : Ce cube a un volume de 64 cm3 . On donne en entre la fonction un paramtre sur lequel elle va faire des calculs1 et la fonction nous retourne en sortie le rsultat : 64. Voyez la gure 8.2.

Fig. 8.2 Calcul du cube


1 Ici,

la longueur de larte : 4.

80

QUEST-CE QUUNE FONCTION ? Grce la fonction, vous navez pas eu besoin de vous souvenir de la manire dont on calcule le volume dun cube. Bon ici ctait assez simple2 , mais vous serez souvent amens faire des oprations de plus en plus complexes et les fonctions vous permettront de ne pas avoir vous soucier des dtails des calculs. Si vous aviez eu dterminer le volume du cube une seule fois, vous auriez pu chercher la formule dans un livre (si vous ne vous en souveniez pas) et crire le calcul la main. Mais si vous aviez le faire 5 fois ? 10 fois ? 100 fois ? En quoi est-ce dirent des boucles ? Avec les boucles on peut faire rpter le mme code plusieurs fois aussi ! Oui, mais les fonctions sont capables de sadapter en fonction des informations que vous leur envoyez. Par exemple dans notre cas, il sut de transmettre la longueur de larte du cube notre fonction pour quelle nous retourne le rsultat. Ces informations que lon donne en entre la fonction sont appeles paramtres3 . Les fonctions ne servent qu faire des calculs mathmatiques ? Je veux juste crer un site web, pas faire des maths ! Jai choisi un exemple mathmatique ici parce que je le trouve simple et parlant, mais dans la pratique on ne passe pas son temps calculer des logarithmes et des exponentielles quand on cre un site web, je suis daccord. Concrtement, les fonctions peuvent permettre de rcuprer des informations comme la date et lheure actuelles, de crypter des donnes, denvoyer des e-mails, de faire des recherches dans du texte, et bien dautres choses encore !

Les fonctions en PHP


Nous avons jusquici imagin le dialogue avec une fonction reprsente par un robot, ce qui nest pas trs intressant. Revenons aux choses srieuses et concrtes.

Appeler une fonction En PHP, comment appelle-t-on une fonction ? Par son nom, pardi ! Par exemple :
<?php calculCube(); ?>
2 Il

3 Un

susait de faire 4 4 4. mot connatre !

81

CHAPITRE 8. LES FONCTIONS La fonction calculCube est une fonction imaginaire : elle nexiste pas4 . Par consquent, nessayez pas dexcuter ce code PHP chez vous car il ne fonctionnera pas. Lisez simplement pour bien comprendre le fonctionnement, vous aurez ensuite loccasion de pratiquer plus loin dans ce chapitre. Comme vous le voyez, jai simplement crit le nom de la fonction, suivi de parenthses vides, puis de linvitable point-virgule. En faisant cela, jappelle la fonction calculCube mais je ne lui envoie aucune information, aucun paramtre. Certaines fonctions peuvent fonctionner sans paramtres, mais elles sont assez rares. Dans le cas de calculCube, a na pas de sens de lappeler sans lui donner la longueur de larte du cube pour faire le calcul ! Si on veut lui envoyer un paramtre (un nombre, une chane de caractres, un boolen...), il faut lcrire entre les parenthses :
<?php calculCube(4); ?>

Ainsi, calculCube saura quelle doit travailler avec le nombre 4. Souvent, les fonctions acceptent plusieurs paramtres. Vous devez dans ce cas les sparer par des virgules :
<?php fonctionImaginaire(17, Vert, true, 41.7); ?>

Cette fonction recevra quatre paramtres : 17, le texte Vert , le boolen vrai et le nombre 41,7. Rcuprer la valeur de retour de la fonction Maintenant que nous savons appeler une fonction et mme lui envoyer plusieurs paramtres, il faut rcuprer ce quelle nous retourne si toutefois elle retourne quelque chose. Il y a en eet deux types de fonctions : celles qui ne retournent aucune valeur5 ; celles qui retournent une valeur. Si la fonction ne retourne aucune valeur, il ny a rien de plus faire que dans les codes prcdents. La fonction est appele, fait son travail, et on ne lui demande rien de plus. En revanche, si la fonction retourne une valeur (comme a devrait tre le cas pour calculCube), on la rcupre dans une variable, comme ceci :
4 5 a

moins quon la cre nous-mmes. ne les empche pas deectuer des actions.

82

LES FONCTIONS PRTES LEMPLOI DE PHP


<?php $volume = calculCube(4); ?>

Sur une ligne comme celle-ci, il se passe en fait les deux choses suivantes (dans lordre, et de droite gauche) : 1. la fonction calculCube est appele avec le paramtre 4 ; 2. le rsultat renvoy par la fonction (lorsquelle a termin) est stock dans la variable $volume. La variable $volume aura donc pour valeur 64 aprs lexcution de cette ligne de code ! Bon savoir : comme on la vu, il est possible denvoyer en entre plusieurs paramtres une fonction ; en revanche cette dernire ne peut retourner quune seule valeur. Il existe un moyen de contourner cette limitation en combinant des variables au sein dun tableau de variables (appel array) dont on parlera dans le prochain chapitre.

Les fonctions prtes lemploi de PHP


PHP propose des centaines et des centaines de fonctions prtes lemploi. Sur le site ociel, la documentation PHP les rpertorie toutes, classes par catgories. Code web : 891142 Ces fonctions sont trs pratiques et trs nombreuses. En fait, cest en partie l que rside la force de PHP : ses fonctions sont vraiment excellentes car elles couvrent la quasi-totalit de nos besoins. Jai en fait remarqu que, pratiquement chaque fois que je mapprtais crire une fonction, celle-ci existait dj. Voici un petit aperu des fonctions qui existent pour vous mettre leau la bouche : Une fonction qui permet de rechercher et de remplacer des mots dans une variable. Une fonction qui envoie un chier sur un serveur. Une fonction qui permet de crer des images miniatures (aussi appeles thumbnails). Une fonction qui envoie un mail avec PHP6 . Une fonction qui permet de modier des images, y crire du texte, tracer des lignes, des rectangles, etc. Une fonction qui crypte des mots de passe. Une fonction qui renvoie lheure, la date. . . Etc. Dans la plupart des cas, il faudra indiquer des paramtres la fonction pour quelle sache sur quoi travailler.
6 Trs

pratique pour faire une newsletter !

83

CHAPITRE 8. LES FONCTIONS Nous allons ici dcouvrir rapidement quelques fonctions pour vous habituer les utiliser. Nous ne pourrons jamais toutes les passer en revue7 mais avec lexprience de ces premires fonctions et la documentation de PHP, vous naurez aucun mal aller plus loin tout seuls. Nous allons voir quelques fonctions qui eectuent des modications sur des chanes de caractres et une qui permet de rcuprer la date. Ce sont seulement des exemples destins vous habituer utiliser des fonctions.

Traitement des chanes de caractres


De nombreuses fonctions permettent de manipuler le texte. En voici quelques-unes qui vont vous montrer leur intrt. strlen : longueur dune chane Cette fonction retourne la longueur dune chane de caractres, cest--dire le nombre de lettres et de chires dont elle est constitue (espaces compris). Exemple :
<?php $phrase = Bonjour les Zros ! Je suis une phrase !; $longueur = strlen($phrase); echo La phrase ci-dessous comporte . $longueur . caractres :<br /> . $phr ase; ?>

Code web : 677760 Mez-vous, il se peut que le nombre de caractres soit parfois inexact. Ceci est d un bug de PHP dans la gestion des encodages de caractres. Ce sera corrig dans les prochaines versions du langage.

str_replace : rechercher et remplacer str_replace remplace une chane de caractres par une autre. Exemple :
<?php $ma_variable = str_replace(b, p, bim bam boum); echo $ma_variable; ?>
7 Jai

dit quil y en avait des centaines et des centaines !

84

LES FONCTIONS PRTES LEMPLOI DE PHP Code web : 965520 On a besoin dindiquer trois paramtres : 1. la chane quon recherche (ici, les b 8 ) ; 2. la chane quon veut mettre la place (ici, on met des p la place des b ) ; 3. la chane dans laquelle on doit faire la recherche. Ce qui nous donne pim pam poum . :D str_shuffle : mlanger les lettres Pour vous amuser mlanger alatoirement les caractres de votre chane !
<?php $chaine = Cette chane va tre mlange !; $chaine = str_shuffle($chaine); echo $chaine; ?>

Code web : 629635 strtolower : crire en minuscules strtolower met tous les caractres dune chane en minuscules.
<?php $chaine = COMMENT CA JE CRIE TROP FORT ???; $chaine = strtolower($chaine); echo $chaine; ?>

Code web : 835679 noter quil existe strtoupper qui fait la mme chose en sens inverse : minuscules majuscules.

Rcuprer la date
Nous allons dcouvrir la fonction qui renvoie lheure et la date. Il sagit de date9 . Cette fonction peut donner beaucoup dinformations. Voici les principaux paramtres connatre :
8 On 9 Un

aurait pu rechercher un mot aussi. nom facile retenir, avouez !

85

CHAPITRE 8. LES FONCTIONS Paramtre H i d m Y Description Heure Minute Jour Mois Anne

Attention ! Respectez les majuscules/minuscules, cest important !

Si vous voulez acher lanne, il faut donc envoyer le paramtre Y la fonction :


<?php $annee = date(Y); echo $annee; ?>

On peut bien entendu faire mieux, voici la date complte et lheure :


<?php // Enregistrons les informations de date dans des variables $jour = date(d); $mois = date(m); $annee = date(Y); $heure = date(H); $minute = date(i); // Maintenant on peut afficher ce quon a recueilli echo Bonjour ! Nous sommes le . $jour . / . $mois . / . $annee . et il e st . $heure. h . $minute.; ?>

Code web : 411576 Et voil le travail ! On a pu acher la date et lheure en un clin dil. Normalement, quand vous avez test le code prcdent, vous avez d avoir la date et lheure exactes10 .
10 Si lheure ntait pas bonne, sachez que cest le serveur qui donne lheure, et le serveur du Site du Zro tant situ Paris, vous comprendrez le dcalage horaire si vous habitez dans un autre pays. Nhsitez donc pas essayer dexcuter ce code source chez vous.

86

CRER SES PROPRES FONCTIONS

Crer ses propres fonctions


Bien que PHP propose des centaines et des centaines de fonctions11 , parfois il ny aura pas ce que vous cherchez et il faudra crire vous-mmes la fonction. Cest une faon pratique dtendre les possibilits oertes par PHP. Quand crire une fonction ? En gnral, si vous eectuez des oprations un peu complexes que vous pensez avoir besoin de refaire rgulirement, il est conseill de crer une fonction. Nous allons dcouvrir la cration de fonctions travers deux exemples : lachage dun message de bienvenue en fonction du nom ; le calcul du volume dun cne.

Premier exemple : dis bonjour au Monsieur


Cest peut-tre un peu fatigant de dire bonjour chacun de ses visiteurs, non ? a serait bien de le faire automatiquement. . . Les fonctions sont justement l pour nous aider ! Regardez le code ci-dessous :
<?php $nom = Sandra; echo Bonjour, . $nom . !<br />; $nom = Patrick; echo Bonjour, . $nom . !<br />; $nom = Claude; echo Bonjour, . $nom . !<br />; ?>

Vous voyez, cest un peu fatigant la longue. . . Alors nous allons crer une fonction qui le fait notre place !
<?php function DireBonjour($nom) { echo Bonjour . $nom . !<br />; } DireBonjour(Marie); DireBonjour(Patrice); DireBonjour(Edouard); DireBonjour(Pascale); DireBonjour(Franois); DireBonjour(Benot);
11 Jinsiste,

mais il faut dire quil y en a tellement !

87

CHAPITRE 8. LES FONCTIONS


DireBonjour(Pre Nol); ?>

Code web : 939284 Alors quy a-t-il de dirent ici ? Cest surtout en haut quil y a une nouveaut : cest la fonction. En fait, les lignes en haut permettent de dnir la fonction (son nom, ce quelle est capable de faire, etc.). Elles ne font rien de particulier, mais elles disent PHP : Une fonction DireBonjour existe maintenant . Pour crer une fonction, vous devez taper function12 . Ensuite, donnez-lui un nom. Par exemple, celle-ci sappelle DireBonjour. Ce qui est plus particulier aprs, cest ce quon met entre parenthses : il y a une variable. Cest le paramtre dont a besoin la fonction pour travailler, an quelle sache qui elle doit dire bonjour dans notre cas. Notre fonction doit forcment tre appele avec un paramtre (le nom) sans quoi elle ne pourra pas travailler. Vous avez peut-tre remarqu que cette ligne est la seule ne pas se terminer par un point-virgule. Cest normal, il ne sagit pas dune instruction mais juste dune carte didentit de la fonction (son nom, ses paramtres. . .). Ensuite, vous reprez des accolades. Elles permettent de marquer les limites de la fonction. Cette dernire commence ds quil y a un { et se termine lorsquil y a un }. Entre les deux, il y a son contenu. Ici, la fonction contient une seule instruction (echo). Jai fait simple pour commencer mais vous verrez quen pratique, une fonction contient plus dinstructions que cela. Voil, la fonction est cre, vous navez plus besoin dy toucher. Aprs, pour faire appel elle, il sut dindiquer son nom, et de prciser ses paramtres entre parenthses. Enn, il ne faut pas oublier le fameux point-virgule ( ; ) car il sagit dune instruction. Par exemple :
<?php DireBonjour(Marie); ?>

vous dessayer ! Crez une page avec cette fonction et dites bonjour qui vous voulez, vous verrez : a marche13 ! Un conseil pour que vous vous entraniez sur les fonctions : basez-vous sur mes exemples et essayez de les retoucher petit petit pour voir ce que a donne. Il peut y avoir des fonctions trs simples comme des fonctions trs compliques, alors allez-y prudemment.
12 En

13 Encore

franais, a veut dire fonction . heureux !

88

CRER SES PROPRES FONCTIONS

Deuxime exemple : calculer le volume dun cne


Allez, on passe la vitesse suprieure. La fonction DireBonjour que lon a cre ne renvoyait aucune valeur, elle se contentait deectuer des actions14 . Maintenant, nous allons crer une fonction qui renvoie une valeur. Ici notre fonction va servir faire un calcul : le calcul du volume dun cne. Le principe est le suivant : vous donnez la fonction le rayon et la hauteur du cne, elle travaille et vous renvoie le volume que vous cherchiez. Bon : tout dabord, il faut connatre la formule pour calculer le volume dun cne. Vous avez oubli comment on fait ? Il faut connatre le rayon de la base et la hauteur. La 1 formule utiliser pour trouver le volume est : rayon 2 hauteur 3 . Voyez la gure 8.3.

Fig. 8.3 Reprsentation dun cne Si vous avez bien suivi dans le chapitre prcdent, vous tes normalement capables de comprendre le code ci-dessous. Seul problme si on a le faire plusieurs fois : cest vite rptitif. Regardez :
<?php // Calcul du volume dun cne de rayon 5 et de hauteur 2 $volume = 5 * 5 * 3.14 * 2 * (1/3); echo Le volume du cne de rayon 5 et de hauteur 2 est : . $volume . cm<sup> 3</sup><br />; // Calcul du volume dun cne de rayon 3 et de hauteur 4 $volume = 3 * 3 * 3.14 * 4 * (1/3); echo Le volume du cne de rayon 3 et de hauteur 4 est : . $volume . cm<sup> 3</sup><br />; ?>

Nous allons donc crer une fonction VolumeCone, qui va calculer le volume du cne en fonction du rayon et de la hauteur. Cette fonction ne va rien acher, on veut juste quelle nous renvoie le volume quon cherche.
14 Acher

un texte, dans le cas prsent.

89

CHAPITRE 8. LES FONCTIONS Regardez attentivement le code ci-dessous, il prsente deux nouveauts :
<?php // Ci-dessous, la fonction qui calcule le volume du cne function VolumeCone($rayon, $hauteur) { $volume = $rayon * $rayon * 3.14 * $hauteur * (1/3); // calcul du volume return $volume; // indique la valeur renvoyer, ici le volume } $volume = VolumeCone(3, 1); echo Le volume d\un cne de rayon 3 et de hauteur 1 est de . $volume; ?>

Code web : 727395 Regardez bien la fonction, il y a linstruction : return $volume ;. Cette instruction indique ce que doit renvoyer la fonction. Ici, elle renvoie le volume. Si vous aviez tap return 15, a aurait chaque fois ach un volume de 1515 . La fonction renvoie une valeur, que lon doit donc rcuprer dans une variable :
<?php $volume = VolumeCone(3, 1); ?>

Ensuite, on peut acher ce que contient la variable laide dune instruction echo. Les possibilits de cration de fonctions sont quasi-innies. Il est clair que normalement, vous nallez pas avoir crer de fonction qui calcule le volume dun cne16 . En fait, tout ce que je vous demande ici, cest de comprendre quune fonction peut se rvler trs pratique et vous faire gagner du temps.

En rsum
Les fonctions sont des blocs de code qui excutent des instructions en fonction de certains paramtres. Les fonctions ont gnralement une entre et une sortie. Par exemple, si on donne la valeur 4 la fonction de calcul du cube, celle-ci renvoie 64 en sortie. PHP propose des centaines et des centaines de fonctions prtes lemploi pour tous types de tches : envoyer un e-mail, rcuprer lheure, crypter des mots de passe, etc. Si PHP ne propose pas la fonction dont on a besoin, il est possible de la crer avec le mot-cl function.

15 Cest 16 Qui

un peu idiot jen conviens, mais faites lessai ! est assez fou pour faire a ?

90

Chapitre

9
Dicult :

Les tableaux

ous abordons ici un aspect trs important du PHP : les arrays. Vous allez voir quil sagit de variables composes , que lon peut imaginer sous la forme de tableaux.

On peut faire normment de choses avec les arrays et leur utilisation nest pas toujours trs facile. Cependant, ils vont trs rapidement nous devenir indispensables et vous devez bien comprendre leur fonctionnement. Si vous y parvenez, nous aurons fait le tour des bases du PHP et vous serez n prts pour la suite, qui sannonce concrte et passionnante.

91

CHAPITRE 9. LES TABLEAUX

Les deux types de tableaux


Un tableau (aussi appel array) est une variable. Mais une variable un peu spciale. Reprenons. Jusquici vous avez travaill avec des variables toutes simples : elles ont un nom et une valeur. Par exemple :
<?php $prenom = Nicole; echo Bonjour . $prenom; // Cela affichera : Bonjour Nicole ?>

Ce qui peut se matrialiser sous la forme : Nom $prenom Valeur Nicole

Ici, nous allons voir quil est possible denregistrer de nombreuses informations dans une seule variable grce aux tableaux. On en distingue deux types : les tableaux numrots ; les tableaux associatifs.

Les tableaux numrots


Ces tableaux sont trs simples imaginer. Regardez par exemple celui-ci, contenu de la variable $prenoms : Cl 0 1 2 3 4 ... Valeur Franois Michel Nicole Vronique Benot ...

$prenoms est un array : cest ce quon appelle une variable tableau . Elle na pas quune valeur, mais plusieurs1 . Dans un array, les valeurs sont ranges dans des cases direntes. Ici, nous travaillons sur un array numrot, cest--dire que chaque case est identie par un numro. Ce numro est appel cl. Attention ! Un array numrot commence toujours la case n0 ! Ne loubliez jamais, ou vous risquez de faire des erreurs par la suite. . .
1 Vous

pouvez en mettre autant que vous voulez.

92

LES DEUX TYPES DE TABLEAUX Construire un tableau numrot Pour crer un tableau numrot en PHP, on utilise gnralement la fonction array. Cet exemple vous montre comment crer larray $prenoms :
<?php // La fonction array permet de crer un array $prenoms = array (Franois, Michel, Nicole, Vronique, Benot); ?>

Lordre a beaucoup dimportance. Le premier lment ( Franois ) aura le n0, ensuite Michel le n1, etc. Vous pouvez aussi crer manuellement le tableau case par case :
<?php $prenoms[0] = Franois; $prenoms[1] = Michel; $prenoms[2] = Nicole; ?>

Si vous ne voulez pas avoir crire vous-mmes le numro de la case que vous crez, vous pouvez laisser PHP le slectionner automatiquement en laissant les crochets vides :
<?php $prenoms[] = Franois; // Crera $prenoms[0] $prenoms[] = Michel; // Crera $prenoms[1] $prenoms[] = Nicole; // Crera $prenoms[2] ?>

Acher un tableau numrot Pour acher un lment, il faut donner sa position entre crochets aprs $prenoms. Cela revient dire PHP : Ache-moi le contenu de la case n1 de $prenoms. Pour faire cela en PHP, il faut crire le nom de la variable, suivi du numro entre crochets. Pour acher Michel , on doit donc crire :
<?php echo $prenoms[1]; ?>

Cest tout bte du moment que vous noubliez pas que Michel est en seconde position et donc quil a le numro 12 .
2 tant

donn quon commence compter partir de 0.

93

CHAPITRE 9. LES TABLEAUX Si vous oubliez de mettre les crochets, a ne marchera pas (a achera juste Array . . .). Ds que vous travaillez sur des arrays, vous tes obligs dutiliser les crochets pour indiquer dans quelle case on doit aller chercher linformation, sinon PHP ne sait pas quoi rcuprer.

Les tableaux associatifs


Les tableaux associatifs fonctionnent sur le mme principe, sauf quau lieu de numroter les cases, on va les tiqueter en leur donnant chacune un nom dirent. Par exemple, supposons que je veuille, dans un seul array, enregistrer les coordonnes de quelquun (nom, prnom, adresse, ville, etc.). Si larray est numrot, comment savoir que le n0 est le nom, le n1 le prnom, le n2 ladresse. . . ? Cest l que les tableaux associatifs deviennent utiles. Construire un tableau associatif Pour en crer un, on utilisera la fonction array comme tout lheure, mais on va mettre ltiquette devant chaque information :
<?php // On cre notre array $coordonnees $coordonnees = array ( prenom => Franois, nom => Dupont, adresse => 3 Rue du Paradis, ville => Marseille); ?>

Note importante : il ny a ici quune seule instruction (un seul point-virgule). Jaurais pu tout mettre sur la mme ligne, mais rien ne mempche de sparer a sur plusieurs lignes pour que ce soit plus facile lire. Vous remarquez quon crit une che (=>) pour dire associ . Par exemple, on dit ville associe Marseille . Nous avons cr un tableau qui ressemble la structure suivante : Cl prenom nom adresse ville Valeur Franois Dupont 3 Rue du Paradis Marseille

Il est aussi possible de crer le tableau case par case, comme ceci : 94

PARCOURIR UN TABLEAU
<?php $coordonnees[prenom] = Franois; $coordonnees[nom] = Dupont; $coordonnees[adresse] = 3 Rue du Paradis; $coordonnees[ville] = Marseille; ?>

Acher un tableau associatif Pour acher un lment, il sut dindiquer le nom de cet lment entre crochets, ainsi quentre guillemets ou apostrophes puisque ltiquette du tableau associatif est un texte. Par exemple, pour extraire la ville, on devra taper :
<?php echo $coordonnees[ville]; ?>

Ce code ache : Marseille . Quand utiliser un array numrot et quand utiliser un array associatif ?

Comme vous lavez vu dans mes exemples, ils ne servent pas stocker la mme chose. . . Les arrays numrots permettent de stocker une srie dlments du mme type, comme des prnoms. Chaque lment du tableau contiendra alors un prnom. Les arrays associatifs permettent de dcouper une donne en plusieurs sous-lments. Par exemple, une adresse peut tre dcoupe en nom, prnom, nom de rue, ville. . .

Parcourir un tableau
Lorsquun tableau a t cr, on a souvent besoin de le parcourir pour savoir ce quil contient. Nous allons voir trois moyens dexplorer un array : la boucle for ; la boucle foreach ; la fonction print_r (utilise principalement pour le dbogage).

La boucle for
Il est trs simple de parcourir un tableau numrot avec une boucle for. En eet, puisquil est numrot partir de 0, on peut faire une boucle for qui incrmente un compteur partir de 0 : 95

CHAPITRE 9. LES TABLEAUX


<?php // On cre notre array $prenoms $prenoms = array (Franois, Michel, Nicole, Vronique, Benot); // Puis on fait une boucle pour tout afficher : for ($numero = 0; $numero < 5; $numero++) { echo $prenoms[$numero] . <br />; // affichera $prenoms[0], $prenoms[1] etc. } ?>

Code web : 355157 Quand on crit $prenoms[$numero], la variable $numero est dabord remplace par sa valeur. Par exemple, si $numero vaut 2, alors cela signie quon cherche obtenir ce que contient $prenoms[2], cest--dire. . . Nicole. Bravo, vous avez compris. :D

La boucle foreach
La boucle for a beau fonctionner, on peut utiliser un autre type de boucle plus adapt aux tableaux quon na pas encore vu jusquici : foreach. Cest une sorte de boucle for spcialise dans les tableaux. foreach va passer en revue chaque ligne du tableau, et lors de chaque passage, elle va mettre la valeur de cette ligne dans une variable temporaire (par exemple $element). Je parle chinois ? Regardez plutt :
<?php $prenoms = array (Franois, Michel, Nicole, Vronique, Benot); foreach($prenoms as $element) { echo $element . <br />; // affichera $prenoms[0], $prenoms[1] etc. } ?>

Code web : 843658 Cest le mme code que tout lheure mais cette fois bas sur une boucle foreach. chaque tour de boucle, la valeur de llment suivant est mise dans la variable $element. On peut donc utiliser $element uniquement lintrieur de la boucle an dacher llment en cours. Lavantage de foreach est quil permet aussi de parcourir les tableaux associatifs.
<?php $coordonnees = array ( prenom => Franois, nom => Dupont,

96

PARCOURIR UN TABLEAU
adresse => 3 Rue du Paradis, ville => Marseille); foreach($coordonnees as $element) { echo $element . <br />; } ?>

Code web : 723139 foreach va mettre tour tour dans la variable $element le prnom, le nom, ladresse et la ville contenus dans larray $coordonnees. On met donc entre parenthses : 1. dabord le nom de larray (ici $coordonnees) ; 2. ensuite le mot-cl as (qui signie quelque chose comme en tant que ) ; 3. enn, le nom dune variable que vous choisissez et qui va contenir tour tour chacun des lments de larray (ici $element). Entre les accolades, on nutilise donc que la variable $element. La boucle sarrte lorsquon a parcouru tous les lments de larray. Toutefois, avec cet exemple, on ne rcupre que la valeur. Or, on peut aussi rcuprer la cl de llment. On doit dans ce cas crire foreach comme ceci :
<?php foreach($coordonnees as $cle => $element) ?>

chaque tour de boucle, on disposera non pas dune, mais de deux variables : $cle, qui contiendra la cl de llment en cours danalyse ( prenom , nom , etc.) ; $element, qui contiendra la valeur de llment en cours ( Franois , Dupont , etc.). Testons le fonctionnement avec un exemple :
<?php $coordonnees = array ( prenom => Franois, nom => Dupont, adresse => 3 Rue du Paradis, ville => Marseille); foreach($coordonnees as $cle => $element) { echo [ . $cle . ] vaut . $element . <br />; } ?>

97

CHAPITRE 9. LES TABLEAUX Code web : 406399 Avec cette faon de procder, vous avez maintenant dans la boucle la cl ET la valeur. Et foreach, croyez-moi, cest une boucle vraiment pratique ! On sen sert rgulirement !

Acher rapidement un array avec print_r


Parfois, en codant votre site en PHP, vous aurez sous les bras un array et vous voudrez savoir ce quil contient, juste pour votre information. Vous pourriez utiliser une boucle for ou, mieux, une boucle foreach. Mais si vous navez pas besoin dune mise en forme spciale et que vous voulez juste savoir ce que contient larray, vous pouvez faire appel la fonction print_r. Cest une sorte de echo spcialis dans les arrays. Cette commande a toutefois un dfaut : elle ne renvoie pas de code HTML comme <br /> pour les retours la ligne. Pour bien les voir, il faut donc utiliser la balise HTML <pre> qui nous permet davoir un achage plus correct.
<?php $coordonnees = array ( prenom => Franois, nom => Dupont, adresse => 3 Rue du Paradis, ville => Marseille); echo <pre>; print_r($coordonnees); echo </pre>; ?>

Code web : 812209 Voil, cest facile utiliser du moment quon noublie pas la balise <pre> pour avoir un achage correct. Bien entendu, vous nacherez jamais des choses comme a vos visiteurs. On peut en revanche sen servir pour le dbogage, pendant la cration du site, an de voir rapidement ce que contient larray.

Rechercher dans un tableau


Nous allons maintenant faire des recherches dans des arrays. Cela vous sera parfois trs utile pour savoir si votre array contient ou non certaines informations. Nous allons voir trois types de recherches, bases sur des fonctions PHP : array_key_exists : pour vrier si une cl existe dans larray ; in_array : pour vrier si une valeur existe dans larray ; array_search : pour rcuprer la cl dune valeur dans larray. 98

RECHERCHER DANS UN TABLEAU

Vrier si une cl existe dans larray : array_key_exists


Voici notre problme : on a un array, mais on ne sait pas si la cl quon cherche sy trouve. Pour vrier a, on va utiliser la fonction array_key_exists qui va parcourir le tableau pour nous et nous dire sil contient cette cl. On doit dabord lui donner le nom de la cl rechercher, puis le nom de larray dans lequel on fait la recherche :
<?php array_key_exists(cle, $array); ?>

La fonction renvoie un boolen, cest--dire true (vrai) si la cl est dans larray, et false (faux) si la cl ne sy trouve pas. a nous permet de faire un test facilement avec un if :
<?php $coordonnees = array ( prenom => Franois, nom => Dupont, adresse => 3 Rue du Paradis, ville => Marseille); if (array_key_exists(nom, $coordonnees)) { echo La cl "nom" se trouve dans les coordonnes !; } if (array_key_exists(pays, $coordonnees)) { echo La cl "pays" se trouve dans les coordonnes !; } ?>

Code web : 766112 On ne trouvera que nom , et pas pays (logique). Seule la premire condition sera donc excute.

Vrier si une valeur existe dans larray : in_array


Le principe est le mme que array_key_exists. . . mais cette fois on recherche dans les valeurs. in_array renvoie true si la valeur se trouve dans larray, false si elle ne sy trouve pas. Pour changer un peu de notre array $coordonnees, je vais en crer un nouveau (numrot) compos de fruits. ;-) 99

CHAPITRE 9. LES TABLEAUX


<?php $fruits = array (Banane, Pomme, Poire, Cerise, Fraise, Framboise); if (in_array(Myrtille, $fruits)) { echo La valeur "Myrtille" se trouve dans les fruits !; } if (in_array(Cerise, $fruits)) { echo La valeur "Cerise" se trouve dans les fruits !; } ?>

Code web : 595747 On ne voit que le message pour la cerise, tout simplement parce que in_array a renvoy true pour Cerise et false pour Myrtille .

Rcuprer la cl dune valeur dans larray : array_search


array_search fonctionne comme in_array : il travaille sur les valeurs dun array. Voici ce que renvoie la fonction : si elle a trouv la valeur, array_search renvoie la cl correspondante3 ; si elle na pas trouv la valeur, array_search renvoie false. On reprend larray numrot avec les fruits :
<?php $fruits = array (Banane, Pomme, Poire, Cerise, Fraise, Framboise); $position = array_search(Fraise, $fruits); echo "Fraise" se trouve en position . $position . <br />; $position = array_search(Banane, $fruits); echo "Banane" se trouve en position . $position; ?>

Code web : 981062 Je sais que je me rpte, mais noubliez pas quun array numrot commence 0 ! Cela explique donc pourquoi on nous rpond que Banane se trouve en position 0. Voil donc les fonctions quil fallait connatre pour faire une recherche dans un array. Il y en a dautres mais vous connaissez maintenant les principales.
3 Cest--dire

le numro si cest un array numrot, ou le nom de la cl si cest un array associatif.

100

RECHERCHER DANS UN TABLEAU

En rsum
Les tableaux (ou arrays) sont des variables reprsentes sous forme de tableau. Elles peuvent donc stocker de grandes quantits dinformations. Chaque ligne dun tableau possde une cl (qui permet de lidentier) et une valeur. Il existe deux types de tableaux : les tableaux numrots : chaque ligne est identie par une cl numrote. La numrotation commence partir de 0 ; les tableaux associatifs : chaque ligne est identie par une courte chane de texte. Pour parcourir un tableau, on peut utiliser la boucle for que lon connat dj, mais aussi la boucle foreach qui est ddie aux tableaux. Il existe de nombreuses fonctions permettant de travailler sur des tableaux et notamment deectuer des recherches.

101

CHAPITRE 9. LES TABLEAUX

102

Deuxime partie

Transmettre des donnes de page en page

103

Chapitre

10
Dicult :

Transmettre des donnes avec lURL

avez-vous ce quest une URL ? Cela signie Uniform Resource Locator, et cela sert reprsenter une adresse sur le web. Toutes les adresses que vous voyez en haut de votre navigateur, comme http://www.siteduzero.com, sont des URL.

Je me doute bien que vous ne passez pas votre temps les regarder (il y a bien mieux faire !), mais je suis sr que vous avez dj t surpris de voir que certaines URL sont assez longues et comportent parfois des caractres un peu curieux. Par exemple, aprs avoir fait une recherche sur Google, la barre dadresse contient une URL longue qui ressemble ceci : http://www.google.fr/search ?rlz=1C1GFR343&q=siteduzero Dans cet exemple, les informations aprs le point dinterrogation sont des donnes que lon fait transiter dune page une autre. Nous allons dcouvrir dans ce chapitre comment cela fonctionne.

105

CHAPITRE 10. TRANSMETTRE DES DONNES AVEC LURL

Envoyer des paramtres dans lURL


En introduction, je vous disais que lURL permettait de transmettre des informations. Comment est-ce que a fonctionne exactement ?

Former une URL pour envoyer des paramtres


Imaginons que votre site sappelle monsite.com et que vous avez une page PHP intitule bonjour.php. Pour accder cette page, vous devez aller lURL suivante : http://www.monsite.com/bonjour.php Jusque-l, rien de bien nouveau. Ce que je vous propose dapprendre faire, cest denvoyer des informations la page bonjour.php. Pour cela, on va ajouter des informations la n de lURL, comme ceci : http://www.monsite.com/bonjour.php ?nom=Dupont&prenom=Jean Ce que vous voyez aprs le point dinterrogation, ce sont des paramtres que lon envoie la page PHP. Celle-ci peut rcuprer ces informations dans des variables. Voyez sur la gure 10.1 comment on peut dcouper cette URL.

Fig. 10.1 Structure dune URL Le point dinterrogation spare le nom de la page PHP des paramtres. Ensuite, ces derniers senchanent selon la forme nom=valeur et sont spars les uns des autres par le symbole &. On peut crire autant de paramtres que lon veut ?

En thorie, oui. Il sut de les sparer par des & comme je lai fait. On peut donc voir une URL de la forme : page.php ?param1=valeur1&param2=valeur2&param3=valeur3&param4=valeur4... La seule limite est la longueur de lURL. En gnral il nest pas conseill de dpasser les 256 caractres, mais les navigateurs arrivent parfois grer des URL plus longues. Quoi quil en soit, vous aurez compris quon ne peut pas non plus crire un roman dans lURL. 106

RCUPRER LES PARAMTRES EN PHP

Crer un lien avec des paramtres


Maintenant que nous savons cela, nous pouvons crer des liens en HTML qui transmettent des paramtres dune page vers une autre. Imaginons que vous avez deux chiers sur votre site : index.php (laccueil) ; bonjour.php. Nous voulons faire un lien de index.php qui mne bonjour.php et qui lui transmet des informations dans lURL, comme le schmatise la gure 10.2.

Fig. 10.2 Lien entre index.php et bonjour.php Pour cela, ouvrez index.php (puisque cest lui qui contiendra le lien) et insrez-y par exemple le code suivant :
<a href="bonjour.php?nom=Dupont&amp;prenom=Jean">Dis-moi bonjour !</a>

Comme vous le voyez, le & dans le code a t remplac par &amp ; dans le lien. a na rien voir avec PHP : simplement, en HTML, on demande ce que les & soient crits &amp ; dans le code source. Si vous ne le faites pas, le code ne passera pas la validation W3C. Ce lien appelle la page bonjour.php et lui envoie deux paramtres : nom : Dupont ; prenom : Jean. Vous avez srement devin ce quon essaie de faire ici : on appelle une page bonjour.php qui va dire Bonjour la personne dont le nom et le prnom ont t envoys en paramtres. Comment faire dans la page bonjour.php pour rcuprer ces informations ? Cest ce que nous allons voir maintenant. ;-)

Rcuprer les paramtres en PHP


Nous savons maintenant comment former des liens pour envoyer des paramtres vers une autre page. Nous avons pour cela ajout des paramtres la n de lURL. Intressons-nous maintenant la page qui rceptionne les paramtres. Dans notre exemple, il sagit de la page bonjour.php. Celle-ci va automatiquement crer un array 107

CHAPITRE 10. TRANSMETTRE DES DONNES AVEC LURL au nom un peu spcial : $_GET. Il sagit dun array associatif1 dont les cls correspondent aux noms des paramtres envoys en URL. Reprenons notre exemple pour mieux voir comment cela fonctionne. Nous avons fait un lien vers bonjour.php ?nom=Dupont&prenom=Jean, cela signie que nous aurons accs aux variables suivantes : Nom $_GET[nom] $_GET[prenom] Valeur Dupont Jean

On peut donc rcuprer ces informations, les traiter, les acher, bref faire ce que lon veut avec. Pour commencer, essayons tout simplement de les acher. Crez un nouveau chier PHP, appellez-le bonjour.php et placez-y le code suivant2 :
<p>Bonjour <?php echo $_GET[prenom]; ?> !</p>

Ici, nous achons le prnom qui a t pass dans lURL. Bien entendu, nous avons aussi accs au nom. Nous pouvons acher le nom et le prnom sans problme :
<p>Bonjour <?php echo $_GET[prenom] . . $_GET[nom]; ?> !</p>

Comme vous le voyez, jen ai prot pour faire une petite concatnation, comme nous avons appris le faire. Ce code que vous voyez l nest pas bien complexe : nous achons le contenu de deux cases de larray $_GET. Cest vraiment trs simple et il ny a rien de nouveau. Tout ce quil faut savoir, cest quon peut retrouver les paramtres envoys dans lURL grce un array nomm $_GET. Si vous voulez tester le rsultat, je vous propose dessayer ce que a donne directement sur le Site du Zro. Le code web suivant ouvre la page index.php. Code web : 158232 Vous devriez aussi faire le test chez vous pour vous assurer que vous comprenez bien le fonctionnement ! Si besoin est, vous pouvez tlcharger mes chiers dexemple index.php et bonjour.php : Code web : 639829

Ne faites jamais conance aux donnes reues !


Il est impossible de terminer ce chapitre sans que je vous mette en garde contre les dangers qui guettent les apprentis webmasters que vous tes. Nous allons en eet
vous souvenez ? Nous avons tudi cela il y a peu ! sr, pour une vraie page web il faudrait crire toutes les informations den-tte ncessaires en HTML : le doctype, la balise <head>, etc. Ici, pour faire simple, je ne mets pas tout ce code. La page ne sera pas trs belle (ni valide W3C, dailleurs) mais ce nest pas encore notre problme : pour linstant, nous faisons juste des tests.
2 Bien 1 Vous

108

NE FAITES JAMAIS CONFIANCE AUX DONNES REUES ! dcouvrir quil ne faut JAMAIS faire conance aux variables qui transitent de page en page, comme $_GET que nous tudions ici. Le but de cette section est, je lavoue, de vous faire peur, car trop peu de dveloppeurs PHP ont conscience des dangers et des failles de scurit quils peuvent rencontrer, ce qui risque pourtant de mettre en pril leur site web ! Oui je suis alarmiste, oui je veux que vous ayez un peu peur ! Mais rassurez-vous : je vais vous expliquer tout ce quil faut savoir pour que a se passe bien et que vous ne risquiez rien. ;-) Ce qui compte, cest que vous ayez conscience trs tt (ds maintenant) des problmes que vous pourrez rencontrer lorsque vous recevrez des paramtres de lutilisateur.

Tous les visiteurs peuvent traquer les URL


Si vous faites les tests des codes prcdents chez vous, vous devriez tomber sur une URL de la forme : http://localhost/tests/bonjour.php ?nom=Dupont&prenom=Jean On vous dit bien Bonjour Jean Dupont ! . Mais si vous tes un peu bricoleurs, vous pouvez vous amuser changer les paramtres directement dans la barre dadresse, comme dans la gure 10.3.

Fig. 10.3 On peut facilement modier les paramtres dans le navigateur Essayez par exemple de modier ladresse pour : http://localhost/tests/bonjour.php ?nom=Dupont&prenom=Marc Comme vous le voyez, a marche ! Nimporte qui peut facilement modier les URL et y mettre ce quil veut : il sut simplement de changer lURL dans la barre dadresse de votre navigateur. Et alors, quel est le problme ? Cest pas plus mal, si le visiteur veut adapter lURL pour quon lui dise bonjour avec son vrai nom et son vrai prnom ? Peut-tre, mais cela montre une chose : on ne peut pas avoir conance dans les donnes quon reoit. Nimporte quel visiteur peut les changer. Dans la page index.php jai fait un lien qui dit bonjour Jean Dupont, mais la page bonjour.php ne va pas forcment acher Bonjour Jean Dupont ! puisque nimporte quel visiteur peut samuser modier lURL. 109

CHAPITRE 10. TRANSMETTRE DES DONNES AVEC LURL Je vous propose de faire des modications encore plus vicieuses et de voir ce quon peut faire pour viter les problmes qui en dcoulent.

Tester la prsence dun paramtre


Allons plus loin. Quest-ce qui empche le visiteur de supprimer tous les paramtres de lURL ? Par exemple, il peut trs bien tenter daccder : http://localhost/tests/bonjour.php Que va acher la page bonjour.php ? Faites le test ! Elle va acher quelque chose comme : Bonjour Notice: Undefined index: prenom in C:\wamp\www \tests\bonjour.php on line 9 Notice: Undefined index: nom in C:\wamp\www \tests\bonjour.php on line 9 ! Que sest-il pass ? On a essay dacher la valeur de $_GET[prenom] et celle de $_GET[nom]. . . Mais comme on vient de les supprimer de lURL, ces variables nont pas t cres et donc elles nexistent pas ! PHP nous avertit quon essaie dutiliser des variables qui nexistent pas, do les Undefined index . Pour rsoudre ce problme, on peut faire appel une fonction un peu spciale : isset(). Cette fonction teste si une variable existe. Nous allons nous en servir pour acher un message spcique si le nom ou le prnom sont absents.
<?php if (isset($_GET[prenom]) AND isset($_GET[nom])) // On a le nom et le prnom { echo Bonjour . $_GET[prenom] . . $_GET[nom] . !; } else // Il manque des paramtres, on avertit le visiteur { echo Il faut renseigner un nom et un prnom !; } ?>

Que fait ce code ? Il teste si les variables $_GET[prenom] et $_GET[nom] existent. Si elles existent, on dit bonjour au visiteur. Sil nous manque une des variables (ou les deux), on ache un message derreur : Il faut renseigner un nom et un prnom ! . Essayez maintenant daccder la page bonjour.php sans les paramtres, vous allez voir quon gre bien le cas o le visiteur aurait retir les paramtres de lURL. Est-ce que cest vraiment la peine de grer ce cas ? Cest vrai quoi, moi je ne mamuse jamais modier mes URL et mes visiteurs non plus, je pense ! 110

NE FAITES JAMAIS CONFIANCE AUX DONNES REUES !

Oui, oui, trois fois oui : il faut que vous pensiez grer le cas o des paramtres que vous attendiez viendraient manquer. Vous vous souvenez de ce que je vous ai dit ? Il ne faut jamais faire conance lutilisateur. Tt ou tard vous tomberez sur un utilisateur malintentionn qui essaiera de traquer lURL pour mettre nimporte quoi dans les paramtres. Il faut que votre site soit prt grer le cas. Dans notre exemple, si on ne grait pas le cas, a ne faisait rien de bien grave3 . Mais lorsque votre site web deviendra plus complexe, cela pourrait avoir des consquences plus ennuyeuses. Un exemple ? Sur le Site du Zro lui-mme, nous avions une fois oubli de grer le cas o un paramtre viendrait manquer. Un utilisateur avait essay de lenlever pour voir : notre page PHP tait faite de telle sorte que si le paramtre manquait, a supprimait toutes les prfrences de tous les membres inscrits du site ! Vous nen tes pas encore l, mais je tiens vous sensibiliser aux problmes potentiels que cela peut provoquer. Soyez donc vigilants ds maintenant et ne supposez jamais que vous allez recevoir tous les paramtres que vous attendiez.

Contrler la valeur des paramtres


Allons plus loin dans notre tripatouillage vicieux de lURL. On va modier notre code source pour grer un nouveau paramtre : le nombre de fois que le message doit tre rpt. Les paramtres vont donc tre : bonjour.php ?nom=Dupont&prenom=Jean&repeter=8 Le paramtre repeter dnit le nombre de fois que lon dit bonjour sur la page. Sauriez-vous adapter notre code pour quil dise bonjour le nombre de fois indiqu ? Voici la solution que je vous propose :
<?php if (isset($_GET[prenom]) AND isset($_GET[nom]) AND isset($_GET[repeter])) { for ($i = 0 ; $i < $_GET[repeter] ; $i++) { echo Bonjour . $_GET[prenom] . . $_GET[nom] . ! <br />; } } else { echo Il faut renseigner un nom, un prnom et un nombre de rptitions !;
3 a

achait juste des messages derreur.

111

CHAPITRE 10. TRANSMETTRE DES DONNES AVEC LURL


} ?>

On teste si le paramtre repeter existe lui aussi (avec isset($_GET[repeter])). Si tous les paramtres sont bien l, on fait une boucle4 . La boucle incrmente une petite variable $i pour rpter le message de bienvenue le nombre de fois indiqu. Le rsultat ? Si on va sur. . . http://localhost/tests/bonjour.php ?nom=Dupont&prenom=Jean&repeter=8 . . . alors le message de bienvenue sachera huit fois : Bonjour Bonjour Bonjour Bonjour Bonjour Bonjour Bonjour Bonjour Jean Jean Jean Jean Jean Jean Jean Jean Dupont Dupont Dupont Dupont Dupont Dupont Dupont Dupont ! ! ! ! ! ! ! !

Nous avons amlior notre page pour quelle puisse dire bonjour plusieurs fois, et ce nombre de fois est personnalisable dans lURL. Trs bien. Maintenant, mettez-vous dans la peau du mchant. Soyez mchants. Soyez vicieux. Que pourrions-nous faire et que nous naurions pas prvu, juste en modiant lURL ? Jai une ide ! On peut mettre un nombre de rptitions trs grand, par exemple 1984986545665156. La page PHP va boucler un trs grand nombre de fois et votre PC ne pourra probablement pas supporter une telle charge de travail. http://localhost/tests/bonjour.php ?nom=Dupont&prenom=Jean&repeter=198498 6545665156 Si vous avez peur dessayer, je vous rassure : votre PC ne va pas prendre feu en faisant a. Par contre, il va se mettre consommer normment de mmoire pour stocker tous les messages bonjour et narrivera srement pas jusquau bout5 . Ou alors sil y arrive, votre page va tre extrmement surcharge de messages bonjour . Mon dieu, cest horrible ! Comment peut-on empcher a ?

En tant plus malins et surtout plus prvoyants. Voici ce quil faut anticiper. Le cas o le nombre quon vous envoie nest pas une valeur raisonnable. Par exemple on peut dire que si on dpasse 100 fois, cest trop, et il faut refuser dexcuter la page.
4 Jai 5 PHP

choisi de faire un for, mais on aurait aussi pu faire un while. sarrte au bout dun certain temps dexcution.

112

NE FAITES JAMAIS CONFIANCE AUX DONNES REUES ! De mme, que se passe-t-il si je demande de rpter 4 fois ? a ne devrait pas tre autoris. Il faut que le nombre soit au moins gal 1. Le cas o la valeur nest pas logique, o elle nest pas du tout ce quon attendait. Rien nempche le visiteur de remplacer la valeur du paramtre repeter par du texte ! Que se passe-t-il si on essaie daccder bonjour.php ?nom=Dupont&prenom=Jean&repeter=grenouille ? Cela ne devrait pas tre autoris. Le mot grenouille na pas de sens, on veut un nombre entier positif. Que se passe-t-il si on essaie daccder bonjour.php ?nom=Dupont&prenom=Jean&repeter=true ? Cela ne devrait pas tre autoris non plus, on attendait un nombre entier positif, pas un boolen. Pour rsoudre ces problmes, on doit : 1. vrier que repeter contient bien un nombre ; 2. vrier ensuite que ce nombre est compris dans un intervalle raisonnable (entre 1 et 100, par exemple). Pour vrier que repeter contient bien un nombre, une bonne solution pourrait tre de forcer la conversion de la variable en type entier (int). On peut utiliser pour cela ce quon appelle le transtypage, une notion quon na pas encore vue jusquici mais qui est trs simple comprendre. Regardez ce code :
<?php $_GET[repeter] = (int) $_GET[repeter]; ?>

Il faut lire cette instruction de droite gauche. Le (int) entre parenthses est comme un tuyau de conversion. Tout ce qui transite travers ressort forcment en une valeur de type int (entier). Voyez la gure 10.4 pour vous en convaincre.

Fig. 10.4 Transtypage Si la valeur est bien un entier (par exemple 14) alors elle nest pas modie. En revanche, si la variable contient autre chose quun entier (par exemple grenouille ), elle est transforme en entier. Ici, comme PHP ne peut pas associer de valeur grenouille, il lui donne 0. 113

CHAPITRE 10. TRANSMETTRE DES DONNES AVEC LURL Aprs avoir excut cette instruction, la variable $_GET[repeter] contient maintenant forcment un nombre entier. Il ne reste plus qu vrier que ce nombre est bien compris entre 1 et 100 laide dune condition6 . Voici donc le code nal scuris qui prvoit tous les cas pour viter dtre pris au dpourvu par un utilisateur malintentionn :
<?php if (isset($_GET[prenom]) AND isset($_GET[nom]) AND isset($_GET[repeter])) { // 1 : On force la conversion en nombre entier $_GET[repeter] = (int) $_GET[repeter]; // 2 : Le nombre doit tre compris entre 1 et 100 if ($_GET[repeter] >= 1 AND $_GET[repeter] < 100) { for ($i = 0 ; $i < $_GET[repeter] ; $i++) { echo Bonjour . $_GET[prenom] . . $_GET[nom] . !<br />; } }

} else { echo Il faut renseigner un nom, un prnom et un nombre de rptitions !; } ?>

Code web : 101769 Cela fait beaucoup de conditions pour quelque chose qui tait la base assez simple, mais ctait ncessaire. Vous devrez toujours faire trs attention et prvoir tous les cas les plus tordus, comme nous venons de le faire : vrier que tous les paramtres que vous attendiez sont bien l ; vrier quils contiennent bien des valeurs correctes comprises dans des intervalles raisonnables. Si vous gardez cela en tte, vous naurez pas de problmes. :-) Nous navons pas encore vu tous les risques lis aux donnes envoyes par lutilisateur. Cette premire approche devrait dj vous avoir sensibiliss au problme, mais nous irons plus loin dans le chapitre suivant pour nir de couvrir ce sujet. Tout ceci est un peu complexe, je suis daccord, mais cest rellement important !

6 Ce

que vous savez faire, normalement !

114

NE FAITES JAMAIS CONFIANCE AUX DONNES REUES !

En rsum
Une URL reprsente ladresse dune page web (commenant gnralement par http://). Lorsquon fait un lien vers une page, il est possible dajouter des paramtres sous la forme bonjour.php ?nom=Dupont&prenom=Jean qui seront transmis la page. La page bonjour.php dans lexemple prcdent recevra ces paramtres dans un array nomm $_GET : $_GET[nom] aura pour valeur Dupont ; $_GET[prenom] aura pour valeur Jean . Cette technique est trs pratique pour transmettre des valeurs une page, mais il faut prendre garde au fait que le visiteur peut les modier trs facilement. Il ne faut donc pas faire aveuglment conance ces informations, et tester prudemment leur valeur avant de les utiliser. La fonction isset() permet de vrier si une variable est dnie ou non. Le transtypage est une technique qui permet de convertir une variable dans le type de donnes souhait. Cela permet de sassurer par exemple quune variable est bien un int (nombre entier).

115

CHAPITRE 10. TRANSMETTRE DES DONNES AVEC LURL

116

Chapitre

11
Dicult :

Transmettre des donnes avec les formulaires

es formulaires constituent le principal moyen pour vos visiteurs dentrer des informations sur votre site. Les formulaires permettent de crer une interactivit.

Par exemple, sur un forum on doit insrer du texte puis cliquer sur un bouton pour envoyer son message. Sur un livre dor, sur un mini-chat, on procde de la mme faon. On a besoin des formulaires partout pour changer des informations avec nos visiteurs. Vous allez voir quil y a de nombreux rappels de HTML dans ce chapitre. . . et ce nest pas un hasard : ici, le PHP et le HTML sont intimement lis. Le HTML permet de crer le formulaire, tandis que le PHP permet de traiter les informations que le visiteur a entres dans le formulaire. Ce chapitre est particulirement important, nous rutiliserons ce que nous avons appris ici dans toute la suite du cours. Soyez attentifs !

117

CHAPITRE 11. TRANSMETTRE DES DONNES AVEC LES FORMULAIRES

Crer la base du formulaire


En HTML, pour insrer un formulaire, on se sert de la balise <form>. On lutilise de la manire suivante :
<form method="post" action="cible.php"> <p> On insrera ici les lments de notre formulaire. </p> </form>

On crira le contenu de notre formulaire entre les balises <form> et </form>. Si vous avez lu mon cours de HTML/CSS, vous verrez quune bonne partie de ce chapitre ne sera compose que de rappels puisque je vais vous expliquer comment on insre les champs du formulaire dans la page. Cependant, et ce sera nouveau, nous allons aussi dcouvrir comment traiter en PHP les donnes qui ont t envoyes par le visiteur. Je souhaite attirer votre attention sur la toute premire ligne de ce code. Il y a deux attributs trs importants connatre pour la balise <form> : la mthode (method) et la cible (action). Il est impratif que vous compreniez quoi ils servent.

La mthode
Il faut savoir quil existe plusieurs moyens denvoyer les donnes du formulaire (plusieurs mthodes ). Vous pouvez en employer deux. get : les donnes transiteront par lURL comme on la appris prcdemment. On pourra les rcuprer grce larray $_GET. Cette mthode est assez peu utilise car on ne peut pas envoyer beaucoup dinformations dans lURL1 . post : les donnes ne transiteront pas par lURL, lutilisateur ne les verra donc pas passer dans la barre dadresse. Cette mthode permet denvoyer autant de donnes que lon veut, ce qui fait quon la privilgie le plus souvent. Nanmoins, les donnes ne sont pas plus scurises quavec la mthode GET et il faudra toujours vrier si tous les paramtres sont bien prsents et valides, comme on la fait dans le chapitre prcdent. On ne doit pas plus faire conance aux formulaires quaux URL. Cest vous de choisir par quelle mthode vous souhaitez que les donnes du formulaire soient envoyes. Si vous hsitez, sachez que dans 99 % des cas la mthode que lon utilise est post, vous crirez donc method="post" comme je lai fait.
1 Je

vous disais dans le chapitre prcdent quil tait prfrable de ne pas dpasser 256 caractres.

118

CRER LA BASE DU FORMULAIRE

La cible
Lattribut action sert dnir la page appele par le formulaire. Cest cette page qui recevra les donnes du formulaire et qui sera charge de les traiter. Imaginons le schma de la gure 11.1.

Fig. 11.1 Appel de la page cible par le formulaire Dans cet exemple, le formulaire se trouve dans la page formulaire.php. Cette page ne fait aucun traitement particulier, mais une fois le formulaire envoy (lorsquon a cliqu sur le bouton Valider ), le visiteur est redirig vers la page cible.php qui reoit les donnes du formulaire, comme vous le montre la gure 11.2.

Fig. 11.2 Fonctionnement dun formulaire Le nom de la page cible est dni grce lattribut action. La page cible ne doit pas forcment sappeler cible.php. Jutilise ce nom dans mes exemples simplement pour que vous compreniez bien que cest la page qui est appele. Remarquez quen thorie rien nempche le formulaire de sappeler lui-mme. Il surait dcrire action="formulaire.php". Dans ce cas, la page du formulaire doit tre capable aussi bien dacher le formulaire que de traiter les donnes. Cest tout fait possible de le faire mais an de ne pas compliquer les choses trop vite, on va viter de faire comme a ici. ;-) Retenez donc bien que vous travaillez normalement sur deux pages direntes : la page qui contient le formulaire (formulaire.php dans notre exemple), et celle qui reoit les donnes du formulaire pour les traiter (cible.php). 119

CHAPITRE 11. TRANSMETTRE DES DONNES AVEC LES FORMULAIRES

Les lments du formulaire


Dans un formulaire, vous le savez peut-tre dj, on peut insrer beaucoup dlments dirents : zones de texte, boutons, cases cocher, etc. Je vais ici tous les numrer et vous montrer comment vous servir de chacun deux dans la page cible.php qui fera le traitement. Vous allez voir, cest vraiment trs simple : au lieu de recevoir un array $_GET, vous allez recevoir un array $_POST contenant les donnes du formulaire !

Les petites zones de texte


Une zone de texte ressemble la gure 11.3.

Fig. 11.3 Zone de texte En HTML, on linsre tout simplement avec la balise :
<input type="text" />

Pour les mots de passe, vous pouvez utiliser type="password", ce qui aura pour eet de cacher le texte entr par le visiteur. part ce dtail, le fonctionnement reste le mme. Il y a deux attributs connatre que lon peut ajouter cette balise. name (obligatoire) : cest le nom de la zone de texte. Choisissez-le bien, car cest lui qui va produire une variable. Par exemple : <input type="text" name="pseudo" />. value (facultatif) : cest ce que contient la zone de texte au dpart. Par dfaut, la zone de texte est vide mais il peut tre pratique de pr-remplir le champ. Exemple : <input type="text" name="pseudo" value="M@teo21" />. Oui, je sais que vous commencez vous inquiter car vous navez pas encore vu de PHP pour le moment mais nayez pas peur. Le fonctionnement est tout simple et a un air de dj vu. Le texte que le visiteur aura entr sera disponible dans cible.php sous la forme dune variable appele $_POST[pseudo]. Pour lexemple, je vous propose de crer un formulaire qui demande le prnom du visiteur puis qui lache rement sur la page cible.php. On va donc distinguer deux codes source : celui de la page du formulaire et celui de la page cible. Voici le code de la page formulaire.php :
<p>

Cette page ne contient que du HTML.<br /> Veuillez taper votre prnom : </p>

120

LES LMENTS DU FORMULAIRE

<form action="cible.php" method="post"> <p> <input type="text" name="prenom" /> <input type="submit" value="Valider" /> </p> </form>

Rappel de HTML : le champ <input type="submit" /> permet de crer le bouton de validation du formulaire qui commande lenvoi des donnes, et donc la redirection du visiteur vers la page cible. Maintenant, je vous propose de crer la page cible.php. Cette page va recevoir le prnom dans une variable nomme $_POST[prenom].
<p>Bonjour !</p> <p>Je sais comment tu tappelles, h h. Tu tappelles <?php echo $_POST[prenom]; ?> !</p> <p>Si tu veux changer de prnom, <a href="formulaire.php">clique ici</a> pour re venir la page formulaire.php.</p>

Le code web suivant ouvre la page formulaire.php pour que vous puissiez tester. Code web : 404079 Dans cible.php on a ach une variable $_POST[prenom] qui contient ce que lutilisateur a entr dans le formulaire.

Les grandes zones de texte


La grande zone de texte2 ressemble la gure 11.4.

Fig. 11.4 Une grande zone de texte


2 On

lappelle aussi zone de saisie multiligne .

121

CHAPITRE 11. TRANSMETTRE DES DONNES AVEC LES FORMULAIRES On peut y crire autant de lignes que lon veut. Cest plus adapt si le visiteur doit crire un long message, par exemple. On va utiliser le code HTML suivant pour insrer cette zone de texte :
<textarea name="message" rows="8" cols="45"> Votre message ici. </textarea>

L encore, on a un attribut name qui va dnir le nom de la variable qui sera cre dans cible.php. Dans notre cas, ce sera la variable $_POST[message]. Vous remarquerez quil ny a pas dattribut value. En fait, le texte par dfaut est ici crit entre le <textarea> et le </textarea>. Si vous ne voulez rien mettre par dfaut, alors ncrivez rien entre <textarea> et </textarea>. Les attributs rows et cols permettent de dnir la taille de la zone de texte en hauteur et en largeur respectivement.

La liste droulante
La gure 11.5 est une liste droulante.

Fig. 11.5 Une liste droulante On utilise le code HTML suivant pour construire une liste droulante :
<select name="choix"> <option value="choix1">Choix <option value="choix2">Choix <option value="choix3">Choix <option value="choix4">Choix </select>

1</option> 2</option> 3</option> 4</option>

Tout btement, on utilise la balise <select> laquelle on donne un nom (ici : choix ). On crit ensuite les direntes options disponibles. . . puis on referme la balise avec </select>. 122

LES LMENTS DU FORMULAIRE Ici, une variable $_POST[choix] sera cre, et elle contiendra le choix qua fait lutilisateur. Sil a choisi Choix 3 , la variable $_POST[choix] sera gale au value correspondant, cest--dire choix3. Vous pouvez aussi dnir le choix par dfaut de la liste. Normalement cest le premier, mais si vous rajoutez lattribut selected="selected" une balise <option>, alors ce sera le choix par dfaut. On pourrait par exemple crire :
<option value="choix3" selected="selected">Choix 3</option>

Les cases cocher


La gure 11.6 reprsente une srie de cases cocher.

Fig. 11.6 Cases cocher On utilisera le code suivant pour acher des cases cocher :
<input type="checkbox" name="case" id="case" /> <label for="case"> Ma case cocher</label>

Lutilisation de la balise <label> nest pas obligatoire mais je la recommande fortement. Elle permet dassocier le libell la case cocher qui a le mme id que son attribut for, ce qui permet de cliquer sur le libell pour cocher la case. On y gagne donc en ergonomie. L encore, on donne un nom la case cocher via lattribut name (ici : case ). Ce nom va gnrer une variable dans la page cible, par exemple $_POST[case]. Si la case a t coche, alors $_POST[case] aura pour valeur on . Si elle na pas t coche, alors $_POST[case] nexistera pas. Vous pouvez faire un test avec isset($_POST[case]) pour vrier si la case a t coche ou non. Si vous voulez que la case soit coche par dfaut, il faudra lui rajouter lattribut checked="checked". Par exemple :
<input type="checkbox" name="case" checked="checked" />

Les boutons doption


Les boutons doption fonctionnent par groupes de deux minimum. Vous trouverez un exemple sur la gure 11.7. 123

CHAPITRE 11. TRANSMETTRE DES DONNES AVEC LES FORMULAIRES

Fig. 11.7 Boutons doption

Le code correspondant cet exemple est le suivant :


Aimez-vous les frites ? <input type="radio" name="frites" value="oui" id="oui" checked="checked" /> <lab el for="oui">Oui</label> <input type="radio" name="frites" value="non" id="non" /> <label for="non">Non</ label>

Comme vous pouvez le voir, les deux boutons doption ont le mme nom ( frites ). Cest trs important, car ils fonctionnent par groupes : tous les boutons doption dun mme groupe doivent avoir le mme nom. Cela permet au navigateur de savoir lesquels dsactiver quand on active un autre bouton du groupe. Il serait bte en eet de pouvoir slectionner la fois Oui et Non . Pour pr-cocher lun de ces boutons, faites comme pour les cases cocher : rajoutez un attribut checked="checked". Ici, comme vous pouvez le voir, Oui est slectionn par dfaut. Dans la page cible, une variable $_POST[frites] sera cre. Elle aura la valeur du bouton doption choisi par le visiteur, issue de lattribut value. Si on aime les frites, alors on aura $_POST[frites] = oui. Il faut bien penser renseigner lattribut value du bouton doption car cest lui qui va dterminer la valeur de la variable.

Les champs cachs


Les champs cachs constituent un type de champ part. En quoi a consiste ? Cest un code dans votre formulaire qui napparatra pas aux yeux du visiteur, mais qui va quand mme crer une variable avec une valeur. On peut sen servir pour transmettre des informations xes. Je mexplique : supposons que vous ayez besoin de retenir que le pseudo du visiteur est Mateo21 . Vous allez taper ce code :
<input type="hidden" name="pseudo" value="Mateo21" />

lcran, sur la page web on ne verra rien. Mais dans la page cible, une variable $_POST[pseudo] sera cre, et elle aura la valeur Mateo21 ! Cest apparemment inutile, mais vous verrez que vous en aurez parfois besoin. 124

NE FAITES JAMAIS CONFIANCE AUX DONNES REUES : LA FAILLE XSS On croit par erreur que, parce que ces champs sont cachs, le visiteur ne peut pas les voir. Cest faux ! En eet, nimporte quel visiteur peut acher le code source de la page et voir quil y a des champs cachs en lisant le code HTML. Mieux, il peut mme modier la valeur du champ cach sil a les outils appropris. Que faut-il retenir ? Ce nest pas parce que le champ est cach que vous devez considrer quil est inviolable. Nimporte quel visiteur (un peu malin) peut le lire, modier sa valeur et mme le supprimer. Ne faites pas conance aux donnes envoyes par le visiteur ! Vous vous souvenez de cette rgle dont je vous ai parl dans le chapire prcdent ? Elle est plus que jamais dactualit.

Ne faites jamais conance aux donnes reues : la faille XSS


Vous vous souvenez des mises en garde que javais faites dans le chapitre prcdent ? Elles ne concernaient pas que les paramtres qui transitent par lURL : tout cela vaut aussi pour les formulaires ! Mais. . . autant je vois comment on peut modier lURL, autant je ne comprends pas comment peut faire un visiteur pour modier le formulaire de mon site et traquer les donnes ! On a tendance croire que les visiteurs ne peuvent pas bidouiller le formulaire mais cest faux. Je vais dans un premier temps vous montrer pourquoi les formulaires ne sont pas plus srs que les URL, puis je vous parlerai dun autre danger important : la faille XSS. Avec a, nous aurons vraiment fait le tour de ce quil faut savoir pour tre tranquilles par la suite !

Pourquoi les formulaires ne sont pas srs


Tout ce que nous avons appris dans le chapitre prcdent sur les URL reste valable ici. Toutes les informations qui proviennent de lutilisateur, savoir les donnes de $_GET et de $_POST, doivent tre traites avec la plus grande mance. Vous ne pouvez pas supposer que vous allez recevoir ce que vous attendiez. Cette rgle est trs simple, mais je vous propose un exemple concret pour bien visualiser le problme. Imaginez que vous demandez vos visiteurs de rentrer dans un champ leur date de naissance au format JJ/MM/AAAA. Combien vont respecter cette mise en forme ? Combien vont se tromper par erreur ? Je vous garantis que parmi tous vos visiteurs, alors que vous attendiez quelque chose comme 04/10/1987 , vous allez tomber sur une personne qui va crire : Je suis n le 4 octobre 1987 . Cest un exemple un peu extrme mais a va vous arriver, soyez-en srs. Par consquent, quand vous ferez le traitement de la date en PHP, il faudra bien vrier quelle respecte le 125

CHAPITRE 11. TRANSMETTRE DES DONNES AVEC LES FORMULAIRES format que vous avez indiqu. Pour vrier si une chane de texte correspond un certain format, comme JJ/MM/AAAA , on peut utiliser une validation par expression rgulire. Les expressions rgulires feront lobjet de deux chapitres vers la n de ce livre car il sagit dun sujet assez complexe. De la mme manire, comme dans le chapitre prcdent, mme si vous demandez un nombre compris entre 1 et 100, il y aura bien quelquun pour crire 48451254523 . Soyez donc vigilants et nayez jamais conance en ce qui vient de lutilisateur, savoir les donnes issues des arrays $_GET et $_POST. Avec les formulaires, vous ne pouvez pas non plus supposer quon va vous envoyer tous les champs que vous attendiez. Un visiteur peut trs bien samuser supprimer un champ de texte, et dans ce cas votre page cible.php ne recevra jamais le texte quelle attendait ! Il faudra imprativement quelle vrie que toutes les donnes quelle attendait sont bien l avant deectuer la moindre opration. Puisque la page du formulaire se trouve sur mon site, comment peut faire un visiteur pour modier ma page web ? Il peut voir les sources mais pas les modier ! En eet, vos visiteurs ne peuvent pas modier vos pages web sur le serveur. . . Mais ils peuvent les reprendre et les modier ailleurs. Souvenez-vous du schma de la gure 11.2 page 119. La page formulaire.php contient le formulaire et cible.php traite les donnes quon lui a envoyes. Autant le code PHP nest jamais visible par vos visiteurs, autant le code HTML du formulaire, lui, peut tre vu par tout le monde. partir de l, quest-ce qui empche quelquun de crer une copie lgrement modie de votre formulaire et de la stocker sur son serveur, limage de la gure 11.8 ? Sur le schma de la gure 11.8, le mchant 3 a pris le code HTML de votre formulaire, la modi et la enregistr sur son serveur (ou mme sur son ordinateur). Lattribut action a t modi pour indiquer ladresse absolue (donc complte) de votre page cible :
<form method="post" action="http://www.monsite.com/cible.php">

Le mchant peut maintenant modier votre formulaire, ajouter des champs, en supprimer, bref faire ce quil veut avec ! Votre page cible.php ny verra que du feu car il est impossible de savoir avec certitude de quel formulaire vient le visiteur. Ces explications sont assez techniques. En fait, on les rserve normalement aux personnes plus exprimentes que les dbutants. Cependant, je tenais volontairement vous montrer comment cest possible. Mme si tout nest pas totalement clair dans votre tte, vous avez au moins lide du mode de fonctionnement.
3 Nous

lappellerons comme a, parce que a lui va bien. ;-)

126

NE FAITES JAMAIS CONFIANCE AUX DONNES REUES : LA FAILLE XSS

Fig. 11.8 Le formulaire modi Sil y a une chose retenir ici, cest que les formulaires sont modiables par tous les visiteurs contrairement ce quon pourrait penser. Par consquent, votre page cible.php devra tre aussi vigilante que nous lavons t dans le chapitre prcdent et ne pas faire conance aux donnes de lutilisateur4 . Il y a un moyen encore plus simple de modier le formulaire de votre site sans avoir accs votre serveur. Internet Explorer 8 et Google Chrome embarquent des outils pour les dveloppeurs qui permettent de modier le code HTML de la page que lon visite en temps rel. Firefox peut faire de mme avec son clbre plugin Firebug.

La faille XSS : attention au code HTML que vous recevez !


Il nous reste un dernier point important voir ensemble et aprs, jarrte de vous faire peur, promis ! La faille XSS (pour cross-site scripting) est vieille comme le monde5 et on la trouve encore sur de nombreux sites web, mme professionnels ! Cest une technique qui consiste injecter du code HTML contenant du JavaScript dans vos pages pour le faire excuter vos visiteurs. Reprenons la page qui ache le prnom quon lui envoie. Elle contient notamment le
4 Les programmeurs ont dailleurs une maxime : Never trust user input , ce qui signie Ne faites jamais conance aux donnes de lutilisateur . 5 Euh, comme le Web.

127

CHAPITRE 11. TRANSMETTRE DES DONNES AVEC LES FORMULAIRES code suivant :
<p>Je sais comment tu tappelles, h h. Tu tappelles <?php echo $_POST[prenom]; ?> !</p>

Si le visiteur dcide dcrire du code HTML la place de son prnom, cela fonctionnera trs bien ! Par exemple, imaginons quil crive dans le champ Prnom le code : <strong>Badaboum</strong>. Le code source HTML qui sera gnr par PHP sera le suivant :
<p>Je sais comment tu tappelles, h h. Tu tappelles <strong>Badaboum</strong> !</p>

Et alors ? Sil veut mettre son prnom en gras, cest son problme, non ?

Outre le fait quil peut insrer nimporte quel code HTML (et rendre votre page invalide), ce qui nest pas le plus grave, il peut aussi ouvrir des balises de type <script> pour faire excuter du code JavaScript au visiteur qui visualisera la page !
<p>Je sais comment tu tappelles, h h. Tu tappelles <script type="text/javas cript">alert(Badaboum)</script> !</p>

Tous les visiteurs qui arriveront sur cette page verront une bote de dialogue JavaScript sacher. Plutt gnant. Voyez la gure 11.9.

Fig. 11.9 Excution de JavaScript par la faille XSS Les choses deviennent vraiment critiques si le visiteur est assez malin pour rcuprer vos cookies de cette faon-l. Les cookies stockent des informations sur votre session et parfois des informations plus condentielles, comme votre pseudonyme et votre mot de passe sur le site ! Il est possible de forcer le visiteur qui lira le code JavaScript envoyer tous les cookies quil a enregistrs pour votre site web, ce qui peut conduire au vol de son compte sur ce site. Je ne rentrerai pas dans le dtail de cette mthode car on sloignerait un peu trop du sujet, mais sachez que cest possible et quil faut donc tout prix viter quun visiteur puisse injecter du code JavaScript dans vos pages. 128

NE FAITES JAMAIS CONFIANCE AUX DONNES REUES : LA FAILLE XSS Rsoudre le problme est facile : il faut protger le code HTML en lchappant, cest-dire en achant les balises (ou en les retirant) plutt que de les faire excuter par le navigateur, comme sur la gure 11.10.

Fig. 11.10 viter la faille XSS en chappant le HTML Pour chapper le code HTML, il sut dutiliser la fonction htmlspecialchars qui va transformer les chevrons des balises HTML <> en &lt ; et &gt ; respectivement. Cela provoquera lachage de la balise plutt que son excution.
<p>Je sais comment tu tappelles, h h. Tu tappelles <?php echo htmlspecialcha rs($_POST[prenom]); ?> !</p>

Le code HTML qui en rsultera sera propre et protg car les balises HTML insres par le visiteur auront t chappes :
<p>Je sais comment tu tappelles, h h. Tu tappelles &lt;strong&gt;Badaboum&lt ;/strong&gt; !</p>

Il faut penser utiliser cette fonction sur tous les textes envoys par lutilisateur qui sont susceptibles dtre achs sur une page web. Sur un forum par exemple, il faut penser chapper les messages posts par vos membres, mais aussi leurs pseudos6 ainsi que leurs signatures. Bref, tout ce qui est ach et qui vient la base dun visiteur, vous devez penser le protger avec htmlspecialchars.
6 Ils

peuvent samuser y mettre du HTML !

129

CHAPITRE 11. TRANSMETTRE DES DONNES AVEC LES FORMULAIRES Si vous prfrez retirer les balises HTML que le visiteur a tent denvoyer plutt que de les acher, utilisez la fonction strip_tags.

Lenvoi de chiers
Vous saviez quon pouvait aussi envoyer des chiers grce aux formulaires ? Vous aurez besoin de lire cette section si vous voulez que vos visiteurs puissent envoyer (on dit aussi uploader) des images, des programmes ou tout autre type de chier sur votre site. Cette section est un peu plus complexe que le reste du chapitre. Sa lecture nest dailleurs pas obligatoire pour la bonne comprhension de la suite du cours. Par consquent, nhsitez pas revenir la lire plus tard, lorsque vous en aurez besoin, si vous ne voulez pas vous attaquer de suite une partie un peu dicile . L encore, a se passe en deux temps. 1. Le visiteur arrive sur votre formulaire et le remplit (en indiquant le chier envoyer). Une simple page HTML sut pour crer le formulaire. 2. PHP rceptionne les donnes du formulaire et, sil y a des chiers dedans, il les enregistre dans un des dossiers du serveur.

Attention : lenvoi du chier peut tre un peu long si celui-ci est gros. Il faudra dire au visiteur de ne pas simpatienter pendant lenvoi. On va commencer par crer le formulaire permettant denvoyer un chier (une simple page HTML). Nous verrons ensuite comment traiter lenvoi du chier ct serveur avec PHP.

Le formulaire denvoi de chier


Ds linstant o votre formulaire propose aux visiteurs denvoyer un chier, il faut ajouter lattribut enctype="multipart/form-data" la balise <form>.
<form action="cible_envoi.php" method="post" enctype="multipart/form-data"> <p>Formulaire denvoi de fichier</p> </form>

Grce enctype, le navigateur du visiteur sait quil sapprte envoyer des chiers. 130

LENVOI DE FICHIERS Maintenant que cest fait, nous pouvons ajouter lintrieur du formulaire une balise permettant denvoyer un chier. Cest une balise trs simple de type <input type="file" />. Il faut penser comme toujours donner un nom ce champ de formulaire (grce lattribut name) pour que PHP puisse reconnatre le champ par la suite.
<form action="cible_envoi.php" method="post" enctype="multipart/form-data"> <p> Formulaire denvoi de fichier :<br /> <input type="file" name="monfichier" /><br /> <input type="submit" value="Envoyer le fichier" /> </p> </form>

Voil, cest susant. Vous pouvez ajouter dautres champs plus classiques au formulaire (champ de texte, cases cocher). Vous pouvez aussi proposer denvoyer plusieurs chiers en mme temps. L, on va se contenter dun seul champ (envoi de chier) pour faire simple.

Le traitement de lenvoi en PHP


Comme vous avez d le remarquer, le formulaire pointe vers une page PHP qui sappelle cible_envoi.php. Le visiteur sera donc redirig sur cette page aprs lenvoi du formulaire. Cest maintenant que a devient important. Il faut que lon crive le code de la page cible_envoi.php pour traiter lenvoi du chier. Traiter lenvoi du chier ? Cest--dire ? Si le chier a t envoy sur le serveur cest bon, non ? Quest-ce que PHP aurait besoin de faire ? En fait, au moment o la page PHP sexcute, le chier a t envoy sur le serveur mais il est stock dans un dossier temporaire. Cest vous de dcider si vous acceptez dnitivement le chier ou non. Vous pouvez par exemple vrier si le chier a la bonne extension (si vous demandiez une image et quon vous envoie un .txt , vous devrez refuser le chier). Si le chier est bon, vous laccepterez grce la fonction move_uploaded_file, et ce, dune manire dnitive. Mais comment je sais si le chier est bon ?

Pour chaque chier envoy, une variable $_FILES[nom_du_champ] est cre. Dans 131

CHAPITRE 11. TRANSMETTRE DES DONNES AVEC LES FORMULAIRES notre cas, la variable sappellera $_FILES[monfichier]. Cette variable est un tableau qui contient plusieurs informations sur le chier : Variable $_FILES[monfichier][name] $_FILES[monfichier][type] Signication Contient le nom du chier envoy par le visiteur. Indique le type du chier envoy. Si cest une image gif par exemple, le type sera image/gif. Indique la taille du chier envoy. Attention : cette taille est en octets. Il faut environ 1 000 octets pour faire 1 Ko, et 1 000 000 doctets pour faire 1 Mo. Attention : la taille de lenvoi est limite par PHP. Par dfaut, impossible duploader des chiers de plus de 8 Mo. Juste aprs lenvoi, le chier est plac dans un rpertoire temporaire sur le serveur en attendant que votre script PHP dcide si oui ou non il accepte de le stocker pour de bon. Cette variable contient lemplacement temporaire du chier (cest PHP qui gre a). Contient un code derreur permettant de savoir si lenvoi sest bien eectu ou sil y a eu un problme et si oui, lequel. La variable vaut 0 sil ny a pas eu derreur.

$_FILES[monfichier][size]

$_FILES[monfichier][tmp_name]

$_FILES[monfichier][error]

Si vous avez mis un second champ denvoi de chier dans votre formulaire, il y aura une seconde variable $_FILES[nom_de_votre_autre_champ] dcoupe de la mme manire que le tableau quon vient de voir ici. $_FILES[nom_de_votre_autre_champ][size] contiendra donc la taille du second chier, et ainsi de suite. Je vous propose de faire les vrications suivantes pour dcider si lon accepte le chier ou non. 1. Vrier tout dabord si le visiteur a bien envoy un chier (en testant la variable $_FILES[monfichier] avec isset()) et sil ny a pas eu derreur denvoi (grce $_FILES[monfichier][error]). 2. Vrier si la taille du chier ne dpasse pas 1 Mo par exemple (environ 1 000 000 doctets) grce $_FILES[monfichier][size]. 3. Vrier si lextension du chier est autorise7 . Dans notre cas, nous autoriserons
7 Il

faut interdire tout prix que les gens puissent envoyer des chiers PHP, sinon ils pourraient

132

LENVOI DE FICHIERS seulement les images (chiers .png, .jpg, .jpeg et .gif). Nous analyserons pour cela la variable $_FILES[monfichier][name]. Nous allons donc faire une srie de tests dans notre page cible_envoi.php. 1/ Tester si le chier a bien t envoy On commence par vrier quun chier a t envoy. Pour cela, on va tester si la variable $_FILES[monfichier] existe avec isset(). On vrie dans le mme temps sil ny a pas derreur denvoi.
<?php // Testons si le fichier a bien t envoy et sil ny a pas derreur if (isset($_FILES[monfichier]) AND $_FILES[monfichier][error] == 0) { } ?>

2/ Vrier la taille du chier On veut interdire que le chier dpasse 1 Mo, soient environ 1 000 000 doctets (jarrondis pour simplier). On doit donc tester $_FILES[monfichier][size] :
<?php // Testons si le fichier a bien t envoy et sil ny a pas derreur if (isset($_FILES[monfichier]) AND $_FILES[monfichier][error] == 0) { // Testons si le fichier nest pas trop gros if ($_FILES[monfichier][size] <= 1000000) { } ?> }

3/ Vrier lextension du chier On peut rcuprer lextension du chier dans une variable grce ce code :
<?php $infosfichier = pathinfo($_FILES[monfichier][name]); $extension_upload = $infosfichier[extension]; ?>
excuter des scripts sur votre serveur.

133

CHAPITRE 11. TRANSMETTRE DES DONNES AVEC LES FORMULAIRES La fonction pathinfo renvoie un array contenant entre autres lextension du chier dans $infosfichier[extension]. On stocke a dans une variable $extension_upload. Une fois lextension rcupre, on peut la comparer un tableau dextensions autorises (un array) et vrier si lextension rcupre fait bien partie des extensions autorises laide de la fonction in_array(). Ouf ! On obtient ce code au nal :
<?php // Testons si le fichier a bien t envoy et sil ny a pas derreur if (isset($_FILES[monfichier]) AND $_FILES[monfichier][error] == 0) { // Testons si le fichier nest pas trop gros if ($_FILES[monfichier][size] <= 1000000) { // Testons si lextension est autorise $infosfichier = pathinfo($_FILES[monfichier][name]); $extension_upload = $infosfichier[extension]; $extensions_autorisees = array(jpg, jpeg, gif, png); if (in_array($extension_upload, $extensions_autorisees)) { } }

} ?>

4/ Valider lupload du chier Si tout est bon, on accepte le chier en appelant move_uploaded_file(). Cette fonction prend deux paramtres : le nom temporaire du chier (on la avec $_FILES[monfichier][tmp_name]) ; le chemin qui est le nom sous lequel sera stock le chier de faon dnitive. On peut utiliser le nom dorigine du chier $_FILES[monfichier][name] ou gnrer un nom au hasard. Je propose de placer le chier dans un sous-dossier uploads . On gardera le mme nom de chier que celui dorigine. Comme $_FILES[monfichier][name] contient le chemin entier vers le chier dorigine (C :\dossier\fichier.png par exemple), il nous faudra extraire le nom du chier. On peut utiliser pour cela la fonction basename qui renverra juste chier.png .
<?php // Testons si le fichier a bien t envoy et sil ny a pas derreur if (isset($_FILES[monfichier]) AND $_FILES[monfichier][error] == 0) { // Testons si le fichier nest pas trop gros if ($_FILES[monfichier][size] <= 1000000)

134

LENVOI DE FICHIERS
{

// Testons si lextension est autorise $infosfichier = pathinfo($_FILES[monfichier][name]); $extension_upload = $infosfichier[extension]; $extensions_autorisees = array(jpg, jpeg, gif, png); if (in_array($extension_upload, $extensions_autorisees)) { // On peut valider le fichier et le stocker dfinitivement move_uploaded_file($_FILES[monfichier][tmp_name], uploads/ . basename($_FILES[monfichier][name])); echo "Lenvoi a bien t effectu !"; } } } ?>

Code web : 148786 Lorsque vous mettrez le script sur Internet laide dun logiciel FTP, vriez que le dossier uploads sur le serveur existe et quil a les droits dcriture. Pour ce faire, sous FileZilla par exemple, faites un clic droit sur le dossier et choisissez Attributs du chier . Cela vous permettra dditer les droits du dossier (on parle de CHMOD). Mettez les droits 733, ainsi PHP pourra placer les chiers uploads dans ce dossier. Ce script est un dbut, mais en pratique il vous faudra srement encore lamliorer. Par exemple, si le nom du chier contient des espaces ou des accents, a posera un problme une fois envoy sur le Web. Dautre part, si quelquun envoie un chier qui a le mme nom que celui dune autre personne, lancien sera cras ! La solution consiste en gnral choisir nous-mmes le nom du chier stock sur le serveur plutt que de se servir du nom dorigine. Vous pouvez faire un compteur qui sincrmente : 1.png, 2.png, 3.jpg, etc. Soyez toujours trs vigilants sur la scurit, vous devez viter que quelquun puisse envoyer des chiers PHP sur votre serveur. Pour aller plus loin, je vous recommande de lire le tutoriel de DHKold sur lupload de chiers par formulaire qui traite le sujet plus en dtail. Code web : 165094 Bonne lecture ! 135

CHAPITRE 11. TRANSMETTRE DES DONNES AVEC LES FORMULAIRES

En rsum
Les formulaires sont le moyen le plus pratique pour le visiteur de transmettre des informations votre site. PHP est capable de rcuprer les donnes saisies par vos visiteurs et de les traiter. Les donnes envoyes via un formulaire se retrouvent dans un array $_POST. De la mme manire que pour les URL, il ne faut pas donner sa conance absolue aux donnes que vous envoie lutilisateur. Il pourrait trs bien ne pas remplir tous les champs voire traquer le code HTML de la page pour supprimer ou ajouter des champs. Traitez les donnes avec vigilance. Que ce soit pour des donnes issues de lURL ($_GET) ou dun formulaire ($_POST), il faut sassurer quaucun texte qui vous est envoy ne contient du HTML si celui-ci est destin tre ach sur une page. Sinon, vous ouvrez une faille appele XSS qui peut tre nfaste pour la scurit de votre site. Pour viter la faille XSS, il sut dappliquer la fonction htmlspecialchars sur tous les textes envoys par vos visiteurs que vous acherez. Les formulaires permettent denvoyer des chiers. On retrouve les informations sur les chiers envoys dans un array $_FILES. Leur traitement est cependant plus complexe.

136

Chapitre

12
Dicult :

TP : page protge par mot de passe

ienvenue dans votre premier TP ! Ce qui suit nest pas un chapitre comme les autres, vous nallez rien apprendre de nouveau. Mais pour la premire fois, vous allez pratiquer pour de bon et raliser votre premier script PHP !

Le but de chacun des TP est de vous montrer quoi peut servir tout ce que vous venez dapprendre. Quand vous lisez un chapitre, vous tes parfois dans le ou, vous vous dites : Ok, jai compris ce que tu veux me dire, mais je ne vois vraiment pas o tu veux en venir : comment je peux faire un site web avec tout a ? . Maintenant, place au concret ! Et bonne surprise vous avez dj le niveau pour protger le contenu dune page par mot de passe ! Cest ce que je vais vous apprendre faire dans ce chapitre.

137

CHAPITRE 12. TP : PAGE PROTGE PAR MOT DE PASSE Comme cest votre premier TP, il est probable que vous vous plantiez lamentablement (vous voyez, je ne vous cache rien). Vous aurez envie de vous pendre ou de vous jeter par la fentre, cest tout fait normal. Je connais peu de monde qui peut se vanter davoir russi du premier coup son premier script PHP. Ne vous dcouragez donc pas, essayez de suivre et de comprendre le fonctionnement de ce TP, et a ira dj mieux au prochain. :-)

Instructions pour raliser le TP


Les prrequis
En rgle gnrale, il faut avoir lu tous les chapitres qui prcdent le TP pour bien le comprendre. Voici la liste des connaissances dont vous aurez besoin pour raliser ce TP : acher du texte avec echo ; utiliser les variables (aectation, achage. . .) ; transmettre des variables via une zone de texte dun formulaire ; utiliser des conditions simples (if, else).

Si lun de ces points est un peu ou pour vous (vous avez peut-tre oubli), nhsitez pas relire le chapitre correspondant, vous en aurez besoin pour traiter convenablement le TP. Vous verrez, il ne vous sera pas demand de faire des choses compliques. Le but est simplement dassembler toutes vos connaissances pour rpondre un problme prcis.

Votre objectif
Voici le scnario : vous voulez mettre en ligne une page web pour donner des informations condentielles certaines personnes. Cependant, pour limiter laccs cette page, il faudra connatre un mot de passe. Dans notre cas, les donnes condentielles seront les codes daccs au serveur central de la NASA1 . Le mot de passe pour pouvoir visualiser les codes daccs sera kangourou. Sauriez-vous raliser une page qui nache ces codes secrets que si lon a rentr le bon mot de passe ?

Comment procder ?
Pour coder correctement, je recommande toujours de travailler dabord au brouillon2 . a peut bien souvent paratre une perte de temps, mais cest tout fait le contraire. Si vous vous mettez crire des lignes de code au fur et mesure, a va tre coup sr le bazar. linverse, si vous prenez cinq minutes pour y rchir devant une feuille
1 Soyons 2 Vous

fous ! savez, avec un stylo et une feuille de papier !

138

INSTRUCTIONS POUR RALISER LE TP de papier, votre code sera mieux structur et vous viterez de nombreuses erreurs (qui font, elles, perdre du temps).

quoi doit-on rchir sur notre brouillon ?

1. Au problme que vous vous posez (quest-ce que je veux arriver faire ?). 2. Au schma du code, cest--dire que vous allez commencer le dcouper en plusieurs morceaux, eux-mmes dcoups en petits morceaux (cest plus facile avaler). 3. Aux fonctions et aux connaissances en PHP dont vous allez avoir besoin (pour tre srs que vous les utilisez convenablement). Et pour montrer lexemple, nous allons suivre cette liste pour notre TP.

Problme pos On doit protger laccs une page par un mot de passe. La page ne doit pas sacher si lon na pas le mot de passe.

Schma du code Pour que lutilisateur puisse entrer le mot de passe, le plus simple est de crer un formulaire. Celui-ci appellera la page protge et lui enverra le mot de passe. Un exemple de ce type de page est reprsent la gure 12.1. Laccs au contenu de la page ne sera autoris que si le mot de passe fourni par lutilisateur est kangourou.

Fig. 12.1 Page protge par mot de passe Vous devez donc crer deux pages web : formulaire.php : contient un simple formulaire comme vous savez les faire ; secret.php : contient les codes secrets mais ne les ache que si on lui donne le mot de passe. 139

CHAPITRE 12. TP : PAGE PROTGE PAR MOT DE PASSE Connaissances requises Nous avons dtaill les connaissances requises au dbut de ce chapitre. Vous allez voir que ce TP nest quune simple application pratique de ce que vous connaissez dj, mais cela sera une bonne occasion de vous entraner. ;-)

vous de jouer !
On a prpar le terrain ensemble ; maintenant, vous savez tout ce quil faut pour raliser le script ! Vous tes normalement capables de trouver le code taper par vous-mmes, et cest ce que je vous invite faire. a ne marchera probablement pas du premier coup, mais ne vous en faites pas : a ne marche jamais du premier coup ! Bon code !

Correction
Maintenant, on corrige ! Vous ne devriez lire cette partie que si vous avez termin votre travail (pour le comparer au mien), ou si vous tes compltement bloqus. Si jamais vous tes bloqus, ne regardez pas toute la correction dun coup. Regardez juste la section qui vous pose problme et essayez de continuer sans la correction. Comme vous le savez, il y a deux pages crer. Commenons par la plus simple, formulaire.php :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> <head> <title>Page protge par mot de passe</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <p>Veuillez entrer le mot de passe pour obtenir les codes daccs au serveur central de la NASA :</p> <form action="secret.php" method="post"> <p> <input type="password" name="mot_de_passe" /> <input type="submit" value="Valider" /> </p> </form> <p>Cette page est rserve au personnel de la NASA. Si vous ne travaillez pas la NASA, inutile dinsister vous ne trouverez jamais le mot de passe ! ;-)</p>

140

CORRECTION
</body>

</html>

Code web : 710963 Si vous avez bien suivi le chapitre sur les formulaires, vous ne devriez avoir eu aucun mal raliser ce formulaire. Jai choisi un champ de type password puisquil sagit dun mot de passe. part a, rien de bien particulier. Maintenant, intressons-nous la page secret.php qui est appele par le formulaire.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> <head> <title>Codes daccs au serveur central de la NASA</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <?php if (isset($_POST[mot_de_passe]) AND $_POST[mot_de_passe] == "kangourou") // Si le mot de passe est bon { // On affiche les codes ?> <h1>Voici les codes daccs :</h1> <p><strong>CRD5-GTFT-CK65-JOPM-V29N-24G1-HH28-LLFV</strong></p> <p> Cette page est rserve au personnel de la NASA. Noubliez pas de la visiter rgulirement car les codes daccs sont changs toutes les semaines.<br /> La NASA vous remercie de votre visite. </p>

<?php } else // Sinon, on affiche un message derreur { echo <p>Mot de passe incorrect</p>; } ?> </body>

</html>

Code web : 655266 141

CHAPITRE 12. TP : PAGE PROTGE PAR MOT DE PASSE Dans la page secrte, on vrie dabord si lon a envoy un mot de passe (avec isset) et si ce mot de passe correspond bien celui que lon attendait (kangourou). Si ces deux conditions sont remplies, on ache alors les codes daccs. Comme vous le voyez, je nai pas insr de echo pour acher tout ce texte. Quand il y a beaucoup de texte acher, il est prfrable de fermer les balises PHP aprs laccolade du if, cest plus simple et plus lisible. En revanche, pour le cas du else, comme il ny avait quune seule petite phrase acher, jai choisi de lacher avec un echo. Vous pouvez tester le fonctionnement du script en ligne laide du code web suivant si vous le dsirez. Code web : 334285 Alors, a vous plat ? Vous aurez beau chercher, on ne peut pas acher la page cache tant quon na pas entr le bon mot de passe. Vous navez qu mettre au d un ami ou un membre de votre famille, il pourra chercher des heures mais il ne verra pas la page cache sil na pas le bon mot de passe ! Cette protection est-elle vraiment ecace ?

Oui, honntement elle lest. Du moins, elle est ecace si vous mettez un mot de passe compliqu (pas simplement kangourou ). Pour moi, un bon mot de passe cest long, avec plein de caractres bizarres, des majuscules, des minuscules, des chires, etc. Par exemple, k7hYTe40Lm8Mf est un bon mot de passe qui a peu de chances dtre trouv par hasard .

Aller plus loin


Si vous le souhaitez, sachez quil est possible de raliser ce TP en une seule page au lieu de deux. Imaginez pour cela que le formulaire, sur la page formulaire.php, sappelle lui-mme. En clair, lattribut action du formulaire serait action="formulaire.php". Cela voudrait dire que les donnes seraient envoyes sur la mme page, comme sur la gure 12.2. Dans ce mode de fonctionnement, la page formulaire.php contiendrait la fois le formulaire et le message secret. Comment peut-on faire a ? Ce nest pas dangereux ? Ce ne serait pas trs scuris, si ? 142

ALLER PLUS LOIN

Fig. 12.2 La page se renvoie les donnes On peut trs bien faire cela de faon tout fait scurise, cest juste un peu plus dicile imaginer. Il faut construire le code de votre page formulaire.php en deux grandes parties : si aucun mot de passe na t envoy (ou sil est faux) : acher le formulaire ; si le mot de passe a t envoy et quil est bon : acher les codes secrets. Toute votre page PHP sera donc construite autour dun grand if qui pourrait ressembler quelque chose comme ceci :
<?php // Le mot de passe na pas t envoy ou nest pas bon if (!isset($_POST[mot_de_passe]) OR $_POST[mot_de_passe] != "kangourou") { // Afficher le formulaire de saisie du mot de passe } // Le mot de passe a t envoy et il est bon else { // Afficher les codes secrets } ?>

Voil dans les grandes lignes comment on ferait. Chaque fois que la page formulaire.php est appele, elle dtermine (grce au if) si on lappelle pour acher la partie secrte ou si on lappelle pour acher le formulaire de saisie du mot de passe. Voici alors ce qui se passera : 1. La premire fois que le visiteur charge la page formulaire.php, aucune donne POST nest envoye la page. Cest donc le formulaire qui sache. 2. Une fois quon a envoy le formulaire, la page formulaire.php est recharge et cette fois, elle reoit les donnes POST quon vient denvoyer. Elle peut donc les analyser et, si le mot de passe est bon, elle ache les codes secrets. Sauriez-vous refaire ce TP en une seule page en vous basant sur mes indices ? Essayez ! 143

CHAPITRE 12. TP : PAGE PROTGE PAR MOT DE PASSE Ce sera un trs bon exercice ! Et si vous avez des dicults, nhsitez pas demander de laide sur le forum PHP du Site du Zro. Code web : 932876 Vous pourriez mme aller plus loin, car dans mon schma de code prcdent, je nai pas prvu de cas pour acher Mot de passe incorrect . Cela peut se faire facilement en dcoupant votre page en trois laide dun elseif : formulaire, mot de passe incorrect, codes secrets.

144

Chapitre

13
Dicult :

Variables superglobales, sessions et cookies

ous avez probablement remarqu que les arrays $_GET et $_POST sont des variables un peu particulires : leur nom est crit en majuscules et commence par un underscore (le trait de soulignement), mais surtout ces variables sont gnres automatiquement par PHP. Ce sont ce quon appelle des variables superglobales.

Il existe dautres types de variables superglobales que nous allons dcouvrir dans ce chapitre. Parmi elles, certaines permettent de stocker des informations pendant la dure dune visite, cest le principe des sessions, mais aussi de stocker des informations sur lordinateur de vos visiteurs pendant plusieurs mois, cest le principe des cookies.

145

CHAPITRE 13. VARIABLES SUPERGLOBALES, SESSIONS ET COOKIES

Les variables superglobales


Les variables superglobales sont des variables un peu particulires pour trois raisons : elles sont crites en majuscules et commencent toutes, une exception prs, par un underscore (_). $_GET et $_POST en sont des exemples que vous connaissez ; les superglobales sont des array car elles contiennent gnralement de nombreuses informations ; enn, ces variables sont automatiquement cres par PHP chaque fois quune page est charge. Elles existent donc sur toutes les pages et sont accessibles partout : au milieu de votre code, au dbut, dans les fonctions, etc. Pour acher le contenu dune superglobale et voir ce quelle contient, le plus simple est dutiliser la fonction print_r, puisquil sagit dun array. Exemple :
<pre> <?php print_r($_GET); ?> </pre>

Je vous propose de passer en revue les principales variables superglobales existantes. Nous ne les utiliserons pas toutes, mais nous aurons fait un petit tour dhorizon pour pouvoir nous concentrer ensuite sur les plus utiles dentre elles. $_SERVER : ce sont des valeurs renvoyes par le serveur. Elles sont nombreuses et quelques-unes dentre elles peuvent nous tre dune grande utilit. Je vous propose de retenir au moins $_SERVER[REMOTE_ADDR]. Elle nous donne ladresse IP du client qui a demand voir la page, ce qui peut tre utile pour lidentier. $_ENV : ce sont des variables denvironnement toujours donnes par le serveur. Cest le plus souvent sous des serveurs Linux que lon retrouve des informations dans cette superglobale. Gnralement, on ne trouvera rien de bien utile l-dedans pour notre site web. $_SESSION : on y retrouve les variables de session. Ce sont des variables qui restent stockes sur le serveur le temps de la prsence dun visiteur. Nous allons apprendre nous en servir dans ce chapitre. $_COOKIE : contient les valeurs des cookies enregistrs sur lordinateur du visiteur. Cela nous permet de stocker des informations sur lordinateur du visiteur pendant plusieurs mois, pour se souvenir de son nom par exemple. $_GET : vous la connaissez, elle contient les donnes envoyes en paramtres dans lURL. $_POST : de mme, cest une variable que vous connaissez et qui contient les informations qui viennent dtre envoyes par un formulaire. $_FILES : elle contient la liste des chiers qui ont t envoys via le formulaire prcdent. Vous connaissez dj une bonne partie de ces variables superglobales, comme vous pouvez le constater. Je vous propose dtudier plus en dtail les sessions et les cookies. Avec a nous aurons fait le tour des principaux moyens de transmettre des variables 146

LES SESSIONS de page en page !

Les sessions
Les sessions constituent un moyen de conserver des variables sur toutes les pages de votre site. Jusquici, nous tions parvenus passer des variables de page en page via la mthode GET (en modiant lURL : page.php ?variable=valeur) et via la mthode POST ( laide dun formulaire). Mais imaginez maintenant que vous souhaitez transmettre des variables sur toutes les pages de votre site pendant la dure de la prsence dun visiteur. Ce ne serait pas facile avec GET et POST car ils sont plutt faits pour transmettre les informations une seule fois, dune page une autre. On sait ainsi envoyer dune page une autre le nom et le prnom du visiteur, mais ds quon charge une autre page ces informations sont oublies . Cest pour cela quon a invent les sessions.

Fonctionnement des sessions


Comment sont gres les sessions en PHP ? Voici les trois tapes connatre. 1. Un visiteur arrive sur votre site. On demande crer une session pour lui. PHP gnre alors un numro unique. Ce numro est souvent trs gros et crit en hexadcimal1 , par exemple : a02bbc6198e6e0cc2715047bc3766f. 2. Une fois la session gnre, on peut crer une innit de variables de session pour nos besoins. Par exemple, on peut crer une variable $_SESSION[nom] qui contient le nom du visiteur, $_SESSION[prenom] qui contient le prnom, etc. Le serveur conserve ces variables mme lorsque la page PHP a ni dtre gnre. Cela veut dire que, quelle que soit la page de votre site, vous pourrez rcuprer par exemple le nom et le prnom du visiteur via la superglobale $_SESSION ! 3. Lorsque le visiteur se dconnecte de votre site, la session est ferme et PHP oublie alors toutes les variables de session que vous avez cres. Il est en fait dicile de savoir prcisment quand un visiteur quitte votre site. En eet, lorsquil ferme son navigateur ou va sur un autre site, le vtre nen est pas inform. Soit le visiteur clique sur un bouton Dconnexion (que vous aurez cr) avant de sen aller, soit on attend quelques minutes dinactivit pour le dconnecter automatiquement : on parle alors de timeout. Le plus souvent, le visiteur est dconnect par un timeout. Tout ceci peut vous sembler un peu compliqu, mais cest en fait trs simple utiliser. Vous devez connatre deux fonctions : session_start() : dmarre le systme de sessions. Si le visiteur vient darriver sur le site, alors un numro de session est gnr pour lui. Vous devez appeler cette
1 Ce numro sert didentiant et est appel ID de session (ou PHPSESSID). PHP transmet automatiquement cet ID de page en page en utilisant gnralement un cookie.

147

CHAPITRE 13. VARIABLES SUPERGLOBALES, SESSIONS ET COOKIES fonction au tout dbut de chacune des pages o vous avez besoin des variables de session. session_destroy() : ferme la session du visiteur. Cette fonction est automatiquement appele lorsque le visiteur ne charge plus de page de votre site pendant plusieurs minutes (cest le timeout), mais vous pouvez aussi crer une page Dconnexion si le visiteur souhaite se dconnecter manuellement. Il y a un petit pige : il faut appeler session_start() sur chacune de vos pages AVANT dcrire le moindre code HTML (avant mme la balise < !DOCTYPE>). Si vous oubliez de lancer session_start(), vous ne pourrez pas accder aux variables superglobales $_SESSION.

Exemple dutilisation des sessions


Je vous propose dtudier un exemple concret pour que vous voyiez quel point cest simple utiliser :
<?php // On dmarre la session AVANT dcrire du code HTML session_start(); // On samuse crer quelques variables de session dans $_SESSION $_SESSION[prenom] = Jean; $_SESSION[nom] = Dupont; $_SESSION[age] = 24; ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" > <head> <title>Titre de ma page</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> Salut <?php echo $_SESSION[prenom]; ?> !<br /> Tu es laccueil de mon site (index.php). Tu veux aller sur une autre page ? </p> <p> <a href="mapage.php">Lien vers mapage.php</a><br /> <a href="monscript.php">Lien vers monscript.php</a><br /> <a href="informations.php">Lien vers informations.php</a> <p>

148

LES SESSIONS
</p> </body> </html>

Code web : 146303 Ne vous y trompez pas : on peut crer les variables de session nimporte o dans le code (pas seulement au dbut comme je lai fait ici). La seule chose qui importe, cest que le session_start() soit fait au tout dbut de la page. Comme vous le voyez, jai cr trois variables de session qui contiennent ici le nom, le prnom et lge du visiteur. Jai aussi fait des liens vers dautres pages de mon site. Notez quelque chose de trs important : ces liens sont tout simples et ne transmettent aucune information. Je ne moccupe de rien : ni de transmettre le nom, le prnom ou lge du visiteur, ni de transmettre lID de session. PHP gre tout pour nous. Maintenant, sur toutes les pages de mon site2 , je peux utiliser si je le souhaite les variables $_SESSION[prenom], $_SESSION[nom] et $_SESSION[age] ! Voici par exemple le code source de la page informations.php :
<?php session_start(); // On dmarre la session AVANT toute chose ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" > <head> <title>Titre de ma page</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <p>Re-bonjour !</p> Je me souviens de toi ! Tu tappelles <?php echo $_SESSION[prenom] . . $_SESSION[nom]; ?> !<br /> Et ton ge hummm... Tu as <?php echo $_SESSION[age]; ?> ans, cest a ? :-D </p> </body> </html>
2 Bien

<p>

entendu, il faudra dmarrer le systme de session sur toutes les pages avec session_start().

149

CHAPITRE 13. VARIABLES SUPERGLOBALES, SESSIONS ET COOKIES Code web : 951093 Vous voyez ? On a juste fait dmarrer la session avec un session_start(), puis on a ach les valeurs des variables de session. Et l, magie ! Les valeurs des variables ont t conserves, on na rien eu faire ! En rsum, on peut crer des variables de session comme on cre des variables classiques, condition de les crire dans larray $_SESSION et davoir lanc le systme de sessions avec session_start(). Ces variables sont ainsi conserves de page en page pendant toute la dure de la prsence de votre visiteur. Si vous voulez dtruire manuellement la session du visiteur, vous pouvez faire un lien Dconnexion amenant vers une page qui fait appel la fonction session_destroy(). Nanmoins, sachez que sa session sera automatiquement dtruite au bout dun certain temps dinactivit.

Lutilit des sessions en pratique


Concrtement, les sessions peuvent servir dans de nombreux cas sur votre site3 . Voici quelques exemples : Imaginez un script qui demande un login et un mot de passe pour quun visiteur puisse se connecter (sauthentier). On peut enregistrer ces informations dans des variables de session et se souvenir de lidentiant du visiteur sur toutes les pages du site ! Puisquon retient son login et que la variable de session nest cre que sil a russi sauthentier, on peut lutiliser pour restreindre certaines pages de notre site certains visiteurs uniquement. Cela permet de crer toute une zone dadministration scurise : si la variable de session login existe, on ache le contenu, sinon on ache une erreur. Cela devrait vous rappeler le TP page protge par mot de passe , sauf quici on peut se servir des sessions pour protger automatiquement plusieurs pages. On se sert activement des sessions sur les sites de vente en ligne. Cela permet de grer un panier : on retient les produits que commande le client quelle que soit la page o il est. Lorsquil valide sa commande, on rcupre ces informations et. . . on le fait payer. ;-) Si votre site est hberg chez Free.fr, vous devrez crer un dossier appel sessions la racine de votre FTP pour activer les sessions.

3 Et

pas seulement pour retenir un nom et un prnom !

150

LES COOKIES

Les cookies
Travailler avec des cookies revient peu prs la mme chose quavec des sessions, quelques petites dirences prs que nous allons voir. Voici ce que nous allons faire pour dcouvrir les cookies : 1. on va voir ce quest exactement un cookie4 ; 2. ensuite, nous verrons comment crire un cookie : cest facile faire, si on respecte quelques rgles ; 3. enn, nous verrons comment rcuprer le contenu dun cookie : ce sera le plus simple.

Quest-ce quun cookie ?


Un cookie, cest un petit chier que lon enregistre sur lordinateur du visiteur. Ce chier contient du texte et permet de retenir des informations sur le visiteur. Par exemple, vous inscrivez dans un cookie le pseudo du visiteur, comme a la prochaine fois quil viendra sur votre site, vous pourrez lire son pseudo en allant regarder ce que son cookie contient. Parfois les cookies ont une mauvaise image. On fait souvent lerreur de penser que les cookies sont dangereux . Non, ce ne sont pas des virus, juste de petits chiers texte qui permettent de retenir des informations. Au pire, un site marchand peut retenir que vous aimez les appareils photos numriques et vous acher uniquement des pubs pour des appareils photos, mais cest tout, ces petites btes sont inoensives pour votre ordinateur. Chaque cookie stocke gnralement une information la fois. Si vous voulez stocker le pseudonyme du visiteur et sa date de naissance, il est donc recommand de crer deux cookies. O sont stocks les cookies sur mon disque dur ?

Cela dpend de votre navigateur web. Gnralement on ne touche pas directement ces chiers, mais on peut acher lintrieur du navigateur la liste des cookies qui sont stocks. On peut choisir de les supprimer tout moment. Si vous avez Mozilla Firefox, vous pouvez aller dans le menu Outils / Options / Vie prive et cliquer sur Supprimer des cookies spcifiques. Vous obtenez la liste et la valeur de tous les cookies stocks, comme sur la gure 13.1. Les cookies sont classs par site web. Chaque site web peut crire, comme vous le voyez, plusieurs cookies. Chacun deux a un nom et une valeur (que vous pouvez voir
4 Parce que si a se trouve, il y en a qui croient en ce moment mme que je vais parler de recettes de cuisine !

151

CHAPITRE 13. VARIABLES SUPERGLOBALES, SESSIONS ET COOKIES

Fig. 13.1 Cookies sous Firefox la ligne Contenu sur la gure 13.1). Vous noterez que comme tout cookie qui se respecte, chacun a une date dexpiration. Aprs cette date, ils ne sont plus bons manger ils sont automatiquement supprims par le navigateur. Les cookies sont donc des informations temporaires que lon stocke sur lordinateur des visiteurs. La taille est limite quelques kilo-octets : vous ne pouvez pas stocker beaucoup dinformations la fois, mais cest en gnral susant.

crire un cookie
Comme une variable, un cookie a un nom et une valeur. Par exemple, le cookie pseudo aurait chez moi la valeur M@teo21. Pour crire un cookie, on utilise la fonction PHP setcookie (qui signie Placer un cookie en anglais). On lui donne en gnral trois paramtres, dans lordre suivant : 1. le nom du cookie (ex. : pseudo) ; 2. la valeur du cookie (ex. : M@teo21) ; 3. la date dexpiration du cookie, sous forme de timestamp (ex. : 1090521508). Le paramtre correspondant la date dexpiration du cookie mrite quelques explications. Il sagit dun timestamp, cest--dire du nombre de secondes coules depuis le 1er janvier 1970. Le timestamp est une valeur qui augmente de 1 toutes les secondes. Pour obtenir le timestamp actuel, on fait appel la fonction time(). Pour dnir une date dexpiration du cookie, il faut ajouter au moment actuel le nombre de secondes au bout duquel il doit expirer. Si vous voulez supprimer le cookie dans un an, il vous faudra donc crire : time() + 365*24*3600. Cela veut dire : timestamp actuel + nombre de secondes dans une anne. 152

LES COOKIES Cela aura pour eet de supprimer votre cookie dans exactement un an. Voici donc comment on peut crer un cookie :
<?php setcookie(pseudo, M@teo21, time() + 365*24*3600); ?>

Scuriser son cookie avec le mode httpOnly Je recommande toutefois dactiver loption httpOnly sur le cookie. Sans rentrer dans les dtails, cela rendra votre cookie inaccessible en JavaScript sur tous les navigateurs qui supportent cette option5 . Cette option permet de rduire drastiquement les risques de faille XSS sur votre site, au cas o vous auriez oubli dutiliser htmlspecialchars un moment. Je vous recommande donc de crer votre cookie plutt comme ceci :
<?php setcookie(pseudo, M@teo21, time() + 365*24*3600, null, null, false, true); ?>

Le dernier paramtre true permet dactiver le mode httpOnly sur le cookie, et donc de le rendre en quelque sorte plus scuris. a ne cote rien et vous diminuez le risque quun jour lun de vos visiteurs puisse se faire voler le contenu dun cookie cause dune faille XSS. Les paramtres du milieu sont des paramtres que nous nutilisons pas, je leur ai donc envoy null.

Crer le cookie avant dcrire du HTML Il y a un petit problme avec setcookie. . . Comme pour session_start, cette fonction ne marche QUE si vous lappelez avant tout code HTML (donc avant la balise < !DOCTYPE>). Ne placez donc JAMAIS le moindre code HTML avant dutiliser setcookie. La plupart des gens qui ont des problmes avec setcookie ont fait cette erreur, donc souvenez-vous en ! Voyons maintenant comment je ferais pour crire deux cookies, un qui retient mon pseudo pendant un an, et un autre qui retient le nom de mon pays :
<?php setcookie(pseudo, M@teo21, time() + 365*24*3600, null, null, false, true); // On crit un cookie
5 Cest

le cas de tous les navigateurs rcents.

153

CHAPITRE 13. VARIABLES SUPERGLOBALES, SESSIONS ET COOKIES


setcookie(pays, France, time() + 365*24*3600, null, null, false, true); // On crit un autre cookie... // Et SEULEMENT MAINTENANT, on peut commencer crire du code html ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" > <head> <title>Ma super page PHP</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> etc.

Et voil, les cookies sont crits ! Comme vous le voyez, pour crire deux cookies il faut appeler deux fois setcookie.

Acher un cookie
Cest la partie la plus simple. Avant de commencer travailler sur une page, PHP lit les cookies du client pour rcuprer toutes les informations quils contiennent. Ces informations sont places dans la superglobale $_COOKIE, sous forme darray, comme dhabitude. De ce fait, si je veux ressortir le pseudo du visiteur que javais inscrit dans un cookie, il sut dcrire : $_COOKIE[pseudo]. Ce qui nous donne un code PHP tout bte pour acher de nouveau le pseudo du visiteur :
<p>

H ! Je me souviens de toi !<br /> Tu tappelles <?php echo $_COOKIE[pseudo]; ?> et tu viens de <?php echo $_COOKIE[pays]; ?> cest bien a ? </p>

Comme vous le voyez encore une fois, le gros avantage cest que les superglobales sont accessibles partout. Vous avez besoin de savoir ce que contient le cookie pseudo ? Achez donc le contenu de la superglobale $_COOKIE[pseudo] ! noter que si le cookie nexiste pas, la variable superglobale nexiste pas. Il faut donc faire un isset pour vrier si le cookie existe ou non. 154

LES COOKIES Les cookies viennent du visiteur. Comme toute information qui vient du visiteur, elle nest pas sre. Nimporte quel visiteur peut crer des cookies et envoyer ainsi de fausses informations votre site. Souvenez-vous en lorsque vous lisez les cookies du visiteur : il peut les avoir modis, donc soyez prudents et nayez pas une conance aveugle en leur contenu !

Modier un cookie existant


Vous vous demandez peut-tre comment modier un cookie dj existant ? L encore, cest trs simple : il faut refaire appel setcookie en gardant le mme nom de cookie, ce qui crasera lancien. Par exemple, si jhabite maintenant en Chine, je ferai :
setcookie(pays, Chine, time() + 365*24*3600, null, null, false, true);

Notez qualors le temps dexpiration du cookie est remis zro pour un an.

En rsum
Les variables superglobales sont des variables automatiquement cres par PHP. Elles se prsentent sous la forme darrays contenant dirents types dinformations. Dans les chapitres prcdents, nous avons dcouvert deux superglobales essentielles : $_GET (qui contient les donnes issues de lURL) et $_POST (qui contient les donnes issues dun formulaire). La superglobale $_SESSION permet de stocker des informations qui seront automatiquement transmises de page en page pendant toute la dure de visite dun internaute sur votre site. Il faut au pralable activer les sessions en appelant la fonction session_start(). La superglobale $_COOKIE reprsente le contenu de tous les cookies stocks par votre site sur lordinateur du visiteur. Les cookies sont de petits chiers que lon peut crire sur la machine du visiteur pour retenir par exemple son nom. On cre un cookie avec la fonction setcookie().

155

CHAPITRE 13. VARIABLES SUPERGLOBALES, SESSIONS ET COOKIES

156

Chapitre

14
Dicult :

Lire et crire dans un chier

es variables sont simples utiliser, mais elles ne contiennent que des informations temporaires. La dure de vie dune variable nest en eet jamais trs longue. Or, vous aurez certainement besoin sur votre site de stocker des informations dnitivement.

Par exemple, il est impossible de stocker les messages dun forum dans des variables. . . puisque celles-ci seront supprimes la n de lexcution de la page ! Pour stocker ces informations longtemps, il faut les crire sur le disque dur. Quoi de plus logique pour cela que de crer des chiers ? PHP permet justement denregistrer des donnes dans des chiers sur le disque dur du serveur.

157

CHAPITRE 14. LIRE ET CRIRE DANS UN FICHIER

Autoriser lcriture de chiers (chmod)


Pour que PHP puisse crer des chiers, il doit avoir accs un dossier qui lui en autorise la cration. Il faut en eet donner le droit PHP de crer et modier les chiers, sinon celui-ci ne pourra rien faire. Pour crer ces droits, on dit en gnral quon doit modier le CHMOD du chier ou du dossier. Cest le nom de la commande qui permet de modier les droits sous Linux. Sous Windows, vous nen avez probablement jamais entendu parler, tout simplement parce que a nexiste pas. Mais le serveur de votre site, lui, est le plus souvent sous Linux. Et sous Linux, on utilise ce quon appelle le CHMOD pour grer les droits. Le CHMOD est un nombre trois chires que lon attribue un chier (par exemple 777). Selon la valeur de ce nombre, Linux autorisera (ou non) la modication du chier. Le problme, cest que Linux nautorise gnralement pas les modications de chiers par un script PHP. Or, cest justement ce quon veut faire. Alors, comment va-t-on faire pour sen sortir ? En modiant le CHMOD, pardi ! Il va falloir passer par. . . votre logiciel FTP ! Oui, celui-l mme qui vous sert envoyer vos pages sur le web. En ce qui me concerne, jutilise FileZilla1 . Connectez-vous votre serveur, et faites un clic-droit sur lun des chiers, pour obtenir la gure 14.1.

Fig. 14.1 Modier les permissions dun chier En gnral, vous devriez avoir un menu CHMOD ou Permissions de chier (comme moi). Cela devrait ouvrir une fentre qui ressemble peu prs la gure 14.2. Et cest l que se trouve la solution tous nos problmes ! Sans rentrer dans les dtails parce quil nest pas question de faire un cours sur Linux ici, voil comment a fonctionne : il y a trois types de personnes qui ont le droit de lire/modier des chiers. Le propritaire : cest lutilisateur sous Linux qui a cr le chier. Lui, il a en
1 Vous

pouvez utiliser celui que vous voulez, la manipulation est quasiment la mme.

158

OUVRIR ET FERMER UN FICHIER

Fig. 14.2 CHMOD 777 pour activer lcriture gnral tous les droits : lire, crire, excuter. Selon les droits quil possde, le premier chire du CHMOD change. Ici, cest 7 : a veut dire quil a tous les droits. Le groupe : a ne nous concerne pas trop l non plus. Ce sont les droits du groupe dutilisateurs auquel appartient le chier. Cela correspond au deuxime chire du CHMOD (ici : 7). Permissions publiques : ah ! L, a devient intressant. Les permissions publiques concernent tout le monde, cest--dire mme vos chiers PHP. Cest le troisime chire du CHMOD (par dfaut 5, il faut mettre cette valeur 7). Si vous rentrez 777 comme valeur pour le CHMOD, cela signie que tous les programmes du serveur ont le droit de modier le chier, notamment PHP. Il faut donc rentrer 777 pour que PHP puisse modier le chier en question. Vous pouvez aussi modier le CHMOD dun dossier. Cela dterminera si on a le droit de lire/crire dans ce dossier. Cela vous sera notamment utile si vous avez besoin de crer des chiers dans un dossier en PHP. Pour ceux qui veulent en savoir plus sur les CHMOD, je traite le sujet beaucoup plus en dtail dans mon cours sur Linux. Nhsitez pas aller lire le tutoriel si le sujet vous intresse. Code web : 525702

Ouvrir et fermer un chier


Avant de lire/crire dans un chier, il faut dabord louvrir. Commencez par crer un chier compteur.txt (par exemple). Envoyez-le sur votre serveur avec votre logiciel FTP, et appliquez-lui un CHMOD 777 comme on vient dapprendre le faire. 159

CHAPITRE 14. LIRE ET CRIRE DANS UN FICHIER Maintenant, on va crer un chier PHP qui va travailler sur compteur.txt. Votre mission, si vous lacceptez : compter le nombre de fois quune page a t vue sur votre site et enregistrer ce nombre dans ce chier. Voici comment nous allons procder :
<?php // 1 : on ouvre le fichier $monfichier = fopen(compteur.txt, r+); // 2 : on fera ici nos oprations sur le fichier... // 3 : quand on a fini de lutiliser, on ferme le fichier fclose($monfichier); ?>

Il y a trois tapes respecter. 1. On ouvre le chier avec fopen. Cette fonction renvoie une information que vous devez mettre dans une variable (ici : $monfichier). Cela nous sera utile tout lheure pour fermer le chier. On indique tout dabord fopen le chier quon veut ouvrir (compteur.txt), puis comment on veut louvrir (ici jai mis r+). Voici, regroupes dans le tableau ci-dessous, les principales possibilits notre disposition. Mode r r+ Explication Ouvre le chier en lecture seule. Cela signie que vous pourrez seulement lire le chier. Ouvre le chier en lecture et criture. Vous pourrez non seulement lire le chier, mais aussi y crire (on lutilisera assez souvent en pratique). Ouvre le chier en criture seule. Mais il y a un avantage : si le chier nexiste pas, il est automatiquement cr. Ouvre le chier en lecture et criture. Si le chier nexiste pas, il est cr automatiquement. Attention : le rpertoire doit avoir un CHMOD 777 dans ce cas ! noter que si le chier existe dj, le texte sera rajout la n.

a a+

Ici, on a cr le chier avant, donc pas besoin dutiliser a+. 2. On fait nos oprations de lecture/criture sur le chier. Nous allons voir comment a fonctionne un peu plus loin. 3. Enn, quand on a ni dutiliser le chier, on fait un fclose pour le fermer. On doit prciser quel chier doit tre ferm : mettez-y la variable $monfichier pour que PHP sache duquel il sagit, et cest bon. 160

LIRE ET CRIRE DANS UN FICHIER Vous ntes absolument pas obligs de donner lextension .txt votre chier. Vous pouvez lappeler comme vous voulez : compteur.cpt, compteur.num, ou mme compteur tout court.

Lire et crire dans un chier


Maintenant que nous savons ouvrir et fermer notre chier, nous allons apprendre le lire et le modier.

Lire
Pour lire, on a deux possibilits : lire caractre par caractre avec la fonction fgetc ; lire ligne par ligne avec fgets. En gnral, on se dbrouillera pour mettre une information par ligne dans notre chier. On se sert donc assez peu de fgetc qui est plutt lourd utiliser2 . Dans notre cas, on va supposer que notre chier ne contient quune ligne : le nombre de pages qui ont t vues sur le site. Pour rcuprer ce nombre, il faudra procder comme ceci :
<?php // 1 : on ouvre le fichier $monfichier = fopen(compteur.txt, r+); // 2 : on lit la premire ligne du fichier $ligne = fgets($monfichier); // 3 : quand on a fini de lutiliser, on ferme le fichier fclose($monfichier); ?>

Il faut indiquer fgets le chier lire. On lui donne notre variable $monfichier qui lui permettra de lidentier. fgets renvoie toute la ligne (la fonction arrte la lecture au premier saut de ligne). Donc notre variable $ligne devrait contenir la premire ligne du chier. Et si mon chier fait quinze lignes, comment je fais pour toutes les lire ?

Il faut faire une boucle. Un premier fgets vous donnera la premire ligne. Au second tour de boucle, le prochain appel fgets renverra la deuxime ligne, et ainsi de suite.
2 Il

faudrait faire une boucle pour lire caractre par caractre.

161

CHAPITRE 14. LIRE ET CRIRE DANS UN FICHIER Cest un peu lourd, mais si on stocke assez peu dinformations dans le chier, cela peut sure. Sinon, si on a beaucoup dinformations stocker, on prfrera utiliser une base de donnes (on en parlera dans la prochaine partie).

crire
Pour lcriture, on na quune seule possibilit : utiliser fputs. Cette fonction va crire la ligne que vous voulez dans le chier. Elle sutilise comme ceci :
<?php fputs($monfichier, Texte crire); ?>

Toutefois, il faut savoir o lon crit le texte. En eet, le fonctionnement dun chier est assez trange. . . 1. Vous louvrez avec fopen. 2. Vous lisez par exemple la premire ligne avec fgets. 3. Oui mais voil : maintenant, le curseur de PHP se trouve la n de la premire ligne (vu quil vient de lire la premire ligne), comme dans la gure 14.3.

Fig. 14.3 Le curseur de PHP est la n de la premire ligne Si vous faites un fputs juste aprs, il va crire la suite ! Pour viter a, on va utiliser la fonction fseek qui va replacer le curseur o lon veut dans le chier. En loccurence, on va replacer le curseur au dbut du chier en faisant : fseek($monfichier, 0) ; Notre curseur sera alors repositionn au dbut, voyez donc la gure 14.4.

Fig. 14.4 Le curseur de PHP est replac lendroit choisi Si vous avez ouvert le chier avec le mode a ou a+, toutes les donnes que vous crirez seront toujours ajoutes la n du chier. La fonction fseek naura donc aucun eet dans ce cas. 4. Ouf, notre curseur est au dbut du chier, on peut maintenant faire un fputs. La ligne va scrire par-dessus lancienne, ce qui fait que lancien texte sera cras (remplac par le nouveau). 162

LIRE ET CRIRE DANS UN FICHIER Pour y voir un peu plus clair, je vous propose ce code source qui compte le nombre de fois que la page a t vue :
<?php $monfichier = fopen(compteur.txt, r+); $pages_vues = fgets($monfichier); // On lit la premire ligne (nombre de pages vues) $pages_vues++; // On augmente de 1 ce nombre de pages vues fseek($monfichier, 0); // On remet le curseur au dbut du fichier fputs($monfichier, $pages_vues); // On crit le nouveau nombre de pages vues fclose($monfichier); echo <p>Cette page a t vue . $pages_vues . fois !</p>; ?>

Code web : 666284 Ce ntait pas si dur, vous voyez. Voici la description des quatre lignes du milieu (les plus importantes) : 1. on rcupre la premire ligne du chier, qui est le nombre de pages qui ont t vues pour le moment sur le site ; 2. on ajoute 1 la variable $pages_vues. Si elle valait 15, elle vaudra dsormais 16 ; 3. on replace notre fameux curseur au dbut du chier (parce que sinon, il se trouvait la n de la premire ligne et on aurait crit la suite) ; 4. on crit notre nouveau nombre de pages vues dans le chier, en crasant lancien nombre. Si vous avez oubli de mettre un CHMOD 777 sur le chier compteur.txt, vous aurez lerreur suivante : Warning : fopen(compteur.txt) : failed to open stream : Permission denied . Ici, PHP essaie de vous dire quil na pas russi ouvrir le chier car il na pas le droit dcrire dedans. Il faut donc absolument mettre ce CHMOD si vous voulez pouvoir toucher au chier ! Voil, vous venez de voir comment on se sert dun chier : ouverture, lecture, criture, fermeture. Pour un gros chier, cela devient vite compliqu, mais pour un petit chier comme celui-ci, cela convient trs bien. Dans la suite de ce cours, nous allons dcouvrir une mthode plus ecace pour stocker des donnes : nous allons utiliser une base de donnes MySQL. 163

CHAPITRE 14. LIRE ET CRIRE DANS UN FICHIER

En rsum
PHP permet denregistrer des informations dans des chiers sur le serveur. Il faut au pralable sassurer que les chiers autorisent PHP les modier. Pour cela, il faut changer les permissions du chier (on parle de CHMOD) laide dun logiciel FTP comme FileZilla. Donnez la permission 777 au chier pour permettre PHP de travailler dessus. La fonction fopen permet douvrir le chier, fgets de le lire ligne par ligne et fputs dy crire une ligne. moins de stocker des donnes trs simples, lutilisation des chiers nest pas vraiment la technique la plus adapte pour enregistrer des informations. Il est vivement recommand de faire appel une base de donnes.

164

Troisime partie

Stocker des informations dans une base de donnes

165

Chapitre

15
Dicult :

Prsentation des bases de donnes

our linstant, vous avez dcouvert le fonctionnement du langage PHP mais vous ne vous sentez probablement pas encore capables de crer de vrais sites web avec ce que vous avez appris. Cest parfaitement normal car il vous manque un lment crucial : la base de donnes. Une base de donnes permet denregistrer des donnes de faon organise et hirarchise. Certes, vous connaissez les variables, mais celles-ci restent en mmoire seulement le temps de la gnration de la page. Vous avez aussi appris crire dans des chiers, mais cela devient vite trs compliqu ds que vous avez beaucoup de donnes enregistrer. Or, il va bien falloir stocker quelque part la liste de vos membres, les messages de vos forums, les options de navigation des membres. . . Les bases de donnes constituent le meilleur moyen de faire cela de faon simple et propre. Nous allons les tudier durant toute cette partie du livre !

167

CHAPITRE 15. PRSENTATION DES BASES DE DONNES

Le langage SQL et les bases de donnes


La base de donnes (BDD) est un systme qui enregistre des informations. Un peu comme un chier texte ? Non, pas vraiment. Ce qui est trs important ici, cest que ces informations sont toujours classes. Et cest a qui fait que la BDD est si pratique : cest un moyen simple de ranger des informations. Et si je prfre rester dsordonn ? Si je nai pas envie de classer mes informations ? Est-on oblig de classer chaque information quon enregistre ? Cest un peu ce que je me disais au dbut. . . Classer certaines choses, daccord, mais il me semblait que je nen aurais besoin que trs rarement. Grave erreur ! Vous allez le voir : 99 % du temps, on range ses informations dans une base de donnes. Pour le reste, on peut les enregistrer dans un chier comme on a appris le faire. . . mais quand on a got aux bases de donnes, on peut dicilement sen passer ensuite ! Imaginez par exemple une armoire, dans laquelle chaque dossier est sa place. Quand tout est sa place, il est beaucoup plus facile de retrouver un objet, nest-ce pas ? Eh bien l, cest pareil : en classant les informations que vous collectez (concernant vos visiteurs par exemple), il vous sera trs facile de rcuprer plus tard ce que vous cherchez.

Les SGBD soccupent du stockage


Je vous ai prsent brivement les SGBD (Systmes de Gestion de Bases de Donnes) dans le premier chapitre de ce livre. Les SGBD sont les programmes qui se chargent du stockage de vos donnes. Les plus connus sont, pour rappel : MySQL : libre et gratuit, cest probablement le SGBD le plus connu. Nous lutiliserons dans cette partie ; PostgreSQL : libre et gratuit comme MySQL, avec plus de fonctionnalits mais un peu moins connu ; SQLite : libre et gratuit, trs lger mais trs limit en fonctionnalits ; Oracle : utilis par les trs grosses entreprises ; sans aucun doute un des SGBD les plus complets, mais il nest pas libre et on le paie le plus souvent trs cher ; Microsoft SQL Server : le SGBD de Microsoft. Il faut donc choisir le SGBD que vous allez utiliser pour stocker les donnes. Je vous recommande de travailler plutt avec les SGBD libres et gratuits, tels que MySQL, PostgreSQL et SQLite. Aprs, tout est question de got et des fonctionnalits que vous recherchez. MySQL est un bon compromis. 168

LE LANGAGE SQL ET LES BASES DE DONNES Nous allons utiliser MySQL, mais sachez que lessentiel de ce que vous allez apprendre fonctionnera de la mme manire avec un autre SGBD. Cette partie est construite an que vous ayez le moins de choses possible apprendre de nouveau si vous choisissez de changer de SGBD.

Vous donnez les ordres au SGBD en langage SQL


Vous allez devoir communiquer avec le SGBD pour lui donner lordre de rcuprer ou denregistrer des donnes. Pour lui parler , on utilise le langage SQL. La bonne nouvelle, cest que le langage SQL est un standard, cest--dire que quel que soit le SGBD que vous utilisez, vous vous servirez du langage SQL. La mauvaise, cest quil y a en fait quelques petites variantes dun SGBD lautre, mais cela concerne gnralement les commandes les plus avances. Comme vous vous en doutez, il va falloir apprendre le langage SQL pour travailler avec les bases de donnes. Ce langage na rien voir avec le PHP, mais nous allons imprativement en avoir besoin. Voici un exemple de commande en langage SQL, pour vous donner une ide :
SELECT id, auteur, message, datemsg FROM livreor ORDER BY datemsg DESC

Le principal objectif de cette partie du livre sera dapprendre utiliser ce langage SQL pour que vous soyez capables de donner nimporte quel ordre la base de donnes, comme par exemple : Rcupre-moi les 10 dernires news de mon site , Supprime le dernier message post dans ce forum , etc.

PHP fait la jonction entre vous et MySQL


Pour compliquer un petit peu laaire (sinon, ce nest pas rigolo), on ne va pas pouvoir parler MySQL directement. Eh non, seul PHP peut le faire ! Cest donc PHP qui va faire lintermdiaire entre vous et MySQL. On devra demander PHP : Va dire MySQL de faire ceci. Je crois quun petit schma ne serait pas du luxe. . . Voyez la gure 15.1. Voici ce qui peut se passer lorsque le serveur a reu une demande dun client qui veut poster un message sur vos forums : 1. le serveur utilise toujours PHP, il lui fait donc passer le message ; 2. PHP eectue les actions demandes et se rend compte quil a besoin de MySQL. En eet, le code PHP contient un endroit Va demander MySQL denregistrer ce message . Il fait donc passer le travail MySQL ; 3. MySQL fait le travail que PHP lui avait soumis et lui rpond O.K., cest bon ! ; 4. PHP renvoie au serveur que MySQL a bien fait ce qui lui tait demand. 169

CHAPITRE 15. PRSENTATION DES BASES DE DONNES

Fig. 15.1 Communication entre PHP et MySQL Maintenant que nous avons fait les prsentations, il va falloir dcouvrir comment est organise une base de donnes. Bien en comprendre lorganisation est en eet absolument indispensable.

Structure dune base de donnes


Avec les bases de donnes, il faut utiliser un vocabulaire prcis. Heureusement, vous ne devriez pas avoir trop de mal vous en souvenir, vu quon va se servir dune image : celle dune armoire. coutez-moi attentivement et nhsitez pas lire lentement, plusieurs fois si cest ncessaire. Je vous demande dimaginer ce qui suit. Larmoire est appele la base dans le langage SQL. Cest le gros meuble dans lequel les secrtaires ont lhabitude de classer les informations. Dans une armoire, il y a plusieurs tiroirs. Un tiroir, en SQL, cest ce quon appelle une table. Chaque tiroir contient des donnes direntes. Par exemple, on peut imaginer un tiroir qui contient les pseudonymes et infos sur vos visiteurs, un autre qui contient les messages posts sur votre forum. . . Mais que contient une table ? Cest l que sont enregistres les donnes, sous la forme dun tableau. Dans ce tableau, les colonnes sont appeles des champs, et les lignes sont appeles des entres. Une table est donc reprsente sous la forme dun tableau ; par exemple, le tableau 15.1 vous montre quoi peut ressembler le contenu dune table appele visiteurs . Table visiteurs Ce tableau reprsente le contenu dune table (cest--dire le tiroir de larmoire). Les champs dans cet exemple sont : Numro , Pseudonyme , E-mail et ge . Chaque ligne est une entre. Ici, il y en a quatre, mais une table peut trs bien contenir 100, 1 000, ou mme 100 0001 entres.
1 Je

vous souhaite davoir autant de visiteurs ! ;-)

170

STRUCTURE DUNE BASE DE DONNES

Tab. 15.1 Table visiteurs Numro 1 2 3 4 ... Pseudonyme Kryptonic Serial_Killer M@teo21 Bibou ... E-mail kryptonic@free.fr serialkiller@unitedgamers.com top_secret@siteduzero.com bibou557@laposte.net ... ge 24 16 18 29 ...

Trs souvent, on cre un champ Numro , aussi appel ID (identiant). Comme nous le verrons plus tard, il est trs pratique de numroter ses entres, mme si ce nest pas obligatoire. Et pour nir, voici lindispensable schma, en gure 15.2, pour que tout a soit clair.

Fig. 15.2 Organisation dune base de donnes MySQL La base de donnes contient plusieurs tables (on peut en mettre autant que lon veut lintrieur). Chaque table est en fait un tableau o les colonnes sont appeles champs et o les lignes sont appeles entres. Pour vous donner quelques exemples concrets, voici quelques noms de tables que lon peut tre amen crer pour les besoins de son site web : news : stocke toutes les news qui sont aches laccueil ; livre_or : stocke tous les messages posts sur le livre dor ; forum : stocke tous les messages posts sur le forum ; newsletter : stocke les adresses e-mail de tous les visiteurs inscrits la newsletter.

Voil, vous devriez commencer comprendre pourquoi vous allez avoir besoin dune BDD sur votre site. Si quelque chose ne vous parat pas clair, si vous avez limpression de mlanger un peu bases , tables , champs ou entres , relisez de nouveau cette partie. Il faut que vous soyez capables de reproduire le schma tout seuls sur un bout de papier. 171

CHAPITRE 15. PRSENTATION DES BASES DE DONNES

Mais o sont enregistres les donnes ?


Avant de terminer le chapitre, voici une question que lon se pose frquemment quand on lit ce genre de chapitre sur les bases de donnes pour la premire fois. Ils sont bien jolis ces tableaux et ces schmas, ces bases, ces champs. . . Mais je vois pas ce que cest concrtement, moi ! O MySQL enregistre-t-il les donnes ? En fait, tout ce que je viens de vous montrer, cest une faon de visualiser la chose. Il faut que vous imaginiez que la base de donnes gre les informations sous forme de tableaux, parce que cest la meilleure reprsentation quon peut sen faire. Mais concrtement, quand MySQL enregistre des informations, il les crit bien quelque part. Oui, comme tout le monde, il les enregistre dans des chiers ! Ces chiers sont quelque part sur votre disque dur, mais il ne faut jamais les ouvrir et encore moins les modier directement. Il faut toujours parler avec MySQL qui va se charger dextraire et de modier les informations dans ces chiers. Chaque SGBD a sa propre faon denregistrer les donnes, mais aucun deux ne peut y chapper : pour que les donnes restent enregistres, il faut les stocker dans des chiers sur le disque dur. Par exemple, avec MySQL sous Windows, si vous utilisez WAMP, vous devriez trouver les chiers o sont stockes les informations dans C:\wamp\mysql\data. Je vous recommande trs fortement de ne pas y toucher car ils ne sont pas prvus pour tre modis directement ! Dans la pratique, on nira jamais toucher ces chiers directement. On demandera TOUJOURS MySQL denregistrer, ou daller lire des choses. Aprs, cest lui qui se dbrouille pour classer a comme il veut dans ses chiers. Et cest justement a, le gros avantage de la base de donnes : pas de prise de tte pour le rangement des informations. Vous demandez MySQL de vous sortir toutes les news de votre site enregistres de fvrier juillet : il va lire dans ses chiers, et vous ressort les rponses. Vous vous contentez de dialoguer avec MySQL. Lui se charge du sale boulot, cest--dire de ranger vos donnes dans ses chiers.

En rsum
Une base de donnes est un outil qui stocke vos donnes de manire organise et vous permet de les retrouver facilement par la suite. On communique avec MySQL grce au langage SQL. Ce langage est commun tous les systmes de gestion de base de donnes2 . PHP fait lintermdiaire entre vous et MySQL. Une base de donnes contient plusieurs tables. Chaque table est un tableau o les colonnes sont appeles champs et les lignes entres .
2 Avec

quelques petites dirences nanmoins pour certaines fonctionnalits plus avances.

172

Chapitre

16
Dicult :

phpMyAdmin

ous allons maintenant faire des manipulations sur une base de donnes. Vous allez voir ce que peuvent contenir une base et ses tables.

Il existe plusieurs faons daccder sa base de donnes et dy faire des modications. On peut utiliser une ligne de commande (console), excuter les requtes en PHP ou faire appel un programme qui nous permet davoir rapidement une vue densemble. Ici, je vous propose de dcouvrir phpMyAdmin, un des outils les plus connus permettant de manipuler une base de donnes MySQL. phpMyAdmin est livr avec WAMP, vous allez donc pouvoir vous en servir tout de suite. Presque tous les hbergeurs permettent dutiliser phpMyAdmin ; renseignez-vous auprs du vtre pour savoir comment y accder.

173

CHAPITRE 16. PHPMYADMIN

Crer une table


La premire chose que je vous demande de faire, cest douvrir phpMyAdmin. Pour cela, dmarrez WAMP, faites un clic gauche sur licne de la barre des tches et allez dans phpMyAdmin . Vous y tes. ;-) phpMyAdmin nest pas un programme mais un ensemble de pages PHP toutes prtes dont on se sert pour gagner du temps. On commence donc simplement : dans ce chapitre, nous ne coderons pas pour le moment ; nous allons simplement manipuler. Laccueil de phpMyAdmin ressemble la gure 16.1.

Fig. 16.1 Accueil de phpMyAdmin Vous pouvez remarquer deux endroits importants, signals par des numros sur ma capture dcran. 1. Liste des bases : cest la liste de vos bases de donnes. Le nombre entre parenthses est le nombre de tables quil y a dans la base. Sur ma capture dcran, on a donc deux bases : information_schema, qui contient 28 tables, et mysql, qui en contient 23. 2. Crer une base : pour crer une nouvelle base de donnes, entrez un nom dans le champ de formulaire droite, cliquez sur Crer et hop ! cest fait. Pour le moment, deux bases existent dj : information_schema et mysql. Ny touchez pas, elles servent au fonctionnement interne de MySQL. Nous allons maintenant crer une nouvelle base test dans laquelle nous travaillerons 174

CRER UNE TABLE tout le temps par la suite. Utilisez le formulaire droite pour crer cette base : entrez le nom test et cliquez sur le bouton Crer. Lcran de la gure 16.2 devrait alors sacher si la base a bien t cre.

Fig. 16.2 La base de test a t cre, vide On vous indique quaucune table na t trouve dans la base. Et si on en crait une ? Dans le champ Crer une nouvelle table sur la base test , entrez le nom news et le nombre de champs 3, comme vous le montre la gure 16.3.

Fig. 16.3 Crer une table Cliquez sur Excuter . La table nest pas immdiatement cre : il faut maintenant indiquer le nom des champs et les donnes quils peuvent contenir. Je vous propose de faire simple car pour linstant on cherche juste tester phpMyAdmin. Pour cette table, on va crer les trois champs suivants. id : comme bien souvent, vous allez devoir crer un champ appel id (prononcez langlaise aille di ). Cest le numro didentication. Grce lui, toutes vos entres seront numrotes, ce qui est bien pratique. Il y aura ainsi la news no 1, no 2, no 3, etc. titre : ce champ contiendra le titre de la news. contenu : enn, ce champ contiendra la news elle-mme. Soyons clairs : je ne suis pas en train de vous apprendre crer un systme de news pour votre site. Nous aurons loccasion dy travailler un peu plus tard. Pour le moment nous cherchons seulement dcouvrir le fonctionnement de phpMyAdmin. 175

CHAPITRE 16. PHPMYADMIN Vous devriez avoir la gure 16.4 sous les yeux.

Fig. 16.4 Cration dune table MySQL Chaque colonne reprsente un champ. Nous avons demand trois champs, il y a donc trois colonnes. phpMyAdmin vous demande beaucoup dinformations mais rassurez-vous, il nest pas ncessaire de tout remplir. La plupart du temps, les sections les plus intressantes seront : Champ : permet de dnir le nom du champ (trs important !) ; Type : le type de donnes que va stocker le champ (nombre entier, texte, date. . .) ; Taille/Valeurs : permet dindiquer la taille maximale du champ, utile pour le type VARCHAR notamment, an de limiter le nombre de caractres autoriss ; Index : active lindexation du champ. Ce mot barbare signie dans les grandes lignes que votre champ sera adapt aux recherches. Le plus souvent, on utilise lindex PRIMARY sur les champs de type id ; AUTO_INCREMENT : permet au champ de sincrmenter tout seul chaque nouvelle entre. On lutilise frquemment sur les champs de type id. Je vous propose de remplir le formulaire comme je lai fait. Veillez bien cocher AUTO_INCREMENT et dnir un index PRIMARY sur le champ id. Une fois que cest fait, cliquez sur le bouton Sauvegarder en bas de la page. Votre table est cre ! Avant daller plus loin, je voudrais revenir un peu plus en dtail sur les types de champs et les index, notamment lindex PRIMARY quon a utilis.

Les types de champs MySQL


Si vous droulez la liste des types que vous propose MySQL, vous devriez tomber la renverse, comme lillustre la gure 16.5. Alors que PHP ne propose que quelques types de donnes que lon connat bien main176

CRER UNE TABLE

Fig. 16.5 Types de donnes MySQL tenant (int, string, bool. . .), MySQL propose une quantit trs importante de types de donnes. En fait, ceux-ci sont classs par catgories. NUMERIC : ce sont les nombres. On y trouve des types ddis aux petits nombres entiers (TINYINT), aux gros nombres entiers (BIGINT), aux nombres dcimaux, etc. DATE and TIME : ce sont les dates et les heures. De nombreux types dirents permettent de stocker une date, une heure, ou les deux la fois. STRING : ce sont les chanes de caractres. L encore, il y a des types adapts toutes les tailles. SPATIAL : cela concerne les bases de donnes spatiales, utiles pour ceux qui font de la cartographie. Ce ne sera pas notre cas, donc nous nen parlerons pas ici. En fait, phpMyAdmin a eu la bonne ide de proposer au tout dbut de cette liste les quatre types de donnes les plus courants : INT : nombre entier ; VARCHAR : texte court (entre 1 et 255 caractres) ; TEXT : long texte (on peut y stocker un roman sans problme) ; DATE : date (jour, mois, anne).

Nous naurons besoin de jongler quentre ces quatre types, donc ce sont eux quil faut retenir. Cela couvrira 99 % de nos besoins. Une petite remarque propos de VARCHAR : cest un type adapt aux textes courts, comme le titre dune news de votre site. Sa seule exigence est que vous devez indiquer la taille maximale du champ (entre 1 et 255). Si vous ne le faites pas, vous ne pourrez pas crer la table. Si vous ne savez pas combien limiter votre champ, vous pouvez mettre la valeur maximale (255) comme je lai fait dans lexemple prcdent.

177

CHAPITRE 16. PHPMYADMIN

Les cls primaires


Toute table doit possder un champ qui joue le rle de cl primaire. La cl primaire permet didentier de manire unique une entre dans la table. En gnral, on utilise le champ id comme cl primaire, comme on vient de le faire. Chaque news de votre site doit pouvoir tre identie de manire unique. Le moyen le plus simple pour cela est de lui donner un numro unique, dans un champ nomm id . Il ne peut pas y avoir deux news avec le mme id ! Il en irait de mme pour les autres tables de votre site : par exemple, chaque membre doit se voir attribuer un numro unique. Si deux membres ont le mme numro, on ne pourra pas les direncier ! Il est vital que chaque table possde sa cl primaire. On ne vous interdira pas de crer des tables sans cl primaire, mais leurs performances seront extrmement rduites. Je vous conseille donc de prendre le rexe de crer chaque fois ce champ id en lui donnant lindex PRIMARY, ce qui aura pour eet den faire une cl primaire. Vous en proterez en gnral pour cocher la case AUTO_INCREMENT an que ce champ gre lui-mme les nouvelles valeurs automatiquement (1, 2, 3, 4. . .).

Modier une table


gauche de votre cran, la table news que vous venez de crer devient visible, telle que vous la voyez sur la gure 16.6.

Fig. 16.6 Liste des tables Si vous cliquez sur le mot news , le contenu de la table sache droite de lcran. Si vous cliquez sur la petite image de tableau gauche, phpMyAdmin vous prsentera la structure de la table. Actuellement, comme notre table est vide (elle ne contient aucune entre), cest la structure de la table (gure 16.7) qui sachera dans les deux cas. Ce tableau vous rappelle de quels champs est constitue votre table : cest sa structure. Notez que le champ id est soulign car cest la cl primaire de la table. Il ny a rien de bien intressant faire ici, mais sachez quil est possible dajouter ou de supprimer des champs tout moment. Ce nest pas parce que votre table a t cre quelle est ge. Vous avez des options pour renommer les champs, les supprimer, en ajouter, etc. Jetez dj un il aux onglets du haut : Structure , Acher , SQL , etc. Cela vous amnera vers direntes options que nous verrons plus loin. Nous allons 178

MODIFIER UNE TABLE

Fig. 16.7 Structure de la table news commencer par nous intresser longlet Insrer , qui va nous permettre dajouter des entres la table. Une page souvre dans laquelle vous pouvez entrer des valeurs pour chacun des champs. Cela va tre pour nous loccasion dinsrer notre premire news, comme le suggre la gure 16.8.

Fig. 16.8 Insertion dun nouvel enregistrement Seule la colonne Valeur nous intresse. Vous pouvez entrer une valeur pour chacun des trois champs. Vous remarquerez que je nai pas mis de valeur pour lid : cest normal, le numro did est automatiquement calcul grce loption auto_increment. Ne vous en occupez pas et choisissez plutt un titre puis insrez un contenu. Lid de la premire news sera 1, celui de la seconde sera 2, etc. Les id ne doivent pas obligatoirement se suivre de 1 en 1. Sil ny a pas de news no 15 par exemple, cela ne pose aucun problme. Ce qui compte, cest quil ny ait pas deux news avec le mme id. Cest dailleurs justement ce que permet dviter la cl primaire : elle interdit que deux entres aient le mme id. 179

CHAPITRE 16. PHPMYADMIN Une fois que vous avez insr le texte que vous vouliez, cliquez sur le premier bouton Excuter de la page. Il y a dautres champs en dessous : ignorez-les. Ils vous permettent dajouter plusieurs entres la fois, mais nous nen avons pas besoin. Recommencez une ou deux fois en faisant la mme manipulation et en laissant le champ id vide. Achez maintenant le contenu de la table. Vous pouvez cliquer soit sur longlet Acher , en haut, soit sur le nom de la table dans le menu gauche. La gure 16.9 vous prsente le contenu que vous devriez voir.

Fig. 16.9 Contenu de la table news Vous reprez ici les champs id , titre et contenu . Cette table possde trois entres, et comme vous pouvez le voir MySQL a bien fait les choses puisque les numros did se sont crs tout seuls. Vous pouvez modier ou supprimer chacun des lments que vous voyez lcran. Il y a beaucoup dautres options en dessous que je vous laisse regarder. Pour linstant, ce qui compte, cest que vous ayez compris la procdure pour ajouter des lments la table et que vous soyez capables de lister son contenu. Mais. . . je ne vais pas devoir passer par phpMyAdmin chaque fois que je veux ajouter ou supprimer un lment, quand mme ? Il faudra passer par l pour ajouter chaque news de son site, mais aussi chaque membre, chaque message des forums ? Non, bien sr que non. Comme son nom lindique, phpMyAdmin est un outil dadministration. Il permet de voir rapidement la structure et le contenu de vos tables. Il est aussi possible dajouter ou de supprimer des lments, comme on vient de le voir, mais on ne le fera que trs rarement. Nous apprendrons crer des pages en PHP qui insrent ou suppriment des lments directement depuis notre site web. Il nous reste encore dcouvrir quelques-unes des fonctionnalits oertes par phpMyAdmin et nous aurons termin notre tour dhorizon de cet outil.

Autres oprations
Nous avons jusquici dcouvert le rle de trois onglets : 180

AUTRES OPRATIONS Acher : ache le contenu de la table ; Structure : prsente la structure de la table (liste des champs) ; Insrer : permet dinsrer de nouvelles entres dans la table. Je souhaite vous prsenter six autres onglets : SQL ; Importer ; Exporter ; Oprations ; Vider ; Supprimer.

SQL
Cliquez sur longlet SQL , prsent sur la gure 16.10.

Fig. 16.10 Onglet SQL La gure 16.11 sache lcran.

Fig. 16.11 criture dune requte SQL Cest ici que vous pouvez excuter ce que lon appelle des requtes SQL pour demander MySQL de faire quelque chose. Cest dans la grande zone de texte que vous pouvez taper ces requtes. Par exemple on nous propose ici :
SELECT * FROM news WHERE 1

Cela signie : Acher tout le contenu de la table news . Cest justement ce langage SQL que nous allons dcouvrir tout au long des prochains chapitres. 181

CHAPITRE 16. PHPMYADMIN Notez quil est aussi possible dcrire des requtes SQL dans une nouvelle fentre. Pour ouvrir une nouvelle fentre de requte SQL, cliquez sur le bouton SQL en haut du menu de gauche, ainsi que vous le propose la gure 16.12.

Fig. 16.12 Ouvrir une nouvelle fentre SQL Cette nouvelle fentre se rvlera souvent trs pratique.

Importer
Il y a aussi un onglet Importer (gure 16.13).

Fig. 16.13 Onglet Importer Dans la page qui sache, vous pouvez envoyer un chier de requtes SQL (gnralement un chier .sql) MySQL pour quil les excute (gure 16.14). Seul le premier champ en haut devrait nous intresser : il nous permet dindiquer un chier sur notre disque dur contenant des requtes SQL excuter. Cliquez ensuite sur le bouton Excuter tout en bas sans vous proccuper des autres champs. Quelle dirence y a-t-il entre crire la requte SQL (comme on vient de le voir juste avant) et envoyer un chier contenant des requtes SQL ? Cest la mme chose, sauf que parfois quand on doit envoyer un trs grand nombre de requtes, il est plus pratique dutiliser un chier. Dailleurs, dans les prochains chapitres du livre, je vous donnerai un chier de requtes excuter, et il faudra utiliser cette mthode. 182

AUTRES OPRATIONS

Fig. 16.14 Importer une table

Exporter
Nous nous intressons maintenant longlet Exporter . Cest ici que vous allez pouvoir rcuprer votre base de donnes sur le disque dur sous forme de chier texte .sql (qui contiendra des tonnes de requtes SQL). Ce chier que lon va exporter , est-ce que cest le mme que celui dont tu nous parlais tout lheure ? Celui situ dans C:\wamp\mysql\data ? Non, pas du tout. Ce que je vous ai montr tout lheure, ctait quelque chose dillisible. Je vous avais dit quon ny toucherait pas, je ne vous ai pas menti. Le chier que vous allez obtenir grce lexportation de phpMyAdmin, cest un chier qui dit MySQL comment recrer votre base de donnes (avec des requtes en langage SQL).

quoi sert ce chier ?

On peut sen servir pour deux choses : 183

CHAPITRE 16. PHPMYADMIN transmettre votre base de donnes sur Internet : pour le moment, votre base de donnes se trouve sur votre disque dur. Mais lorsque vous voudrez hberger votre site sur Internet, il faudra utiliser la base de donnes en ligne de votre hbergeur ! Le chier .sql que vous allez gnrer vous permettra de reconstruire la base de donnes grce loutil dimportation de phpMyAdmin1 ; faire une copie de sauvegarde de la base de donnes : on ne sait jamais, si vous faites une btise ou si quelquun russit dtruire toutes les informations sur votre site (dont la base de donnes), vous serez bien contents davoir une copie de secours sur votre disque dur ! Votre cran doit ressembler la gure 16.15.

Fig. 16.15 Exportation dune table Je vous conseille de laisser les options par dfaut, cest largement susant. Distinguez simplement la structure des donnes de la table. La structure dune table se rsume en quelques lignes : ce sont en fait les noms des champs, leurs types, etc. En revanche, les donnes correspondent aux entres, et il peut y en avoir beaucoup ! Pour
1 En gnral, les hbergeurs proposent eux aussi phpMyAdmin pour que vous puissiez eectuer facilement des oprations sur votre base en ligne.

184

AUTRES OPRATIONS faire une sauvegarde complte, il faut donc prendre la structure ET les donnes. Pensez cocher la case Transmettre en bas, sinon il ne se passera rien. noter que vous pouvez demander une compression, ce qui est utile si votre table est trs grosse. Cliquez sur Excuter . On vous proposera alors de tlcharger un chier : cest tout fait normal. Nhsitez pas regarder ce quil y a dans ce chier : vous allez voir quil contient plusieurs requtes SQL. Cest ce langage que je vais vous apprendre dans les chapitres qui suivent ! Comment dois-je faire pour recrer la base de donnes sur mon site web ?

Il faut aller sur le phpMyAdmin de votre hbergeur. Renseignez-vous pour en connatre ladresse. Par exemple, chez Free cest http://phpmyadmin.free.fr/phpMyAdmin (il faudra indiquer votre login et mot de passe). Une fois dessus, rendez-vous dans longlet Importer quon a vu tout lheure. Cliquez sur Parcourir pour indiquer o se trouve le chier SQL que vous venez de crer sur votre disque dur. Faites Excuter , attendez quil soit envoy, et cest bon ! Votre base de donnes est alors recre sur Internet !

Oprations
Ici, vous pouvez eectuer diverses oprations sur votre table. Je ne vais pas les numrer une une, ni vous expliquer comment elles fonctionnent vu que cest trs simple. Sachez simplement que vous pourriez avoir besoin de : changer le nom de la table : indiquez le nouveau nom pour cette table ; dplacer la table vers : si vous voulez placer cette table dans une autre base de donnes ; copier la table : faire une copie de la table, dans une autre base ou dans la mme (attention : dans ce cas, il faudra quelle ait un nom dirent) ; optimiser la table : force dutiliser une table, surtout si elle est grosse, on nit par avoir des pertes qui font que la table nest plus bien organise. Un clic l-dessus et hop ! cest de nouveau arrang.

Vider
Vide tout le contenu de la table. Toutes les entres vont disparatre, seule la structure de la table restera (cest--dire les champs). 185

CHAPITRE 16. PHPMYADMIN

Attention ! Il nest pas possible dannuler cette opration !

Supprimer
Pour supprimer la totalit de la table (structure et donnes), cliquez sur cet onglet. L encore, rchissez-y deux fois avant de tout supprimer, car vous ne pourrez rien rcuprer par la suite, moins davoir fait une sauvegarde au pralable avec loutil dexportation.

En rsum
phpMyAdmin est un outil qui nous permet de visualiser rapidement ltat de notre base de donnes ainsi que de la modier, sans avoir crire de requtes SQL. On cre gnralement un champ nomm id qui sert numroter les entres dune table. Ce champ doit avoir un index PRIMARY (on dit quon cre une cl primaire) et loption AUTO_INCREMENT qui permet de laisser MySQL grer la numrotation. MySQL gre dirents types de donnes pour ses champs, la manire de PHP. On trouve des types adapts au stockage de nombres, de textes, de dates, etc. phpMyAdmin possde un outil dimportation et dexportation des tables qui nous permettra notamment denvoyer notre base de donnes sur Internet lorsque nous mettrons notre site en ligne.

186

Chapitre

17
Dicult :

Lire des donnes

ans ce chapitre, nous retournons nos pages PHP. partir de maintenant, nous allons apprendre communiquer avec une base de donnes via PHP. Ce sera loccasion de dcouvrir le langage SQL, que nous tudierons tout au long des prochains chapitres.

Ici, nous allons nous entraner lire des donnes dans une table. Il est vivement conseill davoir un peu manipul phpMyAdmin au pralable : cet outil vous permettra de vrier si les manipulations que vous faites en PHP ont bien limpact que vous attendiez dans votre base de donnes.

187

CHAPITRE 17. LIRE DES DONNES

Se connecter la base de donnes en PHP


Pour pouvoir travailler avec la base de donnes en PHP, il faut dabord sy connecter. Nous allons apprendre dans ce chapitre lire des donnes dans une BDD (base de donnes). Or, je vous rappelle que PHP doit faire lintermdiaire entre vous et MySQL. Problme : PHP ne peut pas dire MySQL ds le dbut Rcupre-moi ces valeurs . En eet, MySQL demande dabord un nom dutilisateur et un mot de passe. Sil ne le faisait pas, tout le monde pourrait accder votre BDD et lire les informations (parfois condentielles !) quelle contient. Il va donc falloir que PHP sauthentie : on dit quil tablit une connexion avec MySQL. Une fois que la connexion sera tablie, vous pourrez faire toutes les oprations que vous voudrez sur votre base de donnes !

Comment se connecte-t-on la base de donnes en PHP ?


Bonne question ! En eet, PHP propose plusieurs moyens de se connecter une base de donnes MySQL. Lextension mysql_ : ce sont des fonctions qui permettent daccder une base de donnes MySQL et donc de communiquer avec MySQL. Leur nom commence toujours par mysql_. Toutefois, ces fonctions sont vieilles et on recommande de ne plus les utiliser aujourdhui. Lextension mysqli_ : ce sont des fonctions amliores daccs MySQL. Elles proposent plus de fonctionnalits et sont plus jour. Lextension PDO : cest un outil complet qui permet daccder nimporte quel type de base de donnes. On peut donc lutiliser pour se connecter aussi bien MySQL que PostgreSQL ou Oracle. Ce sont toutes des extensions car PHP est trs modulaire. On peut trs facilement ajouter ou supprimer des lments PHP, car tout le monde na pas forcment besoin de toutes les fonctionnalits. Quel moyen choisir parmi tous ceux-l ?

Vous laurez compris, les fonctions mysql_ ne sont plus utiliser (on dit quelles sont obsoltes ). Il reste choisir entre mysqli_ et PDO. Nous allons ici utiliser PDO car cest cette mthode daccs aux bases de donnes qui va devenir la plus utilise dans les prochaines versions de PHP. Dautre part, le gros avantage de PDO est que vous pouvez lutiliser de la mme manire pour vous connecter nimporte quel autre type de base de donnes1 (gure 17.1). Vous pourrez donc rutiliser ce que vous allez apprendre si vous choisissez dutiliser une autre base de donnes que MySQL.
1 PostgreSQL,

Oracle. . .

188

SE CONNECTER LA BASE DE DONNES EN PHP

Fig. 17.1 PDO permet de se connecter nimporte quel type de base de donnes

Activer PDO
Normalement, PDO est activ par dfaut. Pour le vrier (voir la gure 17.2), faites un clic gauche sur licne de WAMP dans la barre des tches, puis allez dans le menu PHP / Extensions PHP et vriez que php_pdo_mysql est bien coch.

Fig. 17.2 Vriez que lextension PDO est active

Et si je nutilise pas WAMP ?

Vous pouvez ouvrir le chier de conguration de PHP (qui sappelle gnralement php.ini) et rechercher la ligne qui contient php_pdo_mysql. Enlevez le point-virgule devant sil y en a un pour activer lextension :
;extension=php_pdo_firebird.dll ;extension=php_pdo_mssql.dll extension=php_pdo_mysql.dll ;extension=php_pdo_oci.dll ;extension=php_pdo_odbc.dll

Enregistrez le chier puis redmarrez PHP. Il sut pour cela de relancer votre logiciel favori (WAMP, MAMP, XAMPP. . .). 189

CHAPITRE 17. LIRE DES DONNES

Se connecter MySQL avec PDO


Maintenant que nous sommes certains que PDO est activ, nous pouvons nous connecter MySQL. Nous allons avoir besoin de quatre renseignements : le nom de lhte : cest ladresse de lordinateur o MySQL est install (comme une adresse IP). Le plus souvent, MySQL est install sur le mme ordinateur que PHP : dans ce cas, mettez la valeur localhost2 . Nanmoins, il est possible que votre hbergeur web vous indique une autre valeur renseigner (qui ressemblerait ceci : sql.hebergeur.com). Dans ce cas, il faudra modier cette valeur lorsque vous enverrez votre site sur le Web ; la base : cest le nom de la base de donnes laquelle vous voulez vous connecter. Dans notre cas, la base sappelle test. Nous lavons cre avec phpMyAdmin dans le chapitre prcdent ; le login : il permet de vous identier. Renseignez-vous auprs de votre hbergeur pour le connatre. Le plus souvent (chez un hbergeur gratuit), cest le mme login que vous utilisez pour le FTP ; le mot de passe : il y a des chances pour que le mot de passe soit le mme que celui que vous utilisez pour accder au FTP. Renseignez-vous auprs de votre hbergeur. Pour linstant, nous faisons des tests sur notre ordinateur la maison. On dit quon travaille en local . Par consquent, le nom de lhte sera localhost. Quant au login et au mot de passe, par dfaut le login est root et il ny a pas de mot de passe. Voici donc comment on doit faire pour se connecter MySQL via PDO sur la base test :
<?php $bdd = new PDO(mysql:host=localhost;dbname=test, root, ); ?>

Je ne comprends rien ce code, cest normal ?

Oui, il faut reconnatre quil contient quelques nouveauts. En eet, PDO est ce quon appelle une extension oriente objet. Cest une faon de programmer un peu dirente des fonctions classiques que lon a appris utiliser jusquici. Nous aurons loccasion den apprendre plus au sujet de la programmation oriente objet (POO) plus loin dans le livre. Pour linstant, je vous invite rutiliser les codes que je vous propose en suivant mes exemples. Vous comprendrez les dtails de leur mode de fonctionnement un peu plus tard.
2 Cela

signie sur le mme ordinateur .

190

SE CONNECTER LA BASE DE DONNES EN PHP La ligne de code quon vient de voir cre ce quon appelle un objet $bdd. Ce nest pas vraiment une variable3 : cest un objet qui reprsente la connexion la base de donnes. On cre la connexion en indiquant dans lordre dans les paramtres : le nom dhte (localhost) ; la base de donnes (test) ; le login (root) ; le mot de passe (ici il ny a pas de mot de passe, jai donc mis une chane vide).

Lorsque votre site sera en ligne, vous aurez srement un nom dhte dirent ainsi quun login et un mot de passe comme ceci :
<?php $bdd = new PDO(mysql:host=sql.hebergeur.com;dbname=mabase, pierre.durand, s3cr3t); ?>

Il faudra donc penser changer cette ligne pour ladapter votre hbergeur en modiant les informations en consquence lorsque vous enverrez votre site sur le web. Le premier paramtre (qui commence par mysql) sappelle le DSN : Data Source Name. Cest gnralement le seul qui change en fonction du type de base de donnes auquel on se connecte.

Tester la prsence derreurs


Si vous avez renseign les bonnes informations (nom de lhte, de la base, le login et le mot de passe), rien ne devrait sacher lcran. Toutefois, sil y a une erreur (vous vous tes tromps de mot de passe ou de nom de base de donnes, par exemple), PHP risque dacher toute la ligne qui pose lerreur, ce qui inclut le mot de passe ! Vous ne voudrez pas que vos visiteurs puissent voir le mot de passe si une erreur survient lorsque votre site est en ligne. Il est prfrable de traiter lerreur. En cas derreur, PDO renvoie ce quon appelle une exception qui permet de capturer lerreur. Voici comment je vous propose de faire :
<?php try {

$bdd = new PDO(mysql:host=localhost;dbname=test, root, ); } catch (Exception $e) { die(Erreur : . $e->getMessage()); } ?>
3 Mme

si a y ressemble fortement.

191

CHAPITRE 17. LIRE DES DONNES Voil encore un code un peu nouveau pour nous. L encore, sans trop rentrer dans le dtail, il faut savoir que PHP essaie dexcuter les instructions lintrieur du bloc try. Sil y a une erreur, il rentre dans le bloc catch et fait ce quon lui demande (ici, on arrte lexcution de la page en achant un message dcrivant lerreur). Si au contraire tout se passe bien, PHP poursuit lexcution du code et ne lit pas ce quil y a dans le bloc catch. Votre page PHP ne devrait donc rien acher pour le moment. Ouh l ! Tout a semble bien compliqu, je ny comprends pas grand-chose ! Cest grave, docteur ? Non, pas du tout ! En fait, et jinsiste l-dessus, PDO nous fait utiliser des fonctionnalits de PHP que lon na pas tudies jusqu prsent (programmation oriente objet, exceptions. . .). Contentez-vous pour le moment de rutiliser les codes que je vous propose et nayez crainte : nous reviendrons sur ces codes-l plus tard pour les expliquer en dtail. Si vous avez une page blanche, vous pouvez continuer. Si vous avez une erreur, lisez le message et essayez de comprendre ce quil signie. Si vous tes bloqus, nhsitez pas demander de laide sur les forums, sinon vous ne pourrez pas aller plus loin. Code web : 972168

Rcuprer les donnes


Dans un premier temps, nous allons apprendre lire des informations dans la base de donnes, puis nous verrons dans le chapitre suivant comment ajouter et modier des donnes. Pour travailler ici, il nous faut une base de donnes toute prte qui va nous servir de support. Je vous invite tlcharger la table que jai cre pour vous au moyen de ce code web : Code web : 987220 Rien quau nom, vous pouvez vous douter que cette table contient quelque chose en rapport avec des jeux vido. En eet, vous allez le voir, cette table contient une liste dune cinquantaine de jeux. Pour cet exemple, plusieurs amis ont voulu rpertorier tous les jeux vido quils possdent. La base de donnes est pour eux un moyen trs pratique de classer et dorganiser tout cela ; vous allez voir pourquoi. Euh dis, quest-ce que je dois en faire de ce chier jeux_video.sql ?

192

RCUPRER LES DONNES Inutile dessayer de louvrir, a na pas dintrt. Il faut limporter via longlet Importer de phpMyAdmin. Nous avons appris le faire dans le chapitre prcdent. Pensez slectionner votre base de donnes test au pralable. Et voil ! Vous devriez voir une nouvelle table apparatre gauche : jeux_video (gure 17.3). Vous pouvez vous amuser regarder ce quelle contient, pour vous faire une ide.

Fig. 17.3 La table jeux_video apparat maintenant dans phpMyAdmin Voici les cinq premires entres quelle contient (il y en a une cinquantaine en tout !) : nbre_ joueurs_ max 1

ID

nom Super Mario Bros Sonic

possesseur

console

prix

commentaires Un jeu danthologie ! Pour moi, le meilleur jeu au monde ! Un jeu grand, beau et complet comme on en voit rarement de nos jours Un excellent jeu de kart ! Un jeu de baston dlirant !

Florent

NES

Patrick

Megadrive

Zelda : ocarina of time Mario Kart 64 Super Smash Bros Melee

Florent

Nintendo 64

15

Florent

Nintendo 64 GameCube

25

Michel

55

Pour le moment, ne modiez pas cette table. Notre objectif est de crer une page PHP qui va acher ce que contient la table jeux_video.

Faire une requte


Maintenant arrive le grand moment que vous attendiez tous : on va parler MySQL. Nous allons donc commencer parler en SQL ! Pour cela, on va faire ce quon appelle une requte. On va demander poliment MySQL de nous dire tout ce que contient la table jeux_video. 193

CHAPITRE 17. LIRE DES DONNES Pour rcuprer des informations de la base de donnes, nous avons besoin de notre objet reprsentant la connexion la base. Vous vous souvenez, il sagit de $bdd. Nous allons eectuer la requte comme ceci :
$reponse = $bdd->query(Tapez votre requte SQL ici);

On demande ainsi eectuer une requte sur la base de donnes. query en anglais signie requte .

On rcupre ce que la base de donnes nous a renvoy dans un autre objet que lon a appel ici $reponse.

Votre premire requte SQL


Comme je vous lai dit, le SQL est un langage. Cest lui qui nous permet de communiquer avec MySQL. Voici la premire requte SQL que nous allons utiliser :
SELECT * FROM jeux_video

Cela peut se traduire par : Prendre tout ce quil y a dans la table jeux_video . Analysons chaque terme de cette requte. SELECT : en langage SQL, le premier mot indique quel type dopration doit eectuer MySQL. Dans ce chapitre, nous ne verrons que SELECT. Ce mot-cl demande MySQL dacher ce que contient une table. * : aprs le SELECT, on doit indiquer quels champs MySQL doit rcuprer dans la table. Si on nest intress que par les champs nom et possesseur , il faudra taper : SELECT nom, possesseur FROM jeux_video Si vous voulez prendre tous les champs, tapez *. Cette petite toile peut se traduire par tout : Prendre tout ce quil y a. . . . FROM : cest un mot de liaison qui se traduit par dans . FROM fait la liaison entre le nom des champs et le nom de la table. jeux_video : cest le nom de la table dans laquelle il faut aller piocher. Eectuons la requte avec la mthode que lon vient de dcouvrir :
<?php $reponse = $bdd->query(SELECT * FROM jeux_video); ?>

$reponse contient maintenant la rponse de MySQL. 194

RCUPRER LES DONNES

Acher le rsultat dune requte


Le problme, cest que $reponse contient quelque chose dinexploitable. MySQL nous renvoie beaucoup dinformations quil faut organiser. Vous imaginez toutes les informations qui sy trouvent ? Si cest une table 10 champs, avec 200 entres, cela reprsente plus de 2 000 informations ! Pour ne pas tout traiter dun coup, on extrait cette rponse ligne par ligne, cest--dire entre par entre. Pour rcuprer une entre, on prend la rponse de MySQL et on y excute fetch(), ce qui nous renvoie la premire ligne.
<?php $donnees = $reponse->fetch(); ?>

fetch en anglais signie va chercher .

$donnees est un array qui contient champ par champ les valeurs de la premire entre. Par exemple, si vous vous intressez au champ console, vous utiliserez larray $donnees[console]. Il faut faire une boucle pour parcourir les entres une une. Chaque fois que vous appelez $reponse->fetch(), vous passez lentre suivante. La boucle est donc rpte autant de fois quil y a dentres dans votre table. Ouf ! Cela fait beaucoup dinformations la fois. Je vous propose de rsumer tout ce quon vient dapprendre, de la connexion via PDO lachage du rsultat de la requte :
<?php try {

} catch(Exception $e) { // En cas derreur, on affiche un message et on arrte tout die(Erreur : .$e->getMessage()); } // Si tout va bien, on peut continuer // On rcupre tout le contenu de la table jeux_video $reponse = $bdd->query(SELECT * FROM jeux_video);

// On se connecte MySQL $bdd = new PDO(mysql:host=localhost;dbname=test, root, );

195

CHAPITRE 17. LIRE DES DONNES


// On affiche chaque entre une une while ($donnees = $reponse->fetch()) { ?> <p> <strong>Jeu</strong> : <?php echo $donnees[nom]; ?><br /> Le possesseur de ce jeu est : <?php echo $donnees[possesseur]; ?>, et il le vend <?php echo $donnees[prix]; ?> euros !<br /> Ce jeu fonctionne sur <?php echo $donnees[console]; ?> et on peut y jouer <?php echo $donnees[nbre_joueurs_max]; ?> au maximum<br /> <?php echo $donnees[possesseur]; ?> a laiss ces commentaires sur <?php echo $donnees[nom]; ?> : <em><?php echo $donnees[commentaires]; ?></em> </p> <?php } $reponse->closeCursor(); // Termine le traitement de la requte ?>

Si vous souhaitez copier ce code, utilisez le code web suivant : Code web : 481741 Si vous souhaitez voir le rsultat en ligne, testez le code web suivant : Code web : 956930 Alors, vous avez vu ? a en fait un paquet de texte ! Il faut dire que la table que je vous ai donne contient une cinquantaine dentres, donc cest normal que vous ayez beaucoup de rsultats. Concrtement, que se passe-t-il ? On fait une boucle pour chaque entre de la table. On commence par lentre no 1, puis lentre no 2, etc. Chaque fois quon fait une nouvelle boucle, on passe en revue une autre entre. Quelle est la dirence entre $reponse et $donnees ?

$reponse contenait toute la rponse de MySQL en vrac, sous forme dobjet. $donnees est un array renvoy par le fetch(). Chaque fois quon fait une boucle, fetch va chercher dans $reponse lentre suivante et organise les champs dans larray $donnees. Je ne comprends pas la ligne while ($donnees = $reponse->fetch()). . .

En eet, cest un peu curieux et nouveau pour vous. Cette ligne fait deux choses la fois : 196

RCUPRER LES DONNES elle rcupre une nouvelle entre et place son contenu dans $donnees ; elle vrie si $donnees vaut vrai ou faux. Le fetch renvoie faux (false) dans $donnees lorsquil est arriv la n des donnes, cest--dire que toutes les entres ont t passes en revue. Dans ce cas, la condition du while vaut faux et la boucle sarrte. Vous noterez la n la prsence de la ligne :
<?php $reponse->closeCursor(); ?>

Elle provoque la fermeture du curseur danalyse des rsultats . Cela signie, en dautres termes plus humains, que vous devez eectuer cet appel closeCursor() chaque fois que vous avez ni de traiter le retour dune requte, an dviter davoir des problmes la requte suivante. Cela veut dire quon a termin le travail sur la requte.

Acher seulement le contenu de quelques champs


Avec ce que je vous ai appris, vous devriez tre capables dacher ce que vous voulez. Personne ne vous oblige acher tous les champs ! Par exemple, si javais juste voulu lister les noms des jeux, jaurais utilis la requte SQL suivante :
SELECT nom FROM jeux_video

Reprenons le code complet prcdent et adaptons-le pour acher un nom de jeu par ligne :
<?php try {

$bdd = new PDO(mysql:host=localhost;dbname=test, root, ); } catch(Exception $e) { die(Erreur : .$e->getMessage()); } $reponse = $bdd->query(SELECT nom FROM jeux_video); while ($donnees = $reponse->fetch()) { echo $donnees[nom] . <br />; } $reponse->closeCursor(); ?>

197

CHAPITRE 17. LIRE DES DONNES Code web : 247701 Ce code est trs semblable au prcdent, mais cest loccasion pour vous de vous familiariser avec MySQL et PDO. Retenez tout particulirement les choses suivantes : la connexion la base de donnes na besoin dtre faite quune seule fois, au dbut de la page ; il faut fermer les rsultats de recherche avec closeCursor() aprs avoir trait chaque requte.

Les critres de slection


Imaginons que je souhaite obtenir uniquement la liste des jeux disponibles de la console Nintendo 64 et les trier par prix croissants. a parat compliqu faire ? Pas en SQL ! Vous allez voir quen modiant nos requtes SQL, il est possible de ltrer et trier trs facilement vos donnes. Nous allons nous intresser ici aux mots-cls suivants du langage SQL : WHERE ; ORDER BY ; LIMIT.

WHERE
Grce au mot-cl WHERE, vous allez pouvoir trier vos donnes. Supposons par exemple que je veuille lister uniquement les jeux appartenant Patrick. La requte au dbut sera la mme quavant, mais je rajouterai la n WHERE possesseur=Patrick. Cela nous donne la requte :
SELECT * FROM jeux_video WHERE possesseur=Patrick

Traduction : Slectionner tous les champs de la table jeux_video lorsque le champ possesseur est gal Patrick . Vous noterez que pour dlimiter les chanes de caractres on doit les placer entre apostrophes, comme cest ici le cas pour Patrick. En revanche, elles ne sont pas ncessaires pour les nombres. Un petit code pour voir ce que a donne ?
<?php try {

$bdd = new PDO(mysql:host=localhost;dbname=test, root, );

198

LES CRITRES DE SLECTION


} catch(Exception $e) { die(Erreur : .$e->getMessage()); } $reponse = $bdd->query(SELECT nom, possesseur FROM jeux_video WHERE possesseur= \Patrick\); while ($donnees = $reponse->fetch()) { echo $donnees[nom] . appartient . $donnees[possesseur] . <br />; } $reponse->closeCursor(); ?>

Code web : 641696 Si vous vous amusez changer le nom du possesseur (par exemple WHERE possesseur=Michel), a nachera que les jeux appartenant Michel. Essayez, vous verrez ! Il est par ailleurs possible de combiner plusieurs conditions. Par exemple, si je veux lister les jeux de Patrick quil vend moins de 20 euros, je combinerai les critres de slection laide du mot-cl AND (qui signie et ) :
SELECT * FROM jeux_video WHERE possesseur=Patrick AND prix < 20

Traduction : Slectionner tous les champs de jeux_video lorsque le possesseur est Patrick ET lorsque le prix est infrieur 20 . Il existe aussi le mot-cl OR qui signie ou .

ORDER BY
ORDER BY nous permet dordonner nos rsultats. Nous pourrions ainsi classer les rsultats en fonction de leur prix ! La requte SQL serait :
SELECT * FROM jeux_video ORDER BY prix

Traduction : Slectionner tous les champs de jeux_video et ordonner les rsultats par prix croissants . Application : 199

CHAPITRE 17. LIRE DES DONNES


<?php try {

$bdd = new PDO(mysql:host=localhost;dbname=test, root, ); } catch(Exception $e) { die(Erreur : .$e->getMessage()); } $reponse = $bdd->query(SELECT nom, prix FROM jeux_video ORDER BY prix); while ($donnees = $reponse->fetch()) { echo $donnees[nom] . cote . $donnees[prix] . EUR<br />; } $reponse->closeCursor(); ?>

Code web : 370870 Et si je veux classer par ordre dcroissant ?

Facile. Il sut de rajouter le mot-cl DESC la n :


SELECT * FROM jeux_video ORDER BY prix DESC

Traduction : Slectionner tous les champs de jeux_video, et ordonner les rsultats par prix dcroissants . noter : si on avait utilis ORDER BY sur un champ contenant du texte, le classement aurait t fait par ordre alphabtique.

LIMIT
LIMIT nous permet de ne slectionner quune partie des rsultats4 . Cest trs utile lorsquil y a beaucoup de rsultats et que vous souhaitez les paginer5 .
4 Par 5 Cest--dire

exemple les 20 premiers. par exemple acher les 30 premiers rsultats sur la page 1, les 30 suivants sur la page

2, etc.

200

LES CRITRES DE SLECTION la n de la requte, il faut ajouter le mot-cl LIMIT suivi de deux nombres spars par une virgule. Par exemple :
SELECT * FROM jeux_video LIMIT 0, 20

Ces deux nombres ont un sens bien prcis. On indique tout dabord partir de quelle entre on commence lire la table. Ici, jai mis 0 , ce qui correspond la premire entre. Attention, cela na rien voir avec le champ ID ! Imaginez quune requte retourne 100 rsultats : LIMIT tronquera partir du premier rsultat si vous indiquez 0, partir du 21e si vous indiquez 20, etc. Ensuite, le deuxime nombre indique combien dentres on doit slectionner. Ici, jai mis 20 , on prendra donc vingt entres. Quelques exemples : LIMIT 0, 20 : ache les vingt premires entres ; LIMIT 5, 10 : ache de la sixime la quinzime entre ; LIMIT 10, 2 : ache la onzime et la douzime entre. Un petit schma se trouve la gure 17.4 pour rsumer le fonctionnement de LIMIT.

Fig. 17.4 Prsentation du fonctionnement de LIMIT Allez, un petit exemple ! Si on veut acher les 10 premiers jeux de la table, on utilisera le code suivant :
<?php try {

$bdd = new PDO(mysql:host=localhost;dbname=test, root, ); } catch(Exception $e) { die(Erreur : .$e->getMessage()); } $reponse = $bdd->query(SELECT nom FROM jeux_video LIMIT 0, 10);

201

CHAPITRE 17. LIRE DES DONNES

echo <p>Voici les 10 premires entres de la table jeux_video :</p>; while ($donnees = $reponse->fetch()) { echo $donnees[nom] . <br />; } $reponse->closeCursor(); ?>

Code web : 922306 Et voil le travail ! Bonjour, je suis masochiste et avant de terminer cette section, je souhaiterais mlanger toutes les requtes SQL que je viens dapprendre en une seule. Cest possible ? Mais bien entendu, mon petit. ;-) Voil de quoi te triturer les mninges :
SELECT nom, possesseur, console, prix FROM jeux_video WHERE console=Xbox OR console=PS2 ORDER BY prix DESC LIMIT 0,10

Il faut utiliser les mots-cls dans lordre que jai donn : WHERE puis ORDER BY puis LIMIT, sinon MySQL ne comprendra pas votre requte. Essayez donc de traduire a en franais dans un premier temps pour voir si vous avez compris, puis testez cette requte chez vous pour voir si cest bien ce quoi vous vous attendiez.

Construire des requtes en fonction de variables


Les requtes que nous avons tudies jusquici taient simples et eectuaient toujours la mme opration. Or les choses deviennent intressantes quand on utilise des variables de PHP dans les requtes.

La mauvaise ide : concatner une variable dans une requte


Prenons cette requte qui rcupre la liste des jeux appartenant Patrick :
<?php $reponse = $bdd->query(SELECT nom FROM jeux_video

202

CONSTRUIRE DES REQUTES EN FONCTION DE VARIABLES


WHERE possesseur=\Patrick\); ?>

Au lieu de toujours acher les jeux de Patrick, on aimerait que cette requte soit capable de sadapter au nom de la personne dni dans une variable, par exemple $_GET[possesseur]. Ainsi la requte pourrait sadapter en fonction de la demande de lutilisateur ! Nous pourrions tre tents de concatner la variable dans la requte, comme ceci :
<?php $reponse = $bdd->query(SELECT nom FROM jeux_video WHERE possesseur=\ . $_GET[ possesseur] . \); ?>

Il est ncessaire dentourer la chane de caractres dapostrophes comme je vous lai indiqu prcdemment, do la prsence des antislashs pour insrer les apostrophes : \ Bien que ce code fonctionne, cest lillustration parfaite de ce quil ne faut pas faire et que pourtant beaucoup de sites font encore. En eet, si la variable $_GET[possesseur] a t modie par un visiteur6 , il y a un gros risque de faille de scurit quon appelle injection SQL. Un visiteur pourrait samuser insrer une requte SQL au milieu de la vtre et potentiellement lire tout le contenu de votre base de donnes, comme par exemple la liste des mots de passe de vos utilisateurs. Le sujet des injections SQL est un peu complexe pour tre dtaill ici. Si vous souhaitez en apprendre plus ce sujet, je vous invite consulter Wikipdia. Code web : 594932 Nous allons utiliser un autre moyen plus sr dadapter nos requtes en fonction de variables : les requtes prpares.

La solution : les requtes prpares


Le systme de requtes prpares a lavantage dtre beaucoup plus sr mais aussi plus rapide pour la base de donnes si la requte est excute plusieurs fois. Cest ce que je prconise dutiliser si vous voulez adapter une requte en fonction dune ou plusieurs variables. Avec des marqueurs ? Dans un premier temps, on va prparer la requte sans sa partie variable, que lon reprsentera avec un marqueur sous forme de point dinterrogation :
6 Et

nous savons quel point il ne faut pas faire conance lutilisateur !

203

CHAPITRE 17. LIRE DES DONNES


<?php $req = $bdd->prepare(SELECT nom FROM jeux_video WHERE possesseur = ?); ?>

Au lieu dexcuter la requte avec query() comme la dernire fois, on appelle ici prepare(). La requte est alors prte, sans sa partie variable. Maintenant, nous allons excuter la requte en appelant execute et en lui transmettant la liste des paramtres :
<?php $req = $bdd->prepare(SELECT nom FROM jeux_video WHERE possesseur = ?); $req->execute(array($_GET[possesseur])); ?>

La requte est alors excute laide des paramtres que lon a indiqus sous forme darray. Sil y a plusieurs marqueurs, il faut indiquer les paramtres dans le bon ordre :
<?php $req = $bdd->prepare(SELECT nom FROM jeux_video WHERE possesseur = ? AND prix <= ?); $req->execute(array($_GET[possesseur], $_GET[prix_max])); ?>

Le premier point dinterrogation de la requte sera remplac par le contenu de la variable $_GET[possesseur], et le second par le contenu de $_GET[prix_max]. Le contenu de ces variables aura t automatiquement scuris pour prvenir les risques dinjection SQL. Essayons de construire une page capable de lister les jeux appartenant une personne et dont le prix ne dpasse pas une certaine somme :
<?php try {

$bdd = new PDO(mysql:host=localhost;dbname=test, root, ); } catch(Exception $e) { die(Erreur : .$e->getMessage()); } $req = $bdd->prepare(SELECT nom, prix FROM jeux_video WHERE possesseur = ? AND prix <= ? ORDER BY prix); $req->execute(array($_GET[possesseur], $_GET[prix_max])); echo <ul>;

204

TRAQUER LES ERREURS


while ($donnees = $req->fetch()) { echo <li> . $donnees[nom] . ( . $donnees[prix] . EUR)</li>; } echo </ul>; $req->closeCursor(); ?>

Bien que la requte soit scurise (ce qui limine les risques dinjection SQL), il faudrait quand mme vrier que $_GET[prix_max] contient bien un nombre et quil est compris dans un intervalle correct. Vous ntes donc pas dispenss deectuer des vrications supplmentaires si vous estimez que cela est ncessaire. Essayez dappeler cette page (que lon nommera par exemple selection_jeux.php) en modiant les valeurs des paramtres. Vous allez voir que la liste des jeux qui ressort change en fonction des paramtres envoys ! Avec des marqueurs nominatifs Si la requte contient beaucoup de parties variables, il peut tre plus pratique de nommer les marqueurs plutt que dutiliser des points dinterrogation. Voici comment on sy prendrait :
<?php $req = $bdd->prepare(SELECT nom, prix FROM jeux_video WHERE possesseur = :possesseur AND prix <= :prixmax); $req->execute(array(possesseur => $_GET[possesseur], prixmax => $_GET[prix_max])); ?>

Les points dinterrogation ont t remplacs par les marqueurs nominatifs :possesseur et :prixmax (ils commencent par le symbole deux-points, comme vous le voyez). Cette fois-ci, ces marqueurs sont remplacs par les variables laide dun array associatif. Quand il y a beaucoup de paramtres, cela permet parfois davoir plus de clart. De plus, contrairement aux points dinterrogation, nous ne sommes cette fois plus obligs denvoyer les variables dans le mme ordre que la requte.

Traquer les erreurs


Lorsquune requte SQL plante , bien souvent PHP vous dira quil y a eu une erreur la ligne du fetch : 205

CHAPITRE 17. LIRE DES DONNES Fatal error: Call to a member function fetch() on a non-object in C:\wamp\www\tests\index.php on line 13 Ce nest pas trs prcis, je pense que vous tes daccord avec moi. Ce nest pas la ligne du fetch qui est en cause : cest souvent vous qui avez mal crit votre requte SQL quelques lignes plus haut. Prenez lhabitude de rajouter le code or die(print_r($bdd->errorInfo())) sur la mme ligne que votre requte pour acher des dtails sur lerreur.

Cas dune requte simple


Si on reprend lexemple de tout lheure, on doit donc crire :
<?php $reponse = $bdd->query(SELECT nom FROM jeux_video) or die(print_r( $bdd->errorInfo())); ?>

Ce code quon a rajout ne sera excut que sil y a une erreur. Il achera alors des informations dtailles sur lerreur SQL qui vous permettront de comprendre ce qui ne va pas dans votre requte. Par exemple, supposons que jcrive mal le nom du champ :
<?php $reponse = $bdd->query(SELECT champinconnu FROM jeux_video) or die( print_r($bdd->errorInfo())); ?>

Lerreur suivante sachera : Unknown column champinconnu in field list Cest de langlais, certes, mais cest dj beaucoup plus prcis que lerreur que lon avait tout lheure. Si on traduit, cela signie : La colonne champinconnu est introuvable dans la liste des champs . En eet, il ny a aucun champ qui sappelle champinconnu.

Cas dune requte prpare


Si vous utilisez une requte prpare, ajoutez le code qui ache lerreur sur la mme ligne que le prepare() :
<?php $req = $bdd->prepare(SELECT nom, prix FROM jeux_video WHERE possesseur = :possesseur) or die(print_r($bdd->errorInfo())); ?>

206

TRAQUER LES ERREURS Lorsque vous avez un problme avec une requte et que vous voulez demander de laide sur les forums du Site du Zro, donnez toujours lerreur renvoye par le or die(print_r($bdd->errorInfo())). Cela aidera normment les gens comprendre votre erreur.

En rsum
Pour dialoguer avec MySQL depuis PHP, on fait appel lextension PDO de PHP. Avant de dialoguer avec MySQL, il faut sy connecter. On a besoin de ladresse IP de la machine o se trouve MySQL, du nom de la base de donnes ainsi que dun login et dun mot de passe. Les requtes SQL commenant par SELECT permettent de rcuprer des informations dans une base de donnes. Il faut faire une boucle en PHP pour rcuprer ligne par ligne les donnes renvoyes par MySQL. Le langage SQL propose de nombreux outils pour prciser nos requtes, laide notamment des mots-cls WHERE (ltre), ORDER BY (tri) et LIMIT (limitation du nombre de rsultats). Pour construire une requte en fonction de la valeur dune variable, on passe par un systme de requte prpare qui permet dviter les dangereuses failles dinjection SQL.

207

CHAPITRE 17. LIRE DES DONNES

208

Chapitre

18
Dicult :

crire des donnes

ous avons vu dans le chapitre prcdent que lon pouvait facilement rcuprer des informations de notre base de donnes. Nous avons galement pu constater que le langage SQL est trs puissant car il propose de nombreux critres de slection et de tri (WHERE, ORDER BY, etc.). Il est maintenant temps de dcouvrir comment on peut ajouter et modier des donnes dans la base. Pour cela, nous allons aborder de nouvelles requtes SQL fondamentales et quil vous faut connatre : INSERT, UPDATE et DELETE.

209

CHAPITRE 18. CRIRE DES DONNES

INSERT : ajouter des donnes


Votre mission, si vous lacceptez : ajouter une nouvelle entre la table jeux_video sur laquelle nous avons travaill dans le chapitre prcdent. Mouahahahah, mais cest facile. Tu utilises phpMyAdmin et hop ! cest fait ! . . . Quoi, jai dit quelque chose de mal ? Non, non. Cest vrai que phpMyAdmin permet de rajouter de nouvelles entres dans la table. Mais ce qui nous intresse ici, cest de le faire au moyen dun script PHP et dune requte SQL. Tout dabord, je vous rappelle quoi ressemble la table jeux_video : nbre_ joueurs_ max 1

ID

nom Super Mario Bros Sonic

possesseur

console

prix

commentaires Un jeu danthologie ! Pour moi, le meilleur jeu au monde ! Un jeu grand, beau et com plet comme on en voit rare ment de nos jours Un excellent jeu de kart ! Un jeu de baston dlirant ! ...

Florent

NES

Patrick

Megadrive

Zelda : ocarina of time

Florent

Nintendo 64

15

5 ...

Mario Kart 64 Super Smash Bros Melee ...

Florent

Nintendo 64 GameCube ...

25

Michel ...

55 ...

4 ...

La requte INSERT INTO permet dajouter une entre


Pour rajouter une entre, vous aurez besoin de connatre la requte SQL. En voici une par exemple qui ajoute un jeu :
INSERT INTO jeux_video(ID, nom, possesseur, console, prix, nbre_joueurs_max, commentaires) VALUES(, Battlefield 1942, Patrick, PC, 45, 50, 2nde guerre mondiale)

210

INSERT : AJOUTER DES DONNES Les nombres (tels que 45 et 50 ici) nont pas besoin dtre entours dapostrophes. Seules les chanes de caractres les ncessitent. tudions un peu cette requte. Dabord, vous devez commencer par les mots-cls INSERT INTO qui indiquent que vous voulez insrer une entre. Vous prcisez ensuite le nom de la table (ici jeux_video), puis listez entre parenthses les noms des champs dans lesquels vous souhaitez placer des informations. Enn et cest l quil ne faut pas se tromper vous inscrivez VALUES suivi des valeurs insrer dans le mme ordre que les champs que vous avez indiqus. Vous remarquerez que pour le premier champ (ID), jai laiss des apostrophes vides. Cest voulu : le champ a la proprit auto_increment, MySQL mettra donc le numro dID lui-mme. On pourrait mme se passer du champ ID dans la requte :
INSERT INTO jeux_video(nom, possesseur, console, prix, nbre_joueurs_max, commentaires) VALUES(Battlefield 1942, Patrick, PC, 45, 50, 2nde guerre mondiale)

Cest encore plus simple ! Le champ ID sera de toute faon automatiquement rempli par MySQL, il est donc inutile de le lister. Enn, si vous le dsirez, sachez que vous ntes pas obligs de lister les noms des champs en premier ; cette requte marche tout aussi bien (mais elle est moins claire) :
INSERT INTO jeux_video VALUES(, Battlefield 1942, Patrick, PC, 45, 50, 2nde guerre mondiale)

Il faut lister les valeurs pour tous les champs sans exception (ID compris) dans le bon ordre.

Application en PHP
Utilisons cette requte SQL au sein dun script PHP. Cette fois, au lieu de faire appel query() (que lon utilisait dans le chapitre prcdent pour rcuprer des donnes), on va utiliser exec() qui est prvue pour excuter des modications sur la base de donnes :
<?php try {

$bdd = new PDO(mysql:host=localhost;dbname=test, root, ); } catch(Exception $e) {

211

CHAPITRE 18. CRIRE DES DONNES


die(Erreur : .$e->getMessage());

// On ajoute une entre dans la table jeux_video $bdd->exec(INSERT INTO jeux_video(nom, possesseur, console, prix, nbre_joueurs_max, commentaires) VALUES(\Battlefield 1942\, \Patrick\, \PC\, 45, 50, \2nde guerre mondiale\)); echo Le jeu a bien t ajout !; ?>

Que fait ce code ? Il ajoute une entre dans la BDD pour le jeu Battleeld 1942 , appartenant Patrick , qui fonctionne sur PC , qui cote 45 euros, etc. La prsence de multiples apostrophes rend la requte un peu dicile lire et crire cause des antislashs (\) que lon doit rajouter devant. De plus, cette requte insre toujours les mmes donnes. Comme on la vu dans le chapitre prcdent, si on veut rendre une partie de la requte variable, le plus rapide et le plus sr est de faire appel aux requtes prpares.

Insertion de donnes variables grce une requte prpare


Si on choisit dutiliser une requte prpare (ce que je vous recommande si vous souhaitez insrer des variables), le fonctionnement est en fait exactement le mme que dans le chapitre prcdent :
<?php $req = $bdd->prepare(INSERT INTO jeux_video(nom, possesseur, console, prix, nbre_joueurs_max, commentaires) VALUES(:nom, :possesseur, :console, :prix, :nbre_joueurs_max, :commentaires)); $req->execute(array( nom => $nom, possesseur => $possesseur, console => $console, prix => $prix, nbre_joueurs_max => $nbre_joueurs_max, commentaires => $commentaires )); echo Le jeu a bien t ajout !; ?>

Dsormais je ne mets plus ltape de la connexion MySQL avec PDO dans mes codes pour les simplier. Bien entendu, il faut toujours se connecter au pralable si on veut que la requte fonctionne. Pour plus de clart, jai utilis ici des marqueurs nominatifs. Comme vous le voyez, jai cr larray sur plusieurs lignes : cest autoris, et cest surtout bien plus lisible. 212

UPDATE : MODIFIER DES DONNES Les variables telles que $nom et $possesseur doivent avoir t dnies prcdemment. Gnralement, on rcuprera des variables de $_POST (issues dun formulaire) pour insrer une entre dans la base de donnes. Nous dcouvrirons un cas pratique dans le TP suivant.

UPDATE : modier des donnes


Vous venez de rajouter Battleeld dans la BDD et tout sest bien pass. Mais. . . vous vous rendez compte avec stupeur que Battleeld se joue en fait 32 joueurs maximum (au lieu de 50) et quen plus son prix a baiss : on le trouve 10 euros (au lieu de 45).

La requte UPDATE permet de modier une entre


No problemo amigo ! Avec une petite requte SQL, on peut arranger a. En eet, en utilisant UPDATE vous allez pouvoir modier lentre qui pose problme :
UPDATE jeux_video SET prix = 10, nbre_joueurs_max = 32 WHERE ID = 51

Comment a marche ? Tout dabord, le mot-cl UPDATE permet de dire quon va modier une entre. Ensuite, le nom de la table (jeux_video). Le mot-cl SET, qui spare le nom de la table de la liste des champs modier. Viennent ensuite les champs quil faut modier, spars par des virgules. Ici, on modie le champ prix , on lui aecte la valeur 10 (prix = 10), puis on fait de mme pour le champ nbre_joueurs_max. Les autres champs ne seront pas modis. Enn, le mot-cl WHERE est tout simplement indispensable. Il nous permet de dire MySQL quelle entre il doit modier1 . On se base trs souvent sur le champ ID pour indiquer quelle entre doit tre modie. Ici, on suppose que Battleeld a t enregistr sous lID no 51. Si vous voulez, vous pouvez vous baser sur le nom du jeu au lieu de lID pour eectuer votre slection :
UPDATE jeux_video SET prix = 10, nbre_joueurs_max = 32 WHERE nom = Battlefield 1942

Dernire minute ! Florent vient de racheter tous les jeux de Michel. Il va falloir modier a tout de suite. Euh, il va falloir modier chaque entre une une ?
1 Sinon,

toutes les entres seraient aectes !

213

CHAPITRE 18. CRIRE DES DONNES Non ! Il nest pas question de passer des heures modier chaque entre une une pour a ! En rchissant environ 0,5 seconde, vous allez trouver tout seuls la requte SQL qui permet de faire ce quon souhaite. Cest bon, vous avez trouv ? Allez, je vous donne la rponse dans le mille :
UPDATE jeux_video SET possesseur = Florent WHERE possesseur = Michel

Traduction : Dans la table jeux_video, modier toutes les entres dont le champ possesseur est gal Michel, et le remplacer par Florent. Quil y ait 1, 10, 100 ou 1 000 entres, cette requte elle seule sut pour mettre jour toute la table ! Si cest pas beau, le SQL. . . ;-)

Application en PHP
De la mme manire, en PHP on fait appel exec() pour eectuer des modications :
<?php $bdd->exec(UPDATE jeux_video SET prix = 10, nbre_joueurs_max = 32 WHERE nom = \Battlefield 1942\); ?>

Notez que cet appel renvoie le nombre de lignes modies. Essayez de rcuprer cette valeur dans une variable et de lacher, par exemple comme ceci :
<?php $nb_modifs = $bdd->exec(UPDATE jeux_video SET possesseur = \Florent\ WHERE possesseur = \Michel\); echo $nb_modifs . entres ont t modifies !; ?>

Cela achera quelque chose comme : 13 entres ont t modifies !

Avec une requte prpare


Si vous insrez des donnes variables, par exemple envoyes par lutilisateur, je vous recommande l encore de faire appel une requte prpare :
<?php $req = $bdd->prepare(UPDATE jeux_video SET prix = :nvprix, nbre_joueurs_max = :nv_nb_joueurs WHERE nom = :nom_jeu); $req->execute(array( nvprix => $nvprix, nv_nb_joueurs => $nv_nb_joueurs, nom_jeu => $nom_jeu )); ?>

214

DELETE : SUPPRIMER DES DONNES

DELETE : supprimer des donnes


Enn, voil une dernire requte qui pourra se rvler utile : DELETE. Rapide et simple utiliser, elle est quand mme un poil dangereuse : aprs suppression, il ny a aucun moyen de rcuprer les donnes, alors faites bien attention ! Voici comment on supprime par exemple lentre de Battleeld :
DELETE FROM jeux_video WHERE nom=Battlefield 1942

Il ny a rien de plus facile : DELETE FROM : pour dire supprimer dans ; jeux_video : le nom de la table ; WHERE : indispensable pour indiquer quelle(s) entre(s) doi(ven)t tre supprime(s). Si vous oubliez le WHERE, toutes les entres seront supprimes. Cela quivaut vider la table. Je vous laisse essayer cette requte en PHP. Vous pouvez l encore passer par exec() si vous voulez excuter une requte bien prcise, ou bien utiliser une requte prpare si votre requte dpend de variables.

En rsum
On utilise dirents mots-cls en fonction du type de modication que lon souhaite eectuer : INSERT INTO : ajout dune entre ; UPDATE : modication dune ou plusieurs entres ; DELETE : suppression dune ou plusieurs entres. Comme pour la slection de donnes, on utilise les requtes prpares pour personnaliser nos requtes en fonction de variables. Lorsquon utilise UPDATE ou DELETE, il faut penser ltrer avec un WHERE sinon toute la table sera aecte par lopration !

215

CHAPITRE 18. CRIRE DES DONNES

216

Chapitre

19
Dicult :

TP : un mini-chat

oil un TP qui va nous permettre de mettre en pratique tout ce que lon vient dapprendre sur le langage SQL. Il faut dire quon a enchan beaucoup de nouveauts dans les chapitres prcdents : base de donnes, extraction des informations contenues dans une table, etc. Avec les connaissances que vous avez maintenant, vous tes en mesure de raliser de vrais scripts qui pourront vous tre utiles pour votre site, comme un mini-chat (ce quon va faire) ou encore un livre dor, un systme de news (ou blog), etc. Ces scripts sont en fait assez similaires, mais le plus simple dentre eux est le mini-chat. Ce dernier permettra dajouter facilement une touche de dynamisme votre site. . . mais encore faut-il le construire. nous de jouer !

217

CHAPITRE 19. TP : UN MINI-CHAT

Instructions pour raliser le TP


Pour prparer ce TP, nous allons voir les points suivants : prrequis ; objectifs ; structure de la table MySQL ; structure des pages PHP ; rappel sur les consignes de scurit.

Prrequis
Vous pourrez suivre ce TP sans problme si vous avez lu tous les chapitres prcdents. Plus prcisment, nous allons utiliser les notions suivantes : transmission de variables via un formulaire ; lire dans une table ; crire dans une table ; utilisation de PDO et des requtes prpares.

Objectifs
Quest-ce que je vous avais dit quil fallait absolument faire avant de commencer attaquer notre script PHP ? Un brouillon ! Eh oui, votre script ne va pas scrire tout seul, comme par magie, alors il va falloir rchir un petit peu avant de commencer. Il faut particulirement se demander ce que lon veut exactement faire. Quelles seront les fonctionnalits de mon mini-chat ?

Ce sera quelque chose de basique pour commencer, mais rien ne vous empchera de lamliorer votre sauce. On souhaite avoir, sur la mme page et en haut, deux zones de texte : une pour crire votre pseudo, une autre pour crire votre petit message. Ensuite, un bouton Envoyer permettra denvoyer les donnes MySQL pour quil les enregistre dans une table. En dessous, le script devra acher les 10 derniers messages qui ont t enregistrs1 en allant du plus rcent au plus ancien. Cest un peu ou ? O.K., regardez sur la gure 19.1 quoi doit ressembler votre page PHP une fois termine. Une fois que lon sait ce que lon veut obtenir, il nous sera beaucoup plus facile de le raliser ! Et ne rigolez pas, trop de gens se lancent dans un
1 Seulement 10 parce que si vous les achez tous et que vous avez 1 000 messages, a risque dtre un peu long !

218

INSTRUCTIONS POUR RALISER LE TP script sans vraiment savoir ce quils veulent faire, ce qui les conduit bien souvent dans un mur.

Fig. 19.1 Aperu du mini-chat une fois ralis

Structure de la table MySQL


Comme chaque fois que lon se servira dune base de donnes, on va commencer par tudier sa forme, cest--dire la liste des champs quelle contient. Voici un petit tableau que jai ralis en une minute sur une feuille de papier brouillon : ID 1 2 3 4 5 pseudo Tom John Patrice Tom John message Il fait beau aujourdhui, vous ne trouvez pas ? Ouais, a faisait un moment quon navait pas vu la lumire du soleil ! a vous tente daller la plage aujourdhui ? Ya de super vagues ! Cool, bonne ide ! Jamne ma planche ! Comptez sur moi !

On distingue les champs suivants : ID (type INT) : il nous permettra de savoir dans quel ordre ont t posts les messages. Il faudra le mettre en auto_increment pour que les numros scrivent tout seuls, et ne pas oublier de slectionner Primaire (cela dit MySQL que cest le champ qui numrote les entres) ; pseudo (type VARCHAR) : pensez indiquer la taille maximale du champ (je vous conseille de mettre le maximum, 255 ) ; message (type VARCHAR) : de mme, on indiquera une taille maximale de 255 caractres. Si vous pensez que vos messages seront plus longs, utilisez plutt le type TEXT, beaucoup moins limit. Commencez donc par crer cette table dans votre base de donnes avec phpMyAdmin. Appelez-la comme vous voulez, moi jai choisi minichat. 219

CHAPITRE 19. TP : UN MINI-CHAT

Structure des pages PHP


Comme pour le TP Page protge par mot de passe , nous allons utiliser deux chiers PHP : minichat.php : contient le formulaire permettant dajouter un message et liste les 10 derniers messages ; minichat_post.php : insre le message reu avec $_POST dans la base de donnes puis redirige vers minichat.php. Il aurait t possible de tout faire sur une seule page PHP, mais pour bien sparer le code il est prfrable dutiliser deux chiers, comme sur la gure 19.2.

Fig. 19.2 Organisation des pages du mini-chat Vous avez toutes les connaissances ncessaires pour raliser un mini-chat bas sur la structure du schma prcdent. . . lexception de la redirection. En eet, il existe plusieurs moyens de rediriger le visiteur vers une autre page (via une balise <meta> par exemple), mais le plus propre et le plus rapide consiste faire une redirection HTTP. Voici comment il faut procder pour faire cela sur la page minichat_post.php :
<?php // Effectuer ici la requte qui insre le message // Puis rediriger vers minichat.php comme ceci : header(Location: minichat.php); ?>

Le visiteur ne verra jamais la page minichat_post.php. Celle-ci nache rien mais commande en revanche au navigateur du visiteur de retourner sur minichat.php. La fonction header() permet denvoyer ce quon appelle des en-ttes HTTP . Cest le protocole quutilisent le serveur et le client pour changer des pages web. Ici, on utilise une des possibilits de HTTP qui commande une redirection via la commande Location. Par rapport dautres types de redirection (comme la balise <meta>), cette technique a lavantage dtre instantane et transparente pour lutilisateur. De plus, sil rafrachit ensuite la page minichat.php, il ne risque pas davoir le message souvent gnant et droutant : Pour acher cette page, les informations prcdemment transmises doivent tre renvoyes. tes-vous sr de vouloir le faire ? .

220

CORRECTION

Rappel sur les consignes de scurit


Un petit rappel ne peut pas faire de mal : ne faites jamais conance aux donnes de lutilisateur ! Tout ce qui vient de lutilisateur doit tre trait avec la plus grande mance. Ici, on a une page minichat_post.php assez simple qui reoit deux champs : le pseudo et le message. A priori, il ny a pas de vrication supplmentaire faire, si ce nest quil faudra veiller, lors de lachage, protger les chanes de caractres contre la faille XSS2 . Il faudra donc bien veiller appeler htmlspecialchars() pour protger les chanes.

vous de jouer !
Allez, jen ai assez dit. Cest maintenant votre tour de rchir. Avec les lments que je vous ai donns, et avec ce que vous avez appris dans les chapitres prcdents, vous devez tre capables de raliser le mini-chat ! Si vous avez un peu de mal, et si votre script ne marche pas, ne le supprimez pas dans un moment de rage (il ne faut jamais snerver). Faites une pause et revenez-y plus tard. Si vous coincez vraiment, vous pouvez demander de laide sur les forums ou regarder la correction pour vous aider. Faites leort dans tous les cas de travailler ce script ; ce sera trs formateur, vous verrez !

Correction
Hop, hop, hop ! On relve les copies ! Vous allez maintenant voir ce que jattendais de vous. Si vous avez russi faire quelque chose qui marche, bravo ! Et si vous ny tes pas arrivs, ne vous en faites pas trop : le principal est que vous ayez fait leort de rchir. En voyant la correction, vous apprendrez normment de choses ! Il y avait deux chiers ; commenons par minichat.php.

minichat.php : formulaire et liste des derniers messages


Cette page contient le formulaire dajout de message ainsi que la liste des derniers messages.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> <head>
2 Celle

qui permet dinsrer du HTML et du JavaScript dans la page.

221

CHAPITRE 19. TP : UN MINI-CHAT


<title>Mini-chat</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <style type="text/css"> form { text-align:center; } </style> <body> <form action="minichat_post.php" method="post"> <p> <label for="pseudo">Pseudo</label> : <input type="text" name="pseudo" id="pseudo" /><br /> <label for="message">Message</label> : <input type="text" name="message" id="message" /><br /> <input type="submit" value="Envoyer" /> </p> </form> <?php // Connexion la base de donnes try { $bdd = new PDO(mysql:host=localhost;dbname=test, root, ); } catch(Exception $e) { die(Erreur : .$e->getMessage()); } // Rcupration des 10 derniers messages $reponse = $bdd->query(SELECT pseudo, message FROM minichat ORDER BY ID DESC LIMIT 0, 10); // Affichage de chaque message (toutes les donnes sont protges par htmlspecialchars) while ($donnees = $reponse->fetch()) { echo <p><strong> . htmlspecialchars($donnees[pseudo]) . </strong> : . htmlspecialchars($donnees[message]) . </p>; } $reponse->closeCursor(); ?> </body>

222

CORRECTION
</html>

Code web : 889009 Le code de cette page est spar en deux parties : le formulaire (en HTML) ; la liste des messages (ache en PHP laide dune requte SQL). Il ny avait pas de pige particulier, lexception du htmlspecialchars() ne pas oublier sur le message ET sur le pseudo. Toutes les donnes issues du formulaire doivent tre protges pour viter la faille XSS dont nous avons parl dans un chapitre prcdent.

minichat_post.php : enregistrement et redirection


La page minichat_post.php reoit les donnes du formulaire, enregistre le message et redirige ensuite le visiteur sur la liste des derniers messages.
<?php // Connexion la base de donnes try { $bdd = new PDO(mysql:host=localhost;dbname=test, root, ); } catch(Exception $e) { die(Erreur : .$e->getMessage()); } // Insertion du message laide dune requte prpare $req = $bdd->prepare(INSERT INTO minichat (pseudo, message) VALUES(?, ?)); $req->execute(array($_POST[pseudo], $_POST[message])); // Redirection du visiteur vers la page du minichat header(Location: minichat.php); ?>

Code web : 960171 Ce code est relativement court et sans surprise. On se connecte la base, on insre les donnes et on redirige le visiteur vers la page minichat.php comme on vient dapprendre le faire. En fait, ce code peut tre amlior (je vais en parler un peu plus loin). En eet, on ne teste pas si le pseudo et le message existent bien, sils sont vides ou non, etc. Il est donc en thorie possible denregistrer des messages vides, ce qui idalement ne devrait pas tre autoris. 223

CHAPITRE 19. TP : UN MINI-CHAT Vous voulez tester le mini-chat en ligne ? Pas de problme ! Ce code web ouvre la page minichat.php. Code web : 483942

Aller plus loin


Il serait dommage den rester l. . . Le script de mini-chat que je vous ai fait faire est certes amusant, mais je suis sr que vous aimeriez lamliorer ! Cependant, je ne peux que vous donner des ides. Je ne peux pas vous proposer de correction pour chacune de ces ides car ce serait beaucoup trop long. Mais ne vous en faites pas : si je vous propose de procder des amliorations, cest que vous en tes capables. Et puis, noubliez pas quil y a un forum sur le Site du Zro : si jamais vous schez un peu, nhsitez pas aller y demander de laide ! Voici quelques ides pour amliorer le script. Retenir le pseudo. On doit actuellement saisir nouveau son pseudo chaque nouveau message. Comme vous le savez probablement, il est possible en HTML de pr-remplir un champ avec lattribut value. Par exemple :
<input type="text" name="pseudo" value="M@teo21" />

Remplacez M@teo21 par le pseudonyme du visiteur. Ce pseudonyme peut tre issu dun cookie par exemple : lorsquil poste un message, vous inscrivez son pseudo dans un cookie, ce qui vous permet ensuite de pr-remplir le champ. Proposez dactualiser le mini-chat. Le mini-chat ne sactualise pas automatiquement sil y a de nouveaux messages. Cest normal, ce serait dicile faire notre niveau3 . En revanche, ce que vous pouvez facilement faire, cest proposer un lien Rafrachir qui charge nouveau la page minichat.php. Ainsi, sil y a de nouveaux messages, ils apparatront aprs un clic sur le lien. Acher les anciens messages. On ne voit actuellement que les 10 derniers messages. Sauriez-vous trouver un moyen dacher les anciens messages ? Bien sr, les acher tous dun coup sur la mme page nest pas une bonne ide. Vous pourriez imaginer un paramtre $_GET[page] qui permet de choisir le numro de page des messages acher. Au travail !

la base, le Web na pas vraiment t prvu pour ce type dapplications.

224

Chapitre

20
Dicult :

Les fonctions SQL

ous connaissez dj les fonctions en PHP, mais vous allez dcouvrir dans ce chapitre que SQL propose lui aussi toute une srie de fonctions ! Le langage SQL permet en eet deectuer des calculs directement sur ses donnes laide de fonctions toutes prtes. Celles-ci sont moins nombreuses quen PHP mais elles sont spcialement ddies aux bases de donnes et se rvlent trs puissantes dans la pratique. Pour reprendre notre exemple de la table jeux_video, elles permettent de rcuprer trs simplement le prix moyen de lensemble des jeux, de compter le nombre de jeux que possde chaque personne, dextraire le jeu le plus cher ou le moins cher, etc. Les fonctions se rvlent galement indispensables lorsquon doit travailler avec des dates en SQL, comme nous le ferons dans le chapitre suivant.

225

CHAPITRE 20. LES FONCTIONS SQL Les fonctions SQL peuvent tre classes en deux catgories : les fonctions scalaires : elles agissent sur chaque entre. Par exemple, vous pouvez transformer en majuscules la valeur de chacune des entres dun champ ; les fonctions dagrgat : lorsque vous utilisez ce type de fonctions, des calculs sont faits sur lensemble de la table pour retourner une valeur. Par exemple, calculer la moyenne des prix retourne une valeur : le prix moyen.

Les fonctions scalaires


Nous allons dabord dcouvrir le mode demploi dune fonction SQL de type scalaire : la fonction UPPER. Lorsque vous aurez appris vous en servir, vous serez capables de faire de mme avec toutes les autres fonctions scalaires. Je vous proposerai alors une petite slection de fonctions scalaires connatre, sachant quil en existe dautres mais que nous ne pouvons pas toutes les passer en revue car ce serait bien trop long.

Utiliser une fonction scalaire SQL


Pour nos exemples nous allons nous baser sur la table jeux_video que nous connaissons bien maintenant. Pour rappel, voici quoi elle ressemble : nbre_ joueurs_ max 1

ID

nom Super Mario Bros Sonic

possesseur

console

prix

commentaires Un jeu danthologie ! Pour moi, le meilleur jeu au monde ! Un jeu grand, beau et complet comme on en voit rarement de nos jours. Un excellent jeu de kart ! Un jeu de baston dlirant !

Florent

NES

Patrick

Megadrive

Zelda : ocarina of time Mario Kart 64 Super Smash Bros Melee

Florent

Nintendo 64

15

Florent

Nintendo 64 GameCube

25

Michel

55

On crit les noms des fonctions SQL en majuscules, comme on le fait dj pour la plupart des mots-cls comme SELECT, INSERT, etc. Ce nest pas une obligation mais plutt une convention, une habitude quont prise les programmeurs. 226

LES FONCTIONS SCALAIRES Pour vous montrer comment on utilise les fonctions scalaires SQL, je vais me baser sur la fonction UPPER() qui permet de convertir lintgralit dun champ en majuscules. Supposons que nous souhaitions obtenir les noms de tous les jeux en majuscules ; voici comment on crirait la requte SQL :
SELECT UPPER(nom) FROM jeux_video

La fonction UPPER est utilise sur le champ nom. On rcupre ainsi tous les noms des jeux en majuscules.

Cela modie-t-il le contenu de la table ?

Non ! La table reste la mme. La fonction UPPER modie seulement la valeur envoye PHP. On ne touche donc pas au contenu de la table. Cela cre en fait un champ virtuel qui nexiste que le temps de la requte. Il est conseill de donner un nom ce champ virtuel qui reprsente les noms des jeux en majuscules. Il faut utiliser pour cela le mot-cl AS, comme ceci :
SELECT UPPER(nom) AS nom_maj FROM jeux_video

On rcupre les noms des jeux en majuscules via un champ virtuel appel nom_maj. Ce champ virtuel est appel alias.

Voici le tableau que retournera MySQL aprs la requte prcdente : nom_maj SUPER MARIO BROS SONIC ZELDA : OCARINA OF TIME MARIO KART 64 SUPER SMASH BROS MELEE On peut sen servir en PHP pour acher les noms des jeux en majuscules :
<?php $reponse = $bdd->query(SELECT UPPER(nom) AS nom_maj FROM jeux_video); while ($donnees = $reponse->fetch()) { echo $donnees[nom_maj] . <br />; }

227

CHAPITRE 20. LES FONCTIONS SQL

$reponse->closeCursor(); ?>

Code web : 296725 Comme vous le voyez, PHP ne rcupre quun champ nomm nom_maj (mme sil nexiste pas dans la table). En achant le contenu de ce champ, on ne rcupre que les noms des jeux en majuscules. Bien entendu, vous pouvez aussi rcuprer le contenu des autres champs comme avant sans forcment leur appliquer une fonction :
SELECT UPPER(nom) AS nom_maj, possesseur, console, prix FROM jeux_video

On rcuprera alors les donnes suivantes : nom_maj SUPER MARIO BROS SONIC ZELDA : OCARINA OF TIME MARIO KART 64 SUPER SMASH BROS MELEE possesseur Florent Patrick Florent Florent Michel console NES Megadrive Nintendo 64 Nintendo 64 GameCube prix 4 2 15 25 55

Vous savez maintenant utiliser une fonction SQL scalaire. ;-) Passons en revue quelques fonctions du mme type, et qui sutilisent donc de la mme manire.

Prsentation de quelques fonctions scalaires utiles


Je vais vous prsenter une slection de fonctions scalaires quil peut tre utile de connatre. Il en existe bien dautres comme nous le verrons la n de cette liste, mais il serait trop long et peu utile de toutes les prsenter ici.

UPPER : convertir en majuscules Cette fonction convertit le texte dun champ en majuscules. Nous lavons dcouverte pour introduire les fonctions SQL :
SELECT UPPER(nom) AS nom_maj FROM jeux_video

Ainsi, le jeu Sonic sera renvoy sous la forme SONIC dans un champ nomm nom_maj. 228

LES FONCTIONS SCALAIRES LOWER : convertir en minuscules Cette fonction a leet inverse : le contenu sera entirement crit en minuscules.
SELECT LOWER(nom) AS nom_min FROM jeux_video

Cette fois, le jeu Sonic sera renvoy sous la forme sonic dans un champ nomm nom_min. LENGTH : compter le nombre de caractres Vous pouvez obtenir la longueur dun champ avec la fonction LENGTH() :
SELECT LENGTH(nom) AS longueur_nom FROM jeux_video

Pour Sonic , on rcuprera donc la valeur 5 dans un champ longueur_nom. ROUND : arrondir un nombre dcimal La fonction ROUND() sutilise sur des champs comportant des valeurs dcimales. Il ny en a pas dans la table jeux_video, mais si on avait des prix dcimaux, on pourrait arrondir les valeurs avec cette fonction. Celle-ci prend cette fois deux paramtres : le nom du champ arrondir et le nombre de chires aprs la virgule que lon souhaite obtenir. Exemple :
SELECT ROUND(prix, 2) AS prix_arrondi FROM jeux_video

Ainsi, si un jeu cote 25,86999 euros, on obtiendra la valeur 25,87 euros dans un champ prix_arrondi. Et bien dautres ! Il existe beaucoup dautres fonctions SQL du mme type mais je ne peux pas toutes vous les prsenter. La documentation de MySQL vous propose une liste bien plus complte de fonctions mathmatiques (comme ROUND) et de fonctions sur les chanes de caractres (comme UPPER). Si vous voulez en dcouvrir dautres, cest par l quil faut aller ! Voir la liste des fonctions mathmatiques : Code web : 659218 Voir la liste des fonctions sur les chanes de caractres : Code web : 591250 229

CHAPITRE 20. LES FONCTIONS SQL

Les fonctions dagrgat


Comme prcdemment, nous allons dabord voir comment on utilise une fonction dagrgat dans une requte SQL et comment on rcupre le rsultat en PHP, puis je vous prsenterai une slection de fonctions connatre. Bien entendu, il en existe bien dautres que vous pourrez dcouvrir dans la documentation. Lessentiel est de comprendre comment sutilise ce type de fonctions : vous pourrez ensuite appliquer ce que vous connaissez nimporte quelle autre fonction du mme type.

Utiliser une fonction dagrgat SQL


Ces fonctions dirent assez des prcdentes. Plutt que de modier des valeurs une une, elles font des oprations sur plusieurs entres pour retourner une seule valeur. Par exemple, ROUND permettait darrondir chaque prix. On rcuprait autant dentres quil y en avait dans la table. En revanche, une fonction dagrgat comme AVG renvoie une seule entre : la valeur moyenne de tous les prix. Regardons de prs la fonction dagrgat AVG. Elle calcule la moyenne dun champ contenant des nombres. Utilisons-la sur le champ prix :
SELECT AVG(prix) AS prix_moyen FROM jeux_video

On donne l encore un alias au rsultat donn par la fonction. La particularit, cest que cette requte ne va retourner quune seule entre, savoir le prix moyen de tous les jeux : prix_moyen 28.34 Pour acher cette information en PHP, on pourrait faire comme on en a lhabitude (cela fonctionne) :
<?php $reponse = $bdd->query(SELECT AVG(prix) AS prix_moyen FROM jeux_video); while ($donnees = $reponse->fetch()) { echo $donnees[prix_moyen]; } $reponse->closeCursor(); ?>

Nanmoins, pourquoi sembterait-on faire une boucle tant donn quon sait quon ne va rcuprer quune seule entre, puisquon utilise une fonction dagrgat ? 230

LES FONCTIONS DAGRGAT On peut se permettre dappeler fetch() une seule fois et en dehors dune boucle tant donn quil ny a quune seule entre. Le code suivant est donc un peu plus adapt dans le cas prsent :
<?php $reponse = $bdd->query(SELECT AVG(prix) AS prix_moyen FROM jeux_video); $donnees = $reponse->fetch(); echo $donnees[prix_moyen]; $reponse->closeCursor(); ?>

Ce code est plus simple et plus logique. On rcupre la premire et seule entre avec fetch() et on ache ce quelle contient, puis on ferme le curseur. Inutile de le faire dans une boucle tant donn quil ny a pas de seconde entre. Nhsitez pas ltrer ! Bien entendu, vous pouvez proter de toute la puissance du langage SQL pour obtenir, par exemple, le prix moyen des jeux appartenant Patrick. Voici comment on sy prendrait :
SELECT AVG(prix) AS prix_moyen FROM jeux_video WHERE possesseur=Patrick

Le calcul de la moyenne ne sera fait que sur la liste des jeux qui appartiennent Patrick. Vous pourriez mme combiner les conditions pour obtenir le prix moyen des jeux de Patrick qui se jouent un seul joueur. Essayez ! Ne pas mlanger une fonction dagrgat avec dautres champs Soyez attentifs ce point car il nest pas forcment vident comprendre : vous ne devez pas rcuprer dautres champs de la table quand vous utilisez une fonction dagrgat, contrairement tout lheure avec les fonctions scalaires. En eet, quel sens cela aurait-il de faire :
SELECT AVG(prix) AS prix_moyen, nom FROM jeux_video

On rcuprerait dun ct le prix moyen de tous les jeux et de lautre la liste des noms de tous les jeux. . . Il est impossible de reprsenter ceci dans un seul et mme tableau. Comme vous le savez, SQL renvoie les informations sous la forme dun tableau. Or on ne peut pas reprsenter la moyenne des prix (qui tient en une seule entre) en mme temps que la liste des jeux. Si on voulait obtenir ces deux informations il faudrait faire deux requtes. 231

CHAPITRE 20. LES FONCTIONS SQL

Prsentation de quelques fonctions dagrgat utiles


AVG : calculer la moyenne Cest la fonction que lon vient dtudier pour dcouvrir les fonctions dagrgat. Elle retourne la moyenne dun champ contenant des nombres :
SELECT AVG(prix) AS prix_moyen FROM jeux_video

SUM : additionner les valeurs La fonction SUM permet dadditionner toutes les valeurs dun champ. Ainsi, on pourrait connatre la valeur totale des jeux appartenant Patrick :
SELECT SUM(prix) AS prix_total FROM jeux_video WHERE possesseur=Patrick

MAX : retourner la valeur maximale Cette fonction analyse un champ et retourne la valeur maximale trouve. Pour obtenir le prix du jeu le plus cher :
SELECT MAX(prix) AS prix_max FROM jeux_video

MIN : retourner la valeur minimale De mme, on peut obtenir le prix du jeu le moins cher :
SELECT MIN(prix) AS prix_min FROM jeux_video

COUNT : compter le nombre dentres La fonction COUNT permet de compter le nombre dentres. Elle est trs intressante mais plus complexe. On peut en eet lutiliser de plusieurs faons direntes. Lutilisation la plus courante consiste lui donner * en paramtre :
SELECT COUNT(*) AS nbjeux FROM jeux_video

On obtient ainsi le nombre total de jeux dans la table. On peut bien entendu ltrer avec une clause WHERE, pour obtenir le nombre de jeux appartenant Florent par exemple :
SELECT COUNT(*) AS nbjeux FROM jeux_video WHERE possesseur=Florent

232

LES FONCTIONS DAGRGAT Il est possible de compter uniquement les entres pour lesquelles lun des champs nest pas vide, cest--dire quil ne vaut pas NULL. Il ny a pas de jeu de ce type dans notre table jeux_video, mais supposons que pour certains jeux on ne connaisse pas le nombre de joueurs maximum. On laisserait certaines entres vides, ce qui aurait pour eet dacher NULL (pas de valeur) dans la colonne nbre_joueurs_max (comme dans le tableau 20.1). Tab. 20.1 Champs vides dans une table nbre_ joueurs_ max NULL

ID

nom Super Mario Bros Sonic

possesseur

console

prix

commentaires Un jeu danthologie ! Pour moi, le meilleur jeu au monde ! Un jeu grand, beau et complet comme on en voit rarement de nos jours Un excellent jeu de kart ! Un jeu de baston dlirant !

Florent

NES

Patrick

Megadrive

NULL

Zelda : ocarina of time Mario Kart 64 Super Smash Bros Melee

Florent

Nintendo 64

15

Florent

Nintendo 64 GameCube

25

Michel

55

NULL

Dans ce cas, on peut compter uniquement les jeux qui ont un nombre de joueurs maximum dni. On doit indiquer en paramtre le nom du champ analyser :
SELECT COUNT(nbre_joueurs_max) AS nbjeux FROM jeux_video

Dans notre exemple, seuls les jeux Zelda et Mario Kart seront compts car on connat leur nombre de joueurs maximum. Donc on obtiendra 2 en rponse. Enn, il est possible de compter le nombre de valeurs distinctes sur un champ prcis. Par exemple dans la colonne possesseur, Florent apparat plusieurs fois, Patrick aussi, etc. Mais combien y a-t-il de personnes direntes dans la table ? On peut le savoir en utilisant le mot-cl DISTINCT devant le nom du champ analyser, comme ceci :
SELECT COUNT(DISTINCT possesseur) AS nbpossesseurs FROM jeux_video

On peut ainsi facilement savoir combien de personnes direntes sont rfrences dans 233

CHAPITRE 20. LES FONCTIONS SQL la table. Essayez de faire de mme pour connatre le nombre de consoles direntes dans la table !

GROUP BY et HAVING : le groupement de donnes


Je vous disais un peu plus tt quon ne pouvait pas rcuprer dautres champs lorsquon utilisait une fonction dagrgat. Prenons par exemple la requte suivante :
SELECT AVG(prix) AS prix_moyen, console FROM jeux_video

a na pas de sens de rcuprer le prix moyen de tous les jeux et le champ console la fois. Il ny a quun seul prix moyen pour tous les jeux, mais plusieurs consoles. MySQL ne peut pas renvoyer un tableau correspondant ces informations-l.

GROUP BY : grouper des donnes


En revanche, ce qui pourrait avoir du sens, ce serait de demander le prix moyen des jeux pour chaque console ! Pour faire cela, on doit utiliser un nouveau mot-cl : GROUP BY. Cela signie grouper par . On utilise cette clause en combinaison dune fonction dagrgat (comme AVG) pour obtenir des informations intressantes sur des groupes de donnes. Voici un exemple dutilisation de GROUP BY :
SELECT AVG(prix) AS prix_moyen, console FROM jeux_video GROUP BY console

Code web : 103196 Il faut utiliser GROUP BY en mme temps quune fonction dagrgat, sinon il ne sert rien. Ici, on rcupre le prix moyen et la console, et on choisit de grouper par console. Par consquent, on obtiendra la liste des direntes consoles de la table et le prix moyen des jeux de chaque plate-forme ! prix_moyen 12.67 5.00 47.50 console Dreamcast Gameboy GameCube

Cette fois les valeurs sont cohrentes ! On a la liste des consoles et le prix moyen des jeux associs. Exercice : essayez dobtenir de la mme faon la valeur totale des jeux que possde chaque personne. 234

GROUP BY ET HAVING : LE GROUPEMENT DE DONNES

HAVING : ltrer les donnes regroupes


HAVING est un peu lquivalent de WHERE, mais il agit sur les donnes une fois quelles ont t regroupes. Cest donc une faon de ltrer les donnes la n des oprations. Voyez la requte suivante :
SELECT AVG(prix) AS prix_moyen, console FROM jeux_video GROUP BY console HAVING prix_moyen <= 10

Code web : 808028 Avec cette requte, on rcupre uniquement la liste des consoles et leur prix moyen si ce prix moyen ne dpasse pas 10 euros. HAVING ne doit sutiliser que sur le rsultat dune fonction dagrgat. Voil pourquoi on lutilise ici sur prix_moyen et non sur console. Je ne comprends pas la dirence entre WHERE et HAVING. Les deux permettent de ltrer, non ? Oui, mais pas au mme moment. WHERE agit en premier, avant le groupement des donnes, tandis que HAVING agit en second, aprs le groupement des donnes. On peut dailleurs trs bien combiner les deux, regardez lexemple suivant :
SELECT AVG(prix) AS prix_moyen, console FROM jeux_video WHERE possesseur=Patrick GROUP BY console HAVING prix_moyen <= 10

Code web : 874374 a commence faire de la requte maousse costaude. ;-) Ici, on demande rcuprer le prix moyen par console de tous les jeux de Patrick (WHERE), condition que le prix moyen des jeux de la console ne dpasse pas 10 euros (HAVING).

En rsum
MySQL permet dexcuter certaines fonctions lui-mme, sans avoir passer par PHP. Ces fonctions modient les donnes renvoyes. Il existe deux types de fonctions : les fonctions scalaires : elles agissent sur chaque entre rcupre. Elles permettent par exemple de convertir tout le contenu dun champ en majuscules ou darrondir chacune des valeurs ; les fonctions dagrgat : elles eectuent des calculs sur plusieurs entres pour retourner une et une seule valeur. Par exemple : calcul de la moyenne, somme des valeurs, comptage du nombre dentres. . . 235

CHAPITRE 20. LES FONCTIONS SQL On peut donner un autre nom aux champs modis par les fonctions en crant des alias laide du mot-cl AS. Lorsquon utilise une fonction dagrgat, il est possible de regrouper des donnes avec GROUP BY. Aprs un groupement de donnes, on peut ltrer le rsultat avec HAVING. Il ne faut pas le confondre avec WHERE qui ltre avant le groupement des donnes.

236

Chapitre

21
Dicult :

Les dates en SQL

orsque nous avons construit nos tables, nous avons utilis dirents types de champs, notamment INT (nombre entier), VARCHAR (texte court) et TEXT (texte long). Vous avez pu dcouvrir dans phpMyAdmin quil existait de nombreux autres types. La plupart ne sont que des variations de ces types, pour stocker par exemple de trs petits ou de trs grands nombres. La plupart du temps, vous naurez pas vous soucier de tous ces types : INT sut amplement pour les nombres entiers par exemple.

Les dates sont plus dlicates manier en SQL, et, pourtant, on en a trs souvent besoin. Par exemple, dans le TP du mini-chat, on pourrait sen servir pour stocker le jour et lheure prcise o chaque message a t post. Il en va de mme si vous construisez un systme de forum ou de news pour votre site : vous aurez besoin denregistrer la date chaque fois. Nous ferons dabord le tour des types de champs connatre pour stocker des dates avec MySQL et nous verrons comment les utiliser. Nous pourrons ensuite dcouvrir de nouvelles fonctions SQL ddies aux dates.

237

CHAPITRE 21. LES DATES EN SQL

Les champs de type date


Dans ce chapitre, je vous propose damliorer un peu le mini-chat que nous avons cr dans un prcdent TP. Saviez-vous quil tait possible de modier la structure dune table aprs sa cration ? On peut en eet y ajouter (gure 21.1) ou y supprimer des champs tout moment. Ouvrez la table mini_chat dans phpMyAdmin, onglet Structure . Cherchez en bas de la page le formulaire Ajouter 1 champ en n de table et cliquez sur le bouton Excuter .

Fig. 21.1 Ajout dun champ dans phpMyAdmin Un formulaire apparat, vous proposant de crer un nouveau champ. Cest loccasion de passer en revue les dirents types de champs qui permettent de stocker des dates.

Les dirents types de dates


Voici les dirents types de dates que peut stocker MySQL : DATE : stocke une date au format AAAA-MM-JJ (Anne-Mois-Jour) ; TIME : stocke un moment au format HH:MM:SS (Heures:Minutes:Secondes) ; DATETIME : stocke la combinaison dune date et dun moment de la journe au format AAAA-MM-JJ HH:MM:SS. Ce type de champ est donc plus prcis ; TIMESTAMP : stocke une date et un moment sous le format AAAAMMJJHHMMSS ; YEAR : stocke une anne, soit au format AA, soit au format AAAA. Cela fait beaucoup de choix ! Dans la pratique, je vous invite retenir surtout DATE (AAAA-MM-JJ) quand le moment de la journe importe peu, et DATETIME (AAAAMM-JJ HH:MM:SS) quand vous avez besoin du jour et de lheure prcise la seconde prs. Crez un champ nomm date de type DATETIME comme sur la gure 21.2. Bien que cela fonctionne avec MySQL, il est parfois prfrable de donner un autre nom au champ que date. En eet, cest un mot-cl du langage SQL, ce qui peut provoquer des erreurs avec dautres systmes de bases de donnes comme Oracle. Vous pourriez par exemple nommer le champ comme ceci : date_creation, ou encore date_modification.

Utilisation des champs de date en SQL


Les champs de type date sutilisent comme des chanes de caractres : il faut donc les entourer dapostrophes. Vous devez crire la date dans le format du champ. 238

LES CHAMPS DE TYPE DATE

Fig. 21.2 Cration dun champ de date

Par exemple, pour un champ de type DATE :


SELECT pseudo, message, date FROM minichat WHERE date = 2010-04-02

. . . vous renverra la liste des messages posts le 02/04/2010 (2 avril 2010). Si le champ est de type DATETIME1 , il faut aussi indiquer prcisment les heures, minutes et secondes :
SELECT pseudo, message, date FROM minichat WHERE date = 2010-04-02 15:28:22

Cela vous renverra la liste des messages posts le 02/04/2010 15h28min22s. Bon : je reconnais que cest un peu prcis, il est peu probable que beaucoup de messages aient t posts ce moment exact. En revanche, et cest l que les champs de date deviennent rellement intressants, vous pouvez utiliser dautres oprateurs que le signe gal. Par exemple, on peut obtenir la liste de tous les messages posts aprs cette date :
SELECT pseudo, message, date FROM minichat WHERE date >= 2010-04-02 15:28:22

Ou mme la liste de tous les messages posts entre le 02/04/2010 et le 18/04/2010 :


SELECT pseudo, message, date FROM minichat WHERE date >= 2010-04-02 00:00:00 AND date <= 2010-04-18 00:00:00
1 Comme

cest le cas pour notre nouveau mini-chat.

239

CHAPITRE 21. LES DATES EN SQL En SQL, pour rcuprer des donnes comprises entre deux intervalles, comme ici, il y a une syntaxe plus simple et plus lgante avec le mot-cl BETWEEN qui signie entre . On pourrait crire la requte prcdente comme ceci :
SELECT pseudo, message, date FROM minichat WHERE date BETWEEN 2010-04-02 00 :00 :00 AND 2010-04-18 00 :00 :00

Cela signie : rcuprer tous les messages dont la date est comprise entre 2010-04-02 00:00:00 et 2010-04-18 00:00:00 . Vous pouvez aussi utiliser cette syntaxe sur les champs contenant des nombres. Si vous voulez insrer une entre contenant une date, il sut l encore de respecter le format de date de la base de donnes :
INSERT INTO minichat(pseudo, message, date) VALUES(Mateo, Message !, 2010-04-02 16:32:22)

Les fonctions de gestion des dates


Il existe de trs nombreuses fonctions de manipulation des dates. Utilises sur des champs de type DATE ou DATETIME par exemple, elles permettent dextraire trs facilement toutes sortes dinformations utiles sur les dates, comme lanne, le numro du jour du mois, le numro du jour dans lanne, etc. Il est aussi possible deectuer des oprations sur les dates. Il est impossible de lister toutes les fonctions de gestion des dates, mais vous trouverez la liste complte de celles-ci dans la documentation de MySQL au besoin. Cette introduction aux dates devrait tre susante pour que vous puissiez vous dbrouiller tout seuls par la suite. Code web : 835456

NOW() : obtenir la date et lheure actuelles


Cest probablement une des fonctions que vous utiliserez le plus souvent. Lorsque vous insrez un nouveau message dans la base, vous souhaiterez enregistrer la date actuelle les 99 % du temps. Pour cela, rien de plus simple avec la fonction NOW() :
INSERT INTO minichat(pseudo, message, date) VALUES(Mateo, Message !, NOW())

La date sera alors automatiquement remplace par la date et lheure actuelles au format AAAA-MM-JJ HH:MM:SS. Notez quil existe aussi les fonctions CURDATE() et CURTIME() qui retournent respectivement uniquement la date (AAAA-MM-JJ) et lheure (HH:MM:SS). 240

LES FONCTIONS DE GESTION DES DATES

DAY(), MONTH(), YEAR() : extraire le jour, le mois ou lanne


Extraire des informations dune date ? Cest facile ! Voici un exemple dutilisation :
SELECT pseudo, message, DAY(date) AS jour FROM minichat

On rcuprera trois champs : le pseudo, le message et le numro du jour o il a t post.

HOUR(), MINUTE(), SECOND() : extraire les heures, minutes, secondes


De la mme faon, avec ces fonctions il est possible dextraire les heures, minutes et secondes dun champ de type DATETIME ou TIME.
SELECT pseudo, message, HOUR(date) AS heure FROM minichat

DATE_FORMAT : formater une date


Avec les fonctions que lon vient de dcouvrir linstant, on pourrait extraire tous les lments de la date, comme ceci :
SELECT pseudo, message, DAY(date) AS jour, MONTH(date) AS mois, YEAR(date) AS annee, HOUR(date) AS heure, MINUTE(date) AS minute, SECOND(date) AS seconde FROM minichat

On pourrait ensuite acher la date en PHP dans lordre que lon souhaite laide du dcoupage en champs que lon vient de faire :
<?php echo $donnees[jour] . / . $donnees[mois] . / . $donnees[annee] . ...; ?>

Cest cependant un peu compliqu, et il y a plus simple. La fonction DATE_FORMAT vous permet dadapter directement la date au format que vous prfrez. Il faut dire que le format par dfaut de MySQL (AAAA-MM-JJ HH:MM:SS) nest pas trs courant en France. Voici comment on pourrait lutiliser :
SELECT pseudo, message, DATE_FORMAT(date, %d/%m/%Y %Hh%imin%ss) AS date FROM minichat

Ainsi, on rcuprerait les dates avec un champ nomm date sous la forme 11/03/2010 15h47min49s. 241

CHAPITRE 21. LES DATES EN SQL

Comment a marche, ce bazar ?

Les symboles %d, %m, %Y (etc.) sont remplacs par le jour, le mois, lanne, etc. Les autres symboles et lettres sont achs tels quels. Il existe beaucoup dautres symboles pour extraire par exemple le nom du jour2 , le numro du jour dans lanne, etc. La liste des symboles disponibles est dans la doc la section DATE_FORMAT. Code web : 347134

DATE_ADD et DATE_SUB : ajouter ou soustraire des dates


Il est possible dajouter ou de soustraire des heures, minutes, secondes, jours, mois ou annes une date. Il faut envoyer deux paramtres la fonction : la date sur laquelle travailler et le nombre ajouter ainsi que son type. Par exemple, supposons que lon souhaite acher une date dexpiration du message. Celle-ci correspond la date o a t post le message + 15 jours . Voici comment crire la requte :
SELECT pseudo, message, DATE_ADD(date, INTERVAL 15 DAY) AS date_expiration FROM minichat

Le champ date_expiration correspond la date de lentre + 15 jours . Le mot-cl INTERVAL ne doit pas tre chang ; en revanche, vous pouvez remplacer DAY par MONTH, YEAR, HOUR, MINUTE, SECOND, etc. Par consquent, si vous souhaitez indiquer que les messages expirent dans deux mois :
SELECT pseudo, message, DATE_ADD(date, INTERVAL 2 MONTH) AS date_expiration FROM minichat

En rsum
MySQL propose plusieurs types de champs pour stocker des dates. Les deux types les plus couramment utiliss sont : DATE : stocke une date au format AAA-MM-JJ ; DATETIME : stocke une date et une heure au format AAAA-MM-JJ HH:MM:SS. On peut trier et ltrer des champs contenant des dates comme sil sagissait de nombres. Il existe de nombreuses fonctions SQL ddies au traitement des dates. La plus connue est NOW() qui renvoie la date et lheure actuelles.
2 La

plupart du temps en anglais malheureusement, comme Saturday .

242

Chapitre

22
Dicult :

TP : un blog avec des commentaires

e blog est probablement lapplication la plus courante que lon ralise en PHP avec MySQL. Bien quil soit conseill dutiliser un systme tout prt (en tlchargeant Wordpress ou Dotclear, par exemple), en crer un de toutes pices est un excellent exercice. Le but de ce TP nest pas de vous faire crer un blog de A Z, car ce serait un peu long, mais plutt dappliquer les dernires notions de SQL que vous venez dapprendre sur les fonctions et les dates. Chaque billet du blog possdera ses propres commentaires. Dans ce TP, nous nous concentrerons uniquement sur lachage des billets et des commentaires ; ce sera vous par la suite de complter le blog pour y insrer des formulaires dajout et de modication du contenu.

243

CHAPITRE 22. TP : UN BLOG AVEC DES COMMENTAIRES

Instructions pour raliser le TP


Pour ce TP comme pour le prcdent, nous allons nous prparer ensemble en passant en revue les points suivants : prrequis ; objectifs ; structure de la table MySQL ; structure des pages PHP.

Prrequis
Dans ce TP, nous allons nous concentrer sur la base de donnes. Nous aurons besoin des notions suivantes : lire dans une table ; utilisation de PDO et des requtes prpares ; utilisation de fonctions SQL ; manipulation des dates en SQL.

Objectifs
Commenons par dnir ce quon veut arriver faire. Un systme de blog avec des commentaires, oui, mais encore ? Il faut savoir jusquo on veut aller, ce quon a lintention de raliser et ce quon va laisser de ct. Si on est trop ambitieux, on risque de le regretter : on pourrait en eet y passer des jours et ce TP deviendrait long, complexe et fastidieux. Je vous propose donc de raliser lachage de base dun blog et des commentaires associs aux billets, et je vous inviterai par la suite lamliorer pour crer linterface de gestion des billets et dajout de commentaires. Lajout de billets et de commentaires nest donc pas au programme de ce TP, ce qui va nous permettre de nous concentrer sur lachage de ces derniers. Les pages dvelopper Il y aura deux pages raliser : index.php : liste des cinq derniers billets ; commentaires.php : achage dun billet et de ses commentaires. Voici, en gure 22.1, quoi devrait ressembler la liste des derniers billets (index.php). Et en gure 22.2, quoi devrait ressembler lachage dun billet et de ses commentaires (commentaires.php). Comme vous pouvez le constater, lachage est minimaliste. Le but nest pas de raliser le design de ce blog mais bel et bien dobtenir quelque chose de fonctionnel. 244

INSTRUCTIONS POUR RALISER LE TP

Fig. 22.1 Liste des billets

Fig. 22.2 Liste des commentaires

245

CHAPITRE 22. TP : UN BLOG AVEC DES COMMENTAIRES Le CSS Voici le chier CSS (trs simple) que jutiliserai pour ce TP :
h1, h3 { text-align:center; } h3 { background-color:black; color:white; font-size:0.9em; margin-bottom:0px; } .news p { background-color:#CCCCCC; margin-top:0px; } .news { width:70%; margin:auto; } a { }

text-decoration: none; color: blue;

Code web : 977353 Libre vous de lutiliser ou non, de le modier ; bref, faites-en ce que vous voulez. ;-)

Structure des tables MySQL


Eh oui, cette fois nous allons travailler avec non pas une mais deux tables : billets : liste des billets du blog ; commentaires : liste des commentaires du blog pour chaque billet. On va vraiment stocker tous les commentaires dans une seule table, mme sils concernent des billets dirents ? Oui. Cest la bonne faon de faire. Tous les commentaires, quel que soit le billet auquel ils se rapportent, seront stocks dans la mme table. On pourra faire le tri facilement 246

INSTRUCTIONS POUR RALISER LE TP laide dun champ id_billet qui indiquera pour chaque commentaire le numro du billet associ. Voici la structure que je propose pour la table billets : id (int) : identiant du billet, cl primaire et auto_increment ; titre (varchar 255) : titre du billet ; contenu (text) : contenu du billet ; date_creation (datetime) : date et heure de cration du billet. id (int) : identiant du commentaire, cl primaire et auto_increment ; id_billet (int) : identiant du billet auquel correspond ce commentaire ; auteur (varchar 255) : auteur du commentaire ; commentaire (text) : contenu du commentaire ; date_commentaire (datetime) : date et heure auxquelles le commentaire a t post.

De mme, voici la structure que lon va utiliser pour la table commentaires :

Cest vraiment la base. Vous pouvez ajouter dautres champs si vous le dsirez. Par exemple, on na pas dni de champ auteur pour les billets. Notez quil est possible dajouter des champs tout moment, comme nous lavons vu il y a peu. Linterface phpMyAdmin propose des options pour cela. Comme nous nallons pas crer les formulaires dajout de billets et de commentaires dans un premier temps, je vous conseille de remplir vous-mmes les tables laide de phpMyAdmin aprs les avoir cres. Si vous tes du genre emmards, vous pouvez aussi tlcharger mes tables toutes prtes avec quelques donnes lintrieur, mais je vous recommande de vous entraner les crer vous-mmes. Code web : 503724

Structure des pages PHP


tant donn que nous nous concentrons sur lachage, la structure des pages reste trs simple, comme latteste la gure 22.3. Le visiteur arrive dabord sur lindex o sont achs les derniers billets. Sil choisit dacher les commentaires de lun deux, il charge la page commentaires.php qui achera le billet slectionn ainsi que tous ses commentaires. Bien entendu, il faudra envoyer un paramtre la page commentaires.php pour quelle sache quoi acher. . . je vous laisse deviner lequel. Il sera possible de revenir la liste des billets depuis les commentaires laide dun lien de retour. 247

CHAPITRE 22. TP : UN BLOG AVEC DES COMMENTAIRES

Fig. 22.3 Structure des pages du blog

vous de jouer !
Je vous en ai assez dit : la ralisation de ce TP devrait tre relativement simple pour vous si vous avez bien suivi jusquici. Noubliez pas les lments essentiels de scurit, notamment la protection de tous les textes par htmlspecialchars(). Et ne faites jamais conance lutilisateur !

Correction
Si vous lisez ces lignes, cest que vous devez tre venus bout de ce TP. Celui-ci ne prsentait pas de dicults particulires mais il constituait loccasion de vous exercer un peu plus avec MySQL, tout en faisant appel aux fonctions et dates en SQL.

index.php : la liste des derniers billets


Le TP est constitu de deux pages. Voici la correction que je vous propose pour la page index.php qui liste les derniers billets du blog :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr"> <head> <title>Mon blog</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <link href="style.css" rel="stylesheet" type="text/css" /> </head> <body> <h1>Mon super blog !</h1> <p>Derniers billets du blog :</p>

248

CORRECTION
<?php // Connexion la base de donnes try { $bdd = new PDO(mysql:host=localhost;dbname=test, root, ); } catch(Exception $e) { die(Erreur : .$e->getMessage()); } // On rcupre les 5 derniers billets $req = $bdd->query(SELECT id, titre, contenu, DATE_FORMAT(date_creation, \%d/%m/%Y %Hh%imin%ss\) AS date_creation_fr FROM billets ORDER BY date_creation DESC LIMIT 0, 5); while ($donnees = $req->fetch()) { ?> <div class="news"> <h3> <?php echo htmlspecialchars($donnees[titre]); ?> <em>le <?php echo $donnees[date_creation_fr]; ?></em> </h3> <p> <?php // On affiche le contenu du billet echo nl2br(htmlspecialchars($donnees[contenu])); ?> <br /> <em><a href="commentaires.php?billet=<?php echo $donnees[id]; ?>"> Commentaires</a></em> </p> </div> <?php } // Fin de la boucle des billets $req->closeCursor(); ?> </body> </html>

Code web : 534698 Vous constaterez que tous les textes sont protgs par htmlspecialchars(), y compris les titres. Jutilise par ailleurs une fonction qui doit tre nouvelle pour vous : nl2br(). Elle permet de convertir les retours la ligne en balises HTML <br />. Cest une fonction dont vous aurez srement besoin pour conserver facilement les retours la ligne saisis dans les formulaires. 249

CHAPITRE 22. TP : UN BLOG AVEC DES COMMENTAIRES Ct SQL, cette page nexcute quune seule requte : celle qui rcupre les cinq derniers billets.
SELECT id, titre, contenu, DATE_FORMAT(date_creation, %d/%m/%Y %Hh%imin%ss) AS date_creation_fr FROM billets ORDER BY date_creation DESC LIMIT 0, 5

On rcupre toutes les donnes qui nous intressent dans cette table, en mettant la date en forme au passage. Pour cela, on utilise la fonction scalaire DATE_FORMAT qui nous permet dobtenir une date dans un format franais. Les billets sont ordonns par date dcroissante, le plus rcent tant donc en haut de la page. Enn, chaque billet est suivi dun lien vers la page commentaires.php qui transmet le numro du billet dans lURL :
<a href="commentaires.php?billet=<?php echo $donnees[id]; ?>">Commentaires</a>

commentaires.php : achage dun billet et de ses commentaires


Cette page prsente des similitudes avec la prcdente mais elle est un peu plus complexe. En eet, pour acher un billet ainsi que ses commentaires, nous avons besoin de faire deux requtes SQL : une requte pour rcuprer le contenu du billet ; une requte pour rcuprer les commentaires associs au billet.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr"> <head> <title>Mon blog</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <link href="style.css" rel="stylesheet" type="text/css" /> </head> <body> <h1>Mon super blog !</h1> <p><a href="index.php">Retour la liste des billets</a></p> <?php // Connexion la base de donnes try { $bdd = new PDO(mysql:host=localhost;dbname=test, root, ); } catch(Exception $e) {

250

CORRECTION
die(Erreur : .$e->getMessage());

// Rcupration du billet $req = $bdd->prepare(SELECT id, titre, contenu, DATE_FORMAT(date_creation, \%d/%m/%Y %Hh%imin%ss\) AS date_creation_fr FROM billets WHERE id = ?); $req->execute(array($_GET[billet])); $donnees = $req->fetch(); ?> <div class="news"> <h3> <?php echo htmlspecialchars($donnees[titre]); ?> <em>le <?php echo $donnees[date_creation_fr]; ?></em> </h3> <p> <?php echo nl2br(htmlspecialchars($donnees[contenu])); ?> </p> </div> <h2>Commentaires</h2> <?php $req->closeCursor(); // Important : on libre le curseur pour la prochaine requte // Rcupration des commentaires $req = $bdd->prepare(SELECT auteur, commentaire, DATE_FORMAT(date_commentaire, \%d/%m/%Y %Hh%imin%ss\) AS date_commentaire_fr FROM commentaires WHERE id_billet = ? ORDER BY date_commentaire); $req->execute(array($_GET[billet])); while ($donnees = $req->fetch()) { ?> <p><strong><?php echo htmlspecialchars($donnees[auteur]); ?></strong> le <?php echo $donnees[date_commentaire_fr]; ?></p> <p><?php echo nl2br(htmlspecialchars($donnees[commentaire])); ?></p> <?php } // Fin de la boucle des commentaires $req->closeCursor(); ?> </body> </html>

251

CHAPITRE 22. TP : UN BLOG AVEC DES COMMENTAIRES Code web : 886123 Ce code est un peu gros mais on peut le dcouper en deux parties : achage du billet ; achage des commentaires. La requte qui rcupre le billet ressemble celle de la page prcdente, la dirence prs quil sagit dune requte prpare car elle dpend dun paramtre : lid du billet (fourni par $_GET[billet] quon a reu dans lURL). Comme on rcupre forcment un seul billet, il est inutile de faire une boucle. Lachage est identique celui quon faisait pour chaque billet sur la page prcdente, lexception du lien vers la page des commentaires qui ne sert plus rien1 . On pense librer le curseur aprs lachage du billet avec :
<?php $req->closeCursor(); ?>

En eet, cela permet de terminer le traitement de la requte pour pouvoir traiter la prochaine requte sans problme. La rcupration des commentaires se fait ensuite via la requte suivante :
SELECT auteur, commentaire, DATE_FORMAT(date_commentaire, %d/%m/%Y %Hh%imin%ss) AS date_commentaire_fr FROM commentaires WHERE id_billet = ? ORDER BY date_commentaire

Vous noterez que lon ne se connecte la base de donnes quune fois par page. Pas besoin donc de se connecter nouveau pour eectuer cette seconde requte. On rcupre avec cette requte tous les commentaires lis au billet correspondant lid reu dans lURL. Les commentaires sont tris par dates croissantes comme cest habituellement le cas sur les blogs, mais vous pouvez changer cet ordre si vous le dsirez, cest facile.

Aller plus loin


Ce TP ne concernait que la structure de base dun blog avec commentaires. Comme il est relativement simple, les possibilits dextension ne manquent pas. ;-) Alors, comment pourrait-on amliorer notre blog ? Voici quelques suggestions que je vous conseille dtudier et qui vous feront progresser.
1 Puisque

nous sommes sur la page des commentaires.

252

ALLER PLUS LOIN

Un formulaire dajout de commentaires


Sur la page commentaires.php, rajoutez un formulaire pour que nimporte quel visiteur puisse poster un commentaire. Ce formulaire redirigera vers une page qui enregistrera le commentaire puis qui redirigera vers la liste des commentaires, comme on lavait fait avec le mini-chat. Cest ce que vous pouvez voir sur la gure 22.4.

Fig. 22.4 Structure des pages avec ajout de commentaires Cest votre porte ; vous avez dj russi le faire, allez-y !

Utiliser les includes


Certaines portions de code sont un peu rptitives. Par exemple, on retrouve le mme bloc achant un billet sur la page des billets et sur celle des commentaires. Il serait peut-tre plus simple davoir un seul code dans un chier que lon inclurait ensuite depuis index.php et commentaires.php.

Vrier si le billet existe sur la page des commentaires


Imaginez que le visiteur samuse modier lURL de la page des commentaires. Par exemple sil essaie daccder commentaires.php ?billet=819202 et que le billet no 819202 nexiste pas, il naura pas de message derreur2 . Pour que votre site paraisse un peu plus srieux, vous devriez acher une erreur. Pour cela, regardez si la requte qui rcupre le contenu du billet renvoie des donnes. Le plus simple est donc de vrier aprs le fetch() si la variable $donnees est vide ou non, grce la fonction empty(). Ainsi, si la variable est vide, vous pourrez acher un message derreur comme Ce billet nexiste pas . Sinon, vous acherez le reste de la page normalement.
2 En

fait, le contenu de la page sera vide.

253

CHAPITRE 22. TP : UN BLOG AVEC DES COMMENTAIRES

Paginer les billets et commentaires


Quand vous commencerez avoir beaucoup de billets (et beaucoup de commentaires), vous voudrez peut-tre ne pas tout acher sur la mme page. Pour cela, il faut crer un systme de pagination. Supposons que vous souhaitiez acher uniquement cinq commentaires par page. Si vous voulez acher des liens vers chacune des pages, il faut savoir combien votre blog comporte de billets. Par exemple, si vous avez 5 billets, il ny aura quune seule page. Si vous avez 12 billets, il y aura trois pages. Pour connatre le nombre de billets, une requte SQL avec COUNT(*) est indispensable :
SELECT COUNT(*) AS nb_billets FROM billets

Une fois ce nombre de billets rcupr, vous pouvez trouver le nombre de pages et crer des liens vers chacune delles : Page : 1 2 3 4 Chacun de ces nombres amnera vers la mme page et ajoutera dans lURL le numro de la page :
<a href="index.php?page=2">2</a>

laide du paramtre $_GET[page] vous pourrez dterminer quelle page vous devez acher. vous dadapter la requte SQL pour commencer uniquement partir du billet no x. Par exemple, si vous demandez acher la page 2, vous voudrez acher uniquement les billets nos 4 83 . Revoyez la section sur LIMIT au besoin. Et si aucun numro de page nest dni dans lURL, lorsquon arrive la premire fois sur le blog ? Dans ce cas, si $_GET[page] nest pas dni, vous devrez considrer que le visiteur veut acher la page 1 (la plus rcente). a demande un peu de rexion mais le jeu en vaut la chandelle ! Nhsitez pas demander de laide sur les forums si ncessaire.

Raliser une interface dadministration du blog


Cest probablement lamlioration la plus longue. Il faudra crer des pages qui permettent de modier, supprimer et ajouter de nouveaux billets. Un problme cependant : comment protger laccs ces pages ? En eet, vous devriez tre seuls avoir accs votre interface dadministration, sinon nimporte qui pourra ajouter des billets sil connat lURL de la page dadministration !
3 Noubliez

pas quon commence compter partir de 0 !

254

ALLER PLUS LOIN Plusieurs techniques existent pour protger laccs ladministration. Le plus simple dans ce cas est de crer un sous-dossier admin qui contiendra tous les chiers dadministration du blog (ajouter.php, modifier.php, supprimer.php. . .). Ce dossier admin sera entirement protg laide des chiers .htaccess et .htpasswd, ce qui fait que personne ne pourra charger les pages quil contient moins de connatre le login et le mot de passe (gure 22.5).

Fig. 22.5 Structure des pages avec admin Pour en savoir plus sur la protection dun dossier avec ces chiers .htaccess et .htpasswd, je vous invite consulter lannexe du cours correspondante page 387. Code web : 521030 Allez, au boulot ! ;-)

255

CHAPITRE 22. TP : UN BLOG AVEC DES COMMENTAIRES

256

Chapitre

23
Dicult :

Les jointures entre tables

ySQL permet de travailler avec plusieurs tables la fois. Un des principaux intrts dune base de donnes est de pouvoir crer des relations entre les tables, de pouvoir les lier entre elles.

Pour le moment, nous navons travaill que sur une seule table la fois. Dans la pratique, vous aurez certainement plusieurs tables dans votre base, dont la plupart seront interconnectes. Cela vous permettra de mieux dcouper vos informations, dviter des rptitions et de rendre ainsi vos donnes plus faciles grer. Tenez, par exemple, dans notre table jeux_video, on rpte chaque fois le nom du possesseur du jeu. Le mot Patrick est crit de nombreuses fois dans la table. Imaginez que lon souhaite stocker aussi son nom de famille, son adresse, son numro de tlphone. . . On ne va quand mme pas recopier ces informations pour chaque jeu quil possde ! Il est temps de crer une autre table et de la lier.

257

CHAPITRE 23. LES JOINTURES ENTRE TABLES

Modlisation dune relation


Si je voulais stocker les nom, prnom et numro de tlphone de chaque propritaire de jeux vido dans notre table jeux_video, il ny aurait pas dautre solution que de dupliquer ces informations sur chaque entre. . . Cependant ce serait bien trop rptitif ; regardez ce que a donnerait sur le tableau 23.1. Tab. 23.1 Duplication des informations sur chaque entre ID nom prenom nom_ tel possesseur 01 44 Florent Dugommier 77 21 33 03 22 Patrick Lejeune 17 41 22 01 44 Florent Dugommier 77 21 33 01 44 Florent Dugommier 77 21 33 04 11 Michel Doussand 78 02 00 console nbre_ prix joueurs_ commentaires max

Super Mario

NES

Un jeu danthologie !

Sonic

Megadrive 2

Pour moi, le meilleur jeu au monde ! Un jeu grand, beau et complet comme on en voit de nos jours

Zelda : ocarina of time

Nintendo 15 64

Mario Kart

Nintendo 25 64

Un excellent jeu de kart !

Super Smash Bros Melee

Game Cube

55

Un jeu de baston dlirant !

Comme vous le voyez, le nom, le prnom et le numro de tlphone de Florent apparaissent autant de fois quil possde de jeux vido, et il en irait de mme pour Patrick et Michel. Il faut tout prix viter ces rptitions. Ce que je vous propose, cest de crer une autre table, que lon nommera par exemple proprietaires, qui centralisera les informations des propritaires des jeux (tableau 23.2). Cette table liste tous les propritaires de jeux connus et attribue chacun un ID. Les 258

MODLISATION DUNE RELATION

Tab. 23.2 Table proprietaires ID 1 2 3 prenom Florent Patrick Michel nom Dugommier Lejeune Doussand tel 01 44 77 21 33 03 22 17 41 22 04 11 78 02 00

propritaires napparaissant quune seule fois, il ny a pas de doublon. Maintenant, il faut modier la structure de la table jeux_video pour faire rfrence aux propritaires. Pour cela, le mieux est de crer un champ ID_proprietaire qui indique le numro du propritaire dans lautre table (tableau 23.3). Tab. 23.3 Table jeux_video ID_ propritaire nbre_ joueurs_ max 1

ID

nom Super Mario Bros Sonic

console

prix

commentaires

NES

Megadrive

Zelda : ocarina of time Mario Kart 64 Super Smash Bros Melee

Nintendo 64 Nintendo 64 GameCube

15

4 5

25

Un jeu danthologie ! Pour moi, le meilleur jeu au monde ! Un jeu grand, beau et complet comme on en voit rarement de nos jours Un excellent jeu de kart ! Un jeu de baston dlirant !

55

Le nouveau champ ID_proprietaire est de type INT. Il permet de faire rfrence une entre prcise de la table proprietaires. On peut maintenant considrer que les tables sont relies travers ces ID de propritaires, comme le suggre la gure 23.1. MySQL sait donc que lID_proprietaire no 1 dans la table jeux_video correspond Florent ? 259

CHAPITRE 23. LES JOINTURES ENTRE TABLES

Fig. 23.1 Relation entre deux tables

Non, il ne le sait pas. Il ne voit que des nombres et il ne fait pas la relation entre les deux tables. Il va falloir lui expliquer cette relation dans une requte SQL : on va faire ce quon appelle une jointure entre les deux tables.

Quest-ce quune jointure ?


Nous avons donc maintenant deux tables : jeux_video ; proprietaires. Les informations sont spares dans des tables direntes et cest bien. Cela vite de dupliquer des informations sur le disque. Cependant, lorsquon rcupre la liste des jeux, si on souhaite obtenir le nom du propritaire, il va falloir adapter la requte pour rcuprer aussi les informations issues de la table proprietaires. Pour cela, on doit faire ce quon appelle une jointure. Il existe plusieurs types de jointures, qui nous permettent de choisir exactement les donnes que lon veut rcuprer. Je vous propose den dcouvrir deux, les plus importantes : les jointures internes : elles ne slectionnent que les donnes qui ont une correspondance entre les deux tables ; les jointures externes : elles slectionnent toutes les donnes, mme si certaines nont pas de correspondance dans lautre table. Il est important de bien comprendre la dirence entre une jointure interne et une jointure externe. Pour cela, imaginons que nous ayons une 4e personne dans la table des propritaires, un certain Romain Vipelli, qui ne possde aucun jeu (tableau 23.4). 260

QUEST-CE QUUNE JOINTURE ?

Tab. 23.4 Table proprietaires ID 1 2 3 4 prenom Florent Patrick Michel Romain nom Dugommier Lejeune Doussand Vipelli tel 01 44 03 22 04 11 01 21 77 17 78 98 21 41 02 51 33 22 00 01

Romain Vipelli est rfrenc dans la table proprietaires mais il napparat nulle part dans la table jeux_video car il ne possde aucun jeu. Si vous rcuprez les donnes des deux tables laide : dune jointure interne : Romain Vipelli napparatra pas dans les rsultats de la requte. La jointure interne force les donnes dune table avoir une correspondance dans lautre ; dune jointure externe : vous aurez toutes les donnes de la table des propritaires, mme sil ny a pas de correspondance dans lautre table des jeux vido ; donc Romain Vipelli, qui pourtant ne possde aucun jeu vido, apparatra. La jointure externe est donc plus complte car elle est capable de rcuprer plus dinformations, tandis que la jointure interne est plus stricte car elle ne rcupre que les donnes qui ont une quivalence dans lautre table. Voici par exemple les donnes que lon rcuprerait avec une jointure interne (tableau 23.5) : Tab. 23.5 Jointure interne nom_jeu Super Mario Bros Sonic ... prenom Florent Patrick ...

On obtient les jeux et leurs propritaires, mais Romain qui ne possde pas de jeu napparat pas du tout. En revanche, avec une jointure externe (tableau 23.6) : Tab. 23.6 Jointure externe nom_jeu Super Mario Bros Sonic ... NULL prenom Florent Patrick ... Romain

Romain apparat maintenant. Comme il ne possde pas de jeu, il ny a aucun nom de jeu indiqu (NULL). 261

CHAPITRE 23. LES JOINTURES ENTRE TABLES Nous allons maintenant voir comment raliser ces deux types de jointures en pratique.

Les jointures internes


Une jointure interne peut tre eectue de deux faons direntes : laide du mot-cl WHERE : cest lancienne syntaxe, toujours utilise aujourdhui, quil faut donc connatre mais que vous devriez viter dutiliser si vous avez le choix ; laide du mot-cl JOIN : cest la nouvelle syntaxe quil est recommand dutiliser. Elle est plus ecace et plus lisible. Ces deux techniques produisent exactement le mme rsultat, mais il faut les connatre toutes les deux. ;-)

Jointure interne avec WHERE (ancienne syntaxe)


Construction dune jointure interne pas pas Pour raliser ce type de jointure, on va slectionner des champs des deux tables et indiquer le nom de ces deux tables dans la clause FROM :
SELECT nom, prenom FROM proprietaires, jeux_video

Cependant a ne fonctionnera pas car ce nest pas susant. En eet, le champ nom apparat dans les deux tables : une fois pour le nom du propritaire, et une autre fois pour le nom du jeu vido. Cest ce quon appelle une colonne ambigu car MySQL ne sait pas sil doit rcuprer un nom de personne (comme Dugommier) ou un nom de jeu (comme Super Mario Bros). Bref, il est un peu perdu. Lastuce consiste marquer le nom de la table devant le nom du champ, comme ceci :
SELECT jeux_video.nom, proprietaires.prenom FROM proprietaires, jeux_video

Ainsi, on demande clairement de rcuprer le nom du jeu et le prnom du propritaire avec cette requte. Le champ prenom nest pas ambigu, car il napparat que dans la table proprietaires. On pourrait donc se passer dcrire le prxe proprietaires devant, mais a ne cote rien de le faire et cest plus clair : on voit immdiatement en lisant la requte de quelle table est issu ce champ. Il reste encore lier les deux tables entre elles. En eet, les jeux et leurs propritaires ont une correspondance via le champ ID_proprietaire (de la table jeux_video) et le champ ID (de la table proprietaires). On va indiquer cette liaison dans un WHERE, comme ceci : 262

LES JOINTURES INTERNES


SELECT jeux_video.nom, proprietaires.prenom FROM proprietaires, jeux_video WHERE jeux_video.ID_proprietaire = proprietaires.ID

Comme la requte devient longue, je me permets de lcrire sur plusieurs lignes. Cette criture est tout fait autorise et a lavantage dtre plus lisible. On indique bien que le champ ID_proprietaire de la table jeux_video correspond au champ ID de la table proprietaires. Cela tablit la correspondance entre les deux tables telle quon lavait dnie dans le schma 23.1 au dbut du chapitre. Notre requte est enn complte, vous pouvez lessayer. Vous devriez rcuprer les donnes suivantes : nom Super Mario Bros Sonic ... prenom Florent Patrick ...

Utilisez les alias ! Nous avons appris utiliser les alias lorsque nous avons dcouvert les fonctions SQL. Cela nous permettait de crer ce que jappelais des champs virtuels pour reprsenter le rsultat des fonctions. Il est fortement conseill dutiliser des alias lorsquon fait des jointures. On peut utiliser des alias sur les noms de champs (comme on lavait fait) :
SELECT jeux_video.nom AS nom_jeu, proprietaires.prenom AS prenom_proprietaire FROM proprietaires, jeux_video WHERE jeux_video.ID_proprietaire = proprietaires.ID

On rcuprera donc deux champs : nom_jeu et prenom_proprietaire. Ces alias permettent de donner un nom plus clair aux champs que lon rcupre. nom_jeu Super Mario Bros Sonic ... prenom_proprietaire Florent Patrick ...

Il est galement possible de donner un alias aux noms des tables, ce qui est fortement recommand pour leur donner un nom plus court et plus facile crire. En gnral, on cre des alias de tables dune lettre ou deux correspondant leurs initiales, comme ceci : 263

CHAPITRE 23. LES JOINTURES ENTRE TABLES


SELECT j.nom AS nom_jeu, p.prenom AS prenom_proprietaire FROM proprietaires AS p, jeux_video AS j WHERE j.ID_proprietaire = p.ID

Comme vous le voyez, la table jeux_video a pour alias la lettre j et proprietaires la lettre p. On rutilise ces alias dans toute la requte, ce qui la rend plus courte crire1 . Notez que le mot-cl AS est en fait facultatif, les dveloppeurs ont tendance lomettre. Vous pouvez donc tout simplement le retirer de la requte :
SELECT j.nom nom_jeu, p.prenom prenom_proprietaire FROM proprietaires p, jeux_video j WHERE j.ID_proprietaire = p.ID

Jointure interne avec JOIN (nouvelle syntaxe)


Bien quil soit possible de faire une jointure interne avec un WHERE comme on vient de le voir, cest une ancienne syntaxe et aujourdhui on recommande plutt dutiliser JOIN. Il faut dire que nous tions habitus utiliser le WHERE pour ltrer les donnes, alors que nous lutilisons ici pour associer des tables et rcuprer plus de donnes. Pour viter de confondre le WHERE traditionnel qui ltre les donnes et le WHERE de jointure que lon vient de dcouvrir, on va utiliser la syntaxe JOIN. Pour rappel, voici la requte quon utilisait avec un WHERE :
SELECT j.nom nom_jeu, p.prenom prenom_proprietaire FROM proprietaires p, jeux_video j WHERE j.ID_proprietaire = p.ID

Avec un JOIN, on crirait cette mme requte de la faon suivante :


SELECT j.nom nom_jeu, p.prenom prenom_proprietaire FROM proprietaires p INNER JOIN jeux_video j ON j.ID_proprietaire = p.ID

Cette fois, on rcupre les donnes depuis une table principale (ici, proprietaires) et on fait une jointure interne (INNER JOIN) avec une autre table (jeux_video). La liaison entre les champs est faite dans la clause ON un peu plus loin. Le fonctionnement reste le mme : on rcupre les mmes donnes que tout lheure avec la syntaxe WHERE. Si vous voulez ltrer (WHERE), ordonner (ORDER BY) ou limiter les rsultats (LIMIT), vous devez le faire la n de la requte, aprs le ON j.ID_proprietaire = p.ID . Par exemple :
1 Et

plus lisible aussi au nal.

264

LES JOINTURES EXTERNES


SELECT j.nom nom_jeu, p.prenom prenom_proprietaire FROM proprietaires p INNER JOIN jeux_video j ON j.ID_proprietaire = p.ID WHERE j.console = PC ORDER BY prix DESC LIMIT 0, 10

Traduction (inspirez un grand coup avant de lire) : Rcupre le nom du jeu et le prnom du propritaire dans les tables proprietaires et jeux_video, la liaison entre les tables se fait entre les champs ID_proprietaire et ID, prends uniquement les jeux qui tournent sur PC, trie-les par prix dcroissants et ne prends que les 10 premiers. Il faut saccrocher avec des requtes de cette taille-l ! ;-)

Les jointures externes


Les jointures externes permettent de rcuprer toutes les donnes, mme celles qui nont pas de correspondance. On pourra ainsi obtenir Romain Vipelli dans la liste mme sil ne possde pas de jeu vido. Cette fois, la seule syntaxe disponible est base de JOIN. Il y a deux critures connatre : LEFT JOIN et RIGHT JOIN. Cela revient pratiquement au mme, avec une subtile dirence que nous allons voir.

LEFT JOIN : rcuprer toute la table de gauche


Reprenons la jointure base de INNER JOIN et remplaons tout simplement INNER par LEFT :
SELECT j.nom nom_jeu, p.prenom prenom_proprietaire FROM proprietaires p LEFT JOIN jeux_video j ON j.ID_proprietaire = p.ID

proprietaires est appele la table de gauche et jeux_video la table de droite . Le LEFT JOIN demande rcuprer tout le contenu de la table de gauche, donc tous les propritaires, mme si ces derniers nont pas dquivalence dans la table jeux_video. nom_jeu Super Mario Bros Sonic ... NULL prenom_proprietaire Florent Patrick ... Romain

Romain apparat dsormais dans les rsultats de la requte grce la jointure externe. Comme il ne possde aucun jeu, la colonne du nom du jeu est vide. 265

CHAPITRE 23. LES JOINTURES ENTRE TABLES

RIGHT JOIN : rcuprer toute la table de droite


Le RIGHT JOIN demande rcuprer toutes les donnes de la table dite de droite , mme si celle-ci na pas dquivalent dans lautre table. Prenons la requte suivante :
SELECT j.nom nom_jeu, p.prenom prenom_proprietaire FROM proprietaires p RIGHT JOIN jeux_video j ON j.ID_proprietaire = p.ID

La table de droite est jeux_video . On rcuprerait donc tous les jeux, mme ceux qui nont pas de propritaire associ. Comment est-ce possible quun jeu nait pas de propritaire associ ?

Il y a deux cas possibles : soit le champ ID_proprietaire contient une valeur qui na pas dquivalent dans la table des propritaires, par exemple 56 ; soit le champ ID_proprietaire vaut NULL, cest--dire que personne ne possde ce jeu. Cest le cas notamment du jeu Bomberman dans la table que vous avez tlcharge (voir tableau 23.7). Dans ce cas, Bomberman nappartient personne. Avec la requte RIGHT JOIN que lon vient de voir, on obtiendra toutes les lignes de la table de droite (jeux_video) mme si elles nont aucun lien avec la table proprietaires, comme cest le cas ici pour Bomberman. On obtiendra donc les donnes exposes dans le tableau 23.8.

En rsum
Les bases de donnes permettent dassocier plusieurs tables entre elles. Une table peut contenir les id dune autre table ce qui permet de faire la liaison entre les deux. Par exemple, la table des jeux vido contient pour chaque jeu lid de son propritaire. Le nom et les coordonnes du propritaire sont alors stocks dans une table part. Pour rassembler les informations au moment de la requte, on eectue des jointures. On peut faire des jointures avec le mot-cl WHERE, mais il est recommand dutiliser JOIN qui ore plus de possibilits et qui est plus adapt. On distingue les jointures internes, qui retournent des donnes uniquement sil y a une correspondance entre les deux tables, et les jointures externes qui retournent toutes les donnes mme sil ny a pas de correspondance.

266

LES JOINTURES EXTERNES

Tab. 23.7 Table jeux_video ID nom Super Mario Bros Sonic ID_ console proprietaire 1 NES nbre_ prix joueurs_ commentaires max 4 1 Un jeu danthologie ! Pour moi, le meilleur jeu au monde ! Un jeu grand, beau et complet comme on en voit rarement de nos jours Un excellent jeu de kart ! Un jeu de baston dlirant ! ... Un jeu simple et toujours aussi passionnant !

Megadrive 2

Zelda : ocarina of time

Nintendo 64

15

Mario Kart 64 Super 5 Smash Bros Melee ... ...

Nintendo 64

25

GameCube 55

...

... NES

... 5

... 4

51 Bomberman NULL

Tab. 23.8 Rcupration de la table de droite nom_jeu Super Mario Bros Sonic ... Bomberman prenom_proprietaire Florent Patrick ... NULL

267

CHAPITRE 23. LES JOINTURES ENTRE TABLES

268

Quatrime partie

Utilisation avance de PHP

269

Chapitre

24
Dicult :

Crer des images en PHP

ous savez quoi ? Il y a des gens qui croient que le PHP nest fait que pour gnrer des pages web ! Si, si, je vous jure !

Quoi, vous aussi ? Bon. . . remarquez, je ne peux pas vous en vouloir non plus : tout au long de ce cours, on na fait que gnrer des pages HTML avec PHP. Dicile de croire que lon pourrait faire autre chose. . . En fait, la base, PHP a bien t cr pour raliser des pages web. Mais au fur et mesure, on sest rendu compte quil serait dommage de le limiter a. On a donc prvu de pouvoir lui rajouter des extensions . Ainsi, en rajoutant certains chiers (des DLL sous Windows), PHP peut se mettre gnrer des images, ou mme des PDF ! Dans ce chapitre, nous allons parler de lextension spcialise dans la gnration dimages : la bibliothque GD.

271

CHAPITRE 24. CRER DES IMAGES EN PHP

Activer la bibliothque GD
On a dj un problme (a commence fort ;-) ). En eet, la bibliothque GD (qui vous permet de crer des images) est livre avec PHP, mais elle nest pas active. a veut dire quoi ? Quil va falloir demander lactiver tout simplement. La procdure suivre est exactement la mme que celle quon avait vue pour activer PDO lorsque nous avons dcouvert les bases de donnes. Sous WAMP par exemple, faites un clic gauche sur licne de WAMP dans la barre des tches, puis allez dans le menu PHP / Extensions PHP et cochez php_gd2. Et sur Internet, avec mon hbergeur ? Est-ce que je peux utiliser GD ?

Cela dpend des hbergeurs. Une grande partie des hbergeurs gratuits dsactivent GD parce que a consomme beaucoup de ressources du processeur. Si des dizaines de sites se mettent gnrer des images en mme temps, a risquerait de faire ramer toute la machine et donc de ralentir tous les autres sites. Ne dsesprez pas pour autant, il existe certainement des hbergeurs gratuits qui acceptent la bibliothque GD. . . Sinon, il faudra peut-tre trouver un hbergement payant1 .

Les bases de la cration dimage


Voici le plan que nous allons suivre pour crer une image : 1. nous allons dcouvrir ce quest un header ; 2. ensuite, nous allons crer limage de base ; 3. enn, nous verrons comment on ache limage concrtement. Au boulot !

Le header
Il y a deux faons de gnrer une image en PHP. Soit on fait en sorte que notre script PHP renvoie une image (au lieu dune page web, comme on en avait lhabitude). Dans ce cas, si on va sur la page http://www.monsite.com/testgd.php, une image sera ache et non pas une page web ! Soit on demande PHP denregistrer limage dans un chier.
1 On

peut en trouver des pas chers qui ont activ GD !

272

LES BASES DE LA CRATION DIMAGE Dans les deux cas, on utilisera exactement les mmes fonctions. On va commencer par la premire faon de gnrer limage, cest--dire quon va faire en sorte que notre script renvoie une image au lieu dune page web. Mais comment faire pour que le navigateur sache que cest une image et non pas une page HTML quil doit acher ? Il va falloir envoyer ce quon appelle un header (un en-tte). Grce la fonction header, on va dire au navigateur que lon est en train denvoyer une image. Je vous rappelle les types dimages les plus courants sur le web : JPEG : cest un format trs adapt pour les photos par exemple, car on peut utiliser beaucoup de couleurs ; PNG : cest le format le plus rcent, trs adapt dans la plupart des cas. En fait, moins davoir aaire une photo, le mieux est dutiliser le PNG. Le PNG est en quelque sorte le remplaant du format GIF. Donc pour faire simple : si cest une photo, vous faites un JPEG, sinon dans tous les autres cas vous faites un PNG. Voici le code PHP quil faut mettre pour annoncer au navigateur que lon va renvoyer une image PNG :
<?php header ("Content-type: image/png"); ?>

Voil, cest assez simple. Ce code signiera pour le navigateur que lon envoie une image PNG, et non pas une page HTML. Si vous envoyez un JPEG, cest presque pareil, mais vous remplacez le png par jpeg . La fonction header est particulire. Comme setcookie, elle doit tre utilise avant davoir crit le moindre code HTML. En clair, mettez cette ligne au tout dbut de votre code, et vous naurez pas de problmes.

Crer limage de base


Il faut savoir quil y a deux faons de crer une image : soit vous crez une nouvelle image vide, soit vous chargez une image qui existe dj et qui servira de fond votre nouvelle image. partir dune image vide On va commencer par crer une image vide. Pour crer une image vide en PHP, on utilise la fonction imagecreate. 273

CHAPITRE 24. CRER DES IMAGES EN PHP Cette fonction est simple. Elle prend deux paramtres : la largeur et la hauteur de limage que vous voulez crer. Elle renvoie une information que vous devez mettre dans une variable (par exemple $image). Ce qui nous donne :
<?php header ("Content-type: image/png"); $image = imagecreate(200,50); ?>

Ici, nous sommes en train de crer une image de 200 pixels de large et 50 pixels de haut. $image ne contient ni un nombre, ni du texte. Cette variable contient une image . Cest assez dicile imaginer quune variable puisse contenir une image, mais cest comme a. On dit que $image est une ressource . Une ressource est une variable un peu spciale qui contient toutes les informations sur un objet. Ici, il sagit dune image, mais il pourrait trs bien sagir dun PDF ou mme dun chier que vous avez ouvert avec fopen. Tiens, tiens, a vous rappelle quelque chose ?

partir dune image existante Maintenant, lautre possibilit : crer une image partir dune image dj existante. Cette fois, il y a deux fonctions connatre. Laquelle choisir ? a dpend du format de limage que vous voulez charger : JPEG : il faut utiliser la fonction imagecreatefromjpeg ; PNG : il faut utiliser la fonction imagecreatefrompng. Par exemple, jai une jolie photo de coucher de soleil qui sappelle couchersoleil.jpg (gure 24.11). Pour crer une nouvelle image en se basant sur celle-l, je dois utiliser la fonction imagecreatefromjpeg. a nous donnerait le code suivant :
<?php header ("Content-type: image/jpeg"); $image = imagecreatefromjpeg("couchersoleil.jpg"); ?>

Voil, vous savez crer une nouvelle image. Nous allons maintenant voir comment acher limage que vous venez de crer. 274

LES BASES DE LA CRATION DIMAGE

Fig. 24.1 Ma photo couchersoleil.jpg

Quand on a termin : on ache limage


Une fois que vous avez charg limage, vous pouvez vous amuser y crire du texte, dessiner des cercles, des carrs, etc. Nous allons apprendre tout cela juste aprs. Je souhaite vous montrer ici comment faire pour dire PHP quon a ni et quon veut acher limage. La fonction utiliser dpend du type de limage que vous tes en train de crer : JPEG : il faut utiliser la fonction imagejpeg ; PNG : il faut utiliser la fonction imagepng. Ces deux fonctions sutilisent de la mme manire : vous avez juste besoin dindiquer quelle image vous voulez acher. Comme je vous le disais, il y a deux faons dutiliser les images en PHP : vous pouvez les acher directement aprs les avoir cres, ou les enregistrer sur le disque pour pouvoir les r-acher plus tard, sans avoir refaire tous les calculs. Acher directement limage Cest la mthode que lon va utiliser dans ce chapitre. Quand la page PHP est excute, elle vous ache limage que vous lui avez demand de crer. Vous avez toujours votre variable $image sous la main ? Parfait. ;-) Alors voici le code complet que jutilise pour crer une nouvelle image PNG de taille 200 50 et lacher directement :
<?php header ("Content-type: image/png"); // 1 : on indique quon va envoyer une image PNG $image = imagecreate(200,50); // 2 : on cre une nouvelle image de taille 200 x 50

275

CHAPITRE 24. CRER DES IMAGES EN PHP


// 3 : on samuse avec notre image (on va apprendre le faire) imagepng($image); // 4 : on a fini de faire joujou, on demande afficher limage ?>

Cest bien joli, mais l on na quune image sous les yeux. Et si je veux mettre du texte autour ? Les menus de mon site ? En fait, on utilise une technique qui, jen suis sr, va vous surprendre. On va demander acher la page PHP comme une image. Donc, si la page PHP sappelle image.php , vous mettrez ce code HTML pour lacher depuis une autre page :
<img src="image.php" />

Incredible, isnt it ? Mais en fait, cest logique quand on y pense ! La page PHP que lon vient de crer EST une image (puisquon a modi le header). On peut donc acher limage que lon vient de crer depuis nimporte quelle page de votre site en utilisant simplement la balise <img />. Le gros avantage de cette technique, cest que limage ache pourra changer chaque fois ! Enregistrer limage sur le disque Si, au lieu dacher directement limage, vous prfrez lenregistrer sur le disque, alors il faut ajouter un paramtre la fonction imagepng : le nom de limage et ventuellement son dossier. Par contre, dans ce cas, votre script PHP ne va plus renvoyer une image (il va juste en enregistrer une sur le disque). Vous pouvez donc supprimer la fonction header qui ne sert plus rien. Ce qui nous donne :
<?php $image = imagecreate(200,50); // on fait joujou avec notre image imagepng($image, "images/monimage.png"); // on enregistre limage dans le dossier "images" ?>

Cette fois, limage a t enregistre sur le disque avec le nom monimage.png. Pour lacher depuis une autre page web, vous ferez donc comme ceci :
<img src="images/monimage.png" />

a, vous avez un peu plus lhabitude, jimagine. 276

TEXTE ET COULEUR Cette technique a lavantage de ne pas ncessiter de recalculer limage chaque fois (votre serveur aura moins de travail), mais le dfaut cest quune fois quelle est enregistre, limage ne change plus. Mais. . . mais ? Si je teste ces codes, a cre une image toute blanche ! Cest nul, il ne sest rien pass de bien ! Oui, je sais. Vous avez t patients et cest bien, parce que cest maintenant que a va devenir intressant. Allez donc chercher votre baguette magique, je vous attends.

Texte et couleur
Cest bon, vous avez votre baguette magique ? Alors voici ce que nous allons apprendre faire maintenant : manipuler les couleurs ; crire du texte. Vous allez commencer voir un peu ce quil est possible de faire grce la bibliothque GD, mais vous verrez plus loin quon peut faire bien plus.

Manipuler les couleurs


Un ordinateur il faut le savoir dcompose chaque couleur en Rouge-Vert-Bleu. En mlangeant les quantits de rouge, de vert et de bleu, a nous donne une couleur parmi les millions de possibilits ! On indique la quantit de rouge, de vert et de bleu par un nombre compris entre 0 et 255. Par exemple, si je dis que je mets 255 de bleu, a veut dire quon met tout le bleu. Si je mets 100 de bleu, il y a un peu moins de bleu. Si je mets 0, alors l il ny a plus du tout de bleu. On doit crire les trois quantits dans lordre RVB (Rouge Vert Bleu). Par exemple : (255 0 0). a, cest une couleur qui contient plein de rouge, et pas du tout de vert ni de bleu. Cest donc la couleur. . . rouge ! Bravo ! Maintenant, si je mets plein de rouge et de vert : (255 255 0). a nous donne la couleur : jaune ! Allez, un dernier essai pour la route et on arrte l : (255 128 0). a, cest la couleur orange ! Pour info, la couleur blanche correspond (255 255 255), et la couleur noire (0 0 0). 277

CHAPITRE 24. CRER DES IMAGES EN PHP Si vous avez un logiciel de dessin comme Paint et que vous allez dans le menu Couleur / Modifier les couleurs, vous pouvez choisir la couleur que vous voulez, comme sur la gure 24.2.

Fig. 24.2 Slection dune couleur Comme vous pouvez le voir, en cliquant sur la couleur qui vous intresse on vous donne les quantits de Rouge Vert Bleu. Vous pouvez donc choisir la couleur que vous voulez. Allez-y, servez-vous. Mais revenons ce qui nous intresse : PHP. Pour dnir une couleur en PHP, on doit utiliser la fonction imagecolorallocate. On lui donne quatre paramtres : limage sur laquelle on travaille, la quantit de rouge, la quantit de vert, et la quantit de bleu. Cette fonction nous renvoie la couleur dans une variable. Grce cette fonction, on va pouvoir se crer des variables-couleur qui vont nous tre utiles pour indiquer ensuite la couleur. Voici quelques exemples de cration de couleur :
<?php header ("Content-type: image/png"); $image = imagecreate(200,50); $orange = imagecolorallocate($image, 255, 128, 0); $bleu = imagecolorallocate($image, 0, 0, 255); $bleuclair = imagecolorallocate($image, 156, 227, 254); $noir = imagecolorallocate($image, 0, 0, 0); $blanc = imagecolorallocate($image, 255, 255, 255); imagepng($image); ?>

Une chose trs importante noter : la premire fois que vous faites un appel la fonction imagecolorallocate, cette couleur devient la couleur de fond de votre image. 278

TEXTE ET COULEUR Donc, si vous avez bien compris, ce code doit crer une image. . . toute orange ! Essayez ! Code web : 111947 Si javais voulu que le fond soit blanc et non orange, il aurait fallu placer $blanc en premier. Voil, vous savez maintenant crer toutes les couleurs de larc-en-ciel en PHP.

crire du texte
Nous voici enn dans le vif du sujet (ouf !). Nous avons une belle image avec un maaagnique fond orange, et nous voulons y crire du texte. Avec la fonction imagestring, cest facile ! Cette fonction prend beaucoup de paramtres. Elle sutilise comme ceci :
<?php imagestring($image, $police, $x, $y, $texte_a_ecrire, $couleur); ?>

Il existe aussi la fonction imagestringup qui fonctionne exactement de la mme manire, sauf quelle crit le texte verticalement et non horizontalement ! Je vous dtaille ci-dessous les paramtres dans lordre, cest important que vous compreniez bien. $image : cest notre fameuse variable qui contient limage. $police : cest la police de caractres que vous voulez utiliser. Vous devez mettre un nombre de 1 5 ; 1 = petit, 5 = grand. Il est aussi possible dutiliser une police de caractres personnalise, mais il faut avoir des polices dans un format spcial quil serait trop long de dtailler ici. On va donc se contenter des polices par dfaut. ;-) $x et $y : ce sont les coordonnes auxquelles vous voulez placer votre texte sur limage. Et l vous vous dites : Ae, a sent les maths 2 . Vous devez savoir que lorigine se trouve en haut gauche de votre image. Le point de coordonnes (0, 0) reprsente donc le point tout en haut gauche de limage. Voici, en gure 24.3, le schma de notre image orange de tout lheure, qui est de taille 200 50 : Notez que les coordonnes de limage sarrtent (199, 49) et non (200, 50) comme on pourrait sy attendre. En eet, il ne faut pas oublier quon commence compter partir de 0 ! De 0 199 il y a bien 200 points. Comme vous pouvez le voir, jai marqu les quatre points des cts de limage. (0, 0) se trouve tout en haut gauche, et (199, 49) se trouve tout en bas droite.
2 Comme

quoi les maths, a sert.

279

CHAPITRE 24. CRER DES IMAGES EN PHP

Fig. 24.3 Coordonnes de limage $texte_a_ecrire, cest le. . . texte que vous voulez crire. Non, non, il ny a pas de pige. $couleur, cest une couleur que vous avez cre tout lheure avec imagecolorallocate. Voici un exemple concret de ce quon peut faire :
<?php header ("Content-type: image/png"); $image = imagecreate(200,50); $orange = imagecolorallocate($image, 255, 128, 0); $bleu = imagecolorallocate($image, 0, 0, 255); $bleuclair = imagecolorallocate($image, 156, 227, 254); $noir = imagecolorallocate($image, 0, 0, 0); $blanc = imagecolorallocate($image, 255, 255, 255); imagestring($image, 4, 35, 15, "Salut les Zros !", $blanc); imagepng($image); ?>

Nhsitez pas copier ce code chez vous pour tester le rsultat. Code web : 899933 Vous pouvez aussi tester le rsultat en ligne et en image. Code web : 825115 La ligne contenant imagestring peut se traduire par : Mets dans limage $image, avec la police de taille 4, aux coordonnes (35, 15), le texte Salut les Zros ! , de couleur blanche.

Dessiner une forme


Dessiner du texte cest bien, mais a serait bte dtre limit a. Heureusement, PHP a pens tout ! Graphistes en herbe, vous allez certainement trouver votre bonheur dans toutes ces fonctions : vous pouvez crer des lignes, des rectangles, des cercles, des polygones. . . Je vais vous prsenter la plupart de ces fonctions ci-dessous, et je vous montrerai ensuite ce que a donne dans une image de taille 200 200, histoire davoir un aperu. 280

DESSINER UNE FORME

ImageSetPixel
Son rle : dessiner un pixel aux coordonnes (x, y).
ImageSetPixel ($image, $x, $y, $couleur);

Illustration en gure 24.4, grce au code : ImageSetPixel ($image, 100, 100, $noir) ;

Fig. 24.4 ImageSetPixel

ImageLine
Celle-l sert dessiner une ligne entre deux points de coordonnes (x1 , y1 ) et (x2 , y2 ).
ImageLine ($image, $x1, $y1, $x2, $y2, $couleur);

La preuve en image : gure 24.5. Le code utilis est le suivant : ImageLine ($image, 30, 30, 120, 120, $noir) ;

Fig. 24.5 ImageLine

ImageEllipse
Celle-ci dessine une ellipse dont le centre est aux coordonnes (x, y), de largeur $largeur et de hauteur $hauteur. 281

CHAPITRE 24. CRER DES IMAGES EN PHP


ImageEllipse ($image, $x, $y, $largeur, $hauteur, $couleur);

Voici une illustration en gure 24.6. Et voici son code : ImageEllipse ($image, 100, 100, 100, 50, $noir) ;

Fig. 24.6 ImageEllipse

ImageRectangle
Elle, elle dessine un rectangle, dont le coin en haut gauche est de coordonnes (x1 , y1 ) et celui en bas droite (x2 , y2 ).
ImageRectangle ($image, $x1, $y1, $x2, $y2, $couleur);

Figure 24.7, vous avez le rsultat produit par le code suivant : ImageRectangle ($image, 30, 30, 160, 120, $noir) ;

Fig. 24.7 ImageRectangle

ImagePolygon
Elle dessine un polygone ayant un nombre de points gal $nombre_de_points (sil y a trois points, cest donc un triangle). Larray $array_points contient les coordonnes de tous les points du polygone dans lordre : x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 . . .
ImagePolygon ($image, $array_points, $nombre_de_points, $couleur);

282

DES FONCTIONS ENCORE PLUS PUISSANTES Allez, la gure 24.8 pour vous donner un exemple, dont le code est : $points = array(10, 40, 120, 50, 160, 160) ; ImagePolygon ($image, $points, 3, $noir) ;

Fig. 24.8 ImagePolygon

Des fonctions encore plus puissantes


Des rectangles, des ellipses, des lignes. . . Ouais, bof. Cest tout ce quon peut faire ? Bien sr que non ! Il y a dautres fonctions que je veux absolument vous montrer parce quelles permettent de raliser des oprations bien plus complexes ! Nous allons apprendre : rendre une image transparente ; mlanger deux images ; redimensionner une image, pour crer une miniature par exemple. Jespre que vous tes encore en forme, ce serait dommage de sendormir sur les fonctions les plus intressantes.

Rendre une image transparente


Tout dabord, il faut savoir que seul le PNG peut tre rendu transparent. En eet, un des gros dfauts du JPEG est quil ne supporte pas la transparence. Nous allons donc ici travailler sur un PNG. Rendre une image transparente est dune facilit dconcertante. Il sut dutiliser la fonction imagecolortransparent et de lui indiquer quelle couleur on veut rendre transparente. Cette fonction sutilise comme ceci :
<?php imagecolortransparent($image, $couleur); ?>

283

CHAPITRE 24. CRER DES IMAGES EN PHP Je vais reprendre lexemple de limage o jai crit Salut les Zros ! sur un vieux fond orange, et je vais y rajouter la fonction imagecolortransparent pour rendre ce fond transparent :
<?php header ("Content-type: image/png"); $image = imagecreate(200,50); $orange = imagecolorallocate($image, 255, 128, 0); // Le fond est orange (car cest la premire couleur) $bleu = imagecolorallocate($image, 0, 0, 255); $bleuclair = imagecolorallocate($image, 156, 227, 254); $noir = imagecolorallocate($image, 0, 0, 0); $blanc = imagecolorallocate($image, 255, 255, 255); imagestring($image, 4, 35, 15, "Salut les Zros !", $noir); imagecolortransparent($image, $orange); // On rend le fond orange transparent imagepng($image); ?>

Code web : 830616 Et voil, sur la gure 24.9, le PNG transparent que a nous donne.

Fig. 24.9 Un texte dans un PNG Sympa, non ? ;-)

Mlanger deux images


a, cest un tout petit peu plus compliqu que de rendre une image transparente, mais bon je vous rassure : cest loin dtre insurmontable quand mme et a en vaut la peine. La fonction que je vais vous prsenter permet de fusionner deux images en jouant sur un eet de transparence. a a lair tordu comme a, mais cest en fait quelque chose de vraiment gnial ! On peut sen servir par exemple pour acher le logo de son site sur une image. Voyez le logo en gure 24.10.

Fig. 24.10 Logo 284

DES FONCTIONS ENCORE PLUS PUISSANTES Et en gure 24.11, limage en question.

Fig. 24.11 Image marquer par le logo La fonction qui permet de raliser la fusion entre deux images est imagecopymerge. Ce script est un peu plus gros que les autres, alors je prfre vous le donner tout de suite. Je vous expliquerai juste aprs comment il fonctionne.
<?php header ("Content-type: image/jpeg"); // Limage que lon va crer est un jpeg // On charge dabord les images $source = imagecreatefrompng("logo.png"); // Le logo est la source $destination = imagecreatefromjpeg("couchersoleil.jpg"); // La photo est la destination // Les fonctions imagesx et imagesy renvoient la largeur et la hauteur dune image $largeur_source = imagesx($source); $hauteur_source = imagesy($source); $largeur_destination = imagesx($destination); $hauteur_destination = imagesy($destination); // On veut placer le logo en bas droite, on calcule les coordonnes o on doit placer le logo sur la photo $destination_x = $largeur_destination - $largeur_source; $destination_y = $hauteur_destination - $hauteur_source; // On met le logo (source) dans limage de destination (la photo) imagecopymerge($destination, $source, $destination_x, $destination_y, 0, 0, $largeur_source, $hauteur_source, 60); // On affiche limage de destination qui a t fusionne avec le logo imagejpeg($destination); ?>

285

CHAPITRE 24. CRER DES IMAGES EN PHP Code web : 491189 Vous trouverez en gure 24.12 le rsultat que donne ce script.

Fig. 24.12 Le logo a t intgr dans limage imagecopymerge est une fonction vraiment sympa, parce que vous allez maintenant pouvoir copyrighter automatiquement toutes les images de votre site si vous le voulez. Cependant, le script utilis ici est un petit peu plus complexe, et je crois que quelques explications ne seraient pas de refus. Voici donc les points bien comprendre. Dans ce script, on manipule deux images : $source (le logo) et $destination (la photo). Les deux sont cres laide de la fonction imagecreatefrompng (et fromjpeg pour la photo). Il y a ensuite toute une srie de calculs partir des coordonnes et de la largeur et hauteur des images. Jimagine que a a d vous faire peur, mais cest en fait trs simple du moment quon sait faire une soustraction. Notre but est de savoir quelles coordonnes placer le logo sur la photo. Moi, je veux le mettre tout en bas droite. Pour a, jai besoin de connatre les dimensions des images. Jutilise les fonctions imagesx et imagesy pour rcuprer les dimensions du logo et de la photo. Ensuite, pour placer le logo tout en bas, il faut le mettre la position $hauteur_de_la_photo - $hauteur_du_logo. On fait de mme pour placer le logo droite : $largeur_de_la_photo - $largeur_du_logo. Si javais voulu mettre le logo tout en haut gauche, l, a aurait t beaucoup plus simple : pas besoin de faire de calculs, vu quen haut gauche les coordonnes sont (0, 0) ! Vient ensuite la fonction imagecopymerge, la plus importante. Elle prend de nombreux paramtres. Ce quil faut savoir, cest quelle a besoin de deux images : une source et une destination. Elle modie limage de destination (ici, la photo) pour y intgrer limage source. Cela explique pourquoi cest $destination que lon ache la n, et non pas $source (le logo) qui na pas chang. Les paramtres donner la fonction sont, dans lordre, les suivants. 286

DES FONCTIONS ENCORE PLUS PUISSANTES 1. Limage de destination : ici $destination, la photo. Cest limage qui va tre modie et dans laquelle on va mettre notre logo. 2. Limage source : ici $source, cest notre logo. Cette image nest pas modie. 3. Labscisse laquelle vous dsirez placer le logo sur la photo : il sagit ici de labscisse du point situe la position $largeur_de_la_photo - $largeur_du_logo. 4. Lordonne laquelle vous dsirez placer le logo sur la photo : de mme, il sagit de lordonne du point sur la photo (ici, $hauteur_de_la_photo - $hauteur_du_logo). 5. Labscisse de la source : en fait, la fonction imagecopymerge permet aussi de ne prendre quune partie de limage source. a peut devenir un peu compliqu, alors nous, on va dire quon prend tout le logo. On part donc du point situ aux coordonnes (0, 0) de la source. Mettez donc 0 pour labscisse. 6. Lordonne de la source : de mme pour lordonne. Mettez 0. 7. La largeur de la source : cest la largeur qui dtermine quelle partie de limage source vous allez prendre. Nous on prend toute limage source, ne vous prenez donc pas la tte non plus et mettez $largeur_source. 8. La hauteur de la source : de mme, mettez $hauteur_source. 9. Le pourcentage de transparence : cest un nombre entre 0 et 100 qui indique la transparence de votre logo sur la photo. Si vous mettez 0, le logo sera invisible (totalement transparent), et si vous mettez 100, il sera totalement opaque (il ny aura pas deet de fusion ). Mettez un nombre autour de 60-70, en gnral cest bien. ;-) Concrtement, on peut se servir de ce code pour faire une page copyrighter.php. Cette page prendra un paramtre : le nom de limage copyrighter . Par exemple, si vous voulez copyrighter automatiquement tropiques.jpg, vous acherez limage comme ceci :
<img src="copyrighter.php?image=tropiques.jpg" />

vous maintenant dcrire la page copyrighter.php. Si vous vous basez sur le script que je vous ai donn, a ne devrait pas tre bien long. Il faut juste rcuprer le nom de limage charger (via la variable $_GET[image]). Arf, a y est, je vous ai tout dit.

Redimensionner une image


Cest une des fonctionnalits les plus intressantes de la bibliothque GD, mon got. a permet de crer des miniatures de nos images. Vous pouvez vous en servir par exemple pour faire une galerie de photos. Vous achez les miniatures et si vous cliquez sur lune delles, a lache dans sa taille originale. Pour redimensionner une image, on va utiliser la fonction imagecopyresampled. Cest une des fonctions les plus pousses car elle fait beaucoup de calculs mathmatiques 287

CHAPITRE 24. CRER DES IMAGES EN PHP pour crer une miniature de bonne qualit. Le rsultat est trs bon, mais cela donne normment de travail au processeur. Cette fonction est donc puissante mais lente. Tellement lente que certains hbergeurs dsactivent la fonction pour viter que le serveur ne rame. Il serait suicidaire dacher directement limage chaque chargement dune page. Nous allons ici crer la miniature une fois pour toutes et lenregistrer dans un chier. Nous allons donc enregistrer notre miniature dans un chier (mini_couchersoleil.jpg, par exemple). Cela veut dire quon peut dj retirer la premire ligne (le header) qui ne sert plus rien. Comme pour imagecopymerge, on va avoir besoin de deux images : la source et la destination. Ici, la source cest limage originale et la destination, limage miniature que lon va crer. La premire chose faire sera donc de crer une nouvelle image vide. . . Avec quelle fonction ? imagecreate ? Oui, cest presque la bonne rponse. Le problme voyez-vous, cest que imagecreate cre une nouvelle image dont le nombre de couleurs est limit (256 couleurs maximum, en gnral). Or, notre miniature contiendra peut-tre plus de couleurs que limage originale cause des calculs mathmatiques. On va donc devoir utiliser une autre fonction dont je ne vous ai pas encore parl : imagecreatetruecolor. Elle fonctionne de la mme manire que imagecreate mais cette fois, limage pourra contenir beaucoup plus de couleurs. Voici le code que je vais utiliser pour gnrer la miniature de couchersoleil.jpg, ma photo :
<?php $source = imagecreatefromjpeg("couchersoleil.jpg"); // La photo est la source $destination = imagecreatetruecolor(200, 150); // On cre la miniature vide // Les fonctions imagesx et imagesy renvoient la largeur et la hauteur dune image $largeur_source = imagesx($source); $hauteur_source = imagesy($source); $largeur_destination = imagesx($destination); $hauteur_destination = imagesy($destination); // On cre la miniature imagecopyresampled($destination, $source, 0, 0, 0, 0, $largeur_destination, $hauteur_destination, $largeur_source, $hauteur_source); // On enregistre la miniature sous le nom "mini_couchersoleil.jpg" imagejpeg($destination, "mini_couchersoleil.jpg"); ?>

Code web : 109047 288

DES FONCTIONS ENCORE PLUS PUISSANTES

Avant, limage ressemblait la gure 24.13. Grce imagecopyresampled, on a obtenu une version miniature (gure 24.14).

Fig. 24.13 Limage dorigine

Fig. 24.14 Limage redimensionne Vous pouvez acher ensuite limage avec le code HTML : <img src="mini_couchersoleil.jpg" alt="Coucher de soleil" /> On a cr notre miniature vide avec imagecreatetruecolor en dimensions rduites (200 150). Je vous ai dj expliqu les fonctions imagesx et imagesy, je ny reviens pas. Voyons plutt quels sont les paramtres de la fonction imagecopyresampled. 1. Limage de destination : cest $destination, limage quon a cre avec imagecreatetruecolor. 2. Limage source : limage dont on veut crer la miniature ; ici, cest notre couchersoleil.jpg quon a charge avec imagecreatefromjpeg. 3. Labscisse du point laquelle vous placez la miniature sur limage de destination : pour faire simple, on va dire que notre image de destination contiendra uniquement la miniature. Donc on placera la miniature aux coordonnes (0, 0), ce qui fait quil faut mettre 0 cette valeur. 4. Lordonne du point laquelle vous placez la miniature sur limage de destination : pour les mmes raisons, mettez 0. 289

CHAPITRE 24. CRER DES IMAGES EN PHP 5. Labscisse du point de la source : ici, on prend toute limage source et on en fait une miniature. Pour tout prendre, il faut partir du point (0, 0), ce qui fait que l encore on met 0 cette valeur. 6. Lordonne du point de la source : encore 0. 7. La largeur de la miniature : un des paramtres les plus importants, qui dtermine la taille de la miniature crer. Dans notre cas notre miniature fait 200 pixels de large. On a stock ce nombre dans la variable $largeur_destination. 8. La hauteur de la miniature : de mme pour la hauteur de la miniature crer. 9. La largeur de la source : il sut dindiquer la taille de notre image source. On a stock cette valeur dans $largeur_source, donc on la rutilise ici. 10. La hauteur de la source : de mme pour la hauteur. Comme vous pouvez le voir, imagecopyresampled permet de faire beaucoup de choses, et en gnral on ne se servira pas de tout. Plusieurs paramtres sont 0, et ce nest pas vraiment la peine de chercher comprendre pourquoi (mme si ce nest pas bien compliqu). Basez-vous sur mon exemple pour crer vos miniatures, et le tour est jou.

En rsum
PHP permet de faire bien plus que gnrer des pages web HTML. En utilisant des extensions, comme la bibliothque GD, on peut par exemple gnrer des images. Pour quune page PHP renvoie une image au lieu dune page web, il faut modier len-tte HTTP laide de la fonction header() qui indiquera alors au navigateur du visiteur larrive dune image. Il est possible denregistrer limage sur le disque dur si on le souhaite, ce qui vite davoir la gnrer chaque fois quon appelle la page PHP. On peut crer des images avec GD partir dune image vide ou dune image dj existante. GD propose des fonctions dcriture de texte dans une image et de dessin de formes basiques. Des fonctions plus avances de GD permettent de fusionner des images ou den redimensionner.

290

Chapitre

25
Dicult :

Les expressions rgulires (partie 1/2)

ous avez toujours rv dapprendre parler chinois ? a tombe bien ! Dans ce chapitre, je vais vous apprendre crire quelque chose comme ceci :

#(((https ?|ftp)://(w{3}\.) ?)( ?< !www)(\w+- ?)*\.([a-z]{2,4}))#

Croyez-moi si vous voulez, mais ce charabia imprononable. . . eh bien a veut vraiment dire quelque chose ! Si, si, je vous jure ! ;-) Les expressions rgulires constituent un systme trs puissant et trs rapide pour faire des recherches dans des chanes de caractres (des phrases, par exemple). Cest une sorte de fonctionnalit Rechercher / Remplacer trs pousse, dont vous ne pourrez plus vous passer une fois que vous saurez vous en servir.

291

CHAPITRE 25. LES EXPRESSIONS RGULIRES (PARTIE 1/2) Les expressions rgulires vont nous permettre deectuer des recherches et des remplacements pousss dans des textes. Voici quelques exemples pratiques de ce que vous serez en mesure de faire. Vrier automatiquement si ladresse e-mail entre par le visiteur a une forme valide (comme dupont@free.fr ). Modier une date que vous avez au format amricain (08-05-1985) pour la mettre dans le bon ordre en franais (05/08/1985). Remplacer automatiquement toutes les adresses http:// par des liens cliquables, comme cela se fait sur certains forums. Ou encore crer votre propre langage simpli partir du HTML, comme le fameux bbCode ([b][/b]. . .). Ouvrez grand vos oreilles et attachez vos ceintures !

O utiliser une regex ?


POSIX ou PCRE ?
Bonne nouvelle : vous naurez pas activer quoi que ce soit pour faire des expressions rgulires (contrairement la bibliothque GD). Il existe deux types dexpressions rgulires, qui rpondent aux doux noms de : POSIX : cest un langage dexpressions rgulires mis en avant par PHP, qui se veut un peu plus simple que PCRE (a nen reste pas moins assez complexe). Toutefois, son principal et gros dfaut je dirais, cest que ce langage est plus lent que PCRE ; PCRE : ces expressions rgulires sont issues dun autre langage (le Perl). Considres comme un peu plus complexes, elles sont surtout bien plus rapides et performantes. PHP propose donc de choisir entre POSIX et PCRE. Pour ma part, le choix est tout fait : nous allons tudier PCRE. Rassurez-vous, ce nest pas beaucoup plus compliqu que POSIX, mais a a lavantage dtre trs rapide. Et notre niveau de PHP, ce qui nous intresse justement cest la rapidit.

Les fonctions qui nous intressent


Nous avons donc choisi PCRE. Il existe plusieurs fonctions utilisant le langage PCRE et qui commencent toutes par preg_ : preg_grep ; preg_split ; preg_quote ; preg_match ; preg_match_all ; preg_replace ; preg_replace_callback.

292

DES RECHERCHES SIMPLES Chaque fonction a sa particularit : certaines permettent de faire simplement une recherche, dautres une recherche et un remplacement, mais leur gros point commun cest quelles utilisent un langage identique pour eectuer une recherche. Lorsque vous aurez appris le langage PCRE, vous pourrez utiliser chacune delles sans problme. Pour viter de faire trop de thorie, on va commencer, pour sentraner, utiliser une de ces fonctions : preg_match.

preg_match
En utilisant cette fonction, vous pourrez vous exercer en mme temps que moi et voir petit petit si vous avez compris le principe du langage PCRE. Il faut juste savoir que cette fonction renvoie un boolen : VRAI ou FAUX (true ou false en anglais). Elle renvoie true (vrai) si elle a trouv le mot que vous cherchiez dans la chane, false (faux) si elle ne la pas trouv. Vous devez lui donner deux informations : votre regex (cest le petit nom quon donne expression rgulire ) et la chane dans laquelle vous faites une recherche. Voici par exemple comment on peut sen servir, laide dune condition if :
<?php if (preg_match("** Votre REGEX **", "Ce dans quoi vous faites la recherche")) { echo Le mot que vous cherchez se trouve dans la chane; } else { echo Le mot que vous cherchez ne se trouve pas dans la chane; } ?>

la place de ** Votre REGEX ** , vous taperez quelque chose en langage PCRE, comme ce que je vous ai montr au dbut de ce chapitre : #(((https ?|ftp)://(w{3}\.) ?)( ?< !www)(\w+- ?)*\.([a-z]{2,4}))# Cest justement ceci qui nous intresse, cest sur a que nous allons nous pencher par la suite. Parce que au cas o vous ne lauriez pas remarqu ce truc-l nest franchement pas vident lire. . . Et le chinois a lair tout simple ct !

Des recherches simples


On va commencer par faire des recherches trs simples et trs basiques. Normalement, vous ne devriez pas avoir trop de mal suivre pour linstant, cest quand on mlangera tout aprs que a se compliquera. 293

CHAPITRE 25. LES EXPRESSIONS RGULIRES (PARTIE 1/2) Premire chose importante savoir : une regex1 est toujours entoure de caractres spciaux appels dlimiteurs. On peut choisir nimporte quel caractre spcial comme dlimiteur, et pour viter de tourner en rond trop longtemps, je vais vous en imposer un : le dise ! Votre regex se trouve alors entoure de dises, comme ceci : #Ma regex# Euh, mais quoi servent les dises, puisque de toute faon la regex est entoure par des guillemets dans la fonction PHP ? Parce que si on veut, on peut utiliser des options. On ne va pas parler des options tout de suite2 , mais sachez que ces options se placent aprs le second dise, comme ceci : #Ma regex#Options la place de Ma regex , vous devez mettre le mot que vous recherchez. Prenons un exemple : vous aimeriez savoir si une variable contient le mot guitare . Il vous sut dutiliser la regex suivante pour faire la recherche : #guitare# Dans un code PHP, a donne :
<?php if (preg_match("#guitare#", "Jaime jouer de la guitare.")) { echo VRAI; } else { echo FAUX; } ?>

Si vous excutez ce code, vous verrez quil ache VRAI parce que le mot guitare a t trouv dans la phrase Jaime jouer de la guitare. . Retenez bien ce petit bout de code. Nous allons le garder un moment en changeant parfois la regex, parfois la phrase dans laquelle on fait la recherche. Pour que vous compreniez bien comment les regex se comportent, je vais vous prsenter les rsultats dans un tableau, comme ceci : Chane Jaime jouer de la guitare. Jaime jouer de la guitare. Regex #guitare# #piano# Rsultat VRAI FAUX

O.K., cest compris jusque-l ? ;-) On a trouv le mot guitare dans la premire
1 Expression 2 On

rgulire nen a pas besoin pour commencer.

294

DES RECHERCHES SIMPLES phrase, mais pas piano dans la seconde. Jusque-l cest facile, mais je ne vais pas tarder compliquer !

Et tu casses, tu casses, tu casses. . .


Il y a quelque chose quil faut que vous sachiez : les regex font la dirence entre majuscules et minuscules ; on dit quelles sont sensibles la casse . Tenez, regardez ces deux regex par exemple : Chane Jaime jouer de la guitare. Jaime jouer de la guitare. Regex #Guitare# #GUITARE# Rsultat FAUX FAUX

Comment faire si on veut que nos regex ne fassent plus la dirence entre majuscules et minuscules ? On va justement utiliser une option. Cest la seule que vous aurez besoin de retenir pour le moment. Il faut rajouter la lettre i aprs le 2e dise, et la regex ne fera plus attention la casse : Chane Jaime jouer de la guitare Vive la GUITARE ! Vive la GUITARE ! Regex #Guitare#i #guitare#i #guitare# Rsultat VRAI VRAI FAUX

Dans le dernier exemple, je nai pas mis loption i alors on ma rpondu FAUX. Mais dans les autres exemples, vous pouvez voir que le i a permis de ne plus faire la dirence entre majuscules et minuscules. ;-)

Le symbole OU
On va maintenant utiliser le symbole OU, que vous avez dj vu dans le chapitre sur les conditions : cest la barre verticale | . Grce elle, vous allez pouvoir laisser plusieurs possibilits votre regex. Ainsi, si vous tapez : #guitare|piano# . . . cela veut dire que vous cherchez soit le mot guitare , soit le mot piano . Si un des deux mots est trouv, la regex rpond VRAI. Voici quelques exemples : Chane Jaime jouer Jaime jouer Jaime jouer Jaime jouer Regex #guitare|piano# #guitare|piano# #guitare|piano# #guitare|piano|banjo# Rsultat VRAI VRAI FAUX VRAI

de la guitare. du piano. du banjo. du banjo.

Dans le dernier exemple, jai mis deux fois la barre verticale. Cela signie que lon recherche guitare OU piano OU banjo. 295

CHAPITRE 25. LES EXPRESSIONS RGULIRES (PARTIE 1/2) Vous suivez toujours ? Parfait ! On peut maintenant voir les problmatiques de dbut et de n de chane, et ensuite on pourra passer la vitesse suprieure.

Dbut et n de chane
Les regex permettent dtre trs trs prcis, vous allez bientt vous en rendre compte. Jusquici en eet le mot pouvait se trouver nimporte o. Mais supposons que lon veuille que la phrase commence ou se termine par ce mot. Nous allons avoir besoin des deux symboles suivants, retenez-les : ^ (accent circonexe) : indique le dbut dune chane ; $ (dollar) : indique la n dune chane. Ainsi, si vous voulez quune chane commence par Bonjour , il faudra utiliser la regex : #^Bonjour# Si vous placez le symbole ^ devant le mot, alors ce mot devra obligatoirement se trouver au dbut de la chane, sinon on vous rpondra FAUX. De mme, si on veut vrier que la chane se termine par zro , on crira cette regex : #zro$# Compris ? Voici une srie de tests pour que vous voyiez bien comment a fonctionne : Chane Bonjour Bonjour Bonjour Bonjour Regex #^Bonjour# #zro$# #^zro# #zro$# Rsultat VRAI VRAI FAUX FAUX

petit petit petit petit

zro zro zro zro ! ! !

Simple, non ? Dans le dernier cas a ne fonctionne pas, car la chane ne se termine pas par zro mais par ! ! ! . Donc forcment, on nous rpond FAUX. . .

Les classes de caractres


Jusquici, vous avez pu faire des recherches assez simples, mais encore rien de vraiment extraordinaire. Loutil de recherche de Word fait bien tout cela, aprs tout. Mais rassurez-vous, les regex sont bien plus riches (et complexes) que loutil de recherche de Word, vous allez voir. Grce ce quon appelle les classes de caractres, on peut faire varier normment les possibilits de recherche. Tout cela tourne autour des crochets. On place une classe de caractres entre crochets dans une regex. Cela nous permet de tester beaucoup de possibilits de recherche la fois, tout en tant trs prcis. 296

LES CLASSES DE CARACTRES

Des classes simples


Ne tournons pas en rond plus longtemps, et regardons attentivement cette regex : #gr[io]s# Entre crochets, cest ce quon appelle une classe de caractres. Cela signie quune des lettres lintrieur peut convenir. Dans le cas prsent, notre regex reconnat deux mots : gris et gros . Cest un peu comme le OU quon a appris tout lheure, sauf que a sapplique ici une lettre et non pas un mot. Dailleurs, si vous mettez plusieurs lettres comme ceci : #gr[ioa]s# Cela signie i OU o OU a . Donc notre regex reconnat les mots gris , gros et gras ! Allez, on se fait quelques exemples : Chane La nuit, tous les chats sont gris Berk, cest trop gras comme nourriture Berk, cest trop gras comme nourriture Je suis un vrai zro Je suis un vrai zro Regex #gr[aoi]s# #gr[aoi]s# #gr[aoi]s$# #[aeiouy]$# #^[aeiouy]# Rsultat VRAI VRAI FAUX VRAI FAUX

Je suppose que vous comprenez les deux premires regex. Mais je pense que vous auriez besoin dexplications sur les trois dernires. Pour Berk, cest trop gras comme nourriture , jai utilis cette fois la regex #gr[aoi]s$#. Si vous avez bien suivi ce que je vous ai dit tout lheure, a veut dire que notre chane doit se terminer par gris , gras ou gros . Or ici le mot est au milieu, donc on nous rpond FAUX. Essayez de le mettre la n et vous verrez que a marche. Ensuite Je suis un vrai zro avec la regex #[aeiouy]$#. Celle-ci signie que notre regex doit se terminer par une voyelle (aeiouy). a tombe bien, la dernire lettre de la chane est la lettre o , donc on nous rpond VRAI. Enn, mme chane mais avec la regex #^[aeiouy]#. Cette fois, la chane doit commencer par une voyelle (en minuscule, en plus). Or la chane commence par J , donc la rponse est FAUX ! a va, je ne vous ai toujours pas perdus en route ? Si un moment vous sentez que vous avez dcroch, nhsitez pas relire un peu ce qui se trouve au-dessus, a ne vous fera pas de mal.

Les intervalles de classe


Cest partir de ce moment-l que les classes devraient commencer vous bluer. Grce au symbole - (le tiret), on peut autoriser toute une plage de caractres. Par exemple, tout lheure on a utilis la classe [aeiouy]. O.K., ce nest pas trop long. 297

CHAPITRE 25. LES EXPRESSIONS RGULIRES (PARTIE 1/2) Mais que dites-vous de la classe [abcdefghijklmnopqrstuvwxyz] ? Tout a pour dire que vous voulez quil y ait une lettre ? Jai mieux ! ;-) Vous avez le droit dcrire : [a-z] ! Avouez que cest plus court ! Et si vous voulez vous arrter la lettre e , pas de problme non plus : [a-e]. En plus, a fonctionne aussi avec les chires : [0-9]. Si vous voulez plutt un chire entre 1 et 8, tapez : [1-8]. Encore mieux ! Vous pouvez crire deux plages la fois dans une classe : [a-z0-9]. Cela signie Nimporte quelle lettre (minuscule) OU un chire . Bien entendu, vous pouvez aussi autoriser les majuscules sans passer par les options comme on la fait tout lheure. a donnerait : [a-zA-Z0-9]. Cest donc une faon plus courte dcrire : [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]. Faisons quelques tests, voulez-vous ? Chane Cette phrase contient une lettre cette phrase ne comporte ni majuscule ni chire Je vis au 21e sicle <h1>Une balise de titre HTML</h1> Regex #[a-z]# #[A-Z0-9]# #^[0-9]# #<h[1-6]># Rsultat VRAI FAUX FAUX VRAI

Le dernier exemple est particulirement intressant car on se dirige doucement vers la pratique. On y vrie justement si la chane comporte une balise HTML de titre (<h1> ou <h2>, etc., jusqu <h6>).

Et pour dire que je nen veux pas ?


Si vous ne voulez PAS des caractres que vous numrez dans votre classe, vous devrez placer le symbole ^ au dbut de la classe. Mais ? ! Je croyais que ce caractre servait indiquer le dbut dune chane ?

Oui, mais si vous le placez lintrieur dune classe, il sert dire que vous ne VOULEZ PAS de ce qui se trouve lintrieur de cette classe. Ainsi, la regex suivante : #[^0-9]# . . . signie que vous voulez que votre chane comporte au moins un caractre qui ne soit pas un chire. Maintenant, je fais chauer vos cervelles (tableau 25.1). Je vous conseille de faire une petite pause parce que a ne va vraiment pas sarranger 298

LES QUANTIFICATEURS

Tab. 25.1 Exemples Chane Cette phrase contient autre chose que des chires cette phrase contient autre chose que des majuscules et des chires Cette phrase ne commence pas par une minuscule Cette phrase ne se termine pas par une voyelle ScrrmmmblllGnngngnngnMmmmm Regex #[^0-9]# #[^A-Z0-9]# #^[^a-z]# #[^aeiouy]$# #[^aeiouy]# Rsultat VRAI VRAI VRAI FAUX VRAI

par la suite ! Nous allons maintenant dcouvrir le rle des quanticateurs qui vont nous permettre de grer les rptitions.

Les quanticateurs
Les quanticateurs sont des symboles qui permettent de dire combien de fois peuvent se rpter un caractre ou une suite de caractres. Par exemple, pour reconnatre une adresse e-mail comme francois@free.fr, il va falloir dire : Elle commence par une ou plusieurs lettres, suivie(s) dune @ (arobase), suivie de deux lettres au moins, ellesmmes suivies dun point, et enn de deux quatre lettres (pour le .fr, .com, mais aussi .info3 ). Bon : pour le moment, notre but nest pas dcrire une regex qui permet de savoir si ladresse e-mail rentre par le visiteur a la bonne forme (cest encore trop tt). Mais tout a pour vous dire quil est indispensable de savoir indiquer combien de fois une lettre peut se rpter !

Les symboles les plus courants


Vous devez retenir trois symboles : ? (point dinterrogation) : ce symbole indique que la lettre est facultative. Elle peut y tre 0 ou 1 fois. Ainsi, #a ?# reconnat 0 ou 1 a ; + (signe plus) : la lettre est obligatoire. Elle peut apparatre 1 ou plusieurs fois. Ainsi, #a+# reconnat a , aa , aaa , aaaa , etc. ; * (toile) : la lettre est facultative. Elle peut apparatre 0, 1 ou plusieurs fois. Ainsi, #a*# reconnat a , aa , aaa , aaaa , etc. Mais sil ny a pas de a , a fonctionne aussi !
3 Eh

oui, a existe !

299

CHAPITRE 25. LES EXPRESSIONS RGULIRES (PARTIE 1/2) Notez que ces symboles sappliquent la lettre se trouvant directement devant. On peut ainsi autoriser le mot chien , quil soit au singulier comme au pluriel, avec la regex #chiens ?# (fonctionnera pour chien et chiens ). Vous pouvez donc autoriser la rptition dune lettre. Je viens de vous montrer le cas pour chien . Mais on peut aussi sen servir pour une lettre au milieu du mot, comme ceci : #bor ?is# Ce code reconnatra boris et bois ! Et si je veux que ce soient deux lettres ou plus qui se rptent, comment je fais ? Il faut utiliser des parenthses. Par exemple, si on veut reconnatre Ayayayayayay 4 , on devra taper la regex suivante : #Ay(ay)*# Ce code reconnatra Ay , Ayay , Ayayay , Ayayayay , Oue Ae Ae (non, je rigole pour le dernier). Vous pouvez utiliser le symbole | dans les parenthses. La regex #Ay(ay|oy)*# renverra par exemple vrai pour Ayayayoyayayayoyoyoyoyayoy ! Cest le ay OU le oy rpt plusieurs fois, tout simplement ! Autre bonne nouvelle : vous pouvez mettre un quanticateur aprs une classe de caractres (vous savez, avec les crochets !). Ainsi #[0-9]+# permet de reconnatre nimporte quel nombre, du moment quil y a au moins un chire ! Faisons quelques tests pour bien rentrer a dans nos ttes (tableau 25.2). Tab. 25.2 Exemples Chane eeeee ooo magnique Yahoooooo Yahoooooo cest gnial ! Blablablablabla Regex #e+# #u ?# #[0-9]+# #^Yaho+$# #^Yaho+$# #^Bla(bla)*$# Rsultat VRAI VRAI FAUX VRAI FAUX VRAI

Les derniers exemples sont trs intressants. La regex #^Yaho+$# signie que la chane doit commencer et nir par le mot Yahoo . Il peut y avoir un ou plusieurs o . Ainsi Yaho , Yahoo , Yahooo , etc. marchent. . . Mais vous ne devez rien mettre
4 Le

cri de guerre de Speedy Gonzales !

300

LES QUANTIFICATEURS avant ni aprs, car jai indiqu que ctait un dbut ET une n de chane avec ^ et $. Enn, la dernire regex autorise les mots Bla , Blabla , Blablabla , etc. Je me suis servi des parenthses pour indiquer que bla peut tre rpt 0, 1 ou plusieurs fois. a commence faire mal la tte, nest-ce pas ?

tre plus prcis grce aux accolades


Parfois on aimerait indiquer que la lettre peut tre rpte quatre fois, ou de quatre six fois. . . bref, on aimerait tre plus prcis sur le nombre de rptitions. Cest l quentrent en jeu les accolades. Vous allez voir : si vous avez compris les derniers exemples, a va vous paratre tout simple. Il y a trois faons dutiliser les accolades. {3} : si on met juste un nombre, cela veut dire que la lettre (ou le groupe de lettres sil est entre parenthses) doit tre rpte 3 fois exactement. #a{3}# fonctionne donc pour la chane aaa . {3,5} : ici, on a plusieurs possibilits. On peut avoir la lettre de 3 5 fois. #a{3,5}# fonctionne pour aaa , aaaa , aaaaa . {3,} : si vous mettez une virgule, mais pas de 2e nombre, a veut dire quil peut y en avoir jusqu linni. Ici, cela signie 3 fois ou plus . #a{3,}# fonctionne pour aaa , aaaa , aaaaa , aaaaaa , etc.5 Si vous faites attention, vous remarquez que : ? revient crire {0,1} ; + revient crire {1,} ; * revient crire {0,}. On se fait quelques exemples, histoire de se dire quon est prts (tableau 25.3) ?

Tab. 25.3 Exemples Chane eeeee Blablablabla 546781 Regex #e{2,}# #^Bla(bla){4}$# #^[0-9]{6}$# Rsultat VRAI FAUX VRAI

Voil un sacr paquet dingurgit, dites-moi ! Allez, on va sarrter l et faire une bonne pause parce que. . . dans le prochain chapitre, on mlange tout ce quon vient dapprendre !
5 Je

ne vais pas tous les crire, a serait un peu long.

301

CHAPITRE 25. LES EXPRESSIONS RGULIRES (PARTIE 1/2)

En rsum
Les expressions rgulires sont des outils de recherche et de remplacement de texte trs avancs qui permettent deectuer des recherches trs prcises, pour vrier par exemple que le texte saisi par lutilisateur correspond bien la forme dune adresse e-mail ou dun numro de tlphone. La fonction preg_match vrie si un texte correspond la forme dcrite par une expression rgulire. Une expression rgulire est dlimite par un symbole (par exemple le dise #). Les classes de caractres permettent dautoriser un grand nombre de symboles (lettres et chires) selon un intervalle. Les quanticateurs permettent dexiger la rptition dune chane de texte un certain nombre de fois.

302

Chapitre

26
Dicult :

Les expressions rgulires (partie 2/2)

oici donc la suite (et n) de notre aventure avec les expressions rgulires. Le mot dordre de ce chapitre est pratiquer. Hormis quelques points que nous allons aborder au dbut, vous connaissez lessentiel sur les regex mais il vous manque le plus important : la pratique ! Dans la seconde moiti de ce chapitre, nous allons donc en construire ensemble, pour que vous voyiez comment il faut procder pour arriver enn crire ces $%@#$#% de regex ! crire un bout de regex comme on la fait jusquici, cest une chose, mais crer une regex complte, vous allez voir que cest une toute autre paire de manches !

303

CHAPITRE 26. LES EXPRESSIONS RGULIRES (PARTIE 2/2)

Une histoire de mtacaractres


Pour commencer, et avant daller plus loin, il me semble important de porter votre connaissance une nouvelle notion : les mtacaractres. Ce nest pas une insulte de programmeur, mais un mot qui signie tout simplement caractres spciaux . Ce sont des caractres pas comme les autres qui ont un rle ou un sens particulier.

Alerte mon Gnral ! Les mtacaractres schappent !


Dans le langage PCRE (des regex), les mtacaractres quil faut connatre sont les suivants : #! ^ $ ( ) [ ] { }? + * . \ | Il faut bien les retenir. Pour la plupart dentre eux, vous les connaissez dj. Ainsi, le dollar $ est un caractre spcial parce quil permet dindiquer une n de chane. De mme pour laccent circonexe, le dise, les parenthses, les crochets, les accolades et les symboles ? + * : nous les avons tous utiliss dans le chapitre prcdent, souvenez-vous. Pour le point . et lantislash \ , vous ne les connaissez pas mais vous nallez pas tarder les apprendre. Bon, ce sont des caractres spciaux et chacun deux signie quelque chose de prcis. Et alors ? Et alors, le problme vous tombe dessus le jour o vous voulez chercher par exemple Quoi ? dans une chane. Comment cririez-vous la regex ? Comme a ? #Quoi ?# Eh non, surtout pas ! Le point dinterrogation, vous le savez, sert dire que la lettre juste avant est facultative (elle peut apparatre 0 ou 1 fois). Ici, lespace devant le point dinterrogation serait donc facultatif, mais ce nest pas ce quon veut faire ! Alors, comment faire pour faire comprendre quon recherche Quoi ? alors que le point dinterrogation a dj une signication ? Il va falloir lchapper. Cela signie que vous devez placer en fait un antislash \ devant un caractre spcial. Ainsi, la bonne regex serait : #Quoi \ ?# Ici, lantislash sert dire que le point dinterrogation juste aprs nest pas un symbole spcial, mais bel et bien une lettre comme une autre ! Cest la mme chose pour tous les autres mtacaractres que je vous ai montrs plus haut (# ! ^ $ ( ) [ ] { } ? + * . \) : il faut mettre un antislash devant si vous voulez les utiliser dans votre recherche. Vous remarquerez que pour utiliser un antislash il faut. . . un antislash devant ! Comme ceci : \\. 304

LES CLASSES ABRGES Bien tordu tout a, non ? Pourtant, ce que vous devez retenir est simple : si vous voulez utiliser un caractre spcial dans votre recherche, il faut placer un antislash devant. Point barre. Je vous donne quelques exemples dutilisation, a devrait bien vous faire rentrer a dans la tte : Chane Je suis impatient ! Je suis (trs) fatigu Jai sommeil. . . Le smiley :-\ regex #impatient \ !# #\(trs\) fatigu# #sommeil\.\.\.# # :-\\# Rsultat VRAI VRAI VRAI VRAI

Le cas des classes


Il reste une dernire petite chose voir (encore un cas particulier), et cela concerne les classes de caractres. Jusquici, vous avez mis des lettres et des chires entre les crochets ; par exemple : #[a-z0-9]# Oui mais, vous vous en doutez, vous avez le droit de mettre dautres caractres, comme les accents (mais dans ce cas, il faut les numrer un un). Par exemple : [a-z] et ainsi de suite. Jusquici, tout va bien. Mais si vous voulez lister aussi des caractres spciaux, hum ? Par exemple un point dinterrogation (au hasard). Eh bien l, a ne compte pas ! Pas besoin de lchapper : lintrieur de crochets les mtacaractres. . . ne comptent plus ! Ainsi, cette regex marche trs bien : #[a-z ?+*{}]# Elle signie quon a le droit de mettre une lettre, un point dinterrogation, un signe +, etc. 3 cas particuliers, cependant. # (dise) : il sert toujours indiquer la n de la regex. Pour lutiliser, vous DEVEZ mettre un antislash devant, mme dans une classe de caractres. ] (crochet fermant) : normalement, le crochet fermant indique la n de la classe. Si vous voulez vous en servir comme dun caractre que vous recherchez, il faut l aussi mettre un antislash devant. - (tiret) : encore un cas un peu particulier. Le tiret vous le savez sert dnir un intervalle de classe (comme [a-z]). Et si vous voulez ajouter le tiret dans la liste des caractres possibles ? Eh bien il sut de le mettre soit au dbut de la classe, soit la n. Par exemple : [a-z0-9-] permet de chercher une lettre, un chire ou un tiret.

Les classes abrges


La bonne nouvelle, cest que vous tes maintenant prts raliser quasiment toutes les regex que vous voulez. La mauvaise, cest que je viens de dire quasiment . Oh rassurez-vous, a ne sera pas long et vous ne sentirez aucune douleur ( ce stade, on ne ressent plus la douleur de toute faon). Je souhaite juste vous montrer ce quon appelle les classes abrges, et que moi jappelle les raccourcis. 305

CHAPITRE 26. LES EXPRESSIONS RGULIRES (PARTIE 2/2) Certains de ces raccourcis ne vous seront pas indispensables, mais comme vous risquez de les rencontrer un jour ou lautre, je ne voudrais pas que vous soyez surpris et que vous croyiez que je vous ai cach des choses. Voici ce quil faut retenir :

Raccourci \d \D \w \W \t \n \r \s \S .

Signication Indique un chire. a revient exactement taper [0-9] Indique ce qui nest PAS un chire. a revient taper [^0-9] Indique un mot. Cela correspond [a-zA-Z0-9_] Indique ce qui nest PAS un mot. Si vous avez suivi, a revient taper [^a-zA-Z0-9_] Indique une tabulation. Indique une nouvelle ligne. Indique un retour chariot. Indique un espace blanc. Indique ce qui nest PAS un espace blanc (\t \n \r). Le point indique nimporte quel caractre ! Il autorise donc tout !

Il sagit de lettres normales, mais quand on place un antislash devant, on leur donne une signication spciale. Cest linverse de ce quon faisait tout lheure : on utilisait un antislash devant les mtacaractres pour leur enlever leur signication spciale. Pour le point, il existe une exception : il indique tout sauf les entres (\n). Pour faire en sorte que le point indique tout, mme les entres, vous devrez utiliser loption s de PCRE. Exemple : #[0-9]-.#s Allez, cette fois vous en savez susamment, on va pouvoir passer la pratique !

Construire une regex complte


Vous allez enn comprendre pourquoi vous en avez bav tout le long ! Cette fois, nous allons toucher du concret travers des exemples qui vous seront srement utiles. Nous allons construire de grosses regex ensemble, pour que vous compreniez la mthode. Ensuite, vous serez tout fait capables dinventer vos regex et de vous en servir pour vos scripts PHP ! 306

CONSTRUIRE UNE REGEX COMPLTE

Un numro de tlphone
Pour cette premire vraie regex, nous allons essayer de voir si une variable (entre par un visiteur via un formulaire, par exemple) correspond bien un numro de tlphone. Je vais me baser sur les numros de tlphone franais, il faudra donc mexcuser si vous ntes pas franais et que vous ne connaissez pas. Lavantage, cest que vous pourrez ensuite vous exercer crire cette regex pour les numros de tlphone de votre pays. Pour rappel (et pour ceux qui ne savent pas, donc), un numro de tlphone franais comporte 10 chires. Par exemple : 01 53 78 99 99 . Il faut respecter les rgles suivantes : le premier chire est TOUJOURS un 0 ; le second chire va de 1 6 (1 pour la rgion parisienne. . . 6 pour les tlphones portables), mais il y a aussi le 8 (ce sont des numros spciaux). noter que le 7 et le 9 commencent tre utiliss mais que nous ne les prendrons pas en compte dans nos exemples ; ensuite viennent les 8 chires restants (ils peuvent aller de 0 9 sans problme). Pour commencer, et pour faire simple, on va supposer que lutilisateur entre le numro de tlphone sans mettre despace ni quoi que ce soit (mais on complique juste aprs, et vous verrez que cest l le vritable intrt des regex). Ainsi, le numro de tlphone doit ressembler a : 0153789999 . Comment crire une regex qui corresponde un numro de tlphone comme celui-ci ? Voici comment je procde, dans lordre, pour construire cette regex. 1. Primo, on veut quil y ait UNIQUEMENT le numro de tlphone. On va donc commencer par mettre les symboles ^ et $ pour indiquer un dbut et une n de chane : #^$# 2. Continuons. On sait que le premier caractre est forcment un 0. On tape donc : #^0$# 3. Le 0 est suivi dun nombre allant de 1 6, sans oublier le 8 pour les numros spciaux. Il faut donc utiliser la classe [1-68], qui signie Un nombre de 1 6 OU le 8 : #^0[1-68]$# 4. Ensuite, viennent les 8 chires restants, pouvant aller de 0 9. Il nous sut donc dcrire [0-9]{8} pour indiquer que lon veut 8 chires. Au nal, a nous donne cette regex : #^0[1-68][0-9]{8}$# Et cest tout ! Bon, je vois que vous tes en forme, alors ne nous arrtons pas en si bon chemin et amliorons cette regex. Maintenant, on va supposer que la personne peut taper un espace tous les deux chires (comme cest courant de le faire en France), mais aussi un point ou un tiret. Notre regex devra donc accepter les numros de tlphone suivants : 0153789999 01 53 78 99 99 01-53-78-99-99 01.53.78.99.99 307

CHAPITRE 26. LES EXPRESSIONS RGULIRES (PARTIE 2/2) 0153 78 99 99 0153.78 99-99 etc. Et cest l quest toute la puissance des regex ! Les possibilits sont trs nombreuses, et pourtant vous avez juste besoin dcrire la regex correspondante. On reprend donc la cration de notre regex. 1. Primo, le 0 puis le chire de 1 6 sans oublier le 8. a, a ne change pas : #^0[1-68]$# 2. Aprs ces deux premiers chires, il peut y avoir soit un espace, soit un tiret, soit un point, soit rien du tout (si les chires sont attachs). On va donc utiliser la classe [-. ] (tiret, point, espace). Mais comment faire pour dire que le point (ou le tiret, ou lespace) nest pas obligatoire ? Avec le point dinterrogation, bien sr ! a nous donne : #^0[1-68][-. ] ?$# 3. Aprs le premier tiret (ou point, ou espace, ou rien), on a les deux chires suivants. On doit donc rajouter [0-9]{2} notre regex. #^0[1-68][-. ] ?[0-9]{2}$# 4. Et maintenant, rchissez. Il y a moyen de terminer rapidement : on a juste besoin de dire que [-. ] ?[0-9]{2} doit tre rpt quatre fois, et notre regex est termine ! On va se servir des parenthses pour entourer le tout, et placer un {4} juste aprs pour indiquer que tout a doit se rpter quatre fois. Ce qui nous donne nalement : #^0[1-68]([-. ] ?[0-9]{2}){4}$# Vous pouvez lencadrer en gros en poster dans votre chambre : cest votre premire VRAIE regex ! #^0[1-68]([-. ] ?[0-9]{2}){4}$# Voici un petit script que jai fait rapidement, pour que vous puissiez tester toute la puissance des regex :
<p> <?php if (isset($_POST[telephone])) { $_POST[telephone] = htmlspecialchars($_POST[telephone]); // On rend inoffensives les balises HTML que le visiteur a pu entrer if (preg_match("#^0[1-68]([-. ]?[0-9]{2}){4}$#", $_POST[telephone])) { echo Le . $_POST[telephone] . est un numro <strong>valide</strong> !; } else { echo Le . $_POST[telephone] . n\est pas valide, recommencez !; } } ?>

308

CONSTRUIRE UNE REGEX COMPLTE


</p> <form method="post"> <p> <label for="telephone">Votre tlphone ?</label> <input id="telephone" name="telephone" /><br /> <input type="submit" value="Vrifier le numro" /> </p> </form>

Code web : 699997 Vous pouvez essayer tous les numros de tlphone que vous voulez, avec des espaces au milieu ou non si a vous chante : la regex gre tous les cas. Vous auriez pu aussi utiliser le raccourci \d pour indiquer un chire dans votre regex : #^0[1-68]([-. ] ?\d{2}){4}$# Personnellement, je trouve que mettre [0-9] est quand mme plus clair.

Une adresse e-mail


a serait dommage de sarrter sur une si bonne lance. Je vais donc vous prsenter un deuxime exemple qui vous sera certainement utile : tester si ladresse e-mail est valide. Alors, avant de commencer quoi que ce soit, et pour quon soit bien daccord, je vais rappeler comment est construite une adresse e-mail. 1. On a tout dabord le pseudonyme (au minimum une lettre, mais cest plutt rare). Il peut y avoir des lettres minuscules (pas de majuscules), des chires, des points, des tirets et des underscores _ . 2. Il y a ensuite une arobase : @. 3. Ensuite il y a le nom de domaine. Pour ce nom, mme rgle que pour le pseudonyme : que des minuscles, des chires, des tirets, des points et des underscores. La seule dirence vous ne pouviez pas forcment deviner cest quil y a au moins deux caractres (par exemple, a.com nexiste pas, mais aa.com oui). 4. Enn, il y a lextension (comme .fr ). Cette extension comporte un point, suivi de deux quatre lettres (minuscules). En eet, il y a .es , .de , mais aussi .com , .net , .org , .info , etc. Ladresse e-mail peut donc ressembler j.dupont_2@orange.fr. Construisons la regex. 1. Primo, comme tout lheure, on ne veut QUE ladresse e-mail ; on va donc demander ce que a soit un dbut et une n de chane : #^$# 309

CHAPITRE 26. LES EXPRESSIONS RGULIRES (PARTIE 2/2) 2. Ensuite, on a des lettres, chires, tirets, points, underscores, au moins une fois. On utilise donc la classe [a-z0-9._-] la suite de laquelle on rajoute le signe + pour demander ce quil y en ait au moins un : #^[a-z0-9._-]+$# 3. Vient ensuite larobase (l ce nest pas compliqu, on a juste taper le caractre) : #^[a-z0-9._-]+@$# 4. Puis encore une suite de lettres, chires, points, tirets, au moins deux fois. On tape donc {2,} pour dire deux fois ou plus : #^[a-z0-9._-]+@[a-z0-9._-]{2,}$# 5. Ensuite vient le point (de .fr par exemple). Comme je vous lai dit plus haut, cest un caractre spcial qui sert indiquer nimporte quel caractre (mme des accents). Or, ici, on veut enlever sa signication au point pour dire que lon veut le symbole point dans notre regex. On va donc mettre un antislash devant : #^[a-z0-9._-]+@[a-z0-9._-]{2,}\.$# 6. Enn, pour terminer, il nous faut deux quatre lettres. Ce sont forcment des lettres minuscules, et cette fois pas de chire ou de tiret, etc. On crit donc : #^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$# Et voil encore une nouvelle regex de boucle ! #^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$# Vous sentez que vous commencez parler chinois, non ? ;-) Allez, je suis en forme et de bonne humeur, je vous donne le script PHP pour tester cette regex :
<p> <?php if (isset($_POST[mail])) { $_POST[mail] = htmlspecialchars($_POST[mail]); // On rend inoffensives les balises HTML que le visiteur a pu rentrer if (preg_match("#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#", $_POST[mail])) { echo L\adresse . $_POST[mail] . est <strong>valide</strong> !; } else { echo L\adresse . $_POST[mail] . n\est pas valide, recommencez !; } } ?> </p> <form method="post"> <p> <label for="mail">Votre mail ?</label> <input id="mail" name="mail" />

310

CONSTRUIRE UNE REGEX COMPLTE


<br /> <input type="submit" value="Vrifier le mail" /> </p> </form>

Code web : 292829 Testez donc des adresses comme : the_cypher@hotmail.com ; business_consultants@free4work.info ; mega-killer.le-retour@super-site.fr.st ; etc., etc.

Alors, a vous plat ? Je reconnais que a parat tre trs complexe quand on lit une regex la premire fois. Jimagine la tte que vous avez d faire lorsque je vous en ai montr une dans lintroduction du chapitre prcdent. ;-) Mais bon, vous voyez le progrs ? On vient ensemble dcrire un de ces fameux trucs imbuvables, et je ne pense pas que beaucoup dentre vous pensaient y arriver en lisant le chapitre prcdent ! Pourtant nous y voil : nous avons russi crire deux regex compltes. Je ne vais pas vous faire travailler sur une troisime, vous avez je pense compris le principe et vous savez vous dbrouiller comme des grands. Je veux juste vous montrer une dernire petite chose avant de passer la dernire notion importante que nous aborderons (capture et remplacement).

Des regex. . . avec MySQL !


Comme quoi, vous allez vraiment tre heureux den avoir un peu bav pour arriver jusquici. Eh oui, grrrande nouvelle : MySQL comprend les regex ! Et a, bah cest tout bnef pour vous : vous venez dapprendre crire des regex, vous navez presque rien savoir de plus pour vous en servir avec MySQL. Il faut savoir cependant que MySQL ne comprend que les regex en langage POSIX, et pas PCRE comme on a appris. Vous avez juste besoin de retenir ce qui suit pour faire une regex POSIX : il ny a pas de dlimiteur ni doptions. Votre regex nest donc pas entoure de dises ; il ny a pas de classes abrges comme on la vu plus haut, donc pas de \d, etc. En revanche, vous pouvez toujours utiliser le point pour dire : nimporte quel caractre . Le mieux, bien entendu, cest toujours un bon exemple. Supposons que vous ayez stock les IP de vos visiteurs dans une table visiteurs et que vous vouliez les noms des visiteurs dont lIP commence par 84.254 : SELECT nom FROM visiteurs WHERE ip REGEXP ^84\.254(\.[0-9]{1,3}){2}$ Cela signie : Slectionne tous les noms de la table visiteurs dont lIP commence par 84.254 et se termine par deux autres nombres de un trois chire(s) (ex. : 84.254.6.177). 311

CHAPITRE 26. LES EXPRESSIONS RGULIRES (PARTIE 2/2) Toute la puissance des regex dans une requte MySQL pour faire une recherche trs prcise. . . a ne se refuse pas. ;-) Je ne mtends pas plus l-dessus, je sais que vous saurez vous dbrouiller si jamais cela vous est utile. Passons maintenant la dernire notion importante avec les regex : capture et remplacement !

Capture et remplacement
Je vous avais dit au dbut de ces deux chapitres consacrs aux regex quelles servaient faire une recherche puissante1 , mais aussi faire une recherche et un remplacement. Cela va nous permettre par exemple de faire la chose suivante : 1. chercher sil y a des adresses e-mail dans un message laiss par un visiteur ; 2. modier automatiquement son message pour mettre un lien <a href="mailto:blabla@truc.com"> devant chaque adresse, ce qui rendra les adresses e-mail cliquables ! Avec cette technique, on peut faire pareil pour rendre les liens http:// automatiquement cliquables eux aussi. On peut galement, vous allez voir, crer notre propre langage simpli pour le visiteur, comme le fameux bbCode utilis sur la plupart des forums2 .

Les parenthses capturantes


Tout ce que nous allons voir maintenant tourne autour des parenthses. Vous vous tes dj servi delles pour entourer une partie de votre regex et dire quelle devait se rpter quatre fois par exemple (comme on la fait pour le numro de tlphone). Eh bien a, cest la premire utilit des parenthses, mais elles peuvent aussi servir autre chose. partir de maintenant, nous allons travailler avec la fonction preg_replace. Cest avec cette fonction que nous allons pouvoir raliser ce quon appelle une capture de chane. Ce quil faut savoir, cest qu chaque fois que vous utilisez des parenthses, cela cre une variable contenant ce quelles entourent. Je mexplique avec une regex : #\[b\](.+)\[/b\]# Vous ne devriez pas avoir trop de mal la dchirer : elle signie Chercher dans la chane un [b], suivi dun ou plusieurs caractre(s) (le point permet de dire nimporte lesquels ), suivi(s) dun [/b] . Jai t oblig de mettre des antislashs \ devant les crochets pour que PHP ne les confonde pas avec des classes de caractres (comme [a-z]).
1 a, 2 [b][/b]

on vient de le voir, travers les exemples du tlphone et du mail. pour mettre en gras, a vous dit quelque chose ?

312

CAPTURE ET REMPLACEMENT Normalement, si vous rchissez deux secondes, vous devez vous dire quici les parenthses ne sont pas obligatoires. Et cest vrai que pour faire juste une recherche, les parenthses sont eectivement inutiles. Mais pour faire un remplacement, cela va tre trs pratique ! En eet, retenez bien ceci : chaque fois quil y a une parenthse, cela cre une variable appele $1 (pour la premire parenthse), $2 pour la seconde, etc. On va ensuite se servir de ces variables pour modier la chane (faire un remplacement). Sur la regex que je vous ai montre plus haut, il y a une seule parenthse, vous tes daccord ? Donc, il y aura juste une variable $1, qui contiendra ce qui se trouve entre le [b] et le [/b]. Et grce a, on sait ce quon va mettre en gras. Bon, la thorie de tout a est dlicate expliquer, alors je vais vous montrer de suite comment on fait pour mettre en gras tous les mots compris entre des [b][/b] :
<?php $texte = preg_replace(#\[b\](.+)\[/b\]#i, <strong>$1</strong>, $texte); ?>

Voici comment sutilise la fonction preg_replace. 1. On lui donne en premier paramtre la regex. Rien de particulier, comme vous pouvez le constater, part quil faut bien garder en tte que chaque parenthse va crer une variable ($1, $2, etc.). Ici, jai rajout loption i pour que le code fonctionne aussi avec des majuscules ([B][/B]). 2. Ensuite, et cest l quest la nouveaut, on indique le texte de remplacement : <strong>$1</strong> (je vous rappelle que <strong> permet de mettre en gras en HTML). Entre les balises HTML, jai mis $1. Cela signie que ce qui se trouve dans la parenthse capturante (entre [b] et [/b]) sera en fait entour des balises <strong> ! 3. Enn, dernier paramtre, cest le texte dans lequel on fait notre recherche / remplacement (a, vous connaissez dj). La fonction preg_replace renvoie le rsultat aprs avoir fait les remplacements. Si je schmatise le fonctionnement, a donne la gure 26.1.

Fig. 26.1 Fonctionnement de la fonction preg_replace Il y a quelques rgles respecter que vous allez devoir apprendre. Si vous avez plusieurs parenthses, pour savoir le numro de lune delles il sut de les compter dans lordre de gauche droite. Par exemple : #(anti)co(nsti)(tu(tion)nelle)ment# Il y a quatre parenthses dans cette regex (donc $1, $2, $3 et $4). La parenthse numro 3 ($3) contient tutionnelle , et la parenthse $4 contient tion . 313

CHAPITRE 26. LES EXPRESSIONS RGULIRES (PARTIE 2/2) Noubliez pas que cest lordre dans lequel les parenthses sont ouvertes qui est important. Vous pouvez utiliser jusqu 99 parenthses capturantes dans une regex (a vous laisse de la marge). a va donc jusqu $99. Une variable $0 est toujours cre ; elle contient toute la regex. Sur le mme exemple que tout lheure : #(anti)co(nsti)(tu(tion)nelle)ment# . . . $0 contient anticonstitutionnellement . Si, par hasard, vous ne voulez pas quune parenthse soit capturante (pour vous faciliter les comptes, ou parce que vous avez beaucoup beaucoup de parenthses), il faut quelle commence par un point dinterrogation suivi dun deux points : . Par exemple : #(anti)co( ?:nsti)(tu(tion)nelle)ment# La seconde parenthse nest pas capturante. Il ne nous reste que trois variables (quatre si on compte $0) : 1. $0 : anticonstitutionnellement 2. $1 : anti 3. $2 : tutionnelle 4. $3 : tion Voil : si vous avez compris a, vous avez tout compris, bravo ! ;-)

Crez votre bbCode


On peut maintenant passer la pratique et apprendre se servir des parenthses capturantes. Nous allons raliser ce quon appelle un parser (prononcez parseur ). Le parser va servir transformer le texte rdig par un visiteur3 en un texte inoensif (sans balises HTML grce htmlspecialchars) mais qui accepte aussi du bbCode ! On ne va pas faire tous les bbCode qui existent (trop long), mais pour sentraner, ceux-ci suront dj : [b][/b] : pour mettre du texte en gras ; [i][/i] : pour mettre du texte en italique ; [color=red][/color] : pour colorer le texte (il faudra laisser le choix entre plusieurs couleurs). Et nous ferons en sorte de remplacer aussi automatiquement les URL (http://) par des liens cliquables. Commenons par [b] et [i] (cest la mme chose). Vous avez dj vu le code pour [b], et cest en eet presque le bon. Il y a un problme toutefois : il manque des options. Pour que a marche, on va avoir besoin dutiliser trois options : i : pour accepter les majuscules comme les minuscules ([B] et [b]) ; s : pour que le point fonctionne aussi pour les retours la ligne (pour que le texte puisse tre en gras sur plusieurs lignes) ;
3 Pour

un message sur un forum, ou sur votre livre dor, ou mme sur votre mini-chat !

314

CAPTURE ET REMPLACEMENT U : le U majuscule est une option que vous ne connaissez pas et qui signie Ungreedy ( pas gourmand ). Je vous passe les explications un peu complexes sur son fonctionnement, mais sachez que, grosso modo, a ne marcherait pas correctement sil y avait plusieurs [b] dans votre texte. Exemple : Ce texte est [b]important[/b], il faut me [b]comprendre[/b] ! . . . sans activer loption Ungreedy, la regex aurait voulu mettre en gras tout ce quil y a entre le premier [b] et le dernier [/b] (cest--dire important[/b], il faut me [b]comprendre ). En utilisant loption U , la regex sarrtera au premier [/b], et cest ce quon veut. Voici donc le code correct pour mettre en gras et en italique avec le bbCode :
<?php $texte = preg_replace(#\[b\](.+)\[/b\]#isU, <strong>$1</strong>, $texte); $texte = preg_replace(#\[i\](.+)\[/i\]#isU, <em>$1</em>, $texte); ?>

Comme vous pouvez le voir, cest quasiment pareil pour [b] et [i] ( part que la balise HTML quon utilise est <em>). Donc, si vous avez suivi jusquici, a ne doit pas trop vous surprendre. Passons maintenant un cas un peu plus complexe : celui de la balise [color=truc]. On va laisser le choix entre plusieurs couleurs avec le symbole | (OU), et on va utiliser deux parenthses capturantes : 1. la premire pour rcuprer le nom de la couleur qui a t choisie (en anglais, comme a on naura pas besoin de le changer pour le code HTML) ; 2. la seconde pour rcuprer le texte entre [color=truc] et [/color] (pareil que pour gras et italique). Voici le rsultat :
<?php $texte = preg_replace(#\[color=(red|green|blue|yellow|purple|olive)\](.+) \[/col or\]#isU, <span style="color:$1">$2</span>, $texte); ?>

Ainsi, si on tape [color=blue]texte[/color], a crira texte en bleu. Vous pouvez essayer avec les autres couleurs aussi ! Allez, dernire tape, et aprs je vous laisse essayer. Je veux que les liens http:// soient automatiquement transforms en liens cliquables. Essayez dcrire la regex, vous en tes tout fait capables ! Voici la solution :
<?php $texte = preg_replace(#http://[a-z0-9._/-]+#i, <a href="$0">$0</a>, $texte); ?>

315

CHAPITRE 26. LES EXPRESSIONS RGULIRES (PARTIE 2/2) Dans le texte de remplacement, jai utilis $0 qui, si vous vous souvenez bien, prend tout le texte reconnu par la regex (donc ici, toute lURL). Il ny a pas les options s et U car on ne fait jamais de retour la ligne au milieu dune URL, et le mode Ungreedy ne sert pas ici (essayez avec U, vous verrez que le lien sarrte la premire lettre !). Vous remarquerez que jai fait simple pour cette regex. Cest vrai, jaurais pu la faire plus complexe et plus prcise, mais je nai pas envie de vous embrouiller avec a : je veux surtout que vous lamlioriez vous-mmes. En eet, la regex marche trs bien pour http://www.siteduzero.com/images/super_image2.jpg, mais elle ne fonctionne pas sil y a des variables en paramtres dans lURL, comme par exemple : http://www.siteduzero.com/index.php ?page=3&skin=blue Je vous laisse le soin damliorer la regex, a vous fera un peu de travail. Rsumons maintenant notre parser bbCode au complet :
<?php if (isset($_POST[texte])) { $texte = stripslashes($_POST[texte]); // On enlve les slashs qui se seraient ajouts automatiquement $texte = htmlspecialchars($texte); // On rend inoffensives les balises HTML que le visiteur a pu rentrer $texte = nl2br($texte); // On cre des <br /> pour conserver les retours la ligne // On fait passer notre texte la moulinette des regex $texte = preg_replace(#\[b\](.+)\[/b\]#isU, <strong>$1</strong>, $texte); $texte = preg_replace(#\[i\](.+)\[/i\]#isU, <em>$1</em>, $texte); $texte = preg_replace(#\[color=(red|green|blue|yellow|purple|olive)\](.+) \[/color\]#isU, <span style="color:$1">$2</span>, $texte); $texte = preg_replace(#http://[a-z0-9._/-]+#i, <a href="$0">$0</a>, $texte); // Et on affiche le rsultat. Admirez ! echo $texte . <br /><hr />;

} ?> <p>

Bienvenue dans le parser du Site du Zro !<br /> Nous avons crit ce parser ensemble, jespre que vous saurez apprcier de voir que tout ce que vous avez appris va vous tre trs utile ! </p> <p>Amusez-vous utiliser du bbCode. Tapez par exemple~:</p> <blockquote style="font-size:0.8em">

316

CAPTURE ET REMPLACEMENT
<p>

Je suis un gros [b]Zro[/b], et pourtant jai [i]tout appris[/i] sur http://www.siteduzero.com<br /> Je vous [b][color=green]recommande[/color][/b] daller sur ce site, vous pourrez apprendre faire a [i][color=purple]vous aussi[/color][/i] ! </p> </blockquote> <form method="post"> <p> <label for="texte">Votre message ?</label><br /> <textarea id="texte" name="texte" cols="50" rows="8"></textarea><br /> <input type="submit" value="Montre-moi toute la puissance des regex" /> </p> </form>

Si vous voulez copier ce code, utilisez le code web suivant : Code web : 564128 Si vous voulez le tester directement en ligne, utilisez ce code web : Code web : 934745 Pou ! Eh bah si avec a vous me pondez pas un super site, je ne peux plus rien pour vous. Avant de terminer, comme jai peur que vous vous ennuyiez, je vous donne ci-dessous quelques ides de regex que vous pourriez rajouter au parser. Je vous lai dj dit plus haut, mais il serait trs apprciable que les URL cliquables fonctionnent aussi pour des URL avec des variables comme : http://www.siteduzero.com/index.php ?page=3&skin=blue. Vous devriez aussi parser les adresses e-mail en faisant un lien mailto: dessus ! Il serait bien de complter le bbCode avec [u], [img], etc. Mais puisquon y est, pourquoi refaire du bbCode ? Aprs tout, si vous tes allergiques aux crochets, que pour vous [b] ne veut rien dire, vous navez qu inventer le code : {gras} {/gras}. Et si faire des regex vous plat, je peux vous proposer un dernier d qui devrait vous occuper un petit moment : crire une fonction qui colore automatiquement le code HTML ! Vous donnez la fonction le code HTML, elle en fait un htmlspecialchars, puis elle rajoute des <span style="color:..."> pour colorer par exemple en bleu les noms des balises, en vert les attributs, en rouge ce qui est entre guillemets, etc. Bon courage !4

En rsum
Certains caractres sont spciaux au sein dune expression rgulire : on parle de mtacaractres. Si on souhaite les rechercher dans une chane, il faut les chapper en
4 Vous

en aurez besoin !

317

CHAPITRE 26. LES EXPRESSIONS RGULIRES (PARTIE 2/2) plaant un symbole antislash devant. Par exemple : \[. Il existe des classes abrges, cest--dire des classes toutes prtes, comme par exemple \d qui revient crire [0-9]. La fonction preg_replace permet deectuer des remplacements dans une chane de texte. Dans le cas dun remplacement, les parenthses au sein dune expression rgulire permettent de capturer une portion de texte pour la rutiliser dans une autre chane.

318

Chapitre

27
Dicult :

La programmation oriente objet

l est possible de programmer en PHP de nombreuses faons direntes. Cest ce qui fait sa force : on peut en eet commencer crer ses premires pages basiques en PHP avec trs peu de connaissances au dpart, mais il est aussi possible de programmer avec des outils avancs, plus complexes mais aussi plus solides et plus exibles. La programmation oriente objet est une technique de programmation clbre qui existe depuis des annes maintenant. PHP ne la pas invente : dautres langages comme le C++, Java et Python lutilisaient bien avant lui. La programmation oriente objet, que nous abrgerons POO, nest pas le Saint Graal : elle ne va pas amliorer subitement la qualit de votre site comme par magie. En revanche, elle va vous aider mieux organiser votre code, le prparer de futures volutions et rendre certaines portions rutilisables pour gagner en temps et en clart. Cest pour cela que les dveloppeurs professionnels lutilisent dans la plupart de leurs projets.

319

CHAPITRE 27. LA PROGRAMMATION ORIENTE OBJET

Quest-ce quun objet ?


Je lai dit et je le rpte : la programmation oriente objet ne va pas instantanment rvolutionner votre site web, contrairement ce que beaucoup semblent penser. En fait, il est mme probable que cela vous semble un peu inutile au dbut et que vous vous disiez O.K., mais je nen vois pas lintrt, a marchait aussi bien avant . Certaines choses vous paratront aussi un peu abstraites, vous ne verrez peut-tre pas bien comment mettre tout cela en pratique sur votre site. Cest parfaitement normal ; lorsquon apprend la programmation oriente objet, il y a un petit temps dadaptation pendant lequel on ne voit pas le rapport entre la thorie et la pratique. Prenez quand mme le temps de tout lire et de faire leort de comprendre ce qui est expliqu. Petit petit, en pratiquant, vous dcouvrirez que cela vous permet de mieux matriser votre code PHP au fur et mesure quil grossit, et vous verrez par la suite tout lintrt de ce que vous aurez appris. ;-)

Ils sont beaux, ils sont frais mes objets


Nous allons commencer par dnir ce quon appelle un objet en programmation. Alors, de quoi sagit-il ? Encore un concept mystique ? Un dlire de programmeurs aprs une soire trop arrose ? Non parce que franchement, un objet, cest quoi ? Mon cran est un objet, ma voiture est un objet, mon tlphone portable. . . ce sont tous des objets ! Bien vu, cest un premier point. En eet, nous sommes entours dobjets. En fait, tout ce que nous connaissons (ou presque) peut tre considr comme un objet. Lide de la programmation oriente objet, cest de manipuler dans son code source des lments que lon appelle des objets . Mais concrtement, cest quoi ? Une variable ? Une fonction ?

Ni lun, ni lautre. Cest un nouvel lment en programmation. Pour tre plus prcis, un objet cest. . . un mlange de plusieurs variables et fonctions. Allez ne faites pas cette tte-l, vous allez dcouvrir tout cela par la suite.

Imaginez. . . un objet
Pour viter que ce que je vous raconte ressemble un trait dart moderne conceptuel, on va imaginer ensemble ce quest un objet laide de plusieurs schmas concrets1 .
1 Les schmas 3D que vous allez voir par la suite ont t raliss pour moi par Nab, que je remercie dailleurs vivement au passage.

320

QUEST-CE QUUN OBJET ? Imaginez quun programmeur dcide un jour de crer une section de son site web qui permette dajouter des membres, de les placer dans des groupes (administrateurs, modrateurs. . .), de les bannir, de les supprimer. . . Le code est complexe : il a besoin de crer plusieurs fonctions qui sappellent entre elles, des variables pour mmoriser le nom du membre, sa date dinscription, son groupe, etc. Il met du temps crire ce code : cest un peu compliqu, mais il y arrive. Au nal, le code quil a crit est compos de plusieurs fonctions et variables. Quand on regarde a pour la premire fois, a ressemble une exprience de savant fou laquelle on ne comprend rien (gure 27.1).

Fig. 27.1 Notre code ressemble une exprience de savant fou incomprhensible Ce programmeur est content de son code et veut le distribuer sur Internet pour que tout le monde puisse crer sa section membres sur son site sans avoir tout recoder. Seulement voil : moins dtre un expert en chimie certi, vous allez mettre pas mal de temps avant de comprendre comment tout ce bazar fonctionne. Quelle fonction appeler en premier ? Quelles valeurs envoyer quelle fonction pour crer le membre ? Cest l que notre ami programmeur pense nous. Il conoit son code de manire oriente objet. Cela signie quil place tout son bazar chimique lintrieur dun simple cube. Ce cube est ce quon appelle un objet, comme sur la gure 27.2. Ici, une partie du cube a t volontairement mise en transparence pour vous montrer que nos oles chimiques sont bien situes lintrieur du cube. Mais en ralit, le cube est compltement opaque, on ne voit rien de ce quil y a lintrieur (gure 27.3). Ce cube contient toutes les fonctions et les variables (nos oles de chimie), mais il les masque lutilisateur. Au lieu davoir des tonnes de tubes et de oles chimiques dont il faut comprendre le fonctionnement, on nous propose juste quelques boutons sur la face avant du cube : un 321

CHAPITRE 27. LA PROGRAMMATION ORIENTE OBJET

Fig. 27.2 Le code est plac dans une bote qui en simplie laccs

Fig. 27.3 Le programmeur ne voit pas lintrieur (la partie complique)

322

QUEST-CE QUUN OBJET ? bouton crer un membre , un bouton bannir , etc. Lutilisateur na plus qu se servir des boutons du cube et na plus besoin de se soucier de tout ce qui se passe lintrieur. Pour lutilisateur, cest donc compltement simpli. En clair : programmer de manire oriente objet, cest crer du code source (peut-tre complexe), mais que lon masque en le plaant lintrieur dun cube (un objet) travers lequel on ne voit rien. Pour le programmeur qui va lutiliser, travailler avec un objet est donc beaucoup plus simple quavant : il a juste appuyer sur des boutons et na pas besoin dtre diplm en chimie pour sen servir. Bien sr, cest une image, mais cest ce quil faut comprendre et retenir pour le moment.

Vous avez dj utilis des objets !


Eh oui ! Vous vous souvenez de PDO ? Ne me dites pas que vous avez dj oubli. PDO est une extension de PHP et elle est code en orient objet. Cest ce qui explique que son mode demploi tait lgrement dirent des fonctions auxquelles nous tions habitus. Je vous avais promis de vous expliquer plus en dtail comment fonctionnait PDO, cest maintenant loccasion idale ! Souvenez-vous de cette ligne qui nous permettait de nous connecter la base de donnes :
<?php $bdd = new PDO(mysql:host=localhost;dbname=test, root, ); ?>

En fait, $bdd nest pas une variable mais un objet. On cre un objet laide de la commande new suivie du nom de la classe. Classe ? Objet ? Quelle est la dirence ?

La classe est un plan, une description de lobjet. Imaginez quil sagit par exemple des plans de construction dune maison. Lobjet est une instance de la classe, cest--dire une application concrte du plan. Pour reprendre lexemple prcdent, lobjet est la maison. On peut crer plusieurs maisons bases sur un plan de construction. On peut donc crer plusieurs objets partir dune classe. La gure 27.4 schmatise ce que je viens dexposer. Par consquent, si lon reprend le code prcdent, vous aurez devin que : $bdd est lobjet ; PDO est le nom de la classe sur laquelle est bas lobjet. Un objet est, je vous le disais plus tt, un mlange de fonctions et de variables. Lorsquon lutilise, on fait appel ses fonctions : 323

CHAPITRE 27. LA PROGRAMMATION ORIENTE OBJET

Fig. 27.4 Classes et objets


<?php $bdd->query(); $bdd->prepare(); $bdd->execute(); ?>

Cela signie : excuter la fonction query() de mon objet $bdd, puis la fonction prepare(), puis la fonction execute(), etc. La che -> est propre aux objets. Il faut donc comprendre que lon excute la fonction query() de lobjet $bdd qui reprsente la connexion la base de donnes. Autre exemple, imaginaire cette fois, pour tre sr que vous compreniez bien :
<?php $maison1 = new Maison(); $maison2 = new Maison(); $maison1->nettoyer(); ?>

Ici, nous avons plusieurs objets reprsentant des maisons ($maison1 et $maison2), mais nous nappelons que la fonction nettoyer() de la maison 1 : cest donc la seule qui sera propre. Un des avantages de la programmation oriente objet, comme vous le voyez, cest sa lisibilit. Ce code est facile lire et comprendre. 324

CRER UNE CLASSE Nous allons maintenant apprendre dans la suite de ce chapitre crer nos propres classes.

Crer une classe


Pour nos exemples, nous allons imaginer que nous crons une classe Membre qui reprsente un membre de notre site. Nous pourrons charger ce membre partir des informations enregistres en base de donnes, lui demander son pseudonyme, sa date dinscription, mais aussi le bannir, le dconnecter du site, etc. Le code dune classe tant en gnral assez long, il est recommand de crer un chier PHP qui contiendra uniquement la dnition de la classe et que lon inclura chaque fois quon en a besoin. Je vous recommande de crer un chier nomm Membre.class.php. Les dveloppeurs PHP ont lhabitude de donner lextension .class.php leurs chiers contenant des classes pour bien les distinguer. Quelques rgles ce sujet : ne dnissez quune classe par chier et donnez au chier le mme nom que votre classe. Le nom de votre classe devrait par ailleurs commencer par une majuscule. Dans ce chier Membre.class.php, commencez par inscrire le code suivant :
<?php class Membre { } ?>

tant donn que notre chier ne contiendra que du code PHP, il est possible (et mme recommand par des dveloppeurs expriments !) de retirer la balise de fermeture ?> la n du chier. Cela peut paratre surprenant, mais cest en fait un moyen ecace dviter dinsrer des lignes blanches la n du code PHP, ce qui a tendance produire des bogues du type Headers already sent by . lintrieur des accolades, nous allons dnir des variables et des fonctions membres de la classe. Un point de vocabulaire ce sujet : certains dveloppeurs utilisent dautres mots pour dsigner les variables et fonctions membres des classes. Les voici : variables membres : aussi appeles attributs ou proprits ; fonctions membres : aussi appeles mthodes. Essayons maintenant de dnir ensemble quelques variables et fonctions dans la classe Membre. 325

CHAPITRE 27. LA PROGRAMMATION ORIENTE OBJET

Les variables membres


Les variables permettent de dnir lobjet : cest ce qui fait quil sera unique. Alors, quest-ce qui reprsente un membre ? Essayons de dnir quelques-unes de ses proprits2 . Un membre a : un pseudonyme ; une adresse e-mail ; une signature ; un statut (actif ou non, selon que son compte a t valid ou banni).

Nous allons stocker toutes ces informations dans des variables sous forme de texte. Compltez votre classe en rajoutant ces variables :
<?php class Membre { private $pseudo; private $email; private $signature; private $actif; } ?>

Nous indiquons que notre classe Membre est compose de quatre variables : $pseudo, $email, $signature et $actif. Pour linstant, elles ne possdent aucune valeur. Pour le moment, ne vous proccupez pas du mot-cl private devant ces noms de variables, je vous expliquerai un peu plus loin ce que cela signie. ;-)

Les fonctions membres


Maintenant que nous avons dni les variables, nous pouvons crer quelques fonctions. Leur rle sera : soit de lire ou mettre jour les variables. On parle de fonctions getters et setters ; soit dexcuter des actions plus complexes sur le membre (comme lui envoyer un e-mail).

Les getters et setters Ce sont des fonctions qui commencent par get (si lon veut rcuprer le contenu dune variable) ou par set (si lon veut modier le contenu dune variable). Prenons par exemple le pseudonyme : on va crer une fonction getPseudo qui renvoie le pseudo et setPseudo qui modie ce dernier.
2 Si

on en oublie ce nest pas grave, on pourra toujours en rajouter par la suite.

326

CRER UNE CLASSE


<?php class Membre { private $pseudo; private $email; private $signature; private $actif; public function getPseudo() { return $this->pseudo; } public function setPseudo($nouveauPseudo) { $this->pseudo = $nouveauPseudo; }

Nous avons donc deux fonctions qui permettent de manipuler le pseudonyme du visiteur. Comme vous le voyez, elles sont vraiment trs simples. Ainsi, getPseudo renvoie le pseudo :
<?php public function getPseudo() { return $this->pseudo; } ?>

La variable $pseudo est accessible dans les fonctions avec le prxe $this->. Cela signie : Le pseudo de cet objet . En eet, souvenez-vous, on peut crer plusieurs objets partir dune classe. Il peut y avoir plusieurs membres et chacun deux a un pseudo dirent. Le prxe $this-> permet dindiquer que cest bien le pseudonyme du membre sur lequel on travaille que lon veut rcuprer. On fait de mme avec une fonction setPseudo qui prend en paramtre le nouveau pseudo du membre et qui le place dans $this->pseudo. Ces fonctions sont trs simples et un peu inutiles, non ?

En fait, les getters et setters sont souvent des fonctions simples, mais lintrt est quon peut faire des calculs et des vrications sur les donnes. Par exemple, on pourrait amliorer la fonction setPseudo comme ceci :
<?php public function setPseudo($nouveauPseudo)

327

CHAPITRE 27. LA PROGRAMMATION ORIENTE OBJET


{

} ?>

// Vrifier si le nouveau pseudo nest ni vide ni trop long if (!empty($nouveauPseudo) AND strlen($nouveauPseudo) < 15) { // Ok, on change son pseudo $this->pseudo = $nouveauPseudo; }

Ainsi, on autorise le changement de pseudonyme uniquement sil correspond certains critres : pseudo non vide et longueur infrieure quinze caractres. On pourrait proter de cette fonction pour vrier aussi la prsence de caractres non autoriss. Lintrt de passer par une fonction pour modier les variables est donc de pouvoir contrler que lon ninsre pas nimporte quoi. Pour ladresse e-mail, on pourrait ainsi vrier que celle-ci a la forme dune vritable adresse e-mail3 . Les autres fonctions Bien entendu, nous pouvons introduire nimporte quel autre type de fonction dans la classe Membre et pas seulement des fonctions qui se contentent de modier les variables. nous de dcider quelles actions on veut pouvoir eectuer sur le membre : le bannir, lui envoyer un e-mail. . .
<?php class Membre { public function envoyerEMail($titre, $message) { mail($this->email, $titre, $message); } public function bannir() { $this->actif = false; $this->envoyerEMail(Vous avez t banni, Ne revenez plus !); } } ?> ...

La fonction envoyerEMail est toute simple : elle utilise la fonction mail() de PHP qui permet denvoyer un e-mail, et se base sur ladresse e-mail stocke dans lobjet ($this->email).
3 On

pourrait utiliser une expression rgulire !

328

CRER UN OBJET PARTIR DE LA CLASSE Dautre part, la fonction bannir() change le statut actif du membre pour indiquer quil nest plus actif et lui envoie un e-mail pour lavertir de son bannissement. On en prote pour rutiliser la fonction envoyerEMail() de notre classe. Vous remarquerez quon doit placer l aussi le prxe $this-> devant le nom dune fonction de la classe quon appelle. Cest dans lesprit de la programmation oriente objet : on rutilise du code dj crit pour viter de rinventer la roue chaque fois.

Crer un objet partir de la classe


Actuellement, vous devriez avoir un chier Membre.class.php qui contient la dnition de la classe, cest--dire les plans de construction de vos futurs objets :
<?php class Membre { private $pseudo; private $email; private $signature; private $actif; public function envoyerEMail($titre, $message) { mail($this->email, $titre, $message); } public function bannir() { $this->actif = false; $this->envoyerEMail(Vous avez t banni, Ne revenez plus !); } public function getPseudo() { return $this->pseudo; } public function setPseudo($nouveauPseudo) { if (!empty($nouveauPseudo) AND strlen($nouveauPseudo) < 15) { $this->pseudo = $nouveauPseudo; } }

} ?>

329

CHAPITRE 27. LA PROGRAMMATION ORIENTE OBJET Code web : 566172 Maintenant que la classe est prte (mme si on peut encore lamliorer), on peut commencer lutiliser et donc crer des objets. Crez un nouveau chier (que vous appellerez comme vous voulez, par exemple index.php), dans lequel vous allez crer et utiliser un objet de type Membre.
<?php include_once(Membre.class.php); $membre = new Membre(); $membre->setPseudo(M@teo21); echo $membre->getPseudo() . , je vais te bannir !; $membre->bannir(); ?>

On commence par inclure la dnition de la classe Membre qui est situe dans le chier Membre.class.php. On utilise la fonction include_once() qui nous assure que le chier na pas dj t inclus ailleurs dans la page, ce qui aurait provoqu une erreur car il est interdit de dnir deux fois une mme classe. On cre ensuite un nouvel objet de type Membre avec la ligne :
<?php $membre = new Membre(); ?>

Nous avons maintenant un objet $membre qui reprsente un membre vide. On lui dnit ensuite un pseudo, on lache, puis pour samuser on le bannit. ;-) Ne confondez pas la classe et lobjet. La classe commence avec un M majuscule, tandis que lobjet avec un m minuscule. Nous aurions dailleurs pu donner nimporte quel nom notre objet ($mateo, $nouveauVenu. . .), mais faute de trouver un meilleur nom jai utilis le mme que celui de la classe, avec la premire lettre en minuscule pour les direncier. Vous avez donc l un exemple concret dutilisation de la classe. Bien que celle-ci soit basique, vous pourriez dj donner ce chier Membre.class.php des amis programmeurs, accompagn de prfrence dune petite documentation qui explique comment lutiliser, et vos amis pourront comme vous crer et manipuler les donnes des membres. Une classe, cest donc un peu un package prt lemploi. Elle contient son lot de variables et de fonctions. Pour lutiliser, nous faisons tout simplement appel ses fonctions sans nous soucier de ce quelles font lintrieur. Cela rejoint donc les schmas que je vous avais prsents au dbut de ce chapitre (page 322). Les variables et le code des fonctions nintressent pas le programmeur qui utilise la classe. Il se contente simplement dappuyer sur des boutons, cest--dire dappeler les 330

CONSTRUCTEUR, DESTRUCTEUR ET AUTRES FONCTIONS SPCIALES fonctions dont il a besoin pour manipuler les donnes de son membre : Donne-lui le pseudo M@teo21 , Bannis-le , etc.

Constructeur, destructeur et autres fonctions spciales


En plus des fonctions que nous avons cres dans notre classe Membre, il existe un certain nombre de fonctions spciales quil vous faut connatre. On les appelle fonctions magiques ou encore mthodes magiques. On les reconnat facilement car leur nom commence par deux underscores (tiret bas, sous le chire 8 dun clavier AZERTY franais). Par exemple : __construct, __destruct, __get, etc. Ici, nous allons nous intresser plus particulirement aux deux plus importantes dentre elles : le constructeur et le destructeur.

Le constructeur : __construct
Lorsque vous crez un objet, comme nous lavons fait prcdemment, celui-ci est vide au dpart. Ses variables membres ne contiennent rien. Ainsi notre membre navait pas de pseudo, pas dadresse e-mail, rien.
<?php $membre = new Membre(); // Le membre est vide ?>

Or, quand vous crez un objet comme cela avec new, il faut savoir que PHP recherche lintrieur de la classe une fonction nomme __construct. Jusquici nous nen avions pas cr : donc faute den trouver, PHP crait un objet vide. Le rle dune fonction constructeur est justement de construire lobjet (non, sans blague !), cest--dire de le prparer une premire utilisation. Dans notre cas, on aimerait par exemple charger en base de donnes les informations concernant le membre et insrer les bonnes valeurs dans les variables ds le dpart.
<?php class Membre { public function __construct($idMembre) { // Rcuprer en base de donnes les infos du membre // SELECT pseudo, email, signature, actif FROM membres WHERE id = ... // Dfinir les variables avec les rsultats de la base $this->pseudo = $donnees[pseudo]; $this->email = $donnees[email]; // etc.

331

CHAPITRE 27. LA PROGRAMMATION ORIENTE OBJET


} ?> ...

Notre fonction constructeur prend un paramtre : lid du membre. partir de l, on peut charger en base de donnes les informations concernant le membre et les insrer dans lobjet : $this->pseudo, $this->email. . . Comme notre constructeur prend un paramtre, il faudra dsormais crer nos objets en envoyant un id :
<?php $membre = new Membre(32); // Le membre n 32 est charg ! ?>

Notre membre no 32 est maintenant prt ! Il contient dj le bon pseudonyme, la bonne adresse e-mail, etc. vous de faire en sorte ensuite, lorsquon modie par exemple son pseudo, que ce changement soit bien rpercut en base de donnes.

Le destructeur : __destruct
Moins couramment utilis, le destructeur peut nanmoins se rvler utile. Cette fonction est appele automatiquement par PHP lorsque lobjet est dtruit. Mais quand lobjet est-il dtruit ?

Pour dtruire un objet, ou toute autre variable, on peut le faire la main avec la fonction unset() :
<?php unset($membre); ?>

Si vous ne le faites pas, lobjet sera dtruit la n de lenvironnement dans lequel il a t cr. Si lobjet a t cr dans la page (comme ctait le cas dans index.php), il sera supprim la n de lexcution de la page. Cest alors que le destructeur est appel. Son rle est de raliser toutes les oprations ncessaires pour mettre n la vie de lobjet. La classe PDO, par exemple, a besoin dutiliser le destructeur pour fermer la connexion la base de donnes. Elle envoie alors un signal la base de donnes : Fin de la connexion . Dans le cas de notre classe Membre, il ny aurait rien de spcial faire a priori. Nanmoins, pour tester le fonctionnement du destructeur, vous pouvez en crer un qui ache un message signalant que lobjet va tre dtruit : 332

LHRITAGE
<?php public function __destruct() { echo Cet objet va tre dtruit !; } ?>

Vous verrez que ce message apparat la n de la page dans notre cas. Si vous avez cr plusieurs objets, vous verrez autant de messages quil y a dobjets, car chacun deux va tre dtruit !

Les autres fonctions magiques


Il existe de nombreuses autres fonctions magiques dont lutilit est cependant moins importante : __get(), __set(), __call(), __sleep(), __wakeup(). . . Elles permettent de contrler certaines autres tapes de la vie de votre objet. Nous ne les dtaillerons pas ici mais si vous voulez en savoir plus sur elles, vous pouvez lire la page de la documentation qui prsente les fonctions magiques. Code web : 135355

Lhritage
Lhritage est probablement le concept le plus important de la programmation oriente objet. Cest ce qui lui donne toute sa puissance. Cela permet de rutiliser des classes pour en construire de nouvelles. On se sert de certaines classes de base pour construire des classes plus compltes.

Comment reconnatre un hritage ?


Cest LA question se poser. Certains ont tellement t traumatiss par lhritage en cours de programmation quils en voient partout, dautres au contraire (surtout les dbutants) se demandent chaque fois sil y a un hritage faire ou non. Pourtant, ce nest pas mystique , il est trs facile de savoir sil y a une relation dhritage entre deux classes. Comment ? En suivant cette rgle trs simple : Il y a hritage quand on peut dire : A est un B . Pas de panique, ce ne sont pas des maths. ;-) Prenez un exemple trs simple. On peut dire Un administrateur est un membre , ou encore Un modrateur est un membre . Donc on peut faire un hritage : La classe Admin hrite de Membre , La classe Moderateur hrite de Membre . Pour vous imprgner, voici quelques autres bons exemples o un hritage peut tre fait : 333

CHAPITRE 27. LA PROGRAMMATION ORIENTE OBJET une voiture est un vhicule (Voiture hrite de Vehicule) ; un bus est un vhicule (Bus hrite de Vehicule) ; un moineau est un oiseau (Moineau hrite dOiseau) ; un corbeau est un oiseau (Corbeau hrite dOiseau) ; un chirurgien est un docteur (Chirurgien hrite de Docteur ) ; un diplodocus est un dinosaure (Diplodocus hrite de Dinosaure) ; etc.

En revanche, vous ne pouvez pas dire Un dinosaure est un diplodocus , ou encore Un bus est un oiseau . Donc on ne peut pas faire dhritage dans ces cas-l, du moins a naurait aucun sens. ;-)

Raliser un hritage en PHP


Nous allons crer une nouvelle classe Admin qui sera base sur la classe Membre. Elle aura toutes les variables et fonctions de la classe Membre, mais elle aura en plus de nouvelles variables et fonctions. Crez un chier Admin.class.php4 et insrez-y le code suivant pour commencer :
<?php include_once(Membre.class.php); class Admin extends Membre { } ?>

Le nouveau mot-cl ici est extends, qui signie tend . Traduction : la classe Admin tend [les possibilits de] la classe Membre. Cest cela lhritage : nous avons maintenant une classe Admin qui possde toutes les variables et fonctions de Membre, et nous allons pouvoir en dnir de nouvelles qui seront propres aux admins. Pour que PHP connaisse la classe Membre an de permettre lhritage, il est impratif dinclure le chier Membre.class.php au pralable. Rajoutons maintenant des fonctionnalits qui seront propres aux admins. Par exemple, ceux-ci, grce leurs privilges, peuvent choisir la couleur dans laquelle sera crit leur pseudonyme. Ils ont donc une variable $couleur et des fonctions qui permettent de la lire et de la modier :
<?php include_once(Membre.class.php);
4 Souvenez-vous,

on fait un chier par classe !

334

LHRITAGE
class Admin extends Membre { private $couleur; public function setCouleur() { // ... } public function getCouleur() { // ... }

} ?>

Nous avons donc maintenant deux classes : Membre et Admin. Avec Membre, on peut manipuler un pseudo, une adresse e-mail, une signature et un tat actif ou non. Avec Admin, on peut manipuler les mmes choses : un pseudo, une adresse e-mail, une signature et un tat actif ou non. . . mais aussi de nouvelles proprits, comme la couleur du pseudo. Un peu de vocabulaire : on dit que Membre est la classe mre, tandis que Admin est la classe lle. Cest la lle qui hrite de la mre, imparable logique de programmeur. Dans notre chier index.php on peut maintenant crer des membres mais aussi des admins :
<?php $membre = new Membre(31); // Contient un pseudo, une adresse e-mail... $maitreDesLieux = new Admin(2); // Contient les mmes donnes quun membre + la couleur $membre->setPseudo(Arckintox); // OK $maitreDesLieux->setPseudo(M@teo21); // OK $membre->setCouleur(Rouge); // Impossible (un membre na pas de couleur) $maitreDesLieux->setCouleur(Rouge); // OK ?>

Avec peu deorts, nous avons cr une nouvelle classe qui rutilise une classe existante. On peut donc appeler la fonction setPseudo comme pour les membres, et on peut en plus eectuer de nouvelles oprations, comme dnir une couleur de pseudo. 335

CHAPITRE 27. LA PROGRAMMATION ORIENTE OBJET

Les droits daccs et lencapsulation


Pour terminer notre dcouverte de la programmation oriente objet, il me reste vous prsenter un concept trs important : lencapsulation. En eet, il y a beaucoup de rgles en POO et personne ne vous oblige les suivre ; elles paraissent parfois lourdes et un peu contraignantes, ce qui fait que certains nissent par mal programmer en POO. Pourtant, sil y a une rgle suivre en POO, cest bien lencapsulation. Cependant, avant de vous expliquer ce que cette rgle raconte, je dois vous prsenter le principe des droits daccs.

Les droits daccs


Vous vous souvenez de ces petits mots que nous avons utiliss devant nos noms de variables et fonctions dans ce chapitre ? Oui, je fais rfrence public et private. Ce sont ce quon appelle des droits daccs : cela permet dindiquer si lutilisateur de la classe a le droit daccder directement un lment de la classe ou non. Il y a trois droits daccs connatre : public : tout le monde peut accder llment ; private : personne ( part la classe elle-mme) na le droit daccder llment ; protected : identique private, sauf quun lment ayant ce droit daccs dans une classe mre sera accessible aussi dans les classes lles. Essayons de traduire tout a en mots franais, voulez-vous ? Reprenons une version simple de notre classe Membre :
<?php class Membre { private $pseudo; private $email; private $signature; private $actif; public function getPseudo() { } public function setPseudo($nouveauPseudo) { } ?> }

336

LES DROITS DACCS ET LENCAPSULATION Ici, vous voyez que les fonctions sont publiques et les variables sont prives. Rien ne nous empche cependant de faire linverse, mme si ce nest vraiment pas conseill pour les variables, comme nous allons le voir. Quest-ce que cela signie, concrtement ? Que la personne qui utilise la classe travers des objets (dans index.php par exemple) peut uniquement accder ce qui est public et non ce qui est priv :
<?php $membre = new Membre(4); $membre->setPseudo(M@teo21); // OK car setPseudo est public $membre->pseudo = M@teo21; // Interdit car $pseudo est private ?>

Cest donc vous qui dnissez avec ces public, private ou protected si lutilisateur a le droit ou non dappeler la fonction ou la variable. Et protected justement, a correspond quoi ?

Cest identique private mais il y a une dirence lorsquon hrite de la classe. Par exemple, si on dnit la variable $email comme protected dans la classe Membre, cela signie que les classes qui en hritent (comme Admin) auront le droit dy accder. Sinon, en private, elles nauraient pas pu les appeler directement.

Lencapsulation
Pourquoi est-ce quon sembte avec a ? Et si on mettait tout en public ? On se prendrait moins la tte, non ? Si tout tait public, mme les variables membres, nimporte qui pourrait faire :
<?php $membre = new Membre(4); $membre->email = Portnawak; ?>

Or, Portnawak nest pas une vritable adresse e-mail, je pense que vous serez daccord avec moi. Pour viter quon puisse faire nimporte quoi avec ses objets, on a invent une rgle trs simple qui sappelle la rgle dencapsulation. On peut la rsumer comme ceci : Toutes les variables dune classe doivent toujours tre prives ou protges. 337

CHAPITRE 27. LA PROGRAMMATION ORIENTE OBJET Voil pourquoi on prend lhabitude de crer des fonctions get et set : cela nous permet de vrier quon ne fait pas nimporte quoi avec les variables, comme dnir une adresse e-mail invalide. Il arrive en revanche que lon dnisse des fonctions membres prives. Ce sont des fonctions internes la classe que lutilisateur na pas appeler directement. Il est en gnral recommand dutiliser plutt protected que private, surtout si vous pensez hriter de la classe. En eet, leur fonctionnement est le mme mais protected est plus souple si vous avez un jour des classes lles. Le but de lencapsulation est de masquer la personne qui utilise la classe son fonctionnement interne. Quand vous crez un objet, vous ne devez pas avoir vous soucier des variables quil contient, de la faon dont celles-ci sont agences, etc. Vous tes juste une personne qui appuie sur des boutons pour eectuer des actions sur lobjet5 . Vous devez donc passer par des fonctions pour modier vos objets. Pour forcer lutilisateur appuyer sur les boutons plutt que de toucher aux oles chimiques dangereuses quil ne comprend pas , on utilise les droits daccs. Ainsi, les fonctions sont pour la plupart publiques (sauf celles qui servent au fonctionnement interne de la classe) et les variables sont toujours prives ou protges pour que lutilisateur ne puisse pas mettre nimporte quoi lintrieur.

En rsum
La programmation oriente objet est une autre faon de concevoir son code. Elle permet de concevoir les lments de son site comme des objets qui lon donne des ordres et qui sont capables de modier leur tat. La classe est le modle partir duquel on peut crer plusieurs objets. Une classe est constitue de variables membres et de fonctions membres. Les fonctions modient ltat des variables membres. Le constructeur (nomm __construct()) est une fonction appele par PHP lorsquon cre un objet bas sur la classe. De mme pour __destruct(), appele lors de la suppression de lobjet. Une classe peut hriter dune autre classe pour rcuprer toutes ses proprits et rajouter de nouvelles fonctionnalits spciales. On oblige le programmeur qui utilise la classe passer par des fonctions pour modier lobjet. Cest le principe dencapsulation.

ce propos, revoyez mes schmas du dbut du chapitre.

338

Chapitre

28
Dicult :

Organiser son code selon larchitecture MVC

eaucoup de dbutants en PHP disent avoir des dicults organiser le code de leur site web. Ils savent crer des scripts, comme un mini-chat par exemple, mais ne se sentent pas capables de concevoir leur site web de manire globale. Quels dossiers dois-je crer ? , Comment dois-je organiser mes chiers ? , Ai-je besoin dun dossier admin ? , etc. Lobjectif de ce chapitre est de vous faire dcouvrir larchitecture MVC, une bonne pratique de programmation qui va vous aider bien concevoir votre futur site web. Aprs sa lecture, vous vous sentirez largement plus capables de crer un site web de qualit et facile maintenir. ;-)

339

CHAPITRE 28. ORGANISER SON CODE SELON LARCHITECTURE MVC

Quest-ce que larchitecture MVC ?


Vous vous posez certainement beaucoup de questions sur la bonne faon de concevoir votre site web. Laissez-moi vous rassurer ce sujet : ces questions, nous nous les sommes tous poses un jour. En fait, il y a des problmes en programmation qui reviennent tellement souvent quon a cr toute une srie de bonnes pratiques que lon a runies sous le nom de design patterns. Un des plus clbres design patterns sappelle MVC, qui signie Modle - Vue Contrleur. Cest celui que nous allons dcouvrir dans ce chapitre. Le pattern MVC permet de bien organiser son code source. Il va vous aider savoir quels chiers crer, mais surtout dnir leur rle. Le but de MVC est justement de sparer la logique du code en trois parties que lon retrouve dans des chiers distincts, comme lexplique la description qui suit. Modle : cette partie gre les donnes de votre site. Son rle est daller rcuprer les informations brutes dans la base de donnes, de les organiser et de les assembler pour quelles puissent ensuite tre traites par le contrleur. On y trouve donc les requtes SQL1 . Vue : cette partie se concentre sur lachage. Elle ne fait presque aucun calcul et se contente de rcuprer des variables pour savoir ce quelle doit acher. On y trouve essentiellement du code HTML mais aussi quelques boucles et conditions PHP trs simples, pour acher par exemple la liste des messages des forums. Contrleur : cette partie gre la logique du code qui prend des dcisions. Cest en quelque sorte lintermdiaire entre le modle et la vue : le contrleur va demander au modle les donnes, les analyser, prendre des dcisions et renvoyer le texte acher la vue. Le contrleur contient exclusivement du PHP. Cest notamment lui qui dtermine si le visiteur a le droit de voir la page ou non (gestion des droits daccs). La gure 28.1 schmatise le rle de chacun de ces lments.

Fig. 28.1 Larchitecture MVC Il est important de bien comprendre comment ces lments sagencent et communiquent entre eux. Regardez bien la gure 28.2. Il faut tout dabord retenir que le contrleur est le chef dorchestre : cest lui qui reoit la requte du visiteur et qui contacte dautres chiers (le modle et la vue) pour changer
1 Parfois, les donnes ne sont pas stockes dans une base de donnes. Cest plus rare, mais on peut tre amen aller chercher des donnes dans des chiers. Dans ce cas, le rle du modle est de faire les oprations douverture, de lecture et dcriture de chiers (fonctions fopen, fgets, etc.).

340

QUEST-CE QUE LARCHITECTURE MVC ?

Fig. 28.2 change dinformations entre les lments

des informations avec eux. Le chier du contrleur demande les donnes au modle sans se soucier de la faon dont celui-ci va les rcuprer. Par exemple : Donne-moi la liste des 30 derniers messages du forum no 5 . Le modle traduit cette demande en une requte SQL, rcupre les informations et les renvoie au contrleur. Une fois les donnes rcupres, le contrleur les transmet la vue qui se chargera dacher la liste des messages. Le contrleur sert seulement faire la jonction entre le modle et la vue nalement, non ? Dans les cas les plus simples, ce sera probablement le cas. Mais comme je vous le disais, le rle du contrleur ne se limite pas cela : sil y a des calculs ou des vrications dautorisations faire, des images miniaturiser, cest lui qui sen chargera. Concrtement, le visiteur demandera la page au contrleur et cest la vue qui lui sera retourne, comme schmatis sur la gure 28.3. Bien entendu, tout cela est transparent pour lui, il ne voit pas tout ce qui se passe sur le serveur. Cest un schma plus complexe que ce quoi vous avez t habitus, bien videmment : cest pourtant sur ce type darchitecture que repose un trs grand nombre de sites professionnels ! Tout ce que je vous prsente l doit vous paratre bien beau, mais encore trs ou. Je vais vous montrer dans la pratique comment on peut respecter ce principe en PHP. 341

CHAPITRE 28. ORGANISER SON CODE SELON LARCHITECTURE MVC

Fig. 28.3 La requte du client arrive au contrleur et celui-ci lui retourne la vue

Le code du TP blog et ses dfauts


Nous allons reprendre le TP blog sur lequel nous avons travaill un peu plus tt dans le cours2 . Nous allons nous intresser au code de la page qui ache les derniers billets du blog. Voici ce que nous avions produit la n de ce TP :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr"> <head> <title>Mon blog</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <link href="style.css" rel="stylesheet" type="text/css" /> </head> <body> <h1>Mon super blog !</h1> <p>Derniers billets du blog :</p> <?php // Connexion la base de donnes try { $bdd = new PDO(mysql:host=localhost;dbname=test, root, ); } catch(Exception $e) {
2 Si

vous avez un trou de mmoire, nhsitez pas parcourir de nouveau le TP page 243.

342

LE CODE DU TP BLOG ET SES DFAUTS


die(Erreur : .$e->getMessage());

// On rcupre les 5 derniers billets $req = $bdd->query(SELECT id, titre, contenu, DATE_FORMAT(date_creation, \%d/%m/%Y %Hh%imin%ss\) AS date_creation_fr FROM billets ORDER BY date_creation DESC LIMIT 0, 5); while ($donnees = $req->fetch()) { ?> <div class="news"> <h3> <?php echo htmlspecialchars($donnees[titre]); ?> <em>le <?php echo $donnees[date_creation_fr]; ?></em> </h3> <p> <?php // On affiche le contenu du billet echo nl2br(htmlspecialchars($donnees[contenu])); ?> <br /> <em><a href="commentaires.php?billet=<?php echo $donnees[id]; ?>"> Commentaires</a></em> </p> </div> <?php } // Fin de la boucle des billets $req->closeCursor(); ?> </body> </html>

Et alors ? Ce code marche bien, non ? On repre les requtes SQL, le HTML, etc. Moi je le comprends bien en tout cas, je ne vois pas ce quil faut amliorer ! lpoque, nous avions crit le script PHP de faon intuitive sans trop nous soucier de son organisation. Rsultat : notre code tait un joyeux mlange dinstructions PHP, de requtes SQL et de HTML. Sur une page simple comme celle-l3 , cela ne posait pas trop de problmes car il ny avait pas beaucoup de lignes de code. En revanche, si vous ajoutez plus tard des fonctionnalits et des requtes SQL cette page. . . cela va vite devenir un vrai capharnam !
3 Oui, jappelle cela une page simple : il ny a quune requte et le code nest pas trs long. Mais attention : sur votre site web, vous aurez srement des pages bien plus complexes que a !

343

CHAPITRE 28. ORGANISER SON CODE SELON LARCHITECTURE MVC Si on prend la peine de construire cette page en respectant larchitecture MVC, cela va nous prendre un peu plus de temps : il y aura probablement trois chiers au lieu dun seul, mais au nal le code sera beaucoup plus clair et mieux dcoup. Lintrt de respecter larchitecture MVC ne se voit pas forcment de suite. En revanche, si vous amliorez votre site plus tard, vous serez bien heureux davoir pris la peine de vous organiser avant ! De plus, si vous travaillez plusieurs, cela vous permet de sparer les tches : une personne peut soccuper du contrleur, une autre de la vue et la dernire du modle. Si vous vous mettez daccord au pralable sur les noms des variables et fonctions appeler entre les chiers, vous pouvez travailler ensemble en parallle et avancer ainsi beaucoup plus vite !

Amlioration du TP blog en respectant larchitecture MVC


Je vais maintenant vous montrer comment on pourrait dcouper le code prcdent selon une architecture MVC4 . la racine de votre site, je vous propose de crer trois rpertoires : modele ; vue ; controleur. Dans chacun deux, vous pouvez crer un sous-rpertoire pour chaque module de votre site : forums, blog, minichat, etc. Pour le moment, crez un rpertoire blog dans chacun de ces dossiers. On aura ainsi larchitecture suivante : modele/blog : contient les chiers grant laccs la base de donnes du blog ; vue/blog : contient les chiers grant lachage du blog ; controleur/blog : contient les chiers contrlant le fonctionnement global du blog. On peut commencer par travailler sur llment que lon veut ; il ny a pas dordre particulier suivre5 . Je vous propose de commencer par le modle, puis de voir le contrleur et enn la vue.

Le modle
Crez un chier get_billets.php dans modele/blog. Ce chier contiendra une fonction dont le rle sera de retourner un certain nombre de billets depuis la base de
4 Je vais vous proposer une faon de faire, mais nallez pas croire que cest la seule mthode qui existe. On peut respecter larchitecture MVC de direntes manires ; tout dpend de la faon dont on linterprte. Dailleurs, la thorie pure de MVC est bien souvent inapplicable en pratique. Il faut faire des concessions, savoir tre pragmatique : on prend les bonnes ides et on met de ct celles qui se rvlent trop contraignantes. 5 Comme je vous le disais, on peut travailler trois en parallle sur chacun de ces lments.

344

AMLIORATION DU TP BLOG EN RESPECTANT LARCHITECTURE MVC donnes. Cest tout ce quelle fera.
<?php function get_billets($offset, $limit) { global $bdd; $offset = (int) $offset; $limit = (int) $limit; $req = $bdd->prepare(SELECT id, titre, contenu, DATE_FORMAT(date_creation, \%d/%m/%Y %Hh%imin%ss\) AS date_creation_fr FROM billets ORDER BY date_creation DESC LIMIT :offset, :limit); $req->bindParam(:offset, $offset, PDO::PARAM_INT); $req->bindParam(:limit, $limit, PDO::PARAM_INT); $req->execute(); $billets = $req->fetchAll(); return $billets;

Ce code source ne contient pas de relles nouveauts. Il sagit dune fonction qui prend en paramtre un oset et une limite. Elle retourne le nombre de billets demands partir du billet no oset. Ces paramtres sont transmis MySQL via une requte prpare6 . La connexion la base de donnes aura t faite prcdemment. On rcupre lobjet $bdd global7 reprsentant la connexion la base et on lutilise pour eectuer notre requte SQL. Cela nous vite davoir recrer une connexion la base de donnes dans chaque fonction, ce qui serait trs mauvais pour les performances du site (et trs laid dans le code !). Plutt que de faire une boucle de fetch(), jappelle ici la fonction fetchAll() qui assemble toutes les donnes dans un grand array. La fonction retourne donc un array contenant les billets demands. Vous noterez que ce chier PHP ne contient pas la balise de fermeture ?>. Celle-ci nest en eet pas obligatoire, comme je vous lai dit plus tt dans le cours. Je vous recommande de ne pas lcrire surtout dans le modle et le contrleur dune architecture MVC. Cela permet dviter de fcheux problmes lis lenvoi de HTML avant lutilisation de fonctions comme setCookie qui ncessitent dtre appeles avant tout code HTML.
6 Je nai pas utilis la mthode traditionnelle laquelle vous avez t habitus pour transmettre les paramtres la requte SQL. En eet, jai utilis ici la fonction bindParam qui me permet de prciser que le paramtre est un entier (PDO: :PARAM_INT). Cette mthode alternative est obligatoire dans le cas o les paramtres sont situs dans la clause LIMIT car il faut prciser quil sagit dentiers. 7 Il existe une meilleure mthode pour rcuprer lobjet $bdd et qui est base sur le design pattern singleton. Elle consiste crer une classe qui retourne toujours le mme objet. Nous ne dtaillerons pas cette mthode ici, sensiblement plus complexe, mais je vous invite vous renseigner sur le sujet.

345

CHAPITRE 28. ORGANISER SON CODE SELON LARCHITECTURE MVC

Le contrleur
Le contrleur est le chef dorchestre de notre application. Il demande au modle les donnes, les traite et appelle la vue qui utilisera ces donnes pour acher la page. Dans controleur/blog, crez un chier index.php qui reprsentera la page daccueil du blog.

<?php // On demande les 5 derniers billets (modle) include_once(modele/blog/get_billets.php); $billets = get_billets(0, 5); // On effectue du traitement sur les donnes (contrleur) // Ici, on doit surtout scuriser laffichage foreach($billets as $billet) { $billet[titre] = htmlspecialchars($billet[titre]); $billet[contenu] = nl2br(htmlspecialchars($billet[contenu])); } // On affiche la page (vue) include_once(vue/blog/index.php);

On retrouve le cheminement simple que je vous avais dcrit. Le rle de la page daccueil du blog est dacher les cinq derniers billets. On appelle donc la fonction get_billets() du modle, on rcupre la liste brute de ces billets que lon traite dans un foreach pour protger lachage avec htmlspecialchars() et crer les retours la ligne du contenu avec nl2br()89 . Ce qui est intressant, cest que la fonction get_billets() pourra tre rutilise dautres occasions. Ici, on lappelle toujours avec les mmes paramtres, mais on pourrait en avoir besoin dans dautres contrleurs. On pourrait aussi amliorer ce contrleur-ci pour grer la pagination des billets du blog et acher un nombre dirent de billets par page en fonction des prfrences du visiteur.

8 Sil y avait dautres oprations faire avant lappel de la vue, comme la gestion des droits daccs, ce serait le bon moment. En loccurrence, il nest pas ncessaire deectuer dautres oprations dans le cas prsent. 9 Notez que la prsence des fonctions de scurisation des donnes dans le contrleur est discutable. On pourrait laisser cette tche la vue, qui ferait donc les htmlspecialchars, ou bien une couche intermdiaire entre le contrleur et la vue (cest dailleurs ce que proposent certains frameworks dont on parlera plus loin). Comme vous le voyez, il ny a pas une seule bonne approche mais plusieurs, chacune ayant ses avantages et inconvnients.

346

AMLIORATION DU TP BLOG EN RESPECTANT LARCHITECTURE MVC

La vue
Il ne nous reste plus qu crer la vue correspondant la page daccueil des derniers billets du blog. Ce sera trs simple : le chier de la vue devra simplement acher le contenu de larray $billets sans se soucier de la scurit ou des requtes SQL. Tout aura t prpar avant. Vous pouvez crer un chier index.php dans vue/blog et y insrer le code suivant :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org /TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr"> <head> <title>Mon blog</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <link href="vue/blog/style.css" rel="stylesheet" type="text/css" /> </head> <body> <h1>Mon super blog !</h1> <p>Derniers billets du blog :</p> <?php foreach($billets as $billet) { ?> <div class="news"> <h3> <?php echo $billet[titre]; ?> <em>le <?php echo $billet[date_creation_fr]; ?></em> </h3> <p> <?php echo $billet[contenu]; ?> <br /> <em><a href="commentaires.php?billet=<?php echo $billet[id]; ?>"> Commentaires</a></em> </p> </div> <?php } ?> </body> </html>

Ce code source se passe rellement de commentaires. Il contient essentiellement du HTML et quelques morceaux de PHP pour acher le contenu des variables et eectuer la boucle ncessaire. Lintrt est que ce chier est dbarrass de toute logique du code : vous pouvez 347

CHAPITRE 28. ORGANISER SON CODE SELON LARCHITECTURE MVC aisment le donner un spcialiste de la mise en page web pour quil amliore la prsentation. Celui-ci naura pas besoin de connatre le PHP pour travailler sur la mise en page du blog10 .

Le contrleur global du blog


Bien quen thorie ce ne soit pas obligatoire, je vous recommande de crer un chier contrleur global par module la racine de votre site. Son rle sera essentiellement de traiter les paramtres $_GET et dappeler le contrleur correspondant en fonction de la page demande. On peut aussi proter de ce point central pour crer la connexion la base de donnes11 . Vous pouvez donc crer ce chier blog.php la racine de votre site :
<?php include_once(modele/connexion_sql.php); if (!isset($_GET[section]) OR $_GET[section] == index) { include_once(controleur/blog/index.php); }

Pour accder la page daccueil du blog, il sut maintenant douvrir la page blog.php ! Lavantage de cette page est aussi quelle permet de masquer larchitecture de votre site au visiteur. Sans elle, ce dernier aurait d aller sur la page controleur/blog/index.php pour acher votre blog. Cela aurait pu marcher, mais aurait probablement cr de la confusion chez vos visiteurs, en plus de complexier inutilement lURL.

Rsum des chiers crs


Je pense quun schma synthtisant larchitecture des chiers que nous venons de crer ne sera pas de refus ! La gure 28.4 devrait vous permettre de mieux vous reprer. Cela fait beaucoup de chiers alors quauparavant tout tenait dans un seul chier ! La construction de son site selon une architecture MVC est ce prix. Cela multiplie les chiers, mais clarie dans le mme temps leur rle. Si vous les regroupez intelligemment dans des dossiers, il ny aura pas de problme. ;-) Dsormais, si vous avez un problme de requte SQL, vous savez prcisment quel chier ouvrir : le modle correspondant. Si cest un problme dachage, vous ouvrirez
10 Il sut de lui expliquer le principe de la boucle et comment on ache une variable, cest vraiment peu de choses. 11 Jai ici choisi dinclure un chier connexion_sql.php qui cre lobjet $bdd. Ce chier pourra ainsi tre partag entre les dirents modules de mon site.

348

ALLER PLUS LOIN : LES FRAMEWORKS MVC

Fig. 28.4 Larchitecture des chiers crs pour adapter notre blog en MVC la vue. Tout cela rend votre site plus facile maintenir et faire voluer ! Je vous invite tlcharger les chiers dexemple de ce chapitre pour que vous puissiez vous familiariser avec larchitecture MVC. Code web : 509002 Protez-en pour amliorer le code ! Je vous proposais un peu plus tt de grer par exemple la pagination du blog sur la page daccueil. Vous pouvez aussi porter le reste des pages du blog selon cette mme architecture : ce sera le meilleur exercice pour vous former que vous trouverez !

Aller plus loin : les frameworks MVC


Lorganisation en chiers que je vous ai propose dans ce chapitre nest quune faon de faire parmi beaucoup dautres. Vous pouvez vous en inspirer comme dun modle pour crer votre site, mais rien ne vous y oblige. En fait, lidal serait de crer votre site en vous basant sur un framework PHP de qualit12 . Un framework est un ensemble de bibliothques, une sorte de kit prt lemploi pour crer plus rapidement son site web, tout en respectant des rgles de qualit. Vous vous souvenez de la bibliothque GD qui nous permettait de crer des images ? Les frameworks sont des assemblages de bibliothques comme celle-ci. Cest dire si ce sont des outils puissants et complets ! Voici quelques frameworks PHP clbres quil faut connatre : CodeIgniter ; CakePHP ; Symfony ; Jelix ;
12 Mais

cela vous demandera du temps, car il faut apprendre se servir du framework en question !

349

CHAPITRE 28. ORGANISER SON CODE SELON LARCHITECTURE MVC Zend Framework. Ils sont tous bass sur une architecture MVC et proposent en outre de nombreux outils pour faciliter le dveloppement de son site web. Il en existe dautres, mais ceux-l mritent dj le coup doeil. Parmi eux, Symfony et le Zend Framework sont probablement les plus clbres. Ils sont utiliss par de nombreux sites, petits commes grands13 . Ils ont prouv leur robustesse et leur srieux, ce qui en fait des outils de choix pour concevoir des sites de qualit professionnelle. Pour dbuter sur Symfony par exemple, le tutoriel Jobeet est un trs bon point de dpart que je vous invite consulter. Code web : 612487 Ce type de framework ncessite de bonnes connaissances en PHP et en programmation oriente objet. Si vous dbutez compltement, attendez davoir un peu plus dexprience avant de vous y mettre car il risque de vous paratre un peu complexe.

En rsum
MVC est un design pattern, une bonne pratique de programmation qui recommande de dcouper son code en trois parties qui grent les lments suivants : Modle : stockage des donnes ; Vue : achage de la page ; Contrleur : logique, calculs et dcisions. Utiliser larchitecture MVC sur son site web en PHP est recommand, car cela permet davoir un code plus facile maintenir et faire voluer. De nombreux frameworks PHP, tels que Symfony et le Zend Framework, vous permettent de mettre rapidement en place les bases dune architecture MVC sur votre site. Ce sont des outils apprcis des professionnels qui ncessitent cependant un certain temps dadaptation.

13 Prenez le site de partage de vidos Dailymotion : il utilise Symfony depuis quelque temps. Plus rcemment, le Site du Zro a lui aussi commenc migrer vers Symfony.

350

Chapitre

29
Dicult :

TP : crer un espace membres

n de crer un espace communautaire sur leur site web, la plupart des webmasters ont recours un systme de gestion des membres. Cela leur permet de dliser leurs visiteurs, qui peuvent alors participer plus facilement la vie du site.

Cela vous intresse ? Construire son espace membres ne simprovise pas, il y a un certain nombre dlments connatre. Nous allons dcouvrir tout ce quil faut savoir ce sujet au cours de ce TP.

351

CHAPITRE 29. TP : CRER UN ESPACE MEMBRES Ce TP sera lgrement dirent de ceux que vous avez lus jusquici : en eet, nous allons concevoir ensemble et pas pas lespace membres. Plutt que de nous concentrer sur le code source proprement dit, je vous prsenterai la mthode, ce quil faut savoir, mais je ne vous donnerai pas de code PHP prt lemploi . a naurait pas de sens : ce stade, vous avez le niveau pour crire vous-mmes le code laide du canevas que je vais vous proposer. :o)

Conception de lespace membres


Quelles sont les fonctionnalits dun espace membres ?
Cest la premire question que nous devons nous poser : quest-ce que nous souhaitons faire concrtement ? Cela nous permettra aussi de dnir ce que nous souhaitons viter davoir concevoir, au moins dans un premier temps. Vous tes probablement habitus aux espaces membres sur dautres sites1 . Vous devriez donc savoir quun espace membres ncessite au minimum les lments suivants : une page dinscription ; une page de connexion ; une page de dconnexion. On peut ensuite ajouter dautres pages, par exemple pour acher et modier son prol de membre. Cependant, il faut au minimum avoir cr les pages que je viens de mentionner. La gure 29.1 devrait vous permettre davoir une bonne vue densemble des tapes de la vie dun membre, de son inscription sa connexion et sa participation au site.

Fig. 29.1 Les tapes de la vie dun membre Une fois cette base prte, il sera ensuite possible de crer tout lespace participatif de
1 Qui na jamais cr un compte sur un site web ? Sur Twitter ou Facebook ? Vous avez forcment dj vu un espace membres, mme si le site web ne lappelle pas exactement comme cela.

352

CONCEPTION DE LESPACE MEMBRES votre site qui reposera sur les membres : les forums, les commentaires des actualits, etc. Elles sont reprsentes en pointills sur la gure 29.1. Nous utiliserons le numro du membre (son id ) pour lier ses messages son compte, laide des jointures SQL que vous connaissez bien maintenant. Pour commencer, nous allons crer la table MySQL qui stockera les membres de notre site. Cest la premire tape qui nous permettra ensuite daller plus loin et dtudier la cration des principales pages dont nous avons parl : inscription, connexion et dconnexion.

La table des membres


Quest-ce qui caractrise un membre ? Essayons de voir ce que nous avons besoin de stocker au minimum pour crer la table : un pseudonyme ; un mot de passe ; une adresse e-mail ; une date dinscription.

Bien entendu, on pourrait ajouter dautres champs, comme sa signature, sa date de naissance ou son adresse de messagerie instantane. Nous allons cependant faire simple pour commencer, sachant quil est toujours possible dajouter des champs la table par la suite comme nous lavons appris. Je vous propose donc de crer une table nomme membres avec les champs suivants : id (int, primary, auto_increment) ; pseudo (varchar 255) ; pass (varchar 255) ; email (varchar 255) ; date_inscription (date).

Ces champs sont rsums sur la gure 29.2 qui prsente la table une fois cre sous phpMyAdmin.

Fig. 29.2 Les champs de la table membres 353

CHAPITRE 29. TP : CRER UN ESPACE MEMBRES Si vous souhaitez que vos membres appartiennent des groupes dirents, il pourrait tre intressant de crer une table groupes listant tous les groupes (membre, administrateur, modrateur. . .). Vous ajouteriez la table des membres un champ nomm id_groupe qui stockerait le numro du groupe, ce qui vous permettrait de faire une jointure entre les deux tables comme nous lavons fait avec les jeux vido et leurs propritaires plus tt dans le cours.

La problmatique du mot de passe


Un de ces champs mrite une attention particulire : celui qui stocke le mot de passe. En eet, lorsquils sinscriront, vos visiteurs enverront en toute conance un mot de passe votre site. Il est trs probable quils utilisent le mme mot de passe sur de nombreux autres sites. Bien que ce soit une trs mauvaise habitude en matire de scurit (idalement, il faudrait utiliser un mot de passe dirent par site), ce cas de gure est hlas extrmement frquent. Sachant cela, vous avez une certaine obligation morale et thique en tant que webmasters : vous ne devriez pas stocker les mots de passe de vos visiteurs dans la base. Si celle-ci tombait entre de mauvaises mains2 , une personne aurait accs tous les mots de passe de vos membres et pourrait sen servir pour voler leurs comptes sur dautres sites ! Pourtant, je dois bien stocker le mot de passe de mes membres si je veux pouvoir par la suite massurer que ce sont les bonnes personnes ! Cest un problme impossible rsoudre ! Cest ce que vous croyez, et pourtant la solution existe : elle sappelle le hachage. Cest une fonction qui transforme nimporte quel texte en un nombre hexadcimal qui reprsente le mot de passe mais qui est illisible, comme le montre la gure 29.3.

Fig. 29.3 La fonction de hachage rend le mot de passe illisible Pour hacher un mot de passe, il existe plusieurs fonctions qui se basent sur des algorithmes dirents. Je vous conseille dutiliser sha13 sur vos sites web.
2 Cela pourrait arriver dans un cas critique, comme le piratage de votre site, ce que je ne vous souhaite pas. 3 Il existe dautres fonctions ayant le mme rle, notamment md5 qui est trs connue. Cependant, cette fonction de hachage nest plus considre comme sre aujourdhui et il est fortement recommand dutiliser sha1.

354

RALISATION DES PAGES PRINCIPALES DE LESPACE MEMBRES La particularit du hachage est quil fonctionne dans un seul sens : il est impossible de retrouver le mot de passe dorigine une fois quil a t hach. De plus, un hash 4 est unique : il correspond un et un seul mot de passe. Vous stockerez la version hache du mot de passe, qui sera donc pass la moulinette par la fonction sha1. Lorsquun visiteur voudra se connecter, il vous enverra son mot de passe que vous hacherez nouveau et que vous comparerez avec celui stock dans la base de donnes. Si les deux mots de passe hachs sont identiques, alors cela signie que le visiteur a rentr le mme mot de passe que lors de son inscription.

Ralisation des pages principales de lespace membres


Nous avons dtermin un peu plus tt la liste des pages dont nous avons besoin au minimum pour grer nos membres : inscription ; connexion ; dconnexion. Nous nallons pas crire le code de ces pages mais nous allons passer en revue ce quil faut savoir pour les raliser correctement.

La page dinscription
La page dinscription est en gnral constitue de quatre champs : pseudonyme souhait ; mot de passe ; conrmation du mot de passe (pour viter les erreurs de saisie) ; adresse e-mail.

Il est recommand de limiter autant que possible le nombre dinformations demandes. Le visiteur souhaite pouvoir sinscrire trs rapidement. Sil tombe sur une page avec de nombreux champs remplir, il y a de fortes chances quil laisse tomber. Laissez-le remplir les autres champs (comme sa signature, sa messagerie instantane et sa date de naissance) dans un second temps lorsquil sera inscrit. Certains sites ne demandent pas de pseudonyme et utilisent ladresse email comme identiant. Cest une possibilit, notamment sur les sites decommerce, mais si vos membres seront amens poster des messages sur des forums, il est prfrable quils sinscrivent avec un pseudonyme. La gure 29.4 prsente un formulaire basique dinscription. Le champ du mot de passe est de type password an dempcher la lecture du mot de passe lcran par une autre personne. Cest pour cela quil est fortement recommand
4 Nom

donn la version hache du mot de passe.

355

CHAPITRE 29. TP : CRER UN ESPACE MEMBRES

Fig. 29.4 Un formulaire dinscription de demander de saisir nouveau le mot de passe au cas o le visiteur ait fait une faute de frappe quil naurait pas pu voir. Avant denregistrer lutilisateur dans la base de donnes, il faudra penser faire un certain nombre de vrications. Le pseudonyme demand par le visiteur est-il libre ? Sil est dj prsent en base de donnes, il faudra demander au visiteur den choisir un autre. Les deux mots de passe saisis sont-ils identiques ? Sil y a une erreur, il faut inviter le visiteur rentrer nouveau le mot de passe. Ladresse e-mail a-t-elle une forme valide ? Vous pouvez utiliser une expression rgulire pour le vrier. Si toutes ces conditions sont remplies, on peut insrer lutilisateur dans la base de donnes. Comme je vous le disais plus tt, il est trs fortement conseill de hacher le mot de passe avant de le stocker, an quil ne soit plus lisible . Voici dans les grandes lignes quoi pourrait ressembler le code qui insre un nouveau membre dans la base :
// Vrification de la validit des informations // Hachage du mot de passe $pass_hache = sha1($_POST[pass]); // Insertion $req = $bdd->prepare(INSERT INTO membres(pseudo, pass, email, date_inscription) VALUES(:pseudo, :pass, :email, CURDATE())); $req->execute(array( pseudo => $pseudo, pass => $pass_hache, email => $email));

Ce code est un simple canevas qui illustre les principales tapes de la cration dun membre. Cest vous de le complter. De plus, je vous invite respecter larchitecture MVC : vous utiliserez le contrleur pour vrier la validit des informations et pour hacher le mot de passe, tandis que le modle se chargera simplement dexcuter la requte. 356

RALISATION DES PAGES PRINCIPALES DE LESPACE MEMBRES On vrie dabord la validit des informations comme je vous en ai parl plus haut, ensuite on hache le mot de passe et enn on peut insrer le membre dans la base. Sous phpMyAdmin, on voit donc apparatre le membre comme sur la gure 29.5.

Fig. 29.5 Un membre ajout dans la base de donnes Son mot de passe hach nest pas lisible et cela nous assure quon ne peut pas le voler 5 . Nous verrons lors de ltape de connexion comment vrier si le membre entre bien le bon mot de passe. On pourrait ajouter dautres tapes pour renforcer la scurit de linscription. En particulier, renseignez-vous sur les systmes de Captcha qui demandent au visiteur de recopier un mot issu dune image an de vrier quil ne sagit pas dun robot. Dautre part, vous pourriez demander une conrmation par e-mail an de vrier que ladresse est correcte.

La page de connexion
Maintenant que le membre est cr, il doit pouvoir se connecter sur votre site. Pour cela, nous utiliserons le systme de sessions qui est mis notre disposition par PHP et que nous avons appris utiliser plus tt dans ce cours. Habituellement, on demande au moins le pseudonyme (ou login) et le mot de passe du membre. Pour lui faciliter la vie, on peut lui proposer une option de connexion automatique qui lui vitera davoir se connecter de nouveau chaque visite du site (gure 29.6).

Fig. 29.6 Un formulaire de connexion La page qui reoit les donnes du formulaire de connexion doit hacher de nouveau le mot de passe et le comparer celui stock dans la base. Sil existe un membre qui a le mme pseudonyme et le mme mot de passe hach, alors on autorise la connexion et on peut crer les variables de session. Sinon, on renvoie une erreur indiquant que le pseudonyme ou le mot de passe est invalide.
5 Notez que, pour augmenter la scurit, on peut saler le mot de passe. Cela consiste lui ajouter un prxe avant de le hacher an de rajouter une certaine complexit : $pass_hache = sha1(gz . $_POST[pass]) ;

357

CHAPITRE 29. TP : CRER UN ESPACE MEMBRES


// Hachage du mot de passe $pass_hache = sha1($_POST[pass]); // Vrification des identifiants $req = $bdd->prepare(SELECT id FROM membres WHERE pseudo = :pseudo AND pass = :pass); $req->execute(array( pseudo => $pseudo, pass => $pass_hache)); $resultat = $req->fetch(); if (!$resultat) { echo Mauvais identifiant ou mot de passe !; } else { session_start(); $_SESSION[id] = $resultat[id]; $_SESSION[pseudo] = $pseudo; echo Vous tes connect !; }

Aprs avoir de nouveau hach le mot de passe, on essaie de rcuprer une entre dans la table membres qui corresponde ce pseudonyme et ce mot de passe hach. Si $resultat vaut faux, cela signie quaucune entre ne correspond et donc que lidentiant ou le mot de passe est mauvais. Sinon, on peut crer les variables de session et y stocker par exemple lid et le pseudonyme du membre. Dsormais, sur toutes les pages du site, on pourra indiquer au membre quil est connect grce la prsence des variables $_SESSION.
if (isset($_SESSION[id]) AND isset($_SESSION[pseudo])) { echo Bonjour . $_SESSION[pseudo]; }

Si le membre souhaite tre reconnect automatiquement6 , je vous invite crer deux cookies qui stockeront respectivement : le pseudonyme ; le mot de passe hach. Ainsi, si un visiteur non connect qui possde ces deux cookies se prsente, vous naurez qu vrier si un membre correspond ces informations en base de donnes et vous pourrez le connecter automatiquement, sans quil ait eu utiliser le formulaire de connexion. L encore, on prend une certaine mesure de scurit en stockant le mot de passe hach dans un cookie et non le vrai mot de passe.
6 Ce quil est conseill de faire uniquement sur un ordinateur personnel, et non sur un ordinateur partag avec dautres personnes !

358

RALISATION DES PAGES PRINCIPALES DE LESPACE MEMBRES Sachez par ailleurs que de nouvelles mthodes de connexion centralises apparaissent depuis quelque temps. Elles ont pour nom OpenID, Facebook Connect, Windows Live ID, etc. En eectuant quelques manipulations supplmentaires, vous pouvez permettre vos visiteurs de se connecter votre site en saisissant leurs identiants Facebook, Windows Live, Twitter ou encore Google, ce qui leur vite davoir fournir un mot de passe spcialement pour votre site. Le systme RPX est devenu trs populaire car il vous permet de mettre en place rapidement ces moyens de connexion sur votre site (gure 29.7). Il sut seulement dajouter un champ votre table membres et dinstaller un petit script. Renseignezvous sur le site web de RPX si vous souhaitez par la suite vous en servir pour amliorer votre espace membres. Code web : 231709

Fig. 29.7 RPX permet de se connecter votre site avec un autre compte

La page de dconnexion
Au bout dun certain temps dinactivit, la session du membre est automatiquement dtruite et il se retrouve dconnect. Sil charge nouveau une page du site, il apparatra donc dconnect, moins quil ait activ la connexion automatique qui aura pour eet de le reconnecter immdiatement et de manire transparente grce ses cookies. Si la dconnexion est automatique au bout dun certain temps (le fameux timeout), il faut quand mme proposer un lien de dconnexion. La page de dconnexion devra supprimer le contenu de $_SESSION, mettre n au systme de sessions (en appelant session_destroy()) et supprimer les cookies de connexion automatique sils existent.
session_start(); // Suppression des variables de session et de la session $_SESSION = array(); session_destroy(); // Suppression des cookies de connexion automatique

359

CHAPITRE 29. TP : CRER UN ESPACE MEMBRES


setcookie(login, ); setcookie(pass_hache, );

Aller plus loin


Nous avons vu ensemble comment mettre en place les bases dun systme de gestion des membres. Bien entendu, nous avons fait le minimum et cest maintenant vous de jouer pour amliorer ce script comme bon vous semble. :-) Voici quelques pistes pour complter votre espace membres. Proposez au membre denvoyer un avatar. Vous avez appris envoyer des chiers via des formulaires et redimensionner des images avec la bibliothque GD, vous en tes donc tout fait capables ! Bien quil existe plusieurs mthodes, la plus simple consiste crer un dossier avatars et y placer les avatars nomms en fonction des id des membres : 1.png, 2.png, 3.png, etc. Mettez en place une page de prol de prsentation des membres. Vous pouvez y acher toutes sortes dinformations, comme son e-mail (mais il vaut mieux lui demander son accord auparavant), son adresse de messagerie instantane, sa date de naissance, ses passions, son travail, le nom de la ville o il habite, etc. Toutes ces informations pourront tre stockes dans de nouveaux champs de la table membres. Proposez au membre sil le souhaite de changer ses identiants : son pseudonyme et son mot de passe. Il est courant quun membre dsire changer de pseudonyme quelque temps aprs stre inscrit, mais surtout il est vital quil puisse changer son mot de passe tout moment au cas o celui-l serait compromis ! Mme si le membre est dj connect, je vous conseille de lui demander nouveau son mot de passe actuel avant de lautoriser en changer, par mesure de scurit. Donnez au membre la possibilit de choisir parmi plusieurs options de navigation. Tout le monde nutilise pas votre site web de la mme manire, peut-tre que certains souhaiteraient avoir un menu en haut des pages plutt quun autre, peut-tre que dautres prfreraient naviguer avec un design sombre, etc. Votre espace membres devrait commencer tre bien complet partir de l ! Maintenant, pourquoi ne pas commencer mettre en place vos propres forums sur votre site web ? Chaque message des forums sera associ un id de membre : il sura de crer un champ id_membre dans la table des messages. Vous pourrez alors utiliser les jointures pour rcuprer automatiquement le pseudonyme du membre et sa signature chaque message post !

360

Cinquime partie

Annexes

361

Annexe

Codez proprement

n programmation comme partout ailleurs, il y a deux types de personnes : celles qui eectuent leur travail rapidement, mais ne se soucient pas de la qualit, de la lisibilit, et de lvolutivit de leur code , et celles qui font leort de soigner un peu leur travail, car elles ont conscience que ce petit travail supplmentaire sera un gain de temps norme lavenir. Quand on dbute, on a tendance se dire a marche, parfait, ne touchons plus rien et laissons comme a . Cest un mauvais rexe, et je ne serai pas le seul vous le dire : nimporte quel programmeur PHP ayant un peu dexprience sait quun code qui fonctionne nest pas forcment bon. Cette annexe est en fait une suite de petits conseils apparemment peu importants, sur lesquels je voudrais que vous portiez toute votre attention. Cest peu de choses, et cest pourtant ce qui fait la distinction entre un bon programmeur et euh. . . un programmeur du dimanche !

363

ANNEXE A. CODEZ PROPREMENT

Des noms clairs


Jai plusieurs fois insist sur ce point dans les premiers TP du livre, et cette fois jy reviens avec un peu plus dexplications. Quand vous crez un script PHP, vous devez inventer des noms. Vous allez devoir donner des noms dirents types dlments : les variables ; les fonctions ; les classes. Lide est simple : il faut que vous fassiez leort de choisir des noms de variables et de fonctions clairs et comprhensibles. Par exemple, voici de mauvais noms de variables : $temp ; $data ; $info ; $val ; $val2.

Je nai pas invent ces noms de variables ; en fait, pour tout vous dire, ce sont des noms que jai vraiment vus dans de nombreux codes source. Par exemple, $info : info , oui, mais info sur QUOI ? Cest pourtant a qui est crucial : savoir ce que contient une variable. Une variable contient toujours une info, cest vous de prciser laquelle. Je ne vous parle mme pas des variables sans nom : $temp, $tmp et compagnie. Ces noms sont bannir absolument. Mais quoi a peut servir de chercher un nom de variable clair ? Aprs tout, cest mon code, cest pour moi, je comprends trs bien ce que je fais ! Faux. Bien sr que vous savez ce que vous faites (personne nest dans votre esprit, aprs tout). Et pourtant le problme peut apparatre dans deux cas. Si vous donnez votre code PHP un ami pour quil vous aide un endroit o vous bloquez, ou pour quil continue votre code. Essayez par exemple de montrer votre code PHP sur des forums sur Internet, vous verrez que si vous utilisez des noms peu clairs, vous aurez beaucoup moins de rponses parce quil aura t bien plus dicile de comprendre le fonctionnement de votre code ! Un autre cas (sous-estim), cest celui o vous retouchez votre code plus tard. Je ne dis pas le lendemain (les ides sont encore fraches), mais dans trois mois, ou mme dans trois semaines. Croyez-en mon exprience : il mest arriv de devoir relire mon code source en me demandant Mais quest-ce que jai bien pu vouloir faire, l ? . Passez ne serait-ce quune seconde de plus rchir des noms clairs. Nayez pas peur de choisir des noms un peu longs, ce nest pas une perte de temps, bien au contraire.1 Voici quelques exemples de noms de variables clairs :
1 Vous pouvez utiliser le symbole underscore _ pour remplacer les espaces, qui sont, je vous le rappelle, interdits dans les noms de variables et de fonctions.

364

DES NOMS CLAIRS $ip_visiteur ; $pseudo_membre ; $date_news ; $mot_de_passe ; $forum_selectionne.

Pour nir, et en esprant vous convaincre (parce que croyez-moi, cest trs important), voici le mme code source en deux exemplaires : le premier contient des noms courts et pas clairs ; il est dicile de comprendre rapidement ce quil fait ; le deuxime contient des noms un peu plus longs, mais au moins on arrive tout de suite savoir quoi sert telle variable ou telle fonction. Ces deux codes produisent exactement le mme rsultat ; simplement, lun deux est beaucoup plus comprhensible que lautre.

Des noms de variables peu clairs


<?php $mess_page = 20; $ret = $bdd->query(SELECT COUNT(*) AS nb FROM livre); $data = $ret->fetch(); $total = $data[nb]; $nb_total = ceil($total / $mess_page);

echo Page : ; for ($i = 1 ; $i <= $nb_total ; $i++) { echo <a href="livre.php?page= . $i . "> . $i . </a> ; } ?>

Des noms de variables beaucoup plus clairs


<?php $nombreDeMessagesParPage = 20; $retour = $bdd->query(SELECT COUNT(*) AS nb_messages FROM livre); $donnees = $retour->fetch(); $totalDesMessages = $donnees[nb_messages]; $nombreDePages echo Page : ; = ceil($totalDesMessages / $nombreDeMessagesParPage);

365

ANNEXE A. CODEZ PROPREMENT


for ($page_actuelle = 1 ; $page_actuelle <= $nombreDePages ; $page_actuelle++) { echo <a href="livre.php?page= . $page_actuelle . "> . $page_actuelle . </a> ; } ?>

Cest fou comme des noms crits correctement en franais permettent dy voir plus clair.

Indentez votre code


Une des premires choses qui saute aux yeux quand on regarde un code source, cest son indentation. Le principe de lindentation, cest dutiliser intelligemment les tabulations pour dcaler certaines parties de votre code an de montrer plus clairement la structure. La quasi-totalit des diteurs de texte ont lhabitude que vous utilisiez du code indent, et vous aident donc beaucoup clarier votre code. Quand je dis la plupart , je ne parle pas de Bloc-notes. Si vous tapez votre code PHP dans Bloc-notes, vous feriez bien dessayer un vrai logiciel fait pour a, comme Notepad++ dont je vous ai parl dans un des premiers chapitres. Non seulement avec un vrai diteur vous avez une indentation du code semi-automatique, mais en plus votre code est automatiquement color, ce qui aide normment, croyez-moi ! Il y a plusieurs styles dindentation de code ; cela varie un peu selon les gots des dveloppeurs. Celui que je vous propose est simple retenir : chaque fois que vous ouvrez des accolades {, par exemple pour un if, un while ou un for, vous dcalez tout le code qui suit dune tabulation vers la droite ; chaque fois que vous fermez une accolade }, vous dcalez tout le code qui suit dune tabulation vers la gauche.

Avec un code non indent


Cest plus clair avec un exemple, alors voyez vous-mmes. Voici ce que a donne avec un code non indent :
<?php for ($ligne = 1 ; $ligne <= 100 ; $ligne++) { if ($ligne % 2 == 0) { echo $ligne . : <strong>ligne paire</strong>;

366

UN CODE CORRECTEMENT COMMENT


} else { echo $ligne . : <em>ligne impaire</em>; } echo <br />; } ?>

Avec un code indent


Et voici maintenant le mme code correctement indent si on respecte la rgle des tabulations :
<?php for ($ligne = 1 ; $ligne <= 100 ; $ligne++) { if ($ligne % 2 == 0) { echo $ligne . : <strong>ligne paire</strong>; } else { echo $ligne . : <em>ligne impaire</em>; } } ?> echo <br />;

Lavantage avec un code indent, cest quon voit bien les niveaux des instructions. On spare bien les blocs, et on arrive se reprer bien plus facilement. ;-) Avoir un code correctement indent est quasiment indispensable lorsque vous commencez faire des scripts de plusieurs dizaines de lignes2 . Certains dveloppeurs ont tendance remplacer les tabulations par deux ou quatre espaces, car la largeur dune tabulation peut varier dun logiciel un autre, alors que celle dun espace est xe. En gnral, cest lditeur de texte lui-mme qui convertit nos tabulations par des espaces, de faon transparente.

Un code correctement comment


Le dernier point, qui est peut-tre le plus dlicat pour des raisons de dosage, concerne les commentaires dans le code. Les commentaires ne servent rien, puisquils ne sont
2 Ce

qui arrive assez vite !

367

ANNEXE A. CODEZ PROPREMENT pas lus par PHP lors de la gnration de la page. . . comme les noms de variables et lindentation du code, me direz-vous. En eet. Mais l encore, les commentaires sont pour vous, et ventuellement pour la personne qui lira votre code. Il faut commenter votre code, mais il ne faut surtout pas tomber dans lexcs ! Je mexplique. Si aprs une ligne comme celle-ci :
<?php echo $pseudo_visiteur; ?>

. . . vous rajoutez le commentaire Ache le pseudo du visiteur , l je dis non, non et non ! Il est strictement inutile de commenter une une les lignes de votre code ! Si jai insist tout lheure pour que vous choisissiez des noms de variables et de fonctions clairs, cest justement pour vous viter davoir besoin de trop commenter. Le plus judicieux et le plus intelligent, cest de commenter un groupe de lignes pour expliquer brivement quoi elles servent quand cela nest pas vident. Cest le sens gnral de votre code que vous devez expliquer dans les commentaires, et non pas le rle de chaque ligne ! Pour vous aider, on peut distinguer deux types de commentaires : ceux qui commencent par // : ils permettent de commenter sur une seule ligne la fois ; ceux qui commencent par /* et qui se terminent par */ : ils sont utiliss pour de longs commentaires stalant sur plusieurs lignes. Voici une petite illustration dun code correctement comment :
<?php /* Script "Questionnaire de satisfaction" Par M@teo21 Dernire modification : 20 aot XXXX */ // On vrifie dabord sil ny a pas de champ vide if ($_POST[description] == NULL OR $_POST[mail] == NULL) { echo Tous les champs ne sont pas remplis !; } else // Si cest bon, on enregistre les informations dans la base { $bdd->prepare(INSERT INTO enquete VALUES (\\, ?, ?)); $bdd->execute(array($_POST[description], $_POST[mail])); // Puis on envoie les photos

368

UN CODE CORRECTEMENT COMMENT


for ($numero = 1 ; $numero <= 3 ; $numero++) { if ($_FILES[photo . $numero][error] == 0) { if ($_FILES[photo . $numero][size] < 500000) { move_uploaded_file($_FILES[photo . $numero][tmp_name], $numero . .jpg); } else { echo La photo . $numero . n\est pas valide.<br />; $probleme = true; } } } // Enfin, affichage dun message de confirmation si tout sest bien pass if (!(isset($probleme))) { echo Merci ! Les informations ont t correctement enregistres !; }

} ?>

Comme vous le voyez, je nai pas comment toutes les lignes. Jai juste comment des groupes de lignes pour expliquer leur fonction globale, ce qui permet lauteur (moi ou un autre) de se reprer beaucoup plus facilement dans le code plus tard !

369

ANNEXE A. CODEZ PROPREMENT

370

Annexe

Utilisez la documentation PHP !

n des gros avantages en PHP, cest sa documentation trs complte, gratuite, disponible sur Internet, et traduite dans de trs nombreuses langues (dont le franais).

Pourtant, quand quelquun nous dit La solution ton problme se trouve dans la doc , on a tendance trembloter un peu. On pense que la doc est une sorte de pav mal construit, illisible, dans lequel on a toutes les chances de se perdre. Cest un tort. Comme je vous lai dit, la documentation PHP est particulirement complte et bien organise, qui plus est traduite en franais. Tout y est. Le but de cette annexe est de vous montrer comment la doc fonctionne, pour que vous soyez ensuite capables de trouver linformation que vous cherchez tout seuls, sans mon aide. ;-)

371

ANNEXE B. UTILISEZ LA DOCUMENTATION PHP !

Accder la doc
La documentation, cest bien beau, mais cest o ? Comment y accder ?

Pour cela, on a deux possibilits, tout dpend de ce que vous voulez faire. Voir la liste des fonctions classes par thmes : si vous ne savez pas exactement quelle fonction vous cherchez, si vous voulez ner un peu et avoir la liste des fonctions classes par catgories. . . cest la premire mthode que vous utiliserez. Accder la prsentation dune fonction dont on connat le nom : si vous connaissez le nom dune fonction, mais que vous ne savez pas vous en servir, cest cette seconde mthode que lon utilisera. Cest la mthode la plus simple, la plus rapide, et la plus frquemment utilise. Je vais maintenant vous dtailler chacune des deux mthodes permettant daccder la doc. Vous utiliserez lune ou lautre en fonction de vos besoins.

Liste des fonctions classes par thmes


Vous devriez mettre cette adresse dans les favoris pour ne jamais loublier : Code web : 786383 Cest le sommaire des fonctions PHP, en franais. Si vous vous rendez sur la page, vous devriez voir quelque chose qui ressemble la gure B.1. Ce que vous voyez l, cest la liste des thmes de fonctions. Comme vous pouvez le voir, il y en a un sacr paquet ! Ne prenez pas peur si vous ne comprenez mme pas un thme sur dix, mais faites leort de lire un peu tout ce quil y a, et reprez sil y a un thme qui vous intresse plus particulirement quun autre. Par exemple, vous pouvez y voir les thmes Mail et Mathmatiques . Supposons que je sois intress par les fonctions mathmatiques de PHP. Je clique sur Mathmatiques . Code web : 243012 L, une nouvelle page souvre. On vous propose une petite introduction que je vous recommande de lire chaque fois, ainsi que la liste des fonctions. Certains thmes de fonctions ne sont pas activs avec PHP. Cest le cas par exemple de la bibliothque GD pour crer des images. Si cest le cas, on vous indique quil faut activer la bibliothque, comme je vous ai appris le faire dans le chapitre sur GD. Dautres fonctions appartiennent des extensions quil faut installer manuellement. En ce qui concerne les fonctions mathmatiques, elles sont toujours actives par dfaut, 372

ACCDER LA DOC

Fig. B.1 Liste des fonctions classes par thmes donc pas de problme de ce ct-l. Descendez plus bas dans la page (parfois vous devez descendre trs trs bas), jusqu lendroit o est crit Table des matires . Cest l que a nous intresse : il y a la liste des fonctions du thme Mathmatiques , comme le montre la gure B.2.

Fig. B.2 Quelques fonctions mathmatiques gauche, vous avez le nom de la fonction, et droite un trs bref descriptif de ce quelle fait. Si vous cliquez sur un nom de fonction, vous accdez la prsentation de la fonction. Nous verrons comment fonctionne cette page dans la seconde partie de cette annexe. Ici par exemple, je peux tre intress par le calcul dun logarithme nprien (fonction log). Mme si les maths et vous a fait deux, il y a quand mme quelques fonctions qui devraient vous intresser : max qui retourne le nombre le plus grand, ou mt_rand qui gnre un nombre alatoire. 373

ANNEXE B. UTILISEZ LA DOCUMENTATION PHP !

Accs direct une fonction


Il est frquent que vous connaissiez le nom dune fonction, mais que vous ne sachiez pas vous en servir. L, il nest plus question de ner parmi les thmes de fonctions pour en reprer une intressante : on souhaite obtenir directement la description dune fonction. Par exemple, supposons que vous souhaitiez gnrer un nombre alatoire entre 0 et 100. Vous savez que la fonction sappelle mt_rand parce que quelquun en a parl sur un forum. Cette information est normalement susante : vous avez le nom de la fonction et navez plus qu vous documenter. Pour accder directement la prsentation dune fonction, tapez ladresse suivante dans votre navigateur : php.net/nom_de_la_fonction Il est inutile dcrire http://www. devant, il sera rajout tout seul. Cest plus rapide de sen passer. Si la fonction existe, vous tombez directement sur sa prsentation. Sinon, on vous dit que la fonction nexiste pas et on vous propose dautres fonctions qui ont peu prs le mme nom. Si je veux donc tout savoir sur mt_rand, je tape ce qui se trouve sur la gure B.3 dans la barre dadresse de mon navigateur.

Fig. B.3 Accs direct la documentation depuis la barre dadresse du navigateur Lorsque vous validez cette adresse, vous arrivez directement sur la page qui prsente la fonction mt_rand ! Plutt rapide et pratique, non ?

Prsentation dune fonction


Je suppose maintenant que vous avez repr la fonction qui vous intresse. Vous tombez alors sur la page de prsentation de la fonction. On va prendre le cas de la fonction mt_rand : faites comme je vous ai dit plus haut pour accder directement la page concernant cette fonction. La page de prsentation dune fonction a toujours la mme forme, celle de la gure B.4. Ce qui nous intresse le plus l-dedans, cest le mode demploi de la fonction . Il correspond ces lignes : 374

PRSENTATION DUNE FONCTION

Fig. B.4 Prsentation de la fonction mt_rand

375

ANNEXE B. UTILISEZ LA DOCUMENTATION PHP !


int mt_rand ( void ) int mt_rand ( int $min, int $max )

Ces lignes dcrivent le mode demploi de mt_rand. Je vais vous apprendre le dchirer, car lorsque vous saurez le lire, vous saurez utiliser nimporte quelle fonction PHP laide de la doc !

Apprendre lire un mode demploi


Ici, le mode demploi indique quil y a deux faons dutiliser la fonction : avec ou sans paramtres. Prenons le cas avec paramtres, plus complexe :
int mt_rand ( int $min, int $max )

Examinons toutes les infos que cet extrait de code renferme. int : la fonction commence par le mot-cl int. Ce premier mot-cl indique ce que renvoie la fonction. On peut avoir entre autres les mots-cls suivants : int : cela signie que la fonction renvoie un nombre entier. mt_rand renvoie donc un nombre entier (-8, 0, 3, 12, etc.) ; float : la fonction renvoie un nombre dcimal (comme 15.2457) ; number : la fonction renvoie un nombre qui peut tre soit un entier (int) soit un dcimal (float) ; string : la fonction renvoie une chane de caractres, cest--dire du texte. Par exemple Bonjour ; bool : la fonction renvoie un boolen, cest--dire vrai ou faux (true ou false) ; array : la fonction renvoie un array (tableau de variables). Le plus simple en gnral, cest de faire un print_r, comme je vous lai appris, pour voir tout ce que contient cet array ; resource : la fonction renvoie une ressource . Une ressource est un type de donnes particulier, une sorte de super-variable. Il peut sagir dune image, dun chier, etc. Dans le chapitre sur la bibliothque GD par exemple, on manipule une variable $image ; void : la fonction ne renvoie rien du tout. Cest le cas des fonctions qui ne servent qu faire une action et qui nont pas besoin de renvoyer dinformation ; mixed : la fonction peut renvoyer nimporte quel type de donnes (un int, un string, a dpend. . .). mt_rand : l cest tout simple, cest le nom de la fonction. (int $min, int $max) : entre parenthses, il y a la liste des paramtres que lon peut donner la fonction. Ici, on peut donner deux entiers (int) : min et max. Ils servent indiquer que vous voulez un nombre alatoire compris entre 5 et 15 par exemple. La signication des paramtres est explique dans la section Liste des paramtres de la page. Il est aussi possible dappeler la fonction sans aucun paramtre, cest ce que signie la ligne suivante : 376

PRSENTATION DUNE FONCTION


int mt_rand ( void )

Mais alors. . . Quest-ce que a signie si on nenvoie aucun paramtre ? Que va faire la fonction ? Cest crit sur la page : Appele sans les arguments optionnels min et max, mt_rand() retourne un nombre pseudo-alatoire, entre 0 et RAND_MAX (un nombre maximum x par PHP). Pour obtenir un nombre entre 5 et 15 inclus, il faut utiliser mt_rand(5,15). Comme quoi, il sut de lire. ;-)

Un autre exemple : date


Comme vous devez maintenant savoir le faire, rendez-vous sur date pour avoir la description de la fonction. Code web : 162958 Le mode demploi indique ceci :
string date ( string $format [, int $timestamp])

La fonction renvoie une chane de caractres (string) : cest la date. On doit lui donner obligatoirement une chane de caractres appele format (pour demander le mois, lanne, etc. vous vous souvenez ?). On notera quil y a un second paramtre entre crochets, ce qui signie quil est facultatif. Il sagit dun int dnomm timestamp. Pour savoir ce quil signie, lisez la description des paramtres. Faites donc toujours bien attention : certains paramtres sont obligatoires, dautres non (ils sont entre crochets), et la fonction ragit diremment selon les cas. En gnral, le texte descriptif de la fonction vous explique ce qui se passe si vous ne mettez pas les paramtres facultatifs.

Lisez les exemples !


Il y a toujours des exemples pour illustrer lutilisation de la fonction. Cest trs pratique car on vous montre de quelle manire utiliser la fonction, et on nhsite pas vous faire dcouvrir les cas particuliers o la fonction ragit un peu diremment. Par exemple, pour mt_rand on a ce qui se trouve sur la gure B.5. Dans la mesure du possible, essayez de tester les exemples proposs. Il arrive souvent quon comprenne mieux avec des exemples que lon essaie soi-mme. 377

ANNEXE B. UTILISEZ LA DOCUMENTATION PHP !

Fig. B.5 Exemples dutilisation de mt_rand

378

Annexe

Au secours ! Mon script plante !

lors comme a votre script ne marche pas, et PHP vous ache des erreurs incomprhensibles ? Pas de souci vous faire : cest tout fait normal, on ne russit jamais un script du premier coup (en tout cas, moi, jamais !).

Des milliers de messages derreur dirents peuvent survenir (O.K., jusque-l rien de trs rassurant), et je nai pas vraiment la possibilit de vous en dresser une liste complte. . . mais je peux vous prsenter les erreurs les plus courantes, ce qui devrait rsoudre la grande majorit de vos problmes. ;-)

379

ANNEXE C. AU SECOURS ! MON SCRIPT PLANTE !

Les erreurs les plus courantes


Je pense quil est facile de parler derreurs courantes , car vous verrez que certaines erreurs reviennent plus souvent que dautres. Nous allons passer en revue les erreurs suivantes : Parse error ; Undened function ; Wrong parameter count.

Parse error
Si on devait dire quil existe UNE erreur de base, a serait trs certainement celle-l. Impossible de programmer en PHP sans y avoir droit un jour. Le message derreur que vous obtenez ressemble celui-ci :
Parse error: parse error in fichier.php on line 15

Ce message vous indique une erreur dans fichier.php la ligne 15. Gnralement, cela veut dire que votre problme se situe la ligne 15, mais ce nest pas toujours le cas (trop facile, sinon). Parfois cest la ligne prcdente qui a un problme : pensez donc regarder autour de la ligne indique. Avec un diteur de texte spcialis comme Notepad++, vous avez les numros de ligne sur votre gauche, comme sur la gure C.1.

Fig. C.1 Numrotation des lignes dans Notepad++ Bon, concrtement, quest-ce quune parse error ? Une parse error est en fait une instruction PHP mal forme. Il peut y avoir plusieurs causes : Vous avez oubli le point-virgule la n de linstruction. Comme toutes les instructions doivent se terminer par un point-virgule, si vous oubliez den mettre un, a provoquera une parse error. Par exemple :
$id_news = 5

. . . gnrera une parse error. Si vous mettez le point-virgule la n, tout rentrera dans lordre !
$id_news = 5;

Vous avez oubli de fermer un guillemet (ou une apostrophe, ou une parenthse). Par exemple :
echo "Bonjour !;

. . . il sut de fermer correctement les guillemets et vous naurez plus de problme :


echo "Bonjour !";

380

LES ERREURS LES PLUS COURANTES Vous vous tes tromps dans la concatnation, vous avez peut-tre oubli un point :
echo "Jai " . $age " ans";

Une fois lerreur corrige, a donne :


echo "Jai " . $age . " ans";

Il peut aussi sagir dune accolade mal ferme (pour un if, par exemple). Vriez que vous avez correctement ferm toutes vos accolades. Si vous oubliez den fermer une, il est probable que la parse error vous indique que lerreur se trouve la dernire ligne du chier (cest--dire la ligne 115 si votre chier comporte 115 lignes). Donc, si on vous indique une erreur la dernire ligne, il va probablement falloir relire tout le chier PHP la recherche dune accolade mal ferme ! Si on vous dit que lerreur est la ligne 15 et que vous ne voyez vraiment pas derreur cette ligne, nhsitez pas chercher lerreur la ligne juste au-dessus, elle sy trouve peut-tre !

Undened function
Une autre erreur assez classique : la fonction inconnue. Vous obtenez ce message derreur :
Fatal Error: Call to undefined function: fonction_inconnue() in fichier.php on line 27

L, il faut comprendre que vous avez utilis une fonction qui nexiste pas. Deux possibilits : soit la fonction nexiste vraiment pas. Vous avez probablement fait une faute de frappe, vriez si une fonction lorthographe similaire existe ; soit la fonction existe vraiment, mais PHP ne la reconnat pas. Cest parce que cette fonction se trouve dans une extension de PHP que vous navez pas active. Par exemple, si vous essayez dutiliser la fonction imagepng alors que vous navez pas activ la bibliothque GD pour les images en PHP, on vous dira que la fonction nexiste pas. Activez la bibliothque qui utilise la fonction et tout sera rgl. Une dernire chose : il se peut aussi que vous essayiez dutiliser une fonction qui nest pas disponible dans la version de PHP que vous avez. Vriez dans le manuel dans quelles versions de PHP cette fonction est disponible.

Wrong parameter count


Si vous utilisez mal une fonction, vous aurez cette erreur :
Warning: Wrong parameter count for fonction() in fichier.php on line 112

Cela signie que vous avez oubli des paramtres pour la fonction, ou mme que vous en avez trop mis. Comme je vous lai appris dans le chapitre sur la doc PHP, consultez 381

ANNEXE C. AU SECOURS ! MON SCRIPT PLANTE ! le mode demploi de la fonction pour savoir combien de paramtres elle prend et quels sont ceux qui sont facultatifs. Par exemple, la fonction fopen requiert au minimum deux paramtres : le premier pour le nom du chier ouvrir et le second pour le mode douverture (en lecture seule, criture, etc.). Si vous ne mettez que le nom du chier ouvrir, comme ceci :
$fichier = fopen("fichier.txt");

. . . vous aurez lerreur Wrong parameter count . Pensez donc rajouter le paramtre qui manque, par exemple comme ceci :
$fichier = fopen("fichier.txt", "r");

Dans les versions actuelles de PHP, le message derreur vous donne mme le nombre de paramtres que vous avez oublis !

Traiter les erreurs SQL


Comme vous le savez, le langage SQL est un langage part entire dont on se sert en PHP. Sil peut y avoir des erreurs en PHP, il peut aussi y avoir des erreurs en SQL ! Il se peut par exemple que votre requte soit mal crite, que la table que vous voulez ouvrir nexiste pas, etc. Bref, les erreurs possibles sont l encore nombreuses. Toutefois, ce nest pas MySQL qui vous dira quil y a une erreur, mais PHP, et ce dernier nest pas trs bavard en ce qui concerne les erreurs SQL. Nous allons donc voir : 1. comment reprer une erreur SQL en PHP ; 2. comment faire parler PHP pour quil nous donne lerreur SQL (de gr, ou de force !).

Reprer lerreur SQL en PHP


Lorsquil sest produit une erreur SQL, la page ache le plus souvent lerreur suivante : Fatal error : Call to a member function fetch() on a non-object Cette erreur survient lorsque vous voulez acher les rsultats de votre requte, gnralement dans la boucle while ($donnees = $reponse->fetch()). Quand vous avez cette erreur, il ne faut pas chercher plus loin, cest la requte SQL qui prcde qui na pas fonctionn. Il vous manque cependant des dtails sur ce qui a pos problme dans la requte. Nous allons maintenant voir comment on peut remdier cela. ;-) 382

QUELQUES ERREURS PLUS RARES

Allez ! Crache le morceau !


Comme visiblement PHP na pas envie de nous donner lerreur renvoye par MySQL, on va le lui demander dune autre manire. Je vous avais dailleurs prsent cette mthode dans un des premiers chapitres sur MySQL. Reprez la requte qui selon vous plante (certainement celle juste avant la boucle while), et demandez dacher lerreur sil y en a une, comme ceci :
<?php $reponse = $bdd->query(SELECT nom FROM jeux_video) or die(print_r($bdd->errorInfo())); ?>

Si la requte fonctionne, aucune erreur ne sera ache. Si en revanche la requte plante, PHP arrtera de gnrer la page et vous achera lerreur donne par MySQL. . . partir de l, il va falloir vous dbrouiller tout seuls, car les erreurs SQL sont assez nombreuses et je ne peux pas toutes les lister. En gnral, MySQL vous dit You have an error in your SQL syntax near XXX . vous de bien relire votre requte SQL ; lerreur se trouve gnralement prs de lendroit o on vous lindique.

Quelques erreurs plus rares


Les erreurs PHP sont trs varies, et je ne parle mme pas des erreurs SQL. Nesprez donc pas que je vous fasse ici la liste des 3946 erreurs de PHP, jen serais incapable (je ne les ai pas encore toutes eues, mais a ne saurait tarder lallure laquelle je vais). Je vais vous montrer quelques erreurs un peu plus rares que parse error , mais que vous rencontrerez probablement un jour. Si dj je peux vous aider pour ces erreurs-l, ce sera bien. Nous allons voir les erreurs : Headers already sent by. . . ; Limage contient des erreurs ; Maximum execution time exceeded .

Headers already sent by. . .


Voil une erreur classique quand on travaille avec les sessions ou avec les cookies :
Cannot modify header information - headers already sent by ...

Que doit-on comprendre par l ? Les headers sont des informations den-tte qui sont envoyes avant toute chose au navigateur du visiteur. Elles permettent de dire Ce que 383

ANNEXE C. AU SECOURS ! MON SCRIPT PLANTE ! tu vas recevoir est une page HTML , ou Ce que tu vas recevoir est une image PNG , ou encore Inscris un cookie . Toutes ces choses-l doivent tre eectues avant que le moindre code HTML ne soit envoy. En PHP, la fonction qui permet denvoyer des informations de headers sappelle header(). On sen est notamment servi dans le chapitre sur la bibliothque GD pour indiquer que lon envoyait une image et non pas une page HTML. Il y a dautres fonctions qui envoient des headers toutes seules. Cest le cas de session_start() et de setcookie(). Ce que vous devez retenir, cest que chacune des ces fonctions doit tre utilise au tout dbut de votre code PHP. Il ne faut RIEN mettre avant, sinon a provoquera lerreur Headers already sent by. . . . Un exemple de code qui gnre lerreur :
<html> <?php session_start(); ?>

Ici, jai eu le malheur de mettre un peu de code HTML avant le session_start(), et cest ce qui a provoqu lerreur. Mettez le session_start() en tout premier, et vous naurez plus de problme :
<?php session_start(); ?> <html>

Limage contient des erreurs


Cest le navigateur qui vous donne ce message derreur et non pas PHP. Ce message survient lorsque vous travaillez avec la bibliothque GD. Si vous avez fait une erreur dans votre code (par exemple une banale parse error ), cette erreur sera inscrite dans limage. Du coup, limage ne sera pas valide et le navigateur ne pourra pas lacher. Bon daccord, lerreur est dans limage. Mais comment faire pour faire apparatre lerreur ? Deux possibilits : vous pouvez supprimer la ligne suivante dans votre code :
<?php header ("Content-type: image/png"); ?>

Lerreur apparatra la place du message Limage contient des erreurs ; vous pouvez aussi acher le code source de limage (comme si vous alliez regarder la source HTML de la page, sauf que l il sagit dune image). 384

QUELQUES ERREURS PLUS RARES Dans les deux cas, vous verrez le message derreur apparatre. partir de l, il ne vous restera plus qu corriger le bug !

Maximum execution time exceeded


a, cest le genre derreur qui arrive le plus souvent cause dune boucle innie :
Fatal error: Maximum execution time exceeded in fichier.php on line 57

Imaginez que vous fassiez une boucle while, mais que celle-ci ne sarrte jamais : votre script PHP va tourner en boucle sans jamais sarrter. Heureusement, PHP limite le temps dexcution dune page PHP 30 secondes par dfaut. Si une page met plus de 30 secondes se gnrer, PHP arrte tout en signalant que cest trop long. Et il fait bien, parce que sinon cela pourrait ralentir tout le serveur et rendre votre site inaccessible ! Voici un exemple de boucle while qui ne sarrtera jamais :
<?php $nombre = 5; while ($nombre == 5) { echo Zro ; } ?>

Comme vous pouvez le voir, un tel code PHP ne sarrtera jamais parce que $nombre vaut TOUJOURS 5. . . Si vous avez donc lerreur Maximum execution time exceeded , il va falloir reprer une boucle qui ne sarrte jamais, car cest elle qui provoque ce problme. Rassurez-vous : la limite est xe 30 secondes, mais vous ny serez jamais confronts. En gnral, un serveur met moins de 50 millisecondes charger une page PHP (on est trs loin des 30 secondes !).

385

ANNEXE C. AU SECOURS ! MON SCRIPT PLANTE !

386

Annexe

Protger un dossier avec un .htaccess

orsque vous ralisez votre site en PHP, vous tes souvent amens crer une zone Admin o laccs est limit. . . Et il vaut mieux, vu que les personnes qui ont accs la zone Admin peuvent en gnral tout supprimer si elles le dsirent.

Supposons que vous ayez cr un dossier Admin dans lequel il y a tous les chiers dadministration de votre site. Comment empcher que nimporte qui accde ces pages ? Cest l que les chiers .htaccess vont bien nous aider : on peut trs facilement crer une protection par login/mot de passe qui empche laccs tous les chiers du dossier.

387

ANNEXE D. PROTGER UN DOSSIER AVEC UN .HTACCESS Il va falloir crer deux chiers : .htaccess : ce chier contiendra ladresse du .htpasswd et quelques autres options que vous pourrez dnir ; .htpasswd : ce chier contiendra une liste de logins/mots de passe, pour chaque personne autorise accder aux pages !

Crer le .htaccess
La premire tape est de crer sur votre disque dur un chier appel .htaccess. Oui, cest un chier qui na pas de nom et qui a seulement une extension, savoir .htaccess. Ne soyez donc pas tonns sil commence par un point. Ouvrez un nouveau chier avec votre diteur de texte favori. Nous allons crire des codes qui nont rien voir avec du HTML ou du PHP : ce sont des instructions pour le serveur. Elles vont lui expliquer que seules certaines personnes sont autorises accder au dossier. Copiez-y ce code :
AuthName "Page dadministration protge" AuthType Basic AuthUserFile "/home/site/www/admin/.htpasswd" Require valid-user

Parmi ces quatre lignes, il y en a deux que vous allez devoir changer : AuthName : cest le texte qui invitera lutilisateur inscrire son login et son mot de passe. Vous pouvez personnaliser ce texte comme bon vous semble ; AuthUserFile : l cest plus dlicat ; cest le chemin absolu vers le chier .htpasswd (que vous mettrez dans le mme rpertoire que le .htaccess).

Mais comment je trouve ce chemin absolu, moi ?

En eet, la plupart du temps, cela savre dlicat trouver car cela dpend du serveur. Heureusement, il existe une fonction PHP qui va beaucoup nous aider : realpath. Cette fonction donne le chemin absolu vers le chier que vous indiquez. Vous allez donc faire comme suit pour trouver le chemin absolu. 1. Crez un chier appel chemin.php. 2. Inscrivez juste cette ligne de code lintrieur :
<?php echo realpath(chemin.php); ?>

3. Envoyez ce chier sur votre serveur avec votre logiciel FTP, et placez-le dans le dossier que vous voulez protger. 4. Ouvrez votre navigateur et allez voir ce chier PHP. Il vous donne le chemin absolu, par exemple dans mon cas : /home/site/www/admin/chemin.php 388

CRER LE .HTPASSWD 5. Copiez ce chemin dans votre .htaccess, et remplacez le chemin.php par .htpasswd, ce qui nous donne au nal par exemple : /home/site/www/admin/.htpasswd 6. Supprimez le chier chemin.php de votre serveur, il ne nous sert plus rien maintenant quil nous a donn le chemin absolu. Si vous tes hbergs chez Free, il y a une petite subtilit dans la gestion de la localisation du .htpasswd : vous ne devez pas renseigner la ligne AuthUserFile par le chemin absolu du chier, mais par son chemin relatif partir de la racine de votre espace perso. Exemple : si vous utilisez un espace Free nomm monftpfree, et que vous placez votre chier .htpasswd dans un rpertoire admin, le chier chemin.php vous renverra un chemin sous la forme /mnt/XXX/sda/X/X/monftpfree/admin/.htpasswd. Vous devez alors simplement crire : /monftpfree/admin/.htpasswd. Enregistrez le chier en inscrivant le nom entre guillemets, comme ceci : ".htaccess". Cela permet de forcer lditeur enregistrer un chier qui commence par un point. Voil : on a ni de crer le .htaccess, on peut maintenant passer au .htpasswd ! ;-)

Crer le .htpasswd
Crez maintenant un nouveau chier avec votre diteur de texte. Le .htpasswd va contenir la liste des personnes autorises accder aux pages du dossier. On y inscrit une personne par ligne, sous cette forme :
login:mot_de_passe_crypt

Au nal, votre chier .htpasswd devrait ressembler ceci :


mateo21:$1$MEqT//cb$hAVid.qmmSGFW/wDlIfQ81 ptipilou:$1$/lgP8dYa$sQNXcCP47KhP1sneRIZoO0 djfox:$1$lT7nqnsg$cVtoPfe0IgrjES7Ushmoy. vincent:$1$h4oVHp3O$X7Ejpn.uuOhJRkT3qnw3i0

Dans cet exemple, il y a quatre personnes autorises accder au dossier : mateo21, ptipilou, djfox et vincent. Comment peut-on crypter les mots de passe ?

Bonne question ! Encore une fois, il y a une super fonction PHP qui va nous tirer daaire : crypt. Vous lui donnez un mot de passe et elle vous le crypte (ne cherchez pas savoir comment). 389

ANNEXE D. PROTGER UN DOSSIER AVEC UN .HTACCESS Par exemple, si mon mot de passe est kangourou , voici le code PHP que je devrai crire pour lobtenir en version crypte :
<?php echo crypt(kangourou); ?>

Crypter ses mots de passe est trs utile : en eet, si quelquun vient un jour lire votre chier .htpasswd (quelquun qui utilise le mme PC que vous par exemple), il ne verra que le mot de passe crypt. Et l, aucun risque quil ne retrouve votre mot de passe : ce cryptage est indchirable. Il est sens unique1 . Bon : on pourrait en thorie sarrter l pour le .htpasswd, mais mon me de codeur PHP me commande de crer un petit script qui va bien vous tre utile (non, non, ne me remerciez pas, cest tout naturel !).
<p> <?php if (isset($_POST[login]) AND isset($_POST[pass])) { $login = $_POST[login]; $pass_crypte = crypt($_POST[pass]); // On crypte le mot de passe echo Ligne copier dans le .htpasswd :<br /> . $login . : . $pass_crypte; } else // On na pas encore rempli le formulaire { ?> </p> <p>Entrez votre login et votre mot de passe pour le crypter.</p> <form method="post"> <p> Login : <input type="text" name="login"><br /> Mot de passe : <input type="text" name="pass"><br /><br /> <input type="submit" value="Crypter !"> </p> </form> <?php } ?>

Code web : 931593 Il y a deux parties dans ce code :


1 Il

sagit en fait dune autre forme de hachage que lon a dcouvert dans le TP espace membres.

390

ENVOYER LES FICHIERS SUR LE SERVEUR 1. SI les variables $_POST[login] et $_POST[pass] existent, alors cest quon vient de valider le formulaire. On crypte le mot de passe quon a entr, et on ache $login:$pass_crypte pour que vous nayez plus qu copier la ligne dans le .htpasswd ; 2. SINON, si les variables $_POST[login] ou $_POST[pass] nexistent pas, on ache donc le formulaire pour demander dentrer un login et un mot de passe. Le formulaire recharge la mme page car il ny a pas dattribut action dans la balise <form>, comme on la vu dans le chapitre sur les formulaires. Lors du rechargement de la page, les variables $_POST[login] et $_POST[pass] existeront puisque vous venez dentrer le login et le mot de passe. Ce dernier sera alors crypt ! Je vous conseille de crer cette page quelque part sur votre disque dur (ou sur votre serveur, peu importe), pour que vous puissiez crypter rapidement vos mots de passe pour le .htpasswd. Si vous avez la emme de la crer, pas de souci, vous navez qu vous servir du code web ci-dessus. Il y a certains cas dans lesquels vous ne devrez pas crypter les mots de passe. Sous WAMP ou sur les serveurs de Free.fr par exemple, vous ne DEVEZ PAS crypter vos mots de passe pour que cela fonctionne. Vous devrez donc les crire directement. Par exemple : mateo21:kangourou

Envoyer les chiers sur le serveur


Vous avez maintenant deux chiers sur votre disque dur : .htaccess et .htpasswd. Lancez votre logiciel FTP. Transfrez les chiers .htaccess et .htpasswd dans le dossier que vous voulez protger par un mot de passe. Vous devriez voir ce qui se trouve la gure D.1 dans votre logiciel FTP.

Fig. D.1 Le contenu du dossier admin vu dans le logiciel FTP Voil : dsormais, le dossier est protg. ;-) Si quelquun essaie daccder lune des pages du dossier (en loccurrence admin.php), il obtiendra une fentre comme celle de la gure D.2 lui demandant de se logger. Si vous entrez le bon login avec le bon mot de passe, vous serez alors autoriss accder aux pages !

391

ANNEXE D. PROTGER UN DOSSIER AVEC UN .HTACCESS

Fig. D.2 Le navigateur demande le mot de passe

392

Annexe

Mmento des expressions rgulires

ette annexe va tre utile ceux qui ont lu les deux chapitres sur les expressions rgulires. Il sagit dun mmento, cest--dire dun rsum qui vous sera utile lorsque vous crirez vos propres regex.

Rfrez-vous cette annexe ds que vous vous apprtez crire une expression rgulire. Elle vous servira de support pour vous rappeler toutes les possibilits des regex.

393

ANNEXE E. MMENTO DES EXPRESSIONS RGULIRES Cette annexe nest PAS faite pour apprendre se servir des regex. Si vous voulez apprendre, allez voir les chapitres correspondants dans ce livre partir de la page 291. Ici, les explications sont succinctes car le but est de synthtiser au maximum tout ce quil y a savoir sur les regex.

Structure dune regex


Une regex est entoure de symboles appels dlimiteurs. On peut choisir ce quon veut ; nous, nous utilisons le dise. Une regex a la forme suivante : #Regex#Options. Pour tester une chane partir dune regex, on utilise preg_match :
<?php preg_match("regex","chaine"); ?>

Le tableau suivant prsente une utilisation basique des regex. regex #guitare# #guitare|piano# #^guitare# #guitare$# #^guitare$# Explication Cherche le mot guitare dans la chane. Cherche le mot guitare OU piano . La chane doit commencer par guitare . La chane doit se terminer par guitare . La chane doit contenir uniquement guitare .

Classes de caractres
Le tableau qui suit prsente le mode demploi des classes de caractres. regex #gr[ioa]s# [a-z] [0-9] [a-e0-9] [0-57A-Za-z.-] #[^0-9]# #^[^0-9]# Explication Chane qui contient gris , ou gros , ou gras . Caractres minuscules de a z. Chires de 0 9. Lettres de a e ou chires de 0 9. Chires de 0 5, ou 7, ou lettres majuscules, ou lettres minuscules, ou un point, ou un tiret. Chane ne contenant PAS de chires. Chane ne commenant PAS par un chire.

Quanticateurs
Le tableau ci-aprs prsente les dirents quanticateurs qui existent. 394

MTACARACTRES regex #a ?# #a+# #a*# #bor ?is# #Ay(ay|oy)*# #a{3}# #a{3,5}# #a{3,}# Explication a peut apparatre 0 ou 1 fois. a doit apparatre au moins 1 fois. a peut apparatre 0, 1 ou plusieurs fois. bois ou boris . Fonctionne pour Ay, Ayay, Ayoy, Ayayayoyayayoyayoyoyoy, etc. a doit apparatre 3 fois exactement ( aaa ). a doit apparatre de 3 5 fois ( aaa , aaaa , aaaaa ). a doit apparatre au moins 3 fois ( aaa , aaaa , aaaaa , aaaaaa , etc.).

Mtacaractres
Les mtacaractres sont : # ! ^ $ ( ) [ ] { } | ? + * . \ Pour utiliser un mtacaractre dans une recherche, il faut lchapper avec un antislash : \. regex #Hein ?# #Hein\ ?# Explication Cherche Hei ou Hein . Cherche Hein ? .

Les mtacaractres nont pas besoin dtre chapps dans une classe, sauf pour # (symbole de n de la regex) et ] (symbole de la n de la classe) que lon doit faire prcder dun antislash. Si on veut rechercher un tiret dans une classe de caractres, il faut le placer au dbut ou la n de la classe : [a-zA-Z0-9-].

Classes abrges
Les classes abrges sont supportes uniquement par les regex PCRE. Classe abrge \d \D \w \W \t \n \r \s \S . Correspondance [0-9] [^0-9] [a-zA-Z0-9_] [^a-zA-Z0-9_] Tabulation. Nouvelle ligne. Retour chariot. Espace blanc (correspond \t \n \r). Ce qui nest PAS un espace blanc (\t \n \r). Classe universelle. 395

ANNEXE E. MMENTO DES EXPRESSIONS RGULIRES Le point est la classe universelle : il signie nimporte quel caractre .

Capture et remplacement
En utilisant la fonction preg_replace on peut automatiquement faire des remplacements laide de regex.
<?php $texte = preg_replace(#\[b\](.+)\[/b\]#i, <strong>$1</strong>, $texte); ?>

Les parenthses servent entourer un bout de la regex pour crer des variables $1, $2, $3, etc. qui seront utiles pour faire le remplacement. Il peut y avoir jusqu 99 parenthses capturantes, donc jusqu $99. ( ?:texte) est une parenthse non capturante : elle ne cre pas de variable. Une variable $0 est toujours cre et correspond lensemble de la regex. Ainsi, la regex suivante. . . #(anti)co( ?:nsti)(tu(tion)nelle)ment# . . . cre les variables suivantes : $0 $1 $2 $3 : : : : anticonstitutionnellement ; anti ; tutionnelle ; tion.

Options
Il existe de nombreuses options que lon peut utiliser avec les regex PCRE. Parmi les trois que nous sommes le plus souvent amens utiliser, il y a : i : la regex ne fera plus la dirence entre majuscules / minuscules ; s : le point (classe universelle) fonctionnera aussi pour les retours la ligne (\n) ; U : mode Ungreedy (pas gourmand). Utilis pour que la regex sarrte le plus tt possible. Pratique par exemple pour le bbCode [b][/b] : la regex sarrtera la premire occurrence de [/b].

396

Index

D date (SQL) . . . . . . . . . . . . . . . . . . . . . . . . . . 237 DELETE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 destructeur . . . . . . . . . . . . . . . . . . . . . . . . . . 332 B Django . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 balise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 documentation . . . . . . . . . . . . . . . . . . . . . . . 371 base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 droits cration . . . . . . . . . . . . . . . . . . . . . . . . . 174 dossier . . . . . . . . . . . . . . . . . . . . . . . . . . 135 base de donnes . . . . . . . . . . . . . . . . . . . . . . 168 chier . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 connexion . . . . . . . . . . . . . . . . . . . . . . . 190 DSN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 bbCode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 dynamique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 bool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51, 54 E boolen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 boucle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 echo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 diteur de chiers . . . . . . . . . . . . . . . . . . . . . 26 C lPHPant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 champ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 champ cach . . . . . . . . . . . . . . . . . . . . . . . . . 124 elseif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 CHMOD . . . . . . . . . . . . . . . . . . . . . . . . 135, 158 encapsulation . . . . . . . . . . . . . . . . . . . . . . . . 336 classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 entre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 cl envoi de chier . . . . . . . . . . . . . . . . . . . . . . . 130 primaire . . . . . . . . . . . . . . . . . . . . 176, 178 exec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 client. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 expression rgulire . . . . . . . . . . . . . 291, 393 commentaire . . . . . . . . . . . . . . . . . . . . . 41, 367 F concatnation . . . . . . . . . . . . . . . . . . . . . . . . . 55 condition. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .62 faille injection SQL . . . . . . . . . . . . . . . . . . . 203 ternaire. . . . . . . . . . . . . . . . . . . . . . . . . . .71 XSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 constructeur . . . . . . . . . . . . . . . . . . . . . . . . . 331 contrleur . . . . . . . . . . . . . . . . . . . . . . . 340, 346 fetch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 chier 397

A alias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Apache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 architecture MVC . . . . . . . . . . . . . . . . . . . . 340 array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 ASP .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 auto_increment . . . . . . . . . . . . . . . . . . . . . . 176

httpOnly . . . . . . . . . . . . . . . . . . . . . . . . 153 COUNT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232 CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

INDEX droits . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 criture. . . . . . . . . . . . . . . . . . . . . . . . . .161 envoi . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 lecture . . . . . . . . . . . . . . . . . . . . . . . . . . 161 ouverture . . . . . . . . . . . . . . . . . . . . . . . . 159 FILES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 float . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51, 54 fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 dagrgat . . . . . . . . . . . . . . . . . . . . . . . . 230 cration . . . . . . . . . . . . . . . . . . . . . . . . . . 87 scalaire . . . . . . . . . . . . . . . . . . . . . . . . . . 226 fonction (SQL) . . . . . . . . . . . . . . . . . . . . . . . 225 for. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .76, 95 foreach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 formulaire. . . . . . . . . . . . . . . . . . . . . . . . . . . .117 framework . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 INSERT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 instruction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 int. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .51, 54 isset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 J Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 JEE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10 JOIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264 jointure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 externe . . . . . . . . . . . . . . . . . . . . . 260, 265 interne . . . . . . . . . . . . . . . . . . . . . 260, 262 JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 L LAMPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 LEFT JOIN . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 LIMIT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 local . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 localhost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

G GD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 gedit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 GET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 M GROUP BY . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 MAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 guillemets doubles . . . . . . . . . . . . . . . . . . . . . . . 53, 56 md5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 simples . . . . . . . . . . . . . . . . . . . . . . . 53, 56 Microsoft SQL Server . . . . . . . . . . . . . . . . . 11 modle . . . . . . . . . . . . . . . . . . . . . . . . . . 340, 344 H modulo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 hachage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 HAVING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 framework . . . . . . . . . . . . . . . . . . . . . . . 349 header . . . . . . . . . . . . . . . . . . . . . . . . . . 220, 272 MySQL . . . . . . . . . . . . . . . . . . . . . . . . 8, 15, 168 hritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 htaccess . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 N HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Notepad++ . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 htmlspecialchars. . . . . . . . . . . . . . . . . . .129 NOW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 htpasswd . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 NULL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 httpOnly. . . . . . . . . . . . . . . . . . . . . . . . . . . . .153 O I objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320, 323 id . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 Oracle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 ORDER BY . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 P inclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 incrmentation . . . . . . . . . . . . . . . . . . . . . . . . 77 paramtre . . . . . . . . . . . . . . . . . . . . . . . . 80, 106 indentation . . . . . . . . . . . . . . . . . . . . . . . . . . 366 Parse Error . . . . . . . . . . . . . . . . . . . . . . 40, 380 index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 PDO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 injection SQL . . . . . . . . . . . . . . . . . . . . . . . . 203 PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8, 15 INNER JOIN . . . . . . . . . . . . . . . . . . . . . . . . . . 264 phpMyAdmin . . . . . . . . . . . . . . . . . . . . . . . . 173 398

INDEX POO . . voir programmation oriente objet POST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 PostgreSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 preg_match . . . . . . . . . . . . . . . . . . . . . . . . . . 293 preg_replace . . . . . . . . . . . . . . . . . . . . . . . 312 print_r . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 private . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 programmation oriente objet . . . . . . . . 319 protected . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 public . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 Q query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194 T table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 cration . . . . . . . . . . . . . . . . . . . . . . . . . 175 tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 associatif . . . . . . . . . . . . . . . . . . . . . . . . . 94 numrot . . . . . . . . . . . . . . . . . . . . . . . . . 92 tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 ternaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 TextMate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 TextWrangler . . . . . . . . . . . . . . . . . . . . . . . . . 31 timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 transtypage . . . . . . . . . . . . . . . . . . . . . . . . . . 113 U UPDATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 upload . . . . . . . . . . . . . . . voir envoi de chier URL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

R redirection . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 regex . . . . . . . . . . . . voir expression rgulire V requte prpare . . . . . . . . . . . . . . . . 203, 212 return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 VARCHAR . . . . . . . . . . . . . . . . . . . . . . . . . . 177 RIGHT JOIN . . . . . . . . . . . . . . . . . . . . . . . . . . 266 variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 superglobale . . . . . . . . . . . . . . . . . . . . . 146 Ruby on Rails. . . . . . . . . . . . . . . . . . . . . . . . .10 tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 vue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340, 347 S SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194 serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 SGBD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 sha1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 site dynamique. . . . . . . . . . . . . . . . . . . . . . . . .4 statique . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Smultron . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169, 194 exportation . . . . . . . . . . . . . . . . . . . . . . 183 fonction . . . . . . . . . . . . . . . . . . . . . . . . . 225 importation . . . . . . . . . . . . . . . . . . . . . 182 injection. . . . . . . . . . . . . . . . . . . . . . . . .203 jointure . . . . . . . . . . . . . . . . . . . . . . . . . 257 SQL Server . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 statique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 NULL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 string . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51, 53 superglobale . . . . . . . . . . . . . . . . . . . . . . . . . 146 switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Symfony . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 W WAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 WHERE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 WYSIWYG . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

X XAMPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 XSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 Z Zend Framework . . . . . . . . . . . . . . . . . . . . . 350

399

Dpt lgal : mai 2010 ISBN : 978-2-9535278-1-0 Code diteur : 978-2-9535278 Imprim en France

Achev dimprimer le 28 mai 2010 sur les presses de ALBEDIA Imprimeurs (Aurillac) Imprim sur papier PEFC issu de forts gres durablement N PEFC : 10-31-1446 ALBEDIA Imprimeurs est agre IMPRIMVERT

Mentions lgales : Crdit photo Mathieu Nebra 4e de couverture : Xavier Granet - 2009 Conception couverture : Fan Jiyong Illustrations chapitres : Yannick Piault PHP est une marque dpose de PHP Group MySQL est une marque dpose de Oracle Corporation Illustrations p.80 : Fotolia Illustrations p.321 : Nab

You might also like