Vous êtes sur la page 1sur 401

PHP5.

2
Dvelopper un site Web dynamique et interactif

OlivierHEURTEL

Rsum

Ce livre sadresse aux concepteurs et dveloppeurs qui souhaitent utiliser PHP 5.2 pour dvelopper un site Web dynamique et interactif.
Aprs une prsentation des principes de base du langage, lauteur se focalise sur les besoins spcifiques du dveloppement de sites
dynamiques et interactifs en sattachant apporter des rponses prcises et compltes aux problmatiques habituelles (gestion des
formulaires, accs aux bases de donnes, gestion des sessions, envoi de courriers lectroniques...).
Pour toutes les fonctionnalits dtailles, de nombreux exemples de code sont prsents et comments. Ce livre didactique, la fois
complet et synthtique, vous permet daller droit au but cest louvrage idal pour se lancer sur PHP.
Les exemples cits dans le livre sont en tlchargement sur le site de lditeur (www.eni-livres.com)."
L'auteur
Aprs plus de huit ans passs en socit de service, o il a successivement occup les postes de dveloppeur, chef de projet puis
directeur de projet sur des missions portant sur la ralisation de systmes d'information, Olivier Heurtel a dmarr une activit de
consultant/formateur indpendant spcialis sur les bases de donnes (Oracle essentiellement) et les outils de dveloppement Web, au
premier rang desquels... PHP bien sr ! Cet ouvrage est le fruit de toute son exprience dans ce domaine et de toute sa passion pour cet
outil de dveloppement.

Ce livre numrique a t conu et est diffus dans le respect des droits dauteur. Toutes les marques cites ont t dposes par leur diteur respectif. La loi du 11
Mars 1957 nautorisant aux termes des alinas 2 et 3 de larticle 41, dune part, que les copies ou reproductions strictement rserves lusage priv du copiste et non
destines une utilisation collective, et, dautre part, que les analyses et les courtes citations dans un but dexemple et dillustration, toute reprsentation ou
reproduction intgrale, ou partielle, faite sans le consentement de lauteur ou de ses ayants droit ou ayant cause, est illicite (alina 1er de larticle 40). Cette
reprsentation ou reproduction, par quelque procd que ce soit, constituerait donc une contrefaon sanctionne par les articles 425 et suivants du Code Pnal.
Copyright Editions ENI

ENI Editions - All rigths reserved - 1-


Objectifdel'ouvrage

L'objectifdecetouvrageestd'apprendredvelopperunsiteWebdynamiqueetinteractifl'aidedePHP5.

Pour rpondre cet objectif, ce livre prsente rapidement les fonctionnalits de base du langage PHP avant
d'tudierendtaillesfonctionnalitsncessairesaudveloppementd'unsiteWebdynamiqueetinteractif :

- gestion des formulaires ;

- accs aux bases de donnes, notamment MySQL, Oracle et Microsoft SQL Server ;

- gestion des sessions (authentification, gestion d'un contexte, utilisation des cookies) ;

- envoi de courriers lectroniques, notamment au format HTML et avec pice jointe ;

- gestion des fichiers (dont le transfert de fichiers du poste de l'utilisateur vers le serveur "file upload").

Cet ouvrage s'adresse des chefs de projet, des concepteurs ou dveloppeurs ayant une connaissance de
base de la programmation Web en HTML (HyperText Markup Language) et quelques notions de SQL (Structured
Query Language langage standard d'accs aux bases de donnes relationnelles) pour le chapitre consacr aux
basesdedonnes.

Ce livre aborde la version 5 de PHP, les fonctionnalits nouvelles, spcifiques cette version, tant clairement
indiques.

ENI Editions - All rigths reserved - 1-


BrefhistoriquedePHP

Le langage PHP (historiquement Personal Home Page, officiellement acronyme rcursif de PHP : Hypertext
Preprocessor)atconuen1994parRasmusLerdorfpourcesbesoinspersonnels,avantd'trerendupublicau
dbutdel'anne1995.

Courant 1995, une nouvelle version, compltement rcrite, est publie sous le nom PHP/FI version 2. Cette
version, capable de grer les formulaires et d'accder la base mSQL, permet au langage de se dvelopper
rapidement.

En1997,ledveloppementdulangageestprisenchargeparunequipeautourdeRasmusLerdorfetaboutitla
sortiedelaversion3.

En 2000, l'analyseur PHP est migr sur le moteur d'analyse Zend afin d'offrir de meilleures performances et de
supporterunplusgrandnombred'extensions :c'estlaversion4dePHP.

En 2004, la version 5 voit le jour. Cette nouvelle version, base sur la version 2 du moteur Zend, apporte
plusieursnouveauts,laplupartconcernantledveloppementorientobjet.

ce jour, les analystes estiment que PHP est utilis par plus de 15 millions de sites Web dans le monde (en
nombrededomaines).

ENI Editions - All rigths reserved - 1-


OseprocurerPHP ?

De nombreux sites Web sont consacrs au langage PHP. Ils permettent de tlcharger le langage, de consulter
desexemplesdescriptsoudedialoguersurdesforums :

Adresse Contenu
www.php.net Site officiel de PHP qui propose le tlchargement des sources
et un manuel de rfrence en ligne trs pratique. Vous pouvez
notamment saisir www.php.net/nom_fonction pour accder
directement l'aide en ligne d'une fonction PHP.
www.phpindex.com Site en franais consacr PHP qui propose le tlchargement
du langage (sources excutables Win32), des news, des
exemples ainsi qu'un forum de discussion... Bref, un site trs
complet mettre dans ses favoris.
www.phpfrance.com Autre site francophone consacr PHP proposant des rubriques
similaires, l'exception du tlchargement.
www.easyphp.org Site francophone qui propose gratuitement un produit installable
(Easy PHP) sur plate-forme Windows. Ce produit comprend : un
serveur Apache, PHP et MySQL. Vous tlchargez le produit et
double cliquez sur l'excutable qui installe les diffrents lments.
Cinq minutes aprs, votre environnement PHP est oprationnel.
Ce site est indispensable pour ceux qui souhaitent monter
rapidement une configuration oprationnelle complte sur
Windows. Les versions utilises par Easy PHP prsentent
toujours un lger retard par rapport aux dernires versions
officielles.
www.zend.com Site officiel (en anglais) du moteur de script Zend qui propose lui
aussi les rubriques classiques de tlchargement, d'exemples, de
forum...
www.editions-eni.com/ Page du site des ditions ENI sur laquelle les exemples traits
exemples/ dans cet ouvrage peuvent tre tlchargs.

Cette liste est videmment non exhaustive mais tous les sites prsents proposent de nombreux liens vers
d'autressites.N'hsitezpassurfer !

ENI Editions - All rigths reserved - 1-


Conventionsd'criture

Lasyntaxedesfonctionsestdcritedelamaniresuivantedanscetouvrage :

type_retour nom_fonction(type_paramtre nom_paramtre)

type_retour

Typederetourdelafonction.

nom_fonction

Nomdelafonction.

type_paramtre

Typeduparamtreacceptparlafonction.

nom_paramtre

Nomdonnauparamtre.

Les types de donnes possibles seront prsents dans le chapitre 3. Dans le cas o la fonction accepte un
paramtreden'importequeltypeet/ouretourneunevaleurden'importequeltype,letermemixteestutilis.

Silafonctionneretournepasdevaleur,l'informationtype_retourestomise.

Exemple

nom_fonction(type_paramtre nom_paramtre)

Silafonctionneprendaucunparamtre,lesinformationstype_paramtreetnom_paramtresontomises.

Exemple

type_retour nom_fonction()

Lesparamtresoptionnelssontindiqusentrecrochets([ ]).

Exemple

type_retour nom_fonction([type_paramtre nom_paramtre])

Si la fonction accepte plusieurs paramtres, ces derniers sont indiqus, spars par une virgule, selon la mme
convention.

Exemple

type_retour nom_fonction(type_paramtre_1 nom_paramtre_1,


type_paramtre_2 nom_paramtre_2)

Siunparamtrepeuttrerptunnombrequelconquedefois,ilestsimplementsuividelasquence[,...].

Exemple

type_retour nom_fonction(type_paramtre nom_paramtre[, ...])

ENI Editions - All rigths reserved - 1-


Qu'estcequePHP?

PHP est un langage de script qui s'excute ct serveur, le code PHP tant inclus dans une page HTML
classique. Il peut donc tre compar d'autres langages de script qui fonctionnent sur le mme principe : ASP
(ActiveServerPages),JSP(JavaServerPages)ouPL/SQLServerPages(PSP).

la diffrence d'un langage comme le JavaScript, o le code est excut ct client (dans le navigateur), le
code PHP est excut ct serveur. Le rsultat de cette excution est intgr dans la page HTML qui est
envoyeaunavigateur.Cederniern'aaucuneconnaissancedel'existencedutraitementquis'estdroulsurle
serveur.

Cette technique permet de raliser des pages Web dynamiques dont le contenu peut tre compltement ou
partiellementgnraumomentdel'appeldelapage,grcedesinformationsrcupresdansunformulaireou
extraitesd'unebasededonnes.

ExemplesimpledepagePHP :

<HTML>
<HEAD>
<TITLE>Exemple de page PHP</TITLE>
</HEAD>
<BODY>
<?php
echo "Bonjour Olivier !";
?>
</BODY>
</HTML>

La partie en gras est du code PHP inclus dans la page HTML l'intrieur des balises <?php et ?>. Sur cet
exemplesimple,lecodePHPsecontented'afficheruntextestatique"BonjourOlivier !"grcelafonctionecho.
Dans un vrai programme PHP, il est probable que ce texte serait gnr dynamiquement en fonction de
l'identificationdel'utilisateur.

Pour indiquer au serveur Web qu'une page HTML contient du code PHP excuter, il suffit de donner au fichier
uneextensionparticulire :.php(saufconfigurationparticulireduserveur).

LesschmassuivantsexpliquentcommentesttraitunfichierPHPparrapportunfichierHTMLnormal.

CasdufichierHTML

DanslecasdufichierHTML,lapagedemandeestdirectementretourneaunavigateur.

CasdufichierPHP

ENI Editions - All rigths reserved - 1-


DanslecasdufichierPHP,lecodePHPinclusdanslapageHTMLestd'abordexcutsurleserveur.Lersultat
decetteexcutionestinsrdanslapagelaplaceducodePHPetlapageestrenvoyeaunavigateur.Cette
excutionctserveurestparfaitementtransparentepourleposteclient.

Danslesdeuxcas,lersultataffichdanslenavigateurseralemme :"BonjourOlivier !".


D'autres langages, comme le PERL (Practical Extraction and Report Language) ou le C, permettent d'crire des
scripts CGI (Common Gateway Interface) dans le but d'obtenir le mme rsultat. Ces langages sont souvent
considrscommemoinspratiquesetmoinslisiblesquePHPpourraliserunepageWebdynamique.Eneffet,le
programme doit gnrer l'intgralit de la page HTML alors qu'en PHP, seule la partie rellement dynamique sera
codel'intrieurdelapage.EnPERL,l'exempleprsentprcdemmentoffriraitlastructuresuivante :

print "content-type : text/html\n\n";


print "<html>";
print "<HEAD>";
print "<TITLE>Exemple de page PHP</TITLE>";
print "</HEAD>";
print "<BODY>";
print " Bonjour Olivier !";
print "</BODY>";
print "</html>";

De plus, PHP a t crit spcialement pour le Web et possde des fonctionnalits parfaitement adaptes ce
typededveloppement,cequin'estlecasnidePERLniduC(quisontparailleursd'excellentslangages).

- 2- ENI Editions - All rigths reserved


Structuredebased'unepagePHP

LesbalisesPHP

Commenousl'avonsvuprcdemment,lecodePHPestinclusdansunepageHTMLl'intrieurdebalises(aussi
appelestags).

PHPacceptequatresyntaxespourlesbalises :

- <?php ... ?> ;

- <? ... ?> ;

- <script language="php"> ... </script> ;

- <% ... %>.

Lapremiresyntaxeestlasyntaxehabituelle,recommande.
La deuxime syntaxe n'est envisageable que si elle a t autorise dans le fichier de paramtrage de PHP
(php.ini) en mettant le paramtre short_open_tag on. Il est dconseill d'utiliser cette syntaxe si votre
code doit tre dploy sur un serveur dont vous ne matrisez pas la configuration et qui ne supporterait pas
cettesyntaxe.
La troisime syntaxe, plus lourde, utilise la balise standard SCRIPT elle peut tre utile si votre diteur HTML
interprtemallesautressyntaxes.
La quatrime syntaxe permet d'employer la balise ASP mais elle est envisageable uniquelent si elle a t
autorisedanslefichierdeparamtragedePHPenmettantleparamtreasp_tagson.

Dans l'exemple suivant, quatre lignes "Bonjour ..." sont affiches en utilisant les diffrentes syntaxes (en
supposantquelefichierdeparamtragedePHPestcorrectementconfigur).

<HTML>
<?php
echo "Bonjour Olivier !";
?>
<BR>
<?
echo "Bonjour Valrie !";
?>
<BR>
<script language="php">
echo "Bonjour Philippe !";
</script>
<BR>
<%
echo "Bonjour Anne !";
%>
</HTML >

Rsultat:

Bonjour Olivier !
Bonjour Valrie !
Bonjour Philippe !
Bonjour Anne !

Lafonctionecho

La fonction echo est la fonction de base de toute page PHP. Elle permet d'afficher une ou plusieurs chanes et
doncd'incluredutextedanslapageHTMLenvoyeaunavigateur.

Syntaxe :

echo(chane texte)
echo chane texte[,...]

ENI Editions - All rigths reserved - 1-


texte texteafficher

Lapremiresyntaxen'acceptequ'unparamtrealorsqueladeuximeenaccepteplusieurs.

Exemple :

<HTML>
<?php
echo("Bonjour Olivier !");
?>
<?php
echo "Bonjour ","Valrie ", "!";
?>
</HTML>

Rsultat :

Bonjour Olivier !Bonjour Valrie !

Iln'ypasdesautdeligneautomatiquedanslersultatdel'excutionducodePHP.Encasdebesoin,ilestdonc
ncessaired'insrerlabaliseHTML<BR>quiprovoqueunsautdelignedanslapageHTMLfinale.

Exemple avec insertion d'une balise <BR> :

<HTML>
<?php
echo("Bonjour Olivier !");
?>
<BR>
<?php
echo "Bonjour ","Valrie ", "!";
?>
</HTML>

Rsultat :

Bonjour Olivier !
Bonjour Valrie !

Le texte pass en paramtre la fonction echo peut tre crit sur plusieurs lignes dans le source mais il est
affichsuruneseuledanslersultat :

Exemple :

<HTML>
<?php
echo "Bonjour
Olivier ", "!";
?>
</HTML>

Rsultat :

Bonjour Olivier !

Lesparateurd'instructions

En PHP, toutes les instructions doivent se terminer par un point-virgule.

Exemple:

<HTML>
<?php
echo("Bonjour ");
echo("Olivier !");
?>

- 2- ENI Editions - All rigths reserved


</HTML>

Rsultat:

Bonjour Olivier !

Encasd'omission,uneerreurestgnre.

Exemple:

<HTML>
<?php
echo("Bonjour ")
echo("Olivier !");
?>
</HTML>

Rsultat:

Parse error: parse error, unexpected T_ECHO, expecting ',' or ';' in d:\scripts php\index.php
on line 4

La seule exception concerne l'instruction qui prcde la balise de fin pour laquelle le pointvirgule peut tre
omis.

Exemple:

<HTML>
<?php
echo("Bonjour ");
echo("Olivier !")
?>
</HTML>

Rsultat:

Bonjour Olivier !

Il est conseill de systmatiquement mettre le point-virgule, mme sur la dernire instruction. En effet, lors d'une modification
du code, il est possible que cette instruction ne soit plus la dernire ; il est alors frquent d'oublier de lui ajouter le point-virgule.

Plusieurs instructions peuvent tre crites sur la mme ligne partir du moment o elles sont spares par un
pointvirgule.Nanmoins,cettecriturenuitparfoislalisibilitducode.

Exemple:

<HTML>
<?php
echo("Bonjour "); echo("Olivier !");
?>
</HTML>

Rsultat:

Bonjour Olivier !

Lecommentaire

PHPproposedeuxsyntaxes :

- // ou # pour insrer du commentaire sur une ligne "ddie" ou la suite d'une instruction ;

- /* ... */ pour insrer du commentaire sur plusieurs lignes.

ENI Editions - All rigths reserved - 3-


Exemple:

<HTML>
<?php
// commentaire sur une seule ligne
# commentaire sur une seule ligne
/* commentaire sur
plusieur lignes */
echo("Bonjour "); // commentaire jusqu' la fin de la ligne
echo("Olivier !"); # commentaire jusqu' la fin de la ligne
?>
</HTML>

Rsultat:

Bonjour Olivier !

Lescommentaires/*...*/nedoiventpastreimbriqus.

Exemple:

<HTML>
<?php
/* commentaire sur
/* plusieurs lignes */
qui pose problme */
echo("Bonjour Olivier !");
?>
</HTML>

Rsultat:

Parse error: parse error, unexpected T_STRING in d:\scripts php\index.php on line 5

MixerduPHPetdel'HTML

IlexistedenombreusesapprochespourmixerduPHPetdel'HTML.

Cesdiffrentesapprochesreposentnanmoinssurdeuxprincipestrssimples :

- La page peut contenir une ou plusieurs inclusion(s) de code PHP.

- Le code PHP gnre du "texte" qui est intgr dans la page HTML envoye au navigateur. Tout "texte" comprhensible
par le navigateur peut donc tre gnr par le code PHP: du texte simple, du code HTML, du code JavaScript...

LesexemplesquisuiventutilisentdesvariablesetdesfonctionsPHP(rcuprationdeladateetdel'heure).Ces
notionssontprsentesplusendtaildanslechapitre3.

Exemple de page contenant du code PHP en plusieurs endroits:

<?php
// dclaration de variables qui sont utilises plus loin
// cette section de code PHP ne gnre pas de sortie dans la page
// HTML (pas d'appel la fonction echo)
$nom = "Olivier"; // nom de l'utilisateur
$titre_page = "Les ditions ENI prsentent ..."; // titre de la page
$aujourdhui = date("d/m/Y"); // date du jour
$heure = date("H:i:s"); // heure
?>
<HTML>
<HEAD>
<TITLE> <?php /* affichage du titre */ echo $titre_page; ?> </TITLE>
</HEAD>
<BODY>
<?php
/* affichage du nom de l'utilisateur
les balises de mise en gras du nom (<B>) et de retour la ligne
(<BR>) sont incluses dans la chane envoye par la fonction echo */

- 4- ENI Editions - All rigths reserved


echo "Bonjour <B>$nom</B> !<BR>";
// affichage de la date et de l'heure
echo "Nous sommes le $aujourdhui ; il est $heure.";
?>
</BODY>
</HTML>

Rsultat:

Bonjour Olivier !
Nous sommes le 08/03/2004 ; il est 09:41:55.

Sourcedelapagedanslenavigateur(leslmentsgnrsparPHPsontengras) :

<HTML>
<HEAD>
<TITLE> Les ditions ENI prsentent ... </TITLE>
</HEAD>
<BODY>
Bonjour <B>Olivier</B> !<BR>Nous sommes le 08/03/2004 ; il est 09:41:55.</BODY>
</HTML>

Exemple de page gnre entirement par du code PHP (suivant le principe CGI):

<?php
// dclaration de variables qui sont utilises plus loin
$nom = "Olivier"; // nom de l'utilisateur
$titre_page = "Les ditions ENI prsentent ..."; // titre de la page
$aujourdhui = date("d/m/Y"); // date du jour
$heure = date("H:i:s"); // heure
// gnration des balises d'ouverture du document HTML
echo "<HTML>";
echo "<HEAD>";
echo "<TITLE> $titre_page </TITLE>";
echo "</HEAD>";
echo "<BODY>";
/* affichage du nom de l'utilisateur
les balises de mise en gras du nom (<B>) et de retour la ligne
(<BR>) sont incluses dans la chane envoye par la fonction echo */
echo "Bonjour <B>$nom</B> !<BR>";
// affichage de la date et de l'heure
echo "Nous sommes le $aujourdhui ; il est $heure.";
// gnration des balises de fermeture du document HTML
echo "</BODY>";
echo "</HTML>";
?>

Rsultat:

Bonjour Olivier !
Nous sommes le 08/03/2004 ; il est 09:52:17.

Source de la page dans le navigateur (tout est sur une ligne):

<HTML><HEAD><TITLE> Les ditions ENI prsentent ... </TITLE></HEAD>


<BODY>Bonjour <B>Olivier</B> !<BR>Nous sommes le 08/03/2004 ;
il est 09:52:17.</BODY></HTML>

Exemple de page contenant du code PHP qui gnre du JavaScript (en gras):

<?php
// dclaration de variables qui sont utilises plus loin
$nom = "Olivier"; // nom de l'utilisateur
$titre_page = "Les ditions ENI prsentent ..."; // titre de la page
?>
<HTML>
<HEAD>
<TITLE> <?php /* affichage du titre */ echo $titre_page; ?> </TITLE>
</HEAD>
<BODY>
<?php
// gnration du code JavaScript charg de l'affichage echo

ENI Editions - All rigths reserved - 5-


"<SCRIPT LANGUAGE=\"JavaScript\"\n";
echo "aujoudhui = new Date()\n";
echo "document.write('Bonjour <B>$nom</B> !<BR>')\n";
echo "document.write('Nous sommes le ')\n";
echo "document.write(aujoudhui.getDate(),'/')\n";
echo "document.write(aujoudhui.getMonth()+1,'/')\n";
echo "document.write(aujoudhui.getYear(),' ;')\n";
echo "document.write('il est ')\n";
echo "document.write(aujoudhui.getHours(),':')\n";
echo "document.write(aujoudhui.getMinutes(),':')\n";
echo "document.write(aujoudhui.getSeconds(),'.')\n";
echo "/SCRIPT\n";
?>
</BODY>
</HTML>

Rsultat:

Bonjour Olivier !
Nous sommes le 08/03/2004 ; il est 10:31:42.

Source de la page dans le navigateur (les lments gnrs par PHP sont en gras):

<HTML>
<HEAD>
<TITLE> Les ditions ENI prsentent ... </TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
aujoudhui = new Date()
document.write('Bonjour <B>Olivier</B> !<BR>')
document.write('Nous sommes le ')
document.write(aujoudhui.getDate(),'/')
document.write(aujoudhui.getMonth()+1,'/')
document.write(aujoudhui.getYear(),' ;')
document.write('il est ')
document.write(aujoudhui.getHours(),':')
document.write(aujoudhui.getMinutes(),':')
document.write(aujoudhui.getSeconds(),'.')
</SCRIPT>
</BODY>
</HTML>

Surcedernierexemple,c'estlecodeJavaScript,excutdanslenavigateur,quiprovoquel'affichagedursultat
danslapageHTML.

Il n'y a pas de rgle pour mixer du PHP et de l'HTML. Une approche couramment employe par les dveloppeurs consiste
utiliser PHP uniquement pour gnrer la partie rellement dynamique de la page ; le reste est directement crit en HTML dans
le fichier. Cette technique rend le code moins lourd et permet de voir tout de suite o se trouve la logique applicative.

Directivesdeconfiguration

Toutaulongdecetouvrage,nousrencontreronsplusieursdirectivesdeconfigurationutilisablespourmodifierle
comportementdePHP.

CesdirectivesdeconfigurationsontsaisiesdanslefichierdeparamtragedePHP(php.ini).

PHPfournitdeuxexemplesdefichiersphp.ini :php.ini-distetphp.ini-recommended.

Le fichier php.ini-dist est un exemple de fichier de configuration, plutt destin tre utilis dans un
environnementdedveloppement.l'inverse,lefichierphp.ini-recommendedestpluttdestintreemploy
dansunenvironnementd'exploitation ilcontientdesrglagesquirendentPHPplusscuriset/ouperformant.

Ces deux fichiers prsentent beaucoup de commentaires qui expliquent le rle de chaque directive et donnent
desconseilssurleurusage.

Pour utiliser un de ces fichiers, copiezle l'emplacement appropri sur votre plateforme
(normalement /usr/local/lib sous Linux/Unix et c:\windows ou c:\winnt sous Windows) et renommezle en
php.ini.

- 6- ENI Editions - All rigths reserved


Dans cet ouvrage, et sauf indication contraire, nous supposerons que deux directives relatives la gestion des
erreurssontpositionnesdelamaniresuivante :

display_errors = on

Leserreurssontaffiches.

error_reporting =
E_ALL & ~E_NOTICE

Toutesleserreurssontaffiches,saufleserreursdeniveau E_NOTICE(simplesinformations,parexemplelorsde
l'utilisationd'unevariablenoninitialise).

Lagestiondeserreursesttraiteendtaildanslechapitre12.

Informationssurlaconfiguration

PHP propose deux fonctions particulirement utiles pour obtenir des informations sur la configuration :
phpversionetphpinfo.

La fonction phpversion retourne le numro de version de PHP et la fonction phpinfo affiche une grande
quantitd'informationssurlaconfigurationdePHPetsonenvironnement.

Syntaxe

chane phpversion()
entier phpinfo([entier quoi])

Avec

quoi

Naturedel'informationdsire.Utiliseruneouplusieurs(somme)desconstantessuivantes :
INFO_GENERAL (1) : informations gnrales (version, emplacement du fichier php.ini, systme d'exploitation,
etc.)
INFO_CREDITS (2) :informationssurlesauteurs.
INFO_CONFIGURATION (4) :informationssurlaconfiguration(valeursdesdirectives).
INFO_MODULES (8) :informationssurlesmoduleschargs,avecleurconfigurationrespective.
INFO_ENVIRONMENT (16) :informationssurl'environnement(voirlavariable$_ENVenannexe).
INFO_VARIABLES (32) :valeursdetouteslesvariablesprdfinies(voirl'annexe).
INFO_LICENSE (64) :informationssurlalicence.
INFO_ALL (-1) :touteslesinformations(valeurpardfaut).

phpinforetourneTRUEencasdesuccsetFALSEencasd'erreur.

Exemple 1:

<?php
echo phpversion();
?>

Rsultat:

5.0.0RC2

Exemple 2:

<?php
// informations gnrales et informations
// de licence
phpinfo(INFO_GENERAL+INFO_LICENSE);
?>

ENI Editions - All rigths reserved - 7-


Rsultat:

Exemple 3:

<?php
// toutes les informations
phpinfo();
?>

Voir aussi les fonctions ini_get_all, ini_get et get_loaded_extensions qui permettent d'obtenir des informations
sur les directives de compilation et les extensions charges.

UtiliserPHPenlignedecommande

Depuislaversion4.3,PHPpeuttreutilisenlignedecommande.Cemodedefonctionnementnencessitepas
deserveurWebetconvientparexempleaudveloppementdesscriptsd'administration.

- 8- ENI Editions - All rigths reserved


Syntaxe simplifie

php [options] [script]

Avec

options

Optionsdelalignedecommande(parexemple,-hpourobtenirl'aide,-vpourlaversion,etc.)

script

FichiercontenantlecodePHPexcuter.

Exemples

C:\>php -v
PHP 5.0.0RC2 (cli) (built: Apr 25 2004 12:14:44)
Copyright (c) 1997-2004 The PHP Group
Zend Engine v2.0.0RC2, Copyright (c) 1998-2004 Zend Technologies

C:\>php script.php Olivier


Bonjour Olivier !

Contenuduscriptscript.php :

<?php
// afficher un simple message
// en utilisant le paramtre
// pass sur la ligne de commande
echo "Bonjour $argv[1] !";
?>

ENI Editions - All rigths reserved - 9-


Rglesdenommage

TouteentitPHPnomme(variable,constante,fonction...)doitavoirunnomquirespectelesrglessuivantes :

- commencer par une lettre ou un soulign (_) ;

- comporter ensuite des lettres, des chiffres ou le caractre soulign.

Danscettedfinition,unelettrereprsentetoutelettreminusculeoumajusculecompriseentreaetz(azet
A Z) ainsi que tout caractre de code ASCII compris entre 127 et 255. Les caractres accentus sont donc
autoriss,maispaslescaractresdutype#$%&quiontunesignificationspcialedanslelangagePHP.

ENI Editions - All rigths reserved - 1-


Constantes

Dfinition

Lafonctiondefinepermetdedfiniruneconstante.
Une constante est une zone mmoire identifie par un nom qui contient une valeur lisible mais non modifiable
dansleprogramme.

Syntaxe

boolen define(chane nom, mixte valeur[, boolen sensible_casse)

nom

Nomdelaconstante(cf.chapitreVued'ensembledePHPRglesdenommage).

valeur

Valeurdelaconstante.

sensible_casse

Indiquesilenomdelaconstanteestsensiblelacasse(TRUEvaleurpardfaut)ounon(FALSE).

LafonctiondefineretourneTRUEencasdesuccsetFALSEencasd'erreur.

Touttypededonnescalaire(cf.Typesdedonnesdanscechapitre)peuttreutiliscommetypededonne
d'uneconstante.

Le nom d'une constante ne doit pas commencer par un $ car ce prfixe est rserv au nom des variables (cf.
Variables dans ce chapitre). Dfinir une constante dont le nom commence pas un $ ne gnre pas d'erreur
(defineretourneTRUE).Cependant,l'utilisation,laconstanteseravuecommeunevariablenoninitialise.

Unefoiscre,uneconstanten'estplusmodifiable,niparunnouvelappel define (retourneFALSEetlaissela


valeurdelaconstanteinchange),niparuneaffectationdirecte(gnreuneerreurd'analyseduscript).

Exemples

<?php
// dfinir une constante (dont le nom est par dfaut
// sensible la casse)
define("CONSTANTE","valeur de CONSTANTE");
// afficher la valeur de CONSTANTE (=> OK)
echo "CONSTANTE = ",CONSTANTE,"<BR>";
// afficher la valeur de constante (=> vide)
echo "constante = ",constante;
echo " => interprt en littral<BR>";
// tentative de modification de CONSTANTE
define("CONSTANTE","nouvelle valeur de CONSTANTE");
echo "CONSTANTE = ",CONSTANTE;
echo " => inchange<BR>";
// utilisation d'un mauvais nom de constante
define($MAUVAISNOM,"mauvais nom de constante");
echo "\$MAUVAISNOM = ",$MAUVAISNOM;
echo " => c'est une variable (non initialise)<BR>";
?>

Rsultat

CONSTANTE = valeur de CONSTANTE


constante = constante => interprt en littral
CONSTANTE = valeur de CONSTANTE => inchange
$MAUVAISNOM = => c'est une variable (non initialise)

Traditionnellement,lesnomsdesconstantessontdfinisenmajuscules.

ENI Editions - All rigths reserved - 1-


Sur l'exemple prcdent, la notation \$ est utilise afin d'empcher une interprtation particulire lie la prsence d'un $
dans une chane de caractres (cf. chapitre Constantes, variables, types et tableaux - Types de donnes - Types disponibles).

Utiliser une constante non dfinie (ou une variable non initialise) ou tenter de redfinir une constante dj
dfinie gnre une erreur de niveau E_NOTICE. Le niveau d'erreur effectivement signal par PHP dpend de
directivesdeconfigurationdanslefichier php.ini(voirlechapitre12).Lersultatprcdentcorrespondune
configuration dans laquelle les erreurs de niveau E_NOTICE ne sont pas affiches dans le cas contraire, nous
obtiendrionslersultatsuivant :

Rsultat

CONSTANTE = valeur de CONSTANTE


constante =
Notice: Use of undefined constant constante - assumed 'constante'
in d:\scripts php\index.php on line 8
constante => interprt en littral

Notice: Constant CONSTANTE already defined in d:\scripts php\index.php


on line 11
CONSTANTE = valeur de CONSTANTE => inchange
Notice: Undefined variable: MAUVAISNOM in d:\scripts php\index.php
on line 15
$MAUVAISNOM =
Notice: Undefined variable: MAUVAISNOM in d:\scripts php\index.php
on line 16
=> c'est une variable (non initialise)

Porte

La porte d'une constante est le script dans lequel elle est dfinie. Une constante peut donc tre dfinie dans
unepremiresectiondecodePHPetutilisedansuneautresectiondecodePHPdummescript.

Exemple

<?php
// dfinir une constante
define("NOM","Olivier");
?>
<HTML>
<BODY>
Bonjour <B><?php echo NOM; ?></B> !
</BODY>
</HTML>

Rsultat

Bonjour Olivier !

Fonctionsutiles

Lafonctiondefinedpermetdesavoirsiuneconstanteestdfinieounon.

Syntaxe

boolen defined(chane nom)

nom Nomdelaconstante

definedretourneTRUEsilaconstanteestdfinieetFALSEdanslecascontraire.

Exemple

<?php
// tester si la constante CONSTANTE est dfinie
$ok = defined("CONSTANTE");

- 2- ENI Editions - All rigths reserved


if ($ok) {
echo "CONSTANTE est dfinie.<BR>";
} else {
echo "CONSTANTE n'est pas dfinie.<BR>";
};
// dfinir la constante CONSTANTE
define("CONSTANTE","valeur de CONSTANTE");
// tester si la constante CONSTANTE est dfinie
$ok = defined("CONSTANTE");
if ($ok) {
echo "CONSTANTE est dfinie.<BR>";
} else {
echo "CONSTANTE n'est pas dfinie.<BR>";
};
?>

Rsultat

CONSTANTE n'est pas dfinie.


CONSTANTE est dfinie.

Cet exemple utilise la structure de contrle if qui permet de tester une condition et d'agir en consquence (cf. chapitre
Structures de contrle).

Lafonctionconstantretournelavaleurd'uneconstantedontlenomestpassenparamtre.

Syntaxe

mixte constant(chane nom)

Avec

nom Nomdelaconstante.

Cettefonctionestpratiquepourrcuprerlavaleurd'uneconstantedontlenomn'estpasconnuapriori.

Exemple

<?php
// dfinir le nom de la constante dans une variable
$nomConstante = "CONSTANTE";
// dfinir la valeur de la constante
define($nomConstante,"valeur de CONSTANTE");
// afficher la valeur de la constante
echo $nomConstante," = ",constant($nomConstante);
?>

Rsultat

CONSTANTE = valeur de CONSTANTE

D'autres fonctions permettent de connatre le type d'une constante (cf. Chapitre Constantes Fonctions
utiles).

ENI Editions - All rigths reserved - 3-


Variables

Une variable est une zone mmoire identifie par un nom qui contient une valeur lisible ou modifiable dans le
programme.

Initialisationetaffectation

En PHP, les variables sont identifies par le prfixe $ suivi d'un nom qui respectent les rgles de nommage
prsentesdanslechapitre2.

Le nom des variables est sensible la casse : $nom et $Nom sont vues par PHP comme deux variables
diffrentes. Ce comportement est dangereux car, en cas d'utilisation d'une mauvaise syntaxe, une nouvelle
variable vide est cre avec une simple erreur de niveau E_NOTICE qui n'est pas forcment affiche (voir le
chapitreGrerleserreursdansunscriptPHP).Ilestdoncprimordiald'adopteruneconventiondenommageetde
larespecter.Quelquessuggestions :

- tout en minuscules ($nom);

- premire lettre en majuscule et le reste en minuscules ($Nom);

- premire lettre de chaque mot en majuscule et le reste en minuscules ($NomDeFamille).

Les variables PHP sont automatiquement dfinies lors de leur premire utilisation. Il n'y a pas d'instruction
spcifiquepourcrerunevariable.

LesvariablesPHPsonttypesautomatiquement lorsdechaqueaffectationd'unevaleurunevariable,letype
delavariableestautomatiquementdfiniouredfini(cf.Typesdedonnes).

Une valeur peut tre affecte une variable grce l'oprateur d'affectation "= " (cf. chapitre Oprateurs pour
lalistedetouslesoprateurs).

Exemple

<?php
// initialiser une variable $nom
$nom = "Olivier";
// afficher la variable $nom
echo "\$nom = ",$nom,"<BR>";
// afficher la variable $Nom
echo "\$<B>N</B>om = ",$Nom;
echo " => vide (c'est une autre variable)<BR>";
// modifier la valeur (et le type) de la variable $nom
$nom = 123;
// afficher la variable $nom
echo "\$nom = ",$nom,"<BR>";
?>

Rsultat (x les erreurs de niveau E_NOTICE ne sont pas affiches)

$nom = Olivier
$Nom = => vide (c'est une autre variable)
$nom = 123

Tout au long de cet ouvrage, nous aurons l'occasion de rencontrer des variables automatiquement dfinies par PHP et
contenant des valeurs relatives l'environnement, PHP, aux formulaires, aux cookies...

Porteetduredevie

La porte d'une variable est le script dans lequel elle est dfinie. Une variable peut donc tre dfinie dans une
premiresectiondecodePHPetutilisedansuneautresectiondecodePHPdummescript.

La dure de vie d'une variable est le temps de l'excution du script. Lorsque le script se termine, les variables
sontsupprimes.Silemmescriptestappelplustard,denouvellesvariablessontdfinies.

ENI Editions - All rigths reserved - 1-


Exemple

<?php
// afficher le contenu de la variable $nom
echo "\$nom = ",$nom,"<BR>";
// initialiser la variable $nom
$nom = "Olivier";
// afficher de nouveau le contenu de la variable $nom
echo "\$nom = ",$nom,"<BR>";
?>

Rsultat du premier appel du script

$nom =
$nom = Olivier

Rsultat du deuxime appel du script

$nom =
$nom = Olivier

Entre les deux appels, la variable a t supprime. Au dbut du deuxime appel, elle ne contient plus la valeur
qu'ellepossdaitlafindupremierappel(cen'estpluslammevariable).

Nous verrons dans le chapitre 9 comment conserver la valeur d'une variable au-del de l'excution du script ou comment
transmettre la valeur d'une variable d'un script un autre.

Fonctionsutiles

PHPproposeuncertainnombredefonctionsutilessurlesvariables :

Nom Rle
empty Indique si une variable est vide ou non.
isset Indique si une variable est dfinie ou non.
unset Supprime une variable.
var_dump Affiche des informations sur une variable (type et valeur).

empty

Lafonctionemptypermetdetestersiunevariableestvideounon.

Syntaxe

boolen empty(mixte variable)

variable Variabletester

emptyretourneTRUEsilavariableestvideetFALSEdanslecascontraire.

Unevariableestconsidrecommevidesiellen'apastaffecteousiellecontientunechanevide(""),une
chanegale0("0")ou0.

Exemple

<?php
// test d'une variable non initialise
$vide = empty($variable);
echo "\$variable = ",$variable,"<BR>";
if ($vide) {
echo "=> \$variable est vide.<BR>";
} else {

- 2- ENI Editions - All rigths reserved


echo "=> \$variable n'est pas vide.<BR>";
}

// test d'une variable contenant une chane vide


$variable = "";
$vide = empty($variable);
echo "\$variable = ",$variable,"<BR>";
if ($vide) {
echo "=> \$variable est vide.<BR>";
} else {
echo "=> \$variable n'est pas vide.<BR>";
}
// test d'une variable contenant une chane gale 0
$variable = "0";
$vide = empty($variable);
echo "\$variable = ",$variable,"<BR>";
if ($vide) {
echo "=> \$variable est vide.<BR>";
} else {
echo "=> \$variable n'est pas vide.<BR>";
}
// test d'une variable contenant 0
$variable = 0;
$vide = empty($variable);
echo "\$variable = ",$variable,"<BR>";
if ($vide) {
echo "=> \$variable est vide.<BR>";
} else {
echo "=> \$variable n'est pas vide.<BR>";
}
// test d'une variable contenant une chane non vide
$variable = "x";
$vide = empty($variable);
echo "\$variable = ",$variable,"<BR>";
if ($vide) {
echo "=> \$variable est vide.<BR>";
} else {
echo "=> \$variable n'est pas vide.<BR>";
}
// test d'une variable contenant une valeur diffrente de 0
$variable = 1;
$vide = empty($variable);
echo "\$variable = ",$variable,"<BR>";
if ($vide) {
echo "=> \$variable est vide.<BR>";
} else {
echo "=> \$variable n'est pas vide.<BR>";
}
?>

Rsultat

$variable =
=> $variable est vide.
$variable =
=> $variable est vide.
$variable = 0
=> $variable est vide.
$variable = 0
=> $variable est vide.
$variable = x
=> $variable n'est pas vide.
$variable = 1
=> $variable n'est pas vide.

isset

Lafonctionissetpermetdetestersiunevariableestdfinieounon.

Syntaxe

boolen isset(mixte variable)

variable Variabletester

ENI Editions - All rigths reserved - 3-


issetretourneTRUEsilavariableestdfinieetFALSEdanslecascontraire.
Unevariableestconsidrecommenondfiniesiellen'apastaffecte.ladiffrencedelafonctionempty,
une variable qui contient une chane vide (""), une chane gale 0 ("0") ou un 0, n'est pas considre comme
nondfinie.

Exemple

<?php
// test d'une variable non initialise
$dfinie = isset($variable);
echo "\$variable = ",$variable,"<BR>";
if ($dfinie) {
echo "=> \$variable est dfinie.<BR>";
} else {
echo "=> \$variable n'est pas dfinie.<BR>";
}
// test d'une variable contenant une chane vide
$variable = "";
$dfinie = isset($variable);
echo "\$variable = ",$variable,"
";
if ($dfinie) {
echo "=> \$variable est dfinie.<BR>";
} else {
echo "=> \$variable n'est pas dfinie.<BR>";
}
// test d'une variable contenant une chane gale 0
$variable = "0";
$dfinie = isset($variable);
echo "\$variable = ",$variable,"<BR>";
if ($dfinie) {
echo "=> \$variable est dfinie.<BR>";
} else {
echo "=> \$variable n'est pas dfinie.<BR>";
}
// test d'une variable contenant 0
$variable = 0;
$dfinie = isset($variable);
echo "\$variable = ",$variable,"<BR>";
if ($dfinie) {
echo "=> \$variable est dfinie.<BR>";
} else {
echo "=> \$variable n'est pas dfinie.<BR>";
}
// test d'une variable contenant une chane non vide
$variable = "x";
$dfinie = isset($variable);
echo "\$variable = ",$variable,"<BR>";
if ($dfinie) {
echo "=> \$variable est dfinie.<BR>";
} else {
echo "=> \$variable n'est pas dfinie.<BR>";
}
// test d'une variable contenant une valeur diffrente de 0
$variable = 1;
$dfinie = isset($variable);
echo "\$variable = ",$variable,"<BR>";
if ($dfinie) {
echo "=> \$variable est dfinie.<BR>";
} else {
echo "=> \$variable n'est pas dfinie.<BR>";
}
?>

Rsultat

$variable =
=> $variable n'est pas dfinie.
$variable =
=> $variable est dfinie.
$variable = 0
=> $variable est dfinie.
$variable = 0
=> $variable est dfinie.
$variable = x
=> $variable est dfinie.

- 4- ENI Editions - All rigths reserved


$variable = 1
=> $variable est dfinie.

unset

Lafonctionunsetpermetdesupprimerunevariable.

Syntaxe

unset(mixte variable[, ...])

variable Variablesupprimer(ventuellementplusieurs,sparesparunevirgule).

unsetaccepteunelistedevariables.

Aprssuppression,lavariablesetrouvedanslemmetatquesiellen'avaitjamaistaffecte.L'utilisationde
lafonctionissetsurunevariablesupprimeretourneFALSEnotamment.

Exemple

<?php
// dfinir une variable
$variable = 1;
// afficher la variable et tester si elle est dfinie
$dfinie = isset($variable);
echo "\$variable = ",$variable,"<BR>";
if ($dfinie) {
echo "=> \$variable est dfinie.<BR>";
} else {
echo "=> \$variable n'est pas dfinie.<BR>";
}
// supprimer la variable
unset($variable);
// afficher la variable et tester si elle est dfinie
$dfinie = isset($variable);
echo "\$variable = ",$variable,"<BR>";

if ($dfinie) {
echo "=> \$variable est dfinie.<BR>";
} else {
echo "=> \$variable n'est pas dfinie.<BR>";
}
?>

Rsultat

$variable = 1
=> $variable est dfinie.
$variable =
=> $variable n'est pas dfinie.

Affecter un 0 ou une chane vide une variable ne la supprime pas.

var_dump

Lafonctionvar_dumpaffichedesinformationssurunevariable(typeetcontenu).

Syntaxe

var_dump(mixte variable)

variable Variableafficher.

Lafonctionvar_dumpestsurtoutintressantelorsdesphasesdemiseaupoint.

Exemple

ENI Editions - All rigths reserved - 5-


<?php
// afficher les informations sur une variable non initialise
var_dump($variable);
// initialiser la variable avec un nombre entier
$variable = 10;
// afficher les informations sur la variable
echo "<BR>";
var_dump($variable);
// modifier la valeur (et le type) de la variable
$variable = 3.14; // nombre dcimal
// afficher les informations sur la variable
echo "<BR>";
var_dump($variable);
// modifier la valeur (et le type) de la variable
$variable = "abc";
// afficher les informations sur la variable
echo "<BR>";
var_dump($variable);
?>

Rsultat

NULL
int(10)
float(3.14)
string(3) "abc"

Pour une variable non initialise, var_dump retourne NULL. Pour un nombre, var_dump indique le type (int =
entier,float=nombredcimal)suividelavaleurentreparenthses.Pourunechane,var_dumpindiqueletype
(string)suividelalongueurentreparenthses,suiviedelavaleurentreguillemets.

PHPproposeaussilesfonctionsprint_retvar_exportsemblableslafonctionvar_dump.Lafonctionprint_r
affiche ou retourne le contenu de la variable sous une forme plus lisible, sans mention du type de donnes. La
fonction var_export affiche ou retourne une chane donnant un code PHP de dfinition de la variable cette
fonctionestnouvelleenversion5.

Dans la section C - Types de donnes de ce chapitre, nous tudierons d'autres fonctions qui permettent de dterminer le type
d'une variable et d'effectuer des conversions de type (nombre en chane, chane en nombre...).

Variabledynamique(ouvariablevariable)

PHP propose une fonctionnalit de variable dynamique (aussi appele variable variable) utile dans certaines
situations.

Leprincipeconsisteemployerunevariablequistockelenomd'uneautrevariableetd'yfairerfrenceensuite
avecunenotation,dutype$$variableou${$variable}.Aveccettenotation,le$variable"intrieur"estremplac
par la valeur de la variable $variable (valeur par exemple) qui est alors utilise comme nom de variable par le $
"extrieur"(soit$valeursurnotreexemple).

Exemple

<?php
$une_variable = 10;
$nom_variable = "une_variable";
echo "\$une_variable = ",$une_variable,"<BR>";
echo "\$nom_variable = ",$nom_variable,"<BR>";
echo "\$\$nom_variable = ",$$nom_variable,"<BR>";
?>

Rsultat

$une_variable = 10
$nom_variable = une_variable
$$nom_variable = 10

- 6- ENI Editions - All rigths reserved


Typesdedonnes

Typesdisponibles

PHP propose 4 types de donnes scalaires (ne pouvant contenir qu'une valeur), 2 types composs (pouvant
contenirplusieursvaleurs) et2typesspciaux:

- Types scalaires :

- nombre entier ;

- nombre virgule flottante ;

- chane de caractre ;

- boolen

- Types composs :

- tableau (cf. Tableaux);

- objet (cf. chapitre Fonctions et Classes) ;

- Types spciaux :

- NULL ;

- Ressource.

Entier

Letypeentier(integer)permetdestockerunnombreentiersignsur32bits,soitdesvaleurscomprisesentre
2147483648(2^31)et+2147483647(+2^311).

En cas de dpassement de capacit dans un calcul, le rsultat est automatiquement converti en nombre
virguleflottante.

Nombrevirguleflottante

Le type nombre virgule flottante (float) permet de stocker un nombre dcimal sur une plage de valeurs
dpendantedelaplateforme(gnralementdel'ordrede10308 10+308 ).

Un tel nombre peut tre exprim en notation dcimale x.y (par exemple 123.456) ou en notation scientifique
x.yEzoux.yez(parexemple1.23456E2).

Encasdeconversiond'unnombrevirguleflottanteenentier,lenombreesttronqu(pasarrondi)l'entierle
plusproche(1.9donne1parexemple).Encasdedpassementdecapacit,aucunmessagen'estaffich,mais
lavaleurl'arriveestindfinie(frquemment 0).

Des librairies particulires (aussi appeles Bibliothques) sont proposes par PHP pour traiter les nombres de grande taille
(librairies BC ou GMP).

Chanedecaractres

Letypechanedecaractres(string)permetdestockertoutesquencedecaractressurunoctet(codeASCII
comprisentre0et255),sanslimitedetaille.

ENI Editions - All rigths reserved - 1-


Une expression littrale de type chane de caractres peut tre spcifie entre guillemets ("ceci est une
chane") ou entre apostrophes ('ceci aussi est une chane') avec des diffrences de comportement trs
importantesquisontexposesciaprs.

Les guillemets prsents dans une chane dlimite par des guillemets ou les apostrophes prsents dans une
chanedlimitepardesapostrophesdoiventtre"chapps",c'estdireprcdsducaractreantislash(\).
En complment, un antislash prsent en fin de chane, juste avant le guillemet ou l'apostrophe finaux, doit lui
aussitrechappparunantislash.

Exemple

<?php
echo "c'est l't => pas de problme.<BR>";
echo 'je dis "bonjour" => pas de problme.<BR>';
// echo 'c'est l't => erreur de compilation.<BR>';
echo 'c\'est l\'t => problme corrig.<BR>';
// echo "je dis "bonjour" => erreur de compilation.<BR>";
echo "je dis \"bonjour\" => problme corrig.<BR>";
// echo "c:\"," => erreur de compilation.<BR>";
echo "c:\\"," => problme corrig.<BR>";
// echo 'c:\'," => erreur de compilation.<BR>";
echo 'c:\\'," => problme corrig.<BR>";
?>

Rsultat

c'est l't => pas de problme.


je dis "bonjour" => pas de problme.
c'est l't => problme corrig.
je dis "bonjour" => problme corrig.
c:\ => problme corrig.
c:\ => problme corrig.

Unechanepeuttresaisiesurplusieurslignes.

Exemple :

<?php
$chane = "Je m'appelle Olivier
et j'habite en France.";
echo $chane;
?>

Rsultat (dans le navigateur)

Je m'appelle Olivier et j'habite en France.

Rsultat (dans le source)

Je m'appelle Olivier
et j'habite en France.

Le retour la ligne prsent dans la chane initiale est retrouv dans le source de la page, mais n'est pas
interprt comme tel par le navigateur. Il faut une balise <BR> pour obtenir un retour ligne dans le rsultat
affich.

Exemple :

<?php
$chane = "Je m'appelle Olivier<BR>
et j'habite en France.";
echo $chane;
?>

Rsultat (dans le navigateur)

Je m'appelle Olivier

- 2- ENI Editions - All rigths reserved


et j'habite en France.

Lorsqu'unechaneestdlimitepardesguillemets,toutesquencedecaractrescommenantparlesigne$est
interprtecommeunevariableetremplaceparlavaleurdelavariable :c'estlemcanismedesubstitutiondes
variables par leur valeur. Cette fonctionnalit, trs pratique, ne fonctionne pas avec les chanes dlimites par
desapostrophes(premirediffrenceentrelesdeuxtypesdechanes).

Exemple

<?php
$nom = "Olivier";
echo "Je m'appelle $nom.<BR>";
echo "... est plus simple crire que<BR>";
echo "Je m'appelle ",$nom,".<BR>";
echo "... et donne le mme rsultat.<BR>";
echo 'Je m\'appelle $nom, par contre ne fonctionne pas.<BR>';
?>

Rsultat

Je m'appelle Olivier.
... est plus simple crire que
Je m'appelle Olivier.
... et donne le mme rsultat.
Je m'appelle $nom, par contre ne fonctionne pas.

Danscertainscas,cecomportementpeutnepastredsir.Ilsuffitd'chapperlesigne$avecl'antislash (\)
pourqu'ilsecomportecommeun$.

Exemple

<?php
$nom = "Olivier";
echo "\$nom = $nom";
?>

Rsultat

$nom = Olivier

Dans d'autres cas, le comportement peut tre souhait avec le besoin d'accoler du texte complmentaire
derrirelenomdelavariable.

Exemple

<?php
$fruit = "pomme";
echo "Une $fruit ne cote pas cher.<BR>";
echo "Deux $fruits cotent deux fois plus cher.<BR>";
?>

Rsultat

Une pomme ne cote pas cher.


Deux cotent deux fois plus cher.

Surcetexemple,le"s"duplurielestinterprtparPHPcommeappartenantlasquencedecaractressitue
derrire le $ c'est donc la variable $fruits qui est reconnue et remplace par sa valeur (vide puisque la
variablen'ajamaistinitialise).
La solution consiste dlimiter le nom de la variable par des accolades sous la forme {$variable} ou
${variable}. L encore, si cette interprtation de l'accolade n'est pas souhaite, il est possible d'utiliser la
caractred'chappementantislashdevantlapremireaccoladeuniquement.

Exemple

<?php

ENI Editions - All rigths reserved - 3-


$fruit = "pomme";
echo "Une $fruit ne cote pas cher.<BR>";
echo "Deux {$fruit}s cotent deux fois plus cher.<BR>";
echo "Trois ${fruit}s cotent trois fois plus cher.<BR>";
echo "{\$fruit} = \{$fruit}.<BR>";
?>

Rsultat

Une pomme ne cote pas cher.


Deux pommes cotent deux fois plus cher.
Trois pommes cotent trois fois plus cher.
{$fruit} = {pomme}.

Il n'y a pas de mcanisme de substitution quivalent pour les constantes ; c'est une raison valable pour utiliser des variables
en lieu et place de vraies constantes.

En complment, d'autres squences d'chappement peuvent tre utilises dans les chanes dlimites par des
guillemets, mais pas dans celles dlimites par des apostrophes (deuxime diffrence entre les deux types de
chanes).

Squence Valeur
\n Saut de ligne (= LF = code ASCII 10)
\r Retour chariot (= CR = code ASCII 13)
\t Tabulation (= HT = code ASCII 9)
\\ \ (dj abord)
\$ $ (dj abord)
\nnn Le caractre dsign par le code ASCII nnn exprim en octal

Exemple

<?php
echo "Je m'appelle Olivier.<BR>\n";
echo "Je m'appelle \117\154\151\166\151\145\162.";
?>

Rsultat

Je m'appelle Olivier.
Je m'appelle Olivier.

Rappel : un saut de ligne dans le source de la page envoye au navigateur ne provoque pas de saut de ligne dans la page
affiche. C'est le cas de la squence "\n" utilise dans notre exemple. Ici la balise <BR> provoque le retour la ligne dans la
page affiche.

PHPestcapabledeconvertirunechaneennombre(entieroudcimal)l'aidedesrglessuivantes :

- Si le premier caractre non "blanc" (autre que espace, tabulation, LF, CR) n'est ni un chiffre, ni un point ni le signe
"moins", la chane est value 0 (entier).

- Dans le cas contraire, PHP va extraire tous les caractres non "blancs" du dbut de chane jusqu' rencontrer un
caractre non numrique (c'estdire non compris entre 1 et 9, diffrent du point, du signe "moins" et du symbole
scientifique "e" ou "E"); la squence ainsi obtenue est convertie en entier (pas de point ni de symbole scientifique) ou
en dcimal (en cas de prsence d'un point ou du symbole scientifique).

Exemple

<?php
echo '1 + "1" = ',var_dump(1 + "1"),"<BR>";
echo '1 + "1.5" = ',var_dump(1 + "1.5"),"<BR>";
echo '1 + "1.5E2" = ',var_dump(1 + "1.5E2"),"<BR>";
echo '1 + "1e3" = ',var_dump(1 + "1e3"),"<BR>";

- 4- ENI Editions - All rigths reserved


echo '1 + 1abc = ',var_dump(1 + "1abc"),"<BR>";
echo '1 + "1.5abcd" = ',var_dump(1 + "1.5abcd"),"<BR>";
echo '1 + "1.5 abcd" = ',var_dump(1 + "1.5 abcd"),"<BR>";

echo '1 + ".5" = ',var_dump(1 + ".5"),"<BR>";


echo '1 + "-5" = ',var_dump(1 + "-5"),"<BR>";
echo '1 + " \t\n\r 5" = ',var_dump(1 + " \t\n\r 5"),"<BR>";
echo '1 + "abc1" = ',var_dump(1 + "abc1"),"<BR>";
?>

Rsultat

1 + "1" = int(2)
1 + "1.5" = float(2.5)
1 + "1.5E2" = float(151)
1 + "1e3" = float(1001)
1 + 1abc = int(2)
1 + "1.5abcd" = float(2.5)
1 + "1.5 abcd" = float(2.5)
1 + ".5" = float(1.5)
1 + "-5" = int(-4)
1 + " \t\n\r 5" = int(6)
1 + "abc1" = int(1)

Le dernier exemple montre qu'une chane qui ne commence pas par un caractre numrique est convertie en
entiergal0.

Ces mcanismes de conversion se rvlent pratiques dans certains cas mais peuvent galement conduire des
problmesdifficilesdtectercarPHPrefusepeudechoselacompilationduscript !

Il est possible d'accder au nime caractre d'une chane grce la notation $x{i} (ou $x[i] pour la compatibilit
ascendante), $x dsignant la variable de type chane et i le numro du caractre (le premier caractre portant le numro 0).

Boolen

Letypeboolen(boolean)peutprendredeuxvaleurs:TRUE(outrue)etFALSE(oufalse).

Ce type de donnes est principalement utilis dans les structures de contrle pour tester une condition (cf.
chapitreStructuresdecontrle).

PHPestcapabledeconvertirtouttypededonneenboolenselonlesrglessuivantes :

Valeur Rsultat Conversion


nombre entier 0 FALSE
nombre dcimal 0.000...
chane vide ("")
chane gale 0 ("0")
tableau vide
objet vide
constante NULL (cf. Le "type" Null)
tout le reste TRUE

Une valeur gale -1 est convertie en TRUE avec PHP.

Inversement,PHPestcapabled'oprerlesconversionssuivantes :

TRUE FALSE
Boolen -> Nombre 1 0
Boolen -> Chane "1" "" (chane vide)

Compte tenu de la logique de conversion indique prcdemment, toute variable peut tre teste en tant que
boolen (PHP se chargeant de la conversion). Ce fonctionnement est souvent pratique mais peut facilement
conduiredeserreursdlicatesdceler.

ENI Editions - All rigths reserved - 5-


Le"type"NULL

Ce type, introduit dans PHP 4, est un peu particulier et correspond au type d'une variable utilise sans jamais
avoirtinitialise.Ilpossdeuneseulevaleur,lavaleurNULLdfinieparlaconstanteNULL(ounull).

Encasdeconversionenboolen,NULLprendlavaleurFALSE.

Exemple

<?php
var_dump($variable_non_dfinie);
?>

Rsultat

NULL

Letyperessource(resource)

Ce type gnrique, introduit dans PHP 4, est un peu particulier, et correspond une rfrence vers une
ressourceexterne :fichierouvert,connexiondebasededonnes,etc.

plusieurs reprises dans cet ouvrage, nous aurons l'occasion de prsenter des fonctions qui permettent de
manipulercesdonnesdetyperessource.

Conversions

PHPestcapabled'effectuerdesconversionsautomatiquesimplicitesdetype,selonlesrglesprsentesdansle
soustitreprcdentTypesdisponibles.

Lorsqu'unevaleur/expressionestaffecteunevariable,lavariabledevientdutypedelavaleur/expression.

Pour dterminer le type d'une expression compose d'oprandes de types diffrents, PHP value (mais ne
convertit pas) les oprandes en fonction des oprateurs traits dans l'ordre de prcdence (cf. chapitre
Oprateurs Prcdence des oprateurs). Par exemple, les deux oprandes utiliss dans une addition sont
valusennombrealorsquedeuxoprandesutilissavecl'oprateurdeconcatnation(cf.chapitreOprateurs
L'oprateurdechane)sontvalusenchane.

Exemple

<?php
$nombre = 123;
$chane = "456abc";
echo '$nombre + $chane = ';
var_dump($nombre + $chane);
echo '<BR>';
echo '$nombre . $chane = ';
var_dump($nombre . $chane);
echo '<BR>';
echo '$nombre = ';
var_dump($nombre);
echo '<BR>';
echo '$chane = ';
var_dump($chane);
?>

Rsultat

$nombre + $chane = int(579)


$nombre . $chane = string(9) "123456abc"
$nombre = int(123)
$chane = string(6) "456abc"

Surlepremierexemple,lavariable$chaneestvalueennombrepourtredutypeattenduparl'oprateur"+"

- 6- ENI Editions - All rigths reserved


alors que dans le deuxime exemple, c'est $nombre qui est valu en chane pour tre du type attendu par
l'oprateur "." (concatnation). Par contre, les deux derniers affichages montrent que les variables en question
n'ontpastconvertieslorsdesoprations :ellesconserventleurtyperespectifinitial.

Encomplment,PHPproposeunenotationetunefonctionpoureffectueruneconversionmanuelleexplicite.

Notation

La notation consiste indiquer le nom du type souhait entre parenthses devant l'expression convertir. Les
valeursautorisessontlessuivantes :

Notation Conversion en
(int) ou (integer) entier
(bool) ou (boolean) boolen
(real), (double) ou (float) nombre virgule flottante
(string) chane
(array) tableau
(object) objet

Exemple

<?php
echo '(float)"1abc" = ',var_dump((float)"1abc"),"<BR>";
echo '(float)"1.5abc" = ',var_dump((float)"1.5abc"),"<BR>";
echo '(float)"abc1" = ',var_dump((float)"abc1"),"<BR>";
echo '(int)1.7 = ',var_dump((int)1.7),"<BR>";
echo '(int)TRUE = ',var_dump((int)TRUE),"<BR>";
echo '(int)FALSE = ',var_dump((int)FALSE),"<BR>";
echo '(bool)-1 = ',var_dump((bool)-1),"<BR>";
echo '(bool)0 = ',var_dump((bool)0),"<BR>";
echo '(bool)1 = ',var_dump((bool)1),"<BR>";
echo '(bool)"" = ',var_dump((bool)""),"<BR>";
echo '(bool)"0" = ',var_dump((bool)"0"),"<BR>";
echo '(bool)"1" = ',var_dump((bool)"1"),"<BR>";
echo '(bool)"a" = ',var_dump((bool)"a"),"<BR>";
?>

Rsultat

(float)"1abc" = float(1)
(float)"1.5abc" = float(1.5)
(float)"abc1" = float(0)
(int)1.7 = int(1)
(int)TRUE = int(1)
(int)FALSE = int(0)
(bool)-1 = bool(true)
(bool)0 = bool(false)
(bool)1 = bool(true)
(bool)"" = bool(false)
(bool)"0" = bool(false)
(bool)"1" = bool(true)
(bool)"a" = bool(true)

Cesdiffrentsexemplespermettentderetrouverlesrglesdeconversionvoquesprcdemment.

Fonctiondeconversion

Lafonctionsettypepermetdeconvertirunevariabled'untypeunautre.

Syntaxe

boolen settype(mixte variable, chane type)

variable

ENI Editions - All rigths reserved - 7-


Variableconvertir

type

Typesouhaitenutilisantunedesvaleurs suivantes:
booleanoubool(conversionenboolen)
integerouint(conversionenentier)
doubleoufloat(conversionennombrevirguleflottante)
string(conversionenchanedecaractres)
array(conversionentableau)
object(conversionenobjet)

settyperetourneTRUEencasdesuccsetFALSEencasd'erreur.

Exemple

<?php
$x = "1abc";
settype($x,"integer");
echo "\"1abc\" converti en entier = ",var_dump($x),"<BR>";
$x = 1.7;
settype($x,"integer");
echo "1.7 converti en entier = ",var_dump($x),"<BR>";
$x = TRUE;
settype($x,"string");
echo "TRUE converti en chane = ",var_dump($x),"<BR>";
$x = "0";
settype($x,"boolean");
echo "\"0\" converti en boolen = ",var_dump($x),"<BR>";
$x = -1;
settype($x,"boolean");
echo "-1 converti en boolen = ",var_dump($x),"<BR>";
?>

Rsultat

"1abc" converti en entier = int(1)


1.7 converti en entier = int(1)
TRUE converti en chane = string(1) "1"
"0" converti en boolen = bool(false)
-1 converti en boolen = bool(true)

En rgle gnrale, il est conseill de choisir la conversion explicite : le code est plus lisible, plus facile maintenir et mettre
au point.

Fonctionsutiles

Encomplment,PHPproposeplusieursfonctionsutilesrelativesautypedesvariables :

Nom Rle
is_* indique si la variable est du type donn par * :
array = tableau ;
bool = bool en ;
double, float, real = nombre virgule flottante ;
int, integer, long = entier ;
null = type NULL ;
numeric = entier ou nombre virgule flottante ou cha ne
contenant un nombre (entier ou d cimal) ;
object = objet ;
string = cha ne ;
ressource = ressource ;
scalar = type scalaire.
strval Convertit une variable en cha ne.
is_double Convertit une variable en nombre virgule flottante.
floatval

- 8- ENI Editions - All rigths reserved


doubleval
intval Convertit une variable en entier.

is_*

Lafonctionis_*permetdetestersiunevariableestd'untypedonn.

Syntaxe

boolen is_* (mixte variable)

variable Variabletester

Lesdclinaisonssontlessuivantes :

Fonction Type test


is_array tableau
is_bool boolen
is_double nombre virgule flottante
is_float
is_real
is_int entier
is_integer
is_long
is_null type NULL
is_numeric entier ou nombre virgule flottante ou chane contenant un nombre
(entier ou dcimal)
is_object objet
is_string chane
is_resource ressource
is_scalar type scalaire

LafonctionretourneTRUEsilavariableestdutypedemandetFALSEdanslecascontraire.

Exemple

<?php
if (is_null($x)) {
echo "Pour l'instant, \$x est du type NULL.<BR>";
}
$x = (1 < 2);
if (is_bool($x)) {
echo "\$x = (1 < 2) est du type boolen.<BR>";
}
$x = "123abc";
if (is_string($x)) {
echo "\$x = \"123abc\" est du type chane ...<BR>";
}

if (is_numeric($x)) {
echo "... mais aussi est du << type >> <I>numeric</I>.<BR>";
} else {
echo "... mais pas du "type" <I>numeric</I>.<BR>";
}
$x = "1.23e45";
if (is_numeric($x)) {
echo "Par contre, \$x = \"1.23e45\" est du << type >>
<I>numeric</I>.<BR>";
}
?>

Rsultat

ENI Editions - All rigths reserved - 9-


Pour l'instant, $x est du type NULL.
$x = (1 < 2) est du type boolen.
$x = "123abc" est du type chane ...
... mais pas du << type >> numeric.
Par contre, $x = "1.23e45" est du << type >> numeric.

Surcetexemple,lafonction is_numericn'appliquepastoutfaitlesmmesrglespourvaluersiunechane
contient un nombre que celles utilises pour la conversion. Avec la fonction is_numeric, la chane ne doit
conteniraucuncaractrenonnumrique.

strval

Lafonctionstrvalretournelavaleurd'unevariableaprsconversionenchane.

Syntaxe

chane strval(mixte variable)

variable Variabletraiter.

Cettefonctionnes'appliquequ'auxvariablesdetypescalaire(nonvalablepourlestableaux,nilesobjets).
Letypedelavariableresteinchang.

Exemple

<?php
$x = TRUE;
echo var_dump($x)," => ",var_dump(strval($x)),"<BR>";
$x = 1.23e45;
echo var_dump($x)," => ",var_dump(strval($x)),"<BR>";
?>

Rsultat

bool(true) => string(1) "1"


float(1.23E+045) => string(9) "1.23E+045"

floatval(oudoubleval)

La fonction floatval retourne la valeur d'une variable aprs conversion en nombre virgule flottante. La
fonctiondoublevalestunaliasdelafonctionfloatval.

Syntaxe

nombre floatval(mixte variable)

variable Variabletraiter.

Cette fonction ne s'applique qu'aux variables de type scalaire (non valable pour les tableaux, ni les objets). Le
typedelavariableresteinchang.

Exemple

<?php
$x = TRUE;
echo var_dump($x)," => ",var_dump(floatval($x)),"<BR>";
$x = 123;
echo var_dump($x)," => ",var_dump(floatval($x)),"<BR>";
$x = "1.23e45";
echo var_dump($x)," => ",var_dump(floatval($x)),"<BR>";
$x = "123abc";
echo var_dump($x)," => ",var_dump(floatval($x)),"<BR>";
$x = " \n\t\r 123.45abc";
echo var_dump($x)," => ",var_dump(floatval($x)),"<BR>";
?>

- 10 - ENI Editions - All rigths reserved


Rsultat

bool(true) => float(1)


int(123) => float(123)
string(7) "1.23e45" => float(1.23E+045)
string(6) "123abc" => float(123)
string(14) " 123.45abc" => float(123.45)

Lesrglesdeconversionvoquesprcdemmentsontrespectes.

intval

Lafonctionintvalretournelavaleurd'unevariableaprsconversionenentier.

Syntaxe

nombre intval(mixte variable)

Variable Variabletraiter

Cettefonctionnes'appliquequ'auxvariablesdetypescalaire(nonvalablepourlestableaux,nilesobjets).

Letypedelavariableresteinchang.

Exemple

<?php
$x = TRUE;
echo var_dump($x)," => ",var_dump(intval($x)),"<BR>";
$x = 123.9;
echo var_dump($x)," => ",var_dump(intval($x)),"<BR>";
$x = "1.23e45";
echo var_dump($x)," => ",var_dump(intval($x)),"<BR>";
$x = "123abc";
echo var_dump($x)," => ",var_dump(intval($x)),"<BR>";
$x = " \n\t\r 123.45abc";
echo var_dump($x)," => ",var_dump(intval($x)),"<BR>";
?>

Rsultat

bool(true) => int(1)


float(123.9) => int(123)
string(7) "1.23e45" => int(1)
string(6) "123abc" => int(123)
string(14) " 123.45abc" => int(123)

Les rgles de conversion voques prcdemment sont respectes. L encore, il faut rappeler qu'un nombre
virguleflottanteconvertienentieresttronquetnonarrondi :surnotreexemple,123.9donne123etnon124.
Pourconvertirunnombrevirguleflottanteenentier,avecarrondi,ilfaututiliserlafonctionround().

Exemple

<?php
$x = 123.9;
echo "round($x) => ",var_dump(round($x)),"<BR>";
echo "intval(round($x)) => ",
var_dump(intval(round($x))),"<BR>";
echo "(int) round($x) => ",
var_dump((int) round($x)),"<BR>";
?>

Rsultat

round(123.9) => float(124)


intval(round(123.9)) => int(124)
(int) round(123.9) => int(124)

ENI Editions - All rigths reserved - 11 -


La fonctionround()retourneunnombreentierarrondi,maisavecuntypedenombrevirguleflottante.Sil'on
souhaite obtenir un "vrai" type entier l'arrive, il suffit de convertir le rsultat de round() en entier avec la
mthodedevotrechoix.

- 12 - ENI Editions - All rigths reserved


Tableaux

Dfinition

EnPHP,untableauestunecollection(listed'lments)ordonnedecouplescl/valeur.
Laclpeuttredetypeentieroudetypechane.Danslepremiercas,letableauestditnumriqueetlaclest
dsigneparletermeindice.Dansledeuximecas,letableauestditassociatif:lesclsnesontpasforcment
conscutives,niordonnes,etcetableaupeutprsenterdesclsentiresetdesclsdetypechane.

La valeur associe la cl peut tre de n'importe quel type, et notamment de type tableau dans ce cas, le
tableauestditmultidimensionnel.

Exemple

- Tableau numrique (indices ordonns conscutifs)

Cl/Indice Valeur
0 zro
1 un
2 deux
3 trois

- Tableau numrique (indices non ordonns, non conscutifs)

Cl/Indice Valeur
20 vingt
30 trente
10 dix

- Tableau mixte

Cl/Indice Valeur
0 zro
zro 0
un 1
1 un
deux 2
2 deux
trois 3
3 trois

- Tableau multidimensionnel (liste de villes par pays)

Cl/Indice Valeur
FRANCE Cl/Indice Valeur
0 Paris
1 Lyon
2 Nantes
ITALIE Cl/Indice Valeur
0 Rome

ENI Editions - All rigths reserved - 1-


1 Venise

Cration

Une variable de type tableau peut tre dfinie explicitement grce la fonction array ou implicitement en
utilisantunenotationcrochets([]).

Notationcrochets([])

Unevariableutilisepourlapremirefoisavecunenotationdelaforme $variable[...],estautomatiquement
creavecletypetableau.

La mme opration effectue sur une variable dj dfinie, avec un type scalaire, provoque un message
d'erreur.

Lecontenud'untableaupeuttreainsidfiniparplusieursaffectationsdutype$tableau[...] = valeur.

Avecuneaffectationdutype$tableau[] = valeur,PHPrechercheleplusgrandindiceentierutilisetassocie
lavaleurl'indiceimmdiatementsuprieur.Siletableauestvide,l'lmentestplacl'indice0.

Avec une affectation du type $tableau[cl] = valeur, PHP associe la valeur la cl indique (qui peut tre
detypeentieroudetypechane).

Lesdeuxnotationspeuventtremlangesdansunesquenced'affectation.

Exemple

<?php
$nombres[] = "zro"; // => indice 0
$nombres[] = "un"; // => indice max (0) + 1 = 1
$nombres[] = "deux"; // => indice max (1) + 1 = 2
$nombres[] = "trois"; // => indice max (2) + 1 = 3
$nombres[5] = "cinq"; // => indice 5
$nombres[] = "six"; // => indice max (5) + 1 = 6
$nombres["un"] = 1; // indice "un"
$nombres[] = "sept"; // => indice max (6) + 1 = 7
$nombres[-1] = "moins un"; // => -1
?>

Rsultat

Cl/Indice Valeur
0 zro
1 un
2 deux
3 trois
5 cinq
6 six
un 1
7 sept
-1 moins un

Cesnotationspeuventtreutilisespourconstruireuntableaumultidimensionnel,souslaforme $tableau[...]
= $tableau_intrieur ou$tableau[...][...] = valeur.Lapremirenotationpermetdestockeruntableau
dans un emplacement d'un autre tableau, et la deuxime notation, de stocker une valeur directement dans un
emplacementsitul'intrieurd'unautretableau.

Exemple

- 2- ENI Editions - All rigths reserved


- Premire mthode :

<?php
// cration d'un tableau contenant les villes de France
$villes_france[] = "Paris";
$villes_france[] = "Lyon";
$villes_france[] = "Nantes";
// stockage du tableau des villes de France dans le tableau
// des villes
$villes["FRANCE"] = $villes_france;
// idem avec les villes d'Italie
$villes_italie[] = "Rome";
$villes_italie[] = "Venise";
$villes["ITALIE"] = $villes_italie;
?>

- Deuxime mthode :

<?php
// stockage direct des villes dans le tableau
// - pour la France
$villes["FRANCE"][] = "Paris";
$villes["FRANCE"][] = "Lyon";
$villes["FRANCE"][] = "Nantes";
// - pour l'Italie
$villes["ITALIE"][] = "Rome";
$villes["ITALIE"][] = "Venise";
?>

Rsultat (dans les deux cas)

Cl/Indice Valeur
FRANCE Cl/Indice Valeur
0 Paris
1 Lyon
2 Nantes
ITALIE Cl/Indice Valeur
0 Rome
1 Venise

Lafonctionarray

Lafonctionarraypermetdecreruntableaupartird'unelisted'lments.

Syntaxe

tableau array([mixte valeur[, ...]])


ou
tableau array([{chane | entier} cl => mixte valeur[, ...]])

valeur lmentdutableau.

cl Valeurdelacl.

Dans la premire syntaxe, les cls/indices ne sont pas spcifies et c'est un tableau numrique indices
conscutifs commenant 0 qui est cr : le premier argument de la fonction tant stock l'indice 0, le
deuximel'indice1,etc.

Dansladeuximesyntaxe,l'indiceoulaclsontspcifissoitparunentier,soitparunechane etunevaleur
luiestassocieparl'oprateur=>.

Les deux syntaxes peuvent tre mlanges. Dans ce cas, lorsque l'indice ou la cl n'est pas spcifi(e), PHP
recherche le plus grand indice entier utilis et associe la valeur l'indice immdiatement suprieur s'il n'existe

ENI Editions - All rigths reserved - 3-


aucunindiceentier,l'lmentestplacl'indice0.

Lafonctionarray,appelesansargument,creuntableauvide.

Exemple

<?php
$nombres = array("zro","un","deux","trois",
5 => "cinq","six","un" => 1,"sept",-1 => "moins un");
?>

Rsultat

Cl/Indice Valeur
0 zro
1 un
2 deux
3 trois
5 cinq
6 six
un 1
7 sept
-1 moins un

Lafonction arrayaccepteenargumentlesdonnesdetypetableau(soitunevariable,soitunappelimbriqu
array),cequipermetdeconstruireuntableaumultidimensionnel.

Exemple

- Premire mthode :

<?php
// cration d'un tableau contenant les villes de France
$villes_france = array("Paris","Lyon","Nantes");
// idem avec les villes d'Italie
$villes_italie = array("Rome","Venise");
// stockage des 2 tableaux dans le tableau des villes
$villes = array("FRANCE" => $villes_france,
"ITALIE" => $villes_italie);
?>

- Deuxime mthode :

<?php
// cration par imbrication des appels array
$villes = array("FRANCE" => array("Paris","Lyon","Nantes"),
"ITALIE" => array("Rome","Venise"));
?>

Rsultat (dans les deux cas)

Cl/Indice Valeur
FRANCE Cl/Indice Valeur
0 Paris
1 Lyon
2 Nantes
ITALIE Cl/Indice Valeur
0 Rome

- 4- ENI Editions - All rigths reserved


1 Venise

Manipulation

Deuxbesoins"types"existent,relatifslamanipulationd'untableau :

- accder un lment individuel du tableau,

- parcourir le tableau.

Accderunlmentindividueldutableau

Lanotationcrochetsestutilisepouraccder,enlectureouencriture,unlmentindividueldutableau :

- $tableau[i] permet d'accder l'lment d'indice i du tableau (cas du tableau numrique, i tant un entier).

- $tableau["x"] permet d'accder l'lment de cl "x" du tableau (cas du tableau associatif, "x" tant une chane).

- $tableau[] permet d'accder, en criture uniquement, un nouvel lment du tableau qui se verra affecter un
indice entier immdiatement suprieur au plus grand indice entier existant dans le tableau (0 s'il n'y en a pas).

Pourlestableauxmultidimensionnels,plusieurssriesdecrochetsdoiventtreutilises.

Exemple

<?php
$nombres = array("zro","un","deux","trois",
5 => "cinq","six","un" => 1,"sept",-1 => "moins un");
echo $nombres[1],"<BR>";
echo $nombres["un"],"<BR>";
$villes = array("FRANCE" => array("Paris","Lyon","Nantes"),
"ITALIE" => array("Rome","Venise"));
echo $villes["FRANCE"][0],"<BR>";
echo $villes["ITALIE"][1],"<BR>";
?>

Rsultat

un
1
Paris
Venise

PHPacceptequevousomettiezledlimiteurdechane(guillemetouapostrophe)lorsquevousspcifiezunecl
detypechanedansuntableauassociatif.

Exemple

<?php
$nombres = array("un" => 1,"deux" => 2);
// utilisation de $nombres[un] et non $nombres["un"]
echo $nombres[un],"<BR>";
?>

Rsultat (si les erreurs de type E_NOTICE ne sont pas affiches)

Rsultat (si les erreurs de type E_NOTICE sont affiches)

Notice: Use of undefined constant un - assumed 'un' in d:\scripts php\


index.php on line 4
1

ENI Editions - All rigths reserved - 5-


Cette syntaxe est accepte (et fonctionne) mais gnre une erreur de type E_NOTICE. PHP constate que la
constante un n'existe pas et la remplace par la chane 'un' ..., ce qui permet d'obtenir le bon rsultat ...
jusqu'au jour o vous dfinissez une constante un valant 1 par exemple ! En consquence, il est vivement
dconseilld'utilisercettesyntaxe"simplifie".

Le principe de substitution des variables dans les chanes dlimites par des guillemets fonctionne avec les
tableaux.

Exemple

<?php
$nombres = array("zro","un","deux","trois",
5 => "cinq","six","un" => 1,"sept",-1 => "moins un");
echo "\$nombres[1] = $nombres[1]<BR>";
echo "\$nombres[\"un\"] = $nombres[un]<BR>";
echo "\$nombres[\"un\"] = {$nombres['un']}<BR>";
$villes = array("FRANCE" => array("Paris","Lyon","Nantes"),
"ITALIE" => array("Rome","Venise"));
echo "\$villes[\"France\"][0] = $villes[FRANCE][0]<BR>";
echo "\$villes[\"France\"][0] = {$villes[FRANCE][0]}<BR>";
?>

Rsultat

$nombres[1] = un
$nombres["un"] = 1
$nombres["un"] = 1
$villes["France"][0] = Array[0]
$villes["France"][0] = Paris

Cesexemplesappellentdeuxremarques :

- Pour les cls de type chane exprimes sous forme de littral, la syntaxe avec dlimiteur ncessite des accolades
({$nombres['un']}). crire directement $nombres['un'], $nombres["un"] ou $nombres[\"un\"] gnre
une erreur. Dans ce cas, il est acceptable d'utiliser la syntaxe sans dlimiteur ($nombres[un]).

- Pour les tableaux multidimensionnels, il faut utiliser des accolades ({$villes['FRANCE'][0]}). La syntaxe
$villes['FRANCE'][0] gnre une erreur et la syntaxe $villes[FRANCE][0] donne un mauvais rsultat car
PHP interprte $villes[FRANCE] comme une variable et la remplace par sa valeur (mais c'est un tableau que PHP ne
sait pas afficher nativement).

Parcourirletableau

Denombreusesmthodespeuventtreutilisespourparcouriruntableaul'aidedesconstructionssuivantes :

- la structure de contrle itrative for,

- la structure de contrle itrative while,

- la structure de parcours de tableau foreach (introduite dans PHP 4),

Dans ce chapitre, nous allons tudier les deux mthodes les plus simples, et finalement les plus efficaces. Elles
ne ncessitent aucune connaissance particulire sur la nature du tableau (numrique, associatif, plage des
indices/cls...).

- la structure foreach sans conteste la mthode la plus simple pour parcourir un tableau.

Syntaxe

foreach(tableau as variable_valeur)
{ instructions }
ou
foreach(tableau as variable_cl => variable_valeur)

- 6- ENI Editions - All rigths reserved


{ instructions }

Lapremiresyntaxepermetdeparcourirletableaududbutlafin chaqueitration,lavaleurcourantedu
tableaueststockedanslavariablevariable_valeuretlesinstructionsentreaccoladessontexcutes.Cette
syntaxeestsuffisantesiletraitementn'apasbesoindefairerfrenceauxvaleursdelacl.
Ladeuximesyntaxefonctionnesurlemmeprincipe,maischaqueitration,laclcouranteeststockedans
la variable variable_cl et la valeur dans la variable variable_valeur. Cette syntaxe est pratique si le
traitementabesoindefairerfrenceauxvaleursdelacl.

Exemple

<?php
// initialisation d'un tableau
$nombres = array("zro","un","deux",
"zro" => 0,"un" => 1,"deux" => 2);
// Parcours du tableau avec la premire syntaxe
echo "Premire syntaxe :<BR>";
foreach($nombres as $nombre) {
echo "$nombre<BR>";
}
// Parcours du tableau avec la deuxime syntaxe
echo "Deuxime syntaxe :<BR>";
foreach($nombres as $cl => $nombre) {
echo "$cl => $nombre<BR>";
}
?>

Rsultat

Premire syntaxe :
zro
un
deux
0
1
2

Deuxime syntaxe :
0 => zro
1 => un
2 => deux
zro => 0
un => 1
deux => 2

Ces deux exemples montrent bien qu'aucune connaissance pralable du tableau n'est ncessaire pour le
parcourir :nisataille,nisastructuredecls.

Parailleurs,lavaleurcourantedutableauest copiedansunevariable modifiercettevariablen'aaucuneffet


surlecontenudutableau.Pouraffecterlecontenudutableau,l'aided'unestructureforeach,ilfautmodifier
lavaleurdansletableau.

Exemple

<?php
// initialisation d'un tableau
$nombres = array("zro","un","deux",
"zro" => 0,"un" => 1,"deux" => 2);
// Parcours du tableau pour le modifier (mauvaise mthode)
foreach($nombres as $cl => $nombre) {
$nombre = "($nombre)"; // mettre le nombre entre ()
}
// Parcours du tableau pour l'afficher
echo "Rsultat de la mauvaise mthode :<BR>";
foreach($nombres as $cl => $nombre) {
echo "$cl => $nombre<BR>";
}

// Parcours du tableau pour le modifier (bonne mthode)


foreach($nombres as $cl => $nombre) {
$nombres[$cl] = "($nombre)"; // mettre le nombre entre ()

ENI Editions - All rigths reserved - 7-


}
// Parcours du tableau pour l'afficher
echo "Rsultat de la bonne mthode :<BR>";
foreach($nombres as $cl => $nombre) {
echo "$cl => $nombre<BR>";
}
?>

Rsultat

Rsultat de la mauvaise mthode :


0 => zro
1 => un
2 => deux
zro => 0
un => 1
deux => 2
Rsultat de la bonne mthode :
0 => (zro)
1 => (un)
2 => (deux)
zro => (0)
un => (1)
deux => (2)

Une autre mthode (structure while en version 3), proche de la mthode foreach, peut tre utilise pour
parcouriruntableau.

Syntaxe

while(list(variable_cl,variable_valeur) = each(tableau))
{ instructions }

Cette construction permet de parcourir le tableau du dbut la fin chaque itration, la cl courante du
tableau est stocke dans la variable variable_cl, la valeur dans la variable variable_valeur et les
instructionsentreaccoladessontexcutes.L'uneoul'autredesvariablespeuttreomisesiletraitementn'en
apasbesoin.

Encomplment,siletableauapralablementtmanipul,ilfautfaireappellafonction resetpourremettre
le pointeur interne du tableau sur la premire ligne et ainsi tre certain de bien repartir du dbut. Dans la
pratique,cettefonctionestsystmatiquementappele.

Syntaxe

mixte reset(tableau tableau)

tableau Tableauconcern

Lafonctionresetpositionnelepointeurinternedutableausurlapremireligneetretournelavaleur(paslacl)
decettepremireligne.

Exemple de parcours de tableau avec la mthode while

<?php
$nombres = array("zro","un","deux",
"zro" => 0,"un" => 1,"deux" => 2);
reset($nombres); // ici le reset est important
while(list($cl,$nombre) = each($nombres)) {
echo "$cl => $nombre<BR>";
}
?>

Rsultat

0 => zro
1 => un
2 => deux
zro => 0

- 8- ENI Editions - All rigths reserved


un => 1
deux => 2

Pour modifier le contenu du tableau l'aide de cette structure, il faut utiliser la mme technique qu'avec la
constructionforeach.

En cas de besoin, dans les deux constructions, l'instruction break (cf. chapitre Structures de contrle ) peut tre employe
pour interrompre le parcours du tableau avant la fin.

Comme indiqu lors de la description de la fonction reset, un tableau possde un pointeur interne manipulable avec
diffrentes fonctions pour le dplacer (fonctions reset, next, prev et end) ou rcuprer la valeur pointe (current). Ces
fonctions ne sont pas prsentes plus en dtail dans cet ouvrage car elles sont d'un usage moins courant.

La structure for (cf. chapitre Structures de contrle) peut aussi tre utilise pour parcourir un tableau mais elle est moins
pratique car elle ncessite de bien connatre le contenu du tableau.

Dans le chapitre 6, nous allons construire une fonction gnrique qui permet d'afficher le contenu d'un tableau sans
connaissance pralable de sa structure (le tableau pourra mme tre multidimensionnel).

Porte

Les variables de type tableau suivent les mmes rgles de porte et de dure de vie que les variables de type
scalaire(cf.VariablesPorteetduredevie).

Fonctionsutiles

PHPproposeungrandnombredefonctionspermettantdemanipulerlestableaux.

Lesfonctionslesplusutilisessontlessuivantes :

Nom Rle
count Compte le nombre d'lments dans un tableau.
in_array Teste si une valeur est prsente dans un tableau.
array_search Recherche une valeur dans un tableau.
[a|k][r] Trie un tableau (plusieurs variantes possibles).
sort
explode Dcoupe une chane selon un sparateur et stocke les lments dans
un tableau.
implode Regroupe les lments d'un tableau dans un chane l'aide d'un
sparateur.
str_split Dcoupe une chane en morceaux de longueur fixe et stocke les
lments dans un tableau.

La fonction is_array (cf. Types de donnes Fonctions utiles) permet de savoir si une variable est de type
tableau.Nel'oubliezpas.

De nombreuses autres fonctions existent, la description de chaque fonction est accessible en ligne sur le site
www.php.net.Vousytrouvereznotammentdesfonctionspour :

- raliser des calculs (somme...) ;

- extraire un soustableau d'un tableau ;

- fusionner des tableaux ;

- ddoublonner un tableau...

count

ENI Editions - All rigths reserved - 9-


La fonction count permet de connatre le nombre d'lments dans une variable en gnral, un tableau en
particulier.

Syntaxe

entier count (mixte variable)

variable Variableconcerne.

La fonction count retourne le nombre d'lments dans la variable. Si la variable n'est pas initialise, count
retourne 0. Si la variable est initialise mais n'est pas un tableau, count retourne 1 (il y a effectivement un
lmentdansunevariablescalaire).Silavariableestuntableau, countretournelenombred'lmentsprsents
dansletableau(0siletableauestvide).

Exemple

<?php
echo "\$x variable non initialis => ",count($x),"<BR>";
$x = 1;
echo "\$x variable de type scalaire => ",count($x),"<BR>";
$x = array();
echo "\$x tableau vide => ",count($x),"<BR>";
$x = array(1,2);
echo "\$x tableau de 2 lments => ",count($x),"<BR>";
?>

Rsultat

$x variable non initialis => 0


$x variable de type scalaire => 1
$x tableau vide => 0
$x tableau de 2 lments => 2

in_array

Lafonctionin_arraypermetdetestersiunevaleurestprsentedansuntableau.

Syntaxe

boolen in_array(mixte valeur_cherche, tableau tableau[, boolen mme_type])

valeur_cherche Valeurcherchedansletableau.

tableau Tableaudanslequels'effectuelarecherche.

mme_type Indiquesilacomparaisondoitvrifierqueleslmentssontdummetype(FALSEpardfaut).

in_arrayretourneTRUEsil'lmentcherchestprsentdansletableauetFALSEdanslecascontraire.

PHP propose aussi la fonction array_key_exists qui permet de tester si une valeur est prsente dans les cls d'un
tableau.

Exemple

<?php
$nombres = array("zro","un","deux",
"zro" => 0,"un" => 1,"deux" => 2);
echo '"un" type indiffrent => ',
var_dump(in_array("un",$nombres)),"<BR>";
echo '"un" mme type => ',
var_dump(in_array("un",$nombres,TRUE)),"<BR>";
echo '"trois" type indiffrent => ',
var_dump(in_array("trois",$nombres)),"<BR>";
echo '"trois" mme type => ',
var_dump(in_array("trois",$nombres,TRUE)),"<BR>";

- 10 - ENI Editions - All rigths reserved


echo '1 type indiffrent => ',
var_dump(in_array(1,$nombres)),"<BR>";
echo '1 mme type => ',
var_dump(in_array(1,$nombres,TRUE)),"<BR>";
echo '3 type indiffrent => ',
var_dump(in_array(3,$nombres)),"<BR>";
echo '3 mme type => ',
var_dump(in_array(3,$nombres,TRUE)),"<BR>";
echo '"1" type indiffrent => ',
var_dump(in_array("1",$nombres)),"<BR>";
echo '"1" mme type => ',
var_dump(in_array("1",$nombres,TRUE)),"<BR>";
?>

Rsultat

"un" type indiffrent => bool(true)


"un" mme type => bool(true)
"trois" type indiffrent => bool(true)
"trois" mme type => bool(false)
1 type indiffrent => bool(true)
1 mme type => bool(true)
3 type indiffrent => bool(false)
3 mme type => bool(false)
"1" type indiffrent => bool(true)
"1" mme type => bool(false)

Les deux exemples avec "trois" montrent que la fonction in_array est manipuler avec beaucoup de
prcautionlorsqueletableaucontientdeslmentsdetypediffrent.Eneffet,surlarecherchedemmetype,
in_arrayfonctionnecorrectement(iln'yapasdechane"trois"dansletableau).Surlarechercheoletype
estindiffrent,toutsepassecommesilachanetaitconvertieenentier("trois"convertienentierdonne0)
et que la recherche s'effectuait sur le rsultat de cette conversion (0 est bien prsent dans le tableau). La
preuveenestlersultatlorsquel'lment0estenlevdutableau.

Exemple

<?php
$nombres = array("zro","un","deux",
"zro" => "0 est enlev","un" => 1,"deux" => 2);
echo '"trois" type indiffrent => ',
var_dump(in_array("trois",$nombres)),"<BR>";
echo '"trois" mme type => ',
var_dump(in_array("trois",$nombres,TRUE)),"<BR>";
?>

Rsultat

"trois" type indiffrent => 0


"trois" mme type => 0

Cettefois,lesdeuxrecherchesdonnentlemme(bon)rsultat.

array_search

La fonction array_search permet de chercher un lment dans un tableau et de rcuprer la cl de cet


lment,s'ilestprsent.

Syntaxe

mixte array_search(mixte valeur_cherche, tableau tableau[, boolen mme_type])

valeur_cherche

Valeurcherchedansletableau.

tableau

Tableaudanslequels'effectuelarecherche.

ENI Editions - All rigths reserved - 11 -


mme_type

Indiquesilacomparaisondoitvrifierqueleslmentssontdummetype(FALSEpardfaut).

array_search retourne la cl associe l'lment, si ce dernier est prsent dans le tableau et FALSE dans le
cascontraire(NULLavantlaversion4.2.0).

Exemple

<?php
$nombres = array("zro","un","deux",
"zro" => 0,"un" => 1,"deux" => 2);
echo '"un" type indiffrent => ',
var_dump(array_search("un",$nombres)),"<BR>";
echo '"un" mme type => ',
var_dump(array_search("un",$nombres,TRUE)),"<BR>";
echo '"trois" type indiffrent => ',
var_dump(array_search ("trois",$nombres)),"<BR>";
echo '"trois" mme type => ',
var_dump(array_search ("trois",$nombres,TRUE)),"<BR>";
echo '1 type indiffrent => ',
var_dump(array_search(1,$nombres)),"<BR>";
echo '1 mme type => ',
var_dump(array_search(1,$nombres)),"<BR>";
echo '3 type indiffrent => ',
var_dump(array_search(3,$nombres)),"<BR>";
echo '3 mme type => ',
var_dump(array_search(3,$nombres)),"<BR>";
echo '"1" type indiffrent => ',
var_dump(array_search("1",$nombres)),"<BR>";
echo '"1" mme type => ',
var_dump(array_search("1",$nombres,TRUE)),"<BR>";
?>

Rsultat

"un" type indiffrent => int(1)


"un" mme type => int(1)
"trois" type indiffrent => string(4) "zro"
"trois" mme type => bool(false)
1 type indiffrent => string(2) "un"
1 mme type => string(2) "un"
3 type indiffrent => bool(false)
3 mme type => bool(false)
"1" type indiffrent => string(2) "un"
"1" mme type => bool(false)

Nousretrouvons,surcesexemples,leproblmevoquaveclafonctionin_array :larecherchesur"trois",en
typeindiffrent,donnelacl"zro"quicorrespondeffectivementlavaleur0dansletableau.

[a|k][r]sort

Lesfonctionssort, rsort, asort, arsort, ksortet krsortpermettentdetrieruntableauselondiffrentes


variantes.

Syntaxe

boolen [a|k][r]sort(tableau tableau)

tableau Tableautrier.

Lesvariantesdefonctionnementsontlessuivantes :

Fonction Nature du tri


sort Tri croissant sur la valeur, sans prservation des couples cl/valeur.
Quelle que soit la situation de dpart, aprs le tri, les indices du
tableau sont des entiers conscutifs partir de 0.

- 12 - ENI Editions - All rigths reserved


rsort Tri d croissant sur la valeur, sans prservation des couples cl/valeur.

Quelle que soit la situation de dpart, aprs le tri, les indices du


tableau sont des entiers conscutifs partir de 0.
asort Tri croissant sur la valeur, avec prservation des couples cl/valeur.
arsort Tri d croissant sur la valeur, avec prservation des couples cl/valeur.
ksort Tri croissant sur la cl, avec prservation des couples cl/valeur.
krsort Tri d croissant sur la cl, avec prservation des couples cl/valeur.

CesfonctionsretournentTRUEencasdesuccsetFALSEencasd'chec.

Exemple

<?php
$tableau = array("c3" => "rouge","c1" => "vert",
"c2" => "bleu");
// affichage de contrle
echo "<B>Tableau de dpart :</B><BR>";
foreach($tableau as $cl => $valeur)
{ echo "$cl => $valeur<BR>"; }
// sort
echo "<B>sort : tri sur valeur, cls non prserves</B><BR>";
$tableau_bis = $tableau;
sort($tableau_bis);
foreach($tableau_bis as $cl => $valeur)
{ echo "$cl => $valeur<BR>"; }
// asort
echo "<B>asort : tri sur valeur,
couples cl/valeur prservs</B><BR>";
$tableau_bis = $tableau;
asort($tableau_bis);
foreach($tableau_bis as $cl => $valeur)
{ echo "$cl => $valeur<BR>"; }
// ksort
echo "<B>ksort : tri sur cl,
couples cl/valeur prservs</B><BR>";
$tableau_bis = $tableau;
ksort($tableau_bis);
foreach($tableau_bis as $cl => $valeur)
{ echo "$cl => $valeur<BR>"; }
?>

Rsultat

Tableau de dpart :
c3 => rouge
c1 => vert
c2 => bleu
sort : tri sur valeur, cls non prserves
0 => bleu
1 => rouge
2 => vert
asort : tri sur valeur, couples cl/valeur prservs
c2 => bleu
c3 => rouge
c1 => vert
ksort : tri sur cl, couples cl/valeur prservs
c1 => vert
c2 => bleu
c3 => rouge

explode

La fonction explode permet de dcouper une chane selon un sparateur et de stocker les lments dans un
tableau.

Syntaxe

tableau explode(chane sparateur, chane _dcouper[, entier limite])

ENI Editions - All rigths reserved - 13 -


sparateur Sparateurrecherch.

_dcouper Chanedcouper.

limite Sispcifi,nombremaximumd'lmentsdansletableaursultat.

Exemple

<?php
$liste = "bleu, blanc, rouge";
$couleurs = explode(", ",$liste);
// sparateur = virgule+espace
foreach($couleurs as $cl => $valeur)
{ echo "$cl => $valeur<BR>"; }
?>

Rsultat

0 => bleu
1 => blanc
2 => rouge

implode

Lafonctionimplodepermetderegrouperleslmentsd'untableaudansunechanel'aided'unsparateur.

chane implode(chane sparateur, tableau lments)

sparateur Sparateurutilis.

lments Tableaucontenantleslmentsregrouper.

Exemple

<?php
$couleurs = array("bleu","blanc","rouge");
$liste = implode(", ",$couleurs);
// sparateur = virgule+espace
echo $liste;
?>

Rsultat

bleu, blanc, rouge

str_split

La fonction str_split dcoupe une chane en morceaux de longueur fixe et stocke les lments dans un
tableau.

Syntaxe

tableau str_split(chane chane[,entier longueur])

chane Chanedcouper.

longueur Longueurdesmorceaux(1pardfaut).

Exemple

<?php
$chane = "A1B2C3";
$tableau = str_split($chane,2);
foreach($tableau as $cl => $valeur) {

- 14 - ENI Editions - All rigths reserved


echo "\$tableau[$cl] = $valeur<br>";
}
?>

Rsultat

$tableau[0] = A1
$tableau[1] = B2
$tableau[2] = C3

ENI Editions - All rigths reserved - 15 -


Quelquesfonctionsutilessurleschanesdecaractres,lesdatesetlesnombres

Prambule

L'objectif de cette section est de prsenter les fonctions les plus utiles, relatives la manipulation des chanes
decaractresetdesdates,typesdedonnestrsfrquemmentutilisesdanslesapplications.

PHP propose de nombreuses fonctions la description de chaque fonction est accessible en ligne sur le site
www.php.net.

Manipulationdeschanesdecaractres

Lesfonctionslesplusutilespourmanipulerleschanesdecaractressontlessuivantes :

Nom Rle
strlen Retourne le nombre de caractres d'une chane.
strtolower Conversions minuscules/majuscules ventuellement limites au(x)
strtoupper premier(s) mot(s).
ucfirst
ucwords
strcmp Comparaison de chane (sensible la casse ou non).
strcasemp
[s]printf Mise en forme d'une chane (identique aux fonctions C quivalentes).
v[s]printf
number_format Mise en forme d'un nombre.
[1|r]trim Suppression de caractres "blancs".
substr Extraction d'une sous-chane dans une chane.
str_repeat Construction d'une chane par rptition de caractres.
str[r][i]pos Recherche de la position d'une occurrence (caractre ou chane)
l'intrieur d'une chane.
str[i]str Extraction de la sous-chane dans une chane commenant partir
strrchr d'une certaine occurrence d'un caractre ou d'une chane.
str_[i] Remplacement des occurrences d'une chane par une autre chane.
replace
strtr Remplacement des occurrences d'un caractres par un autre caractre
ou d'une chane par une autre chane.
ereg[i] Recherche et remplacement l'aide d'expressions rgulires.
ereg[i]
_replace

N'oubliez pas les fonctions explode, implode et str_split prcdemment prsentes (cf. Tableaux - Fonctions utiles).

D'autres fonctions, plus spcifiquement lies la gestion des formulaires sont tudies dans le chapitre 7.

strlen

Lafonctionstrlenretournelenombredecaractresd'unechane.

Syntaxe

entier strlen(chane chane)

chane Chaneconcerne.

strtolowerstrtoupperucfirstucwords

Ces fonctions permettent de raliser des conversions minuscules/majuscules, ventuellement limites au(x)
premier(s)mot(s)delachane.

ENI Editions - All rigths reserved - 1-


Syntaxe

chane strtolower(chane chane)


chane strtoupper(chane chane)
chane ucfirst(chane chane)
chane ucwords(chane chane)

chane Chanetraiter.

Lafonctionstrtolowerconvertittouslescaractresd'unechaneenminuscules.
Lafonctionstrtoupperconvertittouslescaractresd'unechaneenmajuscules.
Lafonctionucfirstconvertitlepremiercaractred'unechaneenmajuscules.
Lafonctionucwordsconvertitlepremiercaractredechaquemotd'unechaneenmajuscules.

Exemple

<?php
echo "strtolower(\"OLIVIER\") = ",
strtolower("OLIVIER"),"<BR>";
echo "strtoupper(\"olivier\") = ",
strtoupper("olivier"),"<BR>";
echo "ucfirst(\"olivier heurtel\") = ",
ucfirst("olivier heurtel"),"<BR>";
echo "ucwords(\"olivier heurtel\") = ",
ucwords("olivier heurtel"),"<BR>";
?>

Rsultat

strtolower("OLIVIER") = olivier
strtoupper("olivier") = OLIVIER
ucfirst("olivier heurtel") = Olivier heurtel
ucwords("olivier heurtel") = Olivier Heurtel

strcmpstrcasecmp

Cesfonctionspermettentdecomparerdeuxchanesentenantcompteoupasdesmajusculesetminuscules.

Syntaxe

entier strcmp(chane chane1,chane chane2)


entier strcasecmp(chane chane1,chane chane2)

chane1 etchane2 Chanescomparer.

Les deux fonctions retournent un nombre ngatif si chane1 est plus petit que chane2, un nombre gal 0 si
ellessontgales,etunnombrepositifsichane1estplusgrandquechane2.

strcmpestsensiblelacassealorsquestrcasecmpnel'estpas.

Exemple

<?php
echo "strcmp(\"Olivier\",\"olivier\") = ",
strcmp("Olivier","olivier"),"<BR>";
echo "strcasecmp(\"Olivier\",\"olivier\") = ",
strcasecmp("Olivier","olivier"),"<BR>";
?>

Rsultat

strcmp("Olivier","olivier") = -1
strcasecmp("Olivier","olivier") = 0

[s]printf

- 2- ENI Editions - All rigths reserved


Les fonctions printf et sprintf permettent de mettre en forme une chane (identiques aux fonctions C
quivalentes).

Syntaxe

chane sprintf(chane format[, mixte valeur[, ...]])


chane printf(chane format[, mixte valeur[, ...]])

format Chanedemiseenformeprsentantdiversesdirectivesselonlesspcificationsdonnesciaprs

valeur Valeurintgrerdanslachane.

sprintf retourne le rsultat mis en forme (ou FALSE en cas d'erreur) alors que printf affiche directement le
rsultat(commel'instructionecho)etretourneNULLencasdesuccsouFALSEencasd'erreur.

La chane format doit contenir une directive de formatage pour chaque argument valeur cette directive de
formatageprcisel'emplacementetlamiseenformedelavaleurcorrespondante.Lacorrespondanceentreune
directivedeformatageetunevaleurestpositionnelle(premiredirectivepourlapremirevaleur...).

Lesdirectivesdeformatagecommencentparlecaractre%suivid'unecinqinformations,laderniretantla
seuleobligatoire :

%[remplissage][alignement][longueur][prcision]type

Lesinformationssontlessuivantes :

remplissage

Prciselecaractreventuellementutilispourleremplissage.Lecaractrepardfautestl'espace.Toutautre
caractre peut tre employ en le mentionnant prcd d'une apostrophe (seul le caractre zro peut tre
indiqudirectement) :'xindiquequelecaractrederemplissageestle"x".

alignement

Prcise l'alignement. Par dfaut, l'alignement est droite. Le caractre moins ("") permet d'obtenir un
alignementgauche.

longueur

Indiquelenombreminimumdecaractresdel'lmentmisenforme.

prcision

Indiquelenombredechiffresutilisspourlamiseenformed'unnombrevirguleflottante(valableuniquementsi
l'lmentassociestunnombre).

type

Donneletypedelavaleurinsrer :
c :entierremplacerparlecaractredontlecodeASCIIacettevaleur
d :entierreprsentercommetel
f :nombrevirguleflottantereprsentercommetel
s :quelconque,reprsentercommeunechane.

Pourobteniruncaractre"%"danslersultatfinal,ilfautledoublerdansleformat.

Quelquesexemples :

Directive Valeur Rsultat Explication


%d 1 1 Nombre entier sans mise en forme

ENI Editions - All rigths reserved - 3-


particulire
%02d 1 01 02 = complter avec le caractre zro, pour une
longueur de deux minimum
%f 1/3 0.333333 Nombre virgule flottante sans mise en
forme particulire
%.2f 1/3 0.33 .2 = deux chiffres aprs le sparateur dcimal
%02.3f 1/3 00.333 .3 = trois chiffres aprs le sparateur dcimal
02 = complter avec le caractre zro, avant le
sparateur dcimal, pour une longueur de deux
minimum
%s Olivier Olivier Chane sans mise en forme particulire.
%'.10s Olivier ...Olivier '.10 = complter avec un point pour atteindre
une longueur minimum de dix caractres
(alignement par dfaut)
%'.-10s Olivier Olivier... '.-10 = complter avec un point pour
atteindre une longueur minimum de dix
caractres (signe - = alignement gauche)
%'.5.2f 9.9 ....9.90 .2 = deux chiffres aprs le sparateur
dcimal
'.5 = complter avec un point pour
atteindre une longueur minimum de cinq
caractres avant le point dcimal
(alignement par dfaut)

Exemple

<?php
echo "Mise en forme d'une date : ",
sprintf("%02d/%02d/%04d",1,1,2001),"<BR>";
echo "Mise en forme de nombres : ",
sprintf("1er = %01.2f - 2me = %01.2f",
1/3,12345678.9),"<BR>";
echo "Pourcentage : ",
sprintf("%01.2f %%",12.3),"<BR>";
echo "Utilisation des options de remplissage :<BR>";

echo "<TT>"; // police non proportionnelle


printf("%'.-10s%'.5.2f<BR>","Livres",9.35); // printf direct
printf("%'.-10s%'.5.2f<BR>","Disques",99.9); // printf direct
echo "</TT>";
?>

Rsultat

Mise en forme d'une date : 01/01/2001


Mise en forme de nombres : 1er = 0.33 - 2me = 12345678.90
Pourcentage : 12.30 %
Utilisation des options de remplissage :
Livres........9.35
Disques......99.90

v[s]printf

Les fonctions vprintf et vsprintf sont identiques aux fonctions printf et sprintf mais acceptent en
deuximeparamtreuntableaucontenantlesdiffrentesvaleursutiliser(laplacedesparamtresmultiples).

Syntaxe

chane vsprintf(chane format[, tableau valeurs])


chane vprintf(chane format[, tableau valeurs])

Avec

format Chane de mise en forme comprenant diverses directives selon les spcifications donnes

- 4- ENI Editions - All rigths reserved


prcdemment.

valeurs Tableaudonnantlesvaleursintgrerdanslachane.

Exemple

<?php
$donnes = array(array("Livres",9.35),array("Disques",99.9));
echo "<TT>"; // police non proportionnelle
foreach($donnes as $ligne) {
vprintf("%'.-10s%'.5.2f<BR>",$ligne); // printf direct
}
echo "</TT>";
?>

Rsultat

Livres........9.35
Disques......99.90

number_format

Lafonctionnumber_formatpermetdemettreenformeunnombre.

Syntaxe

chane number_format(nombre valeur[, entier dcimales[, chane sparateur_dcimal, chane


sparateur_milliers]])

valeur Nombremettreenforme.

dcimales Nombrededcimales(aucunepartiedcimalepardfaut).

sparateur_dcimal Sparateurdcimal(pointpardfaut).

sparateur_milliers Sparateurdesmilliers(virgulepardfaut).

La fonction peut tre appele avec un, deux ou quatre arguments, pas trois : si le troisime est fourni, le
quatrimeestobligatoire.

Si le nombre a une prcision suprieure celle demande (paramtre dcimales), le nombre est arrondi
laprcisiondemande.

Exemple

<?php
$x = 1234.56;
echo "number_format(\"$x\") = ",
number_format($x),"<BR>";
echo "number_format(\"$x\",1) = ",
number_format($x,1),"<BR>";
echo "number_format(\"$x\",1,\".\",\" \") = ",
number_format($x,1,"."," "),"<BR>";
echo "number_format(\"$x\",3,\".\",\" \") = ",
number_format($x,3,"."," "),"<BR>";
?>

Rsultat

number_format("1234.56") = 1,235
number_format("1234.56",1) = 1,234.6
number_format("1234.56",1,"."," ") = 1 234.6
number_format("1234.56",3,"."," ") = 1 234.560

Notez,surcesexemples,lesarrondisautomatiqueslorsquelaprcisiondemandeestinfrieurelaprcisiondu
nombre.

ENI Editions - All rigths reserved - 5-


ltrim rtrim trim

Ces fonctions permettent de supprimer les caractres "blancs", ou d'autres caractres, en dbut de chane, en
findechaneoudesdeuxcts.

Syntaxe

chane ltrim(chane chane[, chane caractres])


chane rtrim(chane chane[, chane caractres])
chane trim(chane chane[, chane caractres])

Avec

chane Chanetraiter.

caractres Chanedonnantlalistedescaractressupprimer.Siceparamtreestabsent,lescaractres
"blancs"sontsupprims.

Les trois fonctions retournent une chane gale la chane initiale dans laquelle les caractres "blancs" ou les
caractresspcifisonttsupprimsaudbut(ltrim avec -l= left=gauche),lafin(rtrim avec -r=
right=droite)oudesdeuxcts(trim).

Les caractres "blancs" sont le saut de ligne (\n = code ASCII 10), le retour chariot (\r = code ASCII 13), la
tabulation(\t=codeASCII9),lecaractreNULL(\0=codeASCII0)etl'espace.

Exemple 1

<?php
$x = "\0\t\t x \n\r";
echo "strlen(\$x) = ",strlen($x),"<BR>";
echo "strlen(ltrim(\$x)) = ",strlen(ltrim($x)),"<BR>";
echo "strlen(rtrim(\$x)) = ",strlen(rtrim($x)),"<BR>";
echo "strlen(trim(\$x)) = ",strlen(trim($x)),"<BR>";
?>

Rsultat

strlen($x) = 8
strlen(ltrim($x)) = 4
strlen(rtrim($x)) = 5
strlen(trim($x)) = 1

Exemple 2

<?php
$x = "***+-Olivier-+***";
echo "trim(\"$x\",\"*+-\") = ",trim($x,"*+-"),"<BR>";
?>

Rsultat

trim("***+-Olivier-+***","*+-") = Olivier

substr

Lafonctionsubstrpermetd'extraireunesouschanedansunechane.

Syntaxe

chane substr(chane chane, entier dbut[, entier longueur])

chane Chanetraiter.

- 6- ENI Editions - All rigths reserved


dbut Positiondupremiercaractredelasouschaneextraire(attention 0=1e rcaractre).

longueur Nombredecaractresextraire(pardfaut,jusqu'lafindelachane).

- Si l'argument dbut est positif, la souschane extraite commence au caractre dbut (0 = 1er caractre).

- Si l'argument dbut est ngatif, la souschane extraite commence au caractre dbut en partant de la fin (1 =
dernier caractre).

- Si l'argument longueur n'est pas spcifi, la souschane extraite se termine la fin de la chane.

- Si l'argument longueur est spcifi et positif, substr extrait le nombre de caractres indiqu par l'argument
longueur.

- Si l'argument longueur est spcifi et ngatif, la souschane extraite se termine la fin de la chane, moins le
nombre de caractres indiqu par la valeur absolue de l'argument longueur.

Exemple

<?php
// 012345678901234 => pour le contrle
$x = "Olivier Heurtel";
echo "substr(\"$x\",8) = ",substr($x,8),"<BR>";
echo "substr(\"$x\",8,3) = ",substr($x,8,3),"<BR>";
echo "substr(\"$x\",8,-3) = ",substr($x,8,-3),"<BR>";
echo "substr(\"$x\",-7) = ",substr($x,-7),"<BR>";
echo "substr(\"$x\",-7,3) = ",substr($x,-7,3),"<BR>";
echo "substr(\"$x\",-7,-3) = ",substr($x,-7,-3),"<BR>";
?>

Rsultat

substr("Olivier Heurtel",8) = Heurtel


substr("Olivier Heurtel",8,3) = Heu
substr("Olivier Heurtel",8,-3) = Heur
substr("Olivier Heurtel",-7) = Heurtel
substr("Olivier Heurtel",-7,3) = Heu
substr("Olivier Heurtel",-7,-3) = Heur

str_repeat

Lafonctionstr_repeatpermetdeconstruireunechaneparrptitiondecaractres.

Syntaxe

chane str_repeat(chane squence, entier rptitions)

squence Squencedecaractresrpter.

rptitions Nombrederptitionssouhaites.

CettefonctionatintroduiteavecPHP4.

Exemple

<?php
echo str_repeat("abc",3);
?>

Rsultat

abcabcabc

ENI Editions - All rigths reserved - 7-


strposstrrposstriposstrripos

Ces fonctions permettent de rechercher la position d'une occurrence (caractre ou chane) l'intrieur d'une
chane.

Syntaxe

entier strpos(chane _traiter, chane rechercher[, entier dbut])


entier strrpos (chane _traiter, chane chercher[, entier dbut])
entier stripos(chane _traiter, chane chercher[, entier dbut])
entier strripos (chane _traiter, chane chercher[, entier dbut])

Avec

_traiter Chanetraiter.

chercher lmentrecherch.

dbut Numroducaractre(0=premiercaractre)partirduquellarecherchedoittreralise(pardfaut,le
dbutdelachane).

strpos recherche, dans la chane _traiter, la premire occurrence de la chane chercher, en commenant
ventuellementaucaractrenumrodbut(0=premiercaractre).

strrpos recherche, dans la chane _traiter, la dernire occurrence de la chane chercher, en commenant
ventuellement au caractre numro dbut (0 = premier caractre). Si dbut est ngatif (-n), les n derniers
caractresdelachane_traitersontignors.Leparamtre offsetatajoutdanslaversion5.Enversion
4,seullepremiercaractredelachanecherchertaitprisencompte.

Les deux fonctions sont sensibles la casse (une majuscule n'est pas gale une minuscule). Les fonctions
stripos et strripos sont identiques respectivement aux fonctions strpos et strrpos, mais ne sont pas
sensibleslacasse ellesonttintroduitesenversion5.

Cesquatrefonctionsretournentlapositiondel'occurrencetrouve(0=premiercaractre)ouFALSEsil'lment
recherchn'estpastrouv.

FALSEtantquivalent0,ilestfaciledeconfondrelecasol'lmentn'apasttrouvetlecasoilat
trouvendbutdechane.Latechnique,avecPHP4,consisteutiliserl'oprateurdecomparaison"==="(trois
signes gal) qui permet de comparer la valeur et le type de deux expressions (pour plus de dtail, cf. chapitre
Oprateurs).

Exemple

<?php
// 0123456789 ... => pour le contrle
$mail = "contact@olivier-heurtel.fr";
// strrpos
$position = strrpos($mail,"@");
echo "@ est la position $position dans $mail<BR>";
// strpos
$position = strpos($mail,"olivier");
echo "'olivier' est la position $position dans $mail<BR>";

// occurrence en dbut de chane


$position = strpos($mail,"contact");
if (! $position) { // mauvais test
echo "'contact' est introuvable dans $mail<BR>";
} else {
echo "'contact' est la position $position
dans $mail<BR>";
}
if ($position === FALSE) { // bon test : ===
echo "'contact' est introuvable dans $mail<BR>";
} else {
echo "'contact' est la position $position
dans $mail<BR>";
}

- 8- ENI Editions - All rigths reserved


// occurrence non trouve
$position = strpos($mail,"information");
if ($position === FALSE) { // bon test : ===
echo "'information' est introuvable dans $mail<BR>";
} else {
echo "'information' est la position $position
dans $mail<BR>";
}
?>

Rsultat

@@ est la position 7 dans contact@olivier-heurtel.fr


'olivier' est la position 8 dans contact@olivier-heurtel.fr
'contact' est introuvable dans contact@olivier-heurtel.fr
'contact' est la position 0 dans contact@olivier-heurtel.fr
'information' est introuvable dans contact@olivier-heurtel.fr

strstrstristrstrrchr

Ces fonctions permettent d'extraire la souschane commenant partir d'une certaine occurrence d'un
caractreoud'unechane.

Syntaxe

chane strstr(chane _traiter, chane rechercher)


chane stristr(chane _traiter, chane rechercher)
chane strrchr(chane _traiter, caractre rechercher)

_traiter Chanetraiter.

rechercher lmentrecherch.

strstret stristrrecherchent,danslachane_traiter,lapremireoccurrencedela chanerechercher,et


retournentlaportionterminaledelachanecommenantcetteoccurrence(incluse). strstrestsensiblela
casse(unemajusculeestdiffrented'uneminuscule)alorsquestristrnel'estpas.

strrchr recherche, dans la chane _traiter, la dernire occurrence du caractre rechercher et retourne la
portion terminale de la chane commenant cette occurrence (incluse). Si rechercher est une chane de
plusieurscaractres,seullepremierestprisencompte.strrchrestsensiblelacasse.
CestroisfonctionsretournentFALSEsil'lmentrecherchn'estpastrouv.

Exemple

<?php
$mail = "Olivier-Heurtel@olivier-heurtel.fr";
echo "Reste de $mail commenant par :<BR>";
// strrchr
$reste = strrchr($mail,"-");
echo "- la dernire occurrence de '-'<BR>----> $reste <BR>";
// strstr
$reste = strstr($mail,"olivier");
echo "- la premire occurrence de 'olivier'
(sensible la casse)<BR>----> $reste <BR>";
// stristr
$reste = stristr($mail,"olivier");
echo "- la premire occurrence de 'olivier'
(insensible la casse)<BR>----> $reste <BR>";
?>

Rsultat

Reste de Olivier-Heurtel@olivier-heurtel.fr commenant par :


- la dernire occurrence de '-'
----> -heurtel.fr
- la premire occurrence de 'olivier' (sensible la casse)
----> olivier-heurtel.fr
- la premire occurrence de 'olivier' (insensible la casse)
----> Olivier-Heurtel@olivier-heurtel.fr

ENI Editions - All rigths reserved - 9-


str_replacestr_ireplace

La fonctionstr_replacepermetderemplacerlesoccurrencesd'unechaneparuneautrechane.Larecherche
estsensiblelacasse.

La fonction str_ireplace permet la mme action mais n'est pas sensible la casse elle a t introduite en
version5.

Syntaxe

mixte str_replace(mixte rechercher, mixte remplacer, mixte _traiter[,entier nombre])


mixte str_ireplace(mixte rechercher, mixed remplacer, mixed _traiter
[,entier nombre])

_traiter Chanetraiteroutableaudechanestraiter.

rechercher Chanerechercheroutableaudechanesrechercher.

remplacer Chanederemplacementoutableaudonnantunelistedechanesderemplacement.

nombre Variablepermettantdercuprerlenombrederemplacements(version5).

Si rechercher et remplacer sont des chanes, str_replacerecherchetouteslesoccurrencesde rechercher


etlesremplaceparremplacer.

Si rechercher et remplacer sont des tableaux, str_replace recherche toutes les occurrences de chaque
lmentderechercheretlesremplaceparl'lmentcorrespondantderemplacer.

Danslesdeuxcas,letraitementesteffectusurlachane _traiterousurchaquelmentde_traiter, si
cettedernireestuntableau.

Exemple

<?php
// premire syntaxe
$x = "cet t, la plage";
$rechercher = "t";
$remplacer = "hiver";
echo "<B>Premire syntaxe :</B><BR>";
echo "$rechercher => $remplacer <BR>";
echo "$x => ",str_replace($rechercher,$remplacer,$x),"<BR>";
// deuxime syntaxe
$x = array("cet t, la plage","le bateau bleu et vert");
$rechercher = array("t","plage","bleu","vert");
$remplacer = array("hiver","montagne","rouge","jaune");
echo "<B>Deuxime syntaxe :</B><BR>";
foreach($rechercher as $indice => $avant)
{ echo "$avant => $remplacer[$indice]<BR>"; }
// utilisation de la variable $nombre pour rcuprer
// le nombre de remplacements
$y = str_replace($rechercher,$remplacer,$x,$nombre);
echo "$x[0] = $y[0]<BR>";
echo "$x[1] = $y[1]<BR>";
echo "$nombre remplacements<BR>";
?>

Rsultat

Premire syntaxe :
t => hiver
cet t, la plage => cet hiver, la plage
Deuxime syntaxe :
t => hiver
plage => montagne
bleu => rouge
vert => jaune
cet t, la plage => cet hiver, la montagne
le bateau bleu et vert => le bateau rouge et jaune

- 10 - ENI Editions - All rigths reserved


4 remplacements

strtr

La fonction strtr permet de remplacer les occurrences d'un caractre par un autre caractre ou d'une chane
paruneautrechane.

Syntaxe

chane strtr(chane _traiter, chane rechercher, chane remplacer)


ou
chane strtr(chane _traiter, tableau correspondance)

_traiter Chanetraiter.

rechercher Chanedonnantlalistedescaractresremplacer.

remplacer Chanedonnantlalistedescaractresderemplacement.

correspondance Tableauassociatifdonnantunecorrespondancechaneremplacer/chanederemplacement.

strtracceptedeuxsyntaxes,lapremirepermettantderemplacerdescaractrespard'autres,etladeuxime,
deremplacerdeschanespard'autres.

Avec la premire syntaxe, la correspondance entre les caractres remplacer et les caractres de
remplacement est donne par deux chanes (le caractre n de la premire tant remplacer par le caractre n
deladeuxime).

Avecladeuximesyntaxe,lacorrespondanceentreleschanesremplaceretleschanesderemplacementest
donneparuntableauassociatif(lacltantlachanerechercher,etlavaleur,lachanederemplacement).

Exemple

<?php
// premire syntaxe
$x = "cet t, la plage";
$avant = "";
$aprs = "eea";
echo "<B>Premire syntaxe :</B><BR>";
echo "$avant => $aprs<BR>";
echo "$x => ",strtr($x,$avant,$aprs),"<BR>";
// deuxime syntaxe
$x = "le bateau bleu et vert";
$correspondance = array("bleu"=>"rouge","vert"=>"jaune");
echo "Deuxime syntaxe :</B><BR>";
foreach($correspondance as $avant => $aprs)
{ echo "$avant => $aprs<BR>"; }
echo "$x => ",strtr($x,$correspondance),"<BR>";
?>

Rsultat

Premire syntaxe :
=> eea
cet t, la plage => cet ete, a la plage
Deuxime syntaxe :
bleu => rouge
vert => jaune
le bateau bleu et vert => le bateau rouge et jaune

Lesexpressionsrguliresereg[i]ereg[i]_replace

PHP propose plusieurs fonctions qui permettent d'effectuer des recherches ou des remplacements dans une
chanel'aided'unmodleappel"expressionrgulire"dcrivantl'lmentrecherch.

Syntaxe

ENI Editions - All rigths reserved - 11 -


boolen ereg(chane rechercher, chane _traiter[, tableau
rsultat])
boolen eregi(chane rechercher, chane _traiter[, tableau
rsultat])
chane ereg_replace(chane rechercher, chane remplacer,
chane _traiter)
chane eregi_replace(chane rechercher, chane remplacer,
chane _traiter)

_traiter Chanetraiter.

rechercher Chanedonnantlemodle(l'expressionrgulire)del'lmentrecherch.

remplacer Chanederemplacement.

rsultat Sousformedetableau,listedesportionsdelachane_traiterquicorrespondentaumodle
recherch.

ereg et eregi recherchent, dans la chane _traiter, s'il existe une chane qui correspond au modle spcifi
par rechercher(voirciaprspourlesrgles).eregestsensiblelacasse(unemajusculeestdiffrented'une
minuscule)alorsque ereginel'estpas.CesfonctionsretournentTRUEsilemodleesttrouv,et FALSEdansle
cascontraire.

En complment, si le modle le demande (voir ciaprs pour les rgles) et si un troisime paramtre est fourni,
les diffrentes portions de la chane _traiter qui correspondent au modle sont stockes sous forme de
tableaudansletroisimeparamtre.

ereg_replace et eregi_replace effectuent la recherche sur le mme principe et remplacent les diffrentes
portions de la chane _traiter qui correspondent au modle, par la chane remplacer. ereg_replace est
sensible la casse alors que eregi_replace ne l'est pas. Si aucune occurrence n'est trouve, la chane
_traiterestretourne,inchange.
Plusieurscaractresspciauxpeuventtreutilissdanslemodlepourdcrirel'lmentrecherch :

Caractre
Signification
spcial
^ Si ^ est prsent comme premier caractre du modle, indique que la chane doit commencer par ce qui suit.
Si $ est prsent comme dernier caractre du modle, indique que la chane doit terminer par ce qui
prcde :
^abc : doit commencer par abc.
xyz$ : doit terminer par xyz.
$
^abcxyz$ : doit commencer par abcxyz et se terminer par abcxyz (bref tre gal abcxyz !).
Un modle ne comprenant ni ^, ni $, indique que le modle est recherch n'importe o l'intrieur de la
chane :
abc : contient abc.
Indique que le caractre qui prcde, ou la squence qui prcde (voir ci-aprs), peut tre prsente zro, une
* ou plusieurs fois :
ab*c accepte ac, abc, abbc...
Indique que le caractre qui prcde, ou la squence qui prcde (voir ci-aprs), doit tre prsente une ou
+ plusieurs fois :
ab+c accepte abc, abbc... mais refuse ac.
Indique que le caractre qui prcde, ou la squence qui prcde (voir ci-aprs), peut tre prsente zro ou
? une fois :
ab?c accepte ac et abc mais refuse abbc, abbbc...
Indique que le caractre qui prcde, ou la squence qui prcde (voir ci-aprs), doit tre prsente
{x} exactement x fois ({x}) ou au minimum x fois ({x,}) ou entre x et y fois ({x,y}) :
{x,} ab{2}c n'accepte que abbc.
{x,y} ab{2,4}c accepte abbc, abbbc, et abbbbc mais refuse abc (manque un b) ou abbbbbc (un b de trop).
ab{2,}c accepte abbc, abbbc, abbbbc... mais refuse abc (manque un b).
Permet de marquer une squence recherche, typiquement avec les symboles relatifs au nombre
(...) d'occurrences :
a(bc)*d accepte ad, abcd, abcbdd... mais refuse abd ou acd (la squence bc n'est pas trouve).

- 12 - ENI Editions - All rigths reserved


Recherche de x ou de y (gnralement utilis avec les parenthses pour viter toute confusion) :
x|y a(b|c)*d accepte ad, abd, acd, abcd, abbcd, accbd, ... (en clair, un nombre quelconque de b
ou de c situs dans n'importe quel ordre entre un a et un d).
Permet de spcifier une srie de caractres accepts, soit sous la forme c1c2...cn pour une liste
exhaustive prcise, soit sous la forme c1-c2 pour une plage de caractres, soit en mlangeant les deux :
[abcd] accepte un caractre parmi abcd quivalent (a|b|c|d).
[a-z] accepte un caractre compris entre a et z.
[123a-zA-z] accepte un caractre compris entre a et z, ou compris en A et Z ou gal 1 ou 2 ou 3.
[a-zA-z0-9] accepte un caractre compris entre a et z, ou entre A et Z ou entre 0 et 9.
Une exclusion peut tre spcifie en plaant un ^ en premier caractre l'intrieur des crochets :
[^0-9] refuse tout caractre compris entre 0-9.
[...]
[^abc] refuse les caractres a, b et c.
Peut tre combin avec les symboles relatifs au nombre d'occurrences.
a[0-9]{1,3}b accepte toute squence comprenant un a suivi de deux trois caractres compris entre 0 et
9, suivi d'un b : a01b, a11b, a000b mais pas a1234b (trop de chiffres) ni a0b (pas assez de chiffres) ni
a0xb (caractre parasite avant le b).
Remarque : compte tenu de sa signification particulire, le signe -, s'il est recherch en tant que tel, doit
figurer en premier ou en dernier entre les crochets :
[a-z-] accepte tout caractre compris entre a et z ainsi que le caractre -.
Indique un caractre quelconque :
a.b accepte toute squence comprenant un a suivi d'un caractre quelconque, suivi d'un b : axb, ayb, mais
pas ab ni axyb.
.
Peut tre combin avec les symboles relatifs au nombre d'occurrences.
a.{0,2}b accepte toute squence comprenant un a, suivi de 0 2 caractres quelconques, suivi d'un b : ab,
axb, axyb, mais pas axyzb.
Permet d'chapper les caractres spciaux (^.[$()|*+?{\) lorsque ceux-ci sont recherchs en tant que
tel, sauf lorsqu'il sont mentionns entre crochets :
a\*{2,4}b permet de rechercher les squences commenant par un a suivi de deux quatre toiles suivies
\
d'un b (notez le \*).
a[$*+]{2,4}b permet de rechercher les squences commenant par un a suivi de deux quatre caractres
(pris parmi $, * et +), suivis d'un b (pas besoin de \).
Les parenthses ont une deuxime signification lorsqu'elles englobent tout le modle ou des parties du
modle. Elle permettent de "capturer" dans la chane les squences qui rpondent au modle ou la portion
de modle entre parenthses. Dans le cas de l'utilisation des fonctions ereg et eregi, les portions
captures sont stockes sous forme de tableau dans le troisime paramtre (s'il est spcifi) : la premire
(...) ligne (indice 0) du tableau contient une copie de la chane correspondant la totalit du modle et les portions
captures sont stockes dans les lignes suivantes. Dans le cas de l'utilisation des fonctions ereg_replace
et eregi_replace, les portions captures peuvent tre reprises dans la chane de remplacement grce la
notation \\n, avec n entier (0 dsignant la portion de la chane correspondant la totalit du modle et les
numros 1 n les portions captures).

Les expressions rgulires sont des outils trs puissants pour effectuer des recherches dans une chane ou
validerlaconformitd'unesaisiecertainesrgles.

Les diffrents sites Web prsents dans le chapitre 1, regorgent d'exemples de code utilisant les expressions
rgulires.

En complment des quelques exemples prsents ciaprs, le chapitre 7 illustre l'utilisation des expressions
rgulirespourvaliderlasaisied'unutilisateur.

Exemple

<?php
// vrifier qu'une chane commence par une lettre et
// est suivie d'au moins 3 lettres ou chiffres ou caractres
// spciaux _#*$
// utilisation de eregi (insensible la casse)
$chane = "A0_#b*1$2";
echo "$chane OK => ",
(int) eregi("^[a-z][a-z0-9_#*$]{3,}",$chane),"<BR>";
$chane = "0_#b*1$2"; // ne commence pas par une lettre
echo "$chane : ne commence pas par une lettre => ",
(int) eregi("^[a-z][a-z0-9_#*$]{3,}",$chane),"<BR>";
$chane = " A0_#"; // longueur insuffisante

ENI Editions - All rigths reserved - 13 -


echo "$chane : longueur insuffisante => ",
(int) eregi("^[a-z][a-z0-9_#*$]{3,}",$chane),"<BR>";
$chane = " A0__#"; // caractre invalide
echo "$chane : caractre invalide => ",
(int) eregi("^[a-z][a-z0-9_#*$]{3,}",$chane),"<BR>";
?>

Rsultat

A0_#b*1$2 OK => 1
0_#b*1$2 : ne commence pas par une lettre => 0
A0_# : longueur insuffisante => 0
A0__# : caractre invalide => 0

Lersultatdeeregiestconvertienentierpourl'affichage(0=FALSE, 1=TRUE).

Quelquesexplicationssurl'expressionrgulireutilise(^[a-z][a-z0-9_#*$]{3,}) :

- eregi est utilise afin de ne pas faire de diffrence entre majuscules et minuscules.

- ^ = commence par ...

- [a-z] = une lettre entre a et z (ou A et Z eregi tant utilise) ...

- [a-z0-9_#*$]{3,} = suivi d'au moins 3 ({3,}) caractres parmi ceux indiqus: a z (et donc A Z), 0 9 et les
caractres _#*$.

Exemple

<?php
// effectuer des remplacements simples (en l'occurrence,
// remplacer par une chane vide = supprimer)
$chane = "aBc12dEFg453hijk";
echo "Expurger $chane :<BR>";
echo "- des chiffres => ",
ereg_replace("[0-9]+","",$chane),"<BR>";
echo "- des lettres => ",
eregi_replace("[a-z]+","",$chane),"<BR>";
// eregi_replace => insensible la casse
?>

Rsultat

Expurger aBc12dEFg453hijk :
- des chiffres => aBcdEFghijk
- des lettres => 12453

Exemple

<?php
// vrifier qu'une chane a une structure conforme celle
// d'une date au format [J]J/[M]M/AAAA et rcuprer
// les 3 composantes jour, mois et anne.
$date = "21/09/2001";
$ok = ereg(
"^([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})$",
$date,
$rsultat);
if ($ok) {
echo "$date valide.
";
echo "- jour = $rsultat[1]<BR>";
echo "- mois = $rsultat[2]<BR>";
echo "- anne = $rsultat[3]<BR>";
} else {
echo "$date invalide.<BR>";
}

- 14 - ENI Editions - All rigths reserved


$date = "1/2/2001";
$ok = ereg(
"^([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})$",
$date,
$rsultat);
if ($ok) {
echo "$date valide.<BR>";
echo "- jour = $rsultat[1]<BR>";
echo "- mois = $rsultat[2]<BR>";
echo "- anne = $rsultat[3]<BR>";
} else {
echo "$date invalide.<BR>";
}
$date = "21/09/01";
$ok = ereg(
"^([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})$",
$date,
$rsultat);
if ($ok) {
echo "$date valide.<BR>";
echo "- jour = $rsultat[1]<BR>";
echo "- mois = $rsultat[2]<BR>";
echo "- anne = $rsultat[3]<BR>";
} else {
echo "$date invalide (anne incomplte).<BR>";
}
$date = "210/09/2001";
$ok = ereg(
"^([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})$",
$date,
$rsultat);
if ($ok) {
echo "$date valide.<BR>";
echo "- jour = $rsultat[1]<BR>";
echo "- mois = $rsultat[2]<BR>";
echo "- anne = $rsultat[3]<BR>";
} else {
echo "$date invalide (jour trop long).<BR>";
}
$date = "Olivier";
$ok = ereg(
"^([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})$",
$date,
$rsultat);
if ($ok) {
echo "$date valide.<BR>";
echo "- jour = $rsultat[1]<BR>";
echo "- mois = $rsultat[2]<BR>";
echo "- anne = $rsultat[3]<BR>";
} else {
echo "$date invalide (rien voir !).<BR>";
}
?>

Rsultat

21/09/2001 valide.
- jour = 21
- mois = 09
- anne = 2001
1/2/2001 valide.
- jour = 1
- mois = 2
- anne = 2001
21/09/01 invalide (anne incomplte).
210/09/2001 invalide (jour trop long).
Olivier invalide (rien voir !).

Quelquesexplicationssurl'expressionrgulireutilise(^([0-9]{1,2})/
([0-9]{1,2})/([0-9]{4})$) :

- ^ = commence par ...

- [0-9]{1,2} = un ou deux chiffres ...

ENI Editions - All rigths reserved - 15 -


- / = suivi du caractre "/" ...

- [0-9]{1,2} = un ou deux chiffres ...

- / = suivi du caractre "/" ...

- [0-9]{4} = suivi de quatre chiffres ...

- $ = suivi de ... rien du tout! La chane doit se terminer immdiatement.

Ce test permet de vrifier qu'une chane cense contenir une date est bien forme. Il convient ensuite de vrifier, avec la
fonction checkdate par exemple, que les trois composantes correspondent une date valide.

Exemple

<?php
// utiliser ereg_replace pour rorganiser une chane
// en l'occurrence, il s'agit de transformer une date
// au format JJ/MM/AAAA en date au format AAAA-MM-JJ
$avant = "21/09/2001";
$aprs = ereg_replace(
"^([0-9]{2})/([0-9]{2})/([0-9]{4})$",
"\\3-\\2-\\1",
$avant);
echo "$avant => $aprs";
?>

Rsultat

21/09/2001 => 2001-09-21

Danslachanederemplacement,lessquences\\ndsignentlestroisportionscapturesparlesparenthses :

- \\1 = premire ([0-9]{2})= 21 ;

- \\2 = deuxime ([0-9]{2})= 09 ;

- \\3 = troisime ([0-9]{4})= 2001.

Le rsultat de la recherche, qui est gal la chane complte dans ce cas, est ensuite remplac par la chane
"\\3-\\2-\\1"soit2001-09-21.

Manipulationdesdates

PHP ne gre pas les dates avec un type de donne spcifique. Nanmoins, des dates peuvent tre manipules,
soitsouslaformed'unechanedecaractres,soitsouslaformed'untimestampUnix(correspondantaunombre
desecondescoulesdepuisle1e rjanvier197001:00:00).

Plusieursfonctionspermettentdemanipulerlesdatessousl'uneoul'autredecesformes :

Nom Rle
checkdate Vrifie que trois entiers reprsentant le jour, le mois et l'anne
correspondent une date valide.
date Convertit en chane une date donne sous la forme d'un timestamp Unix.
strftime Convertit en chane une date donne sous la forme d'un timestamp Unix,
en utilisant des caractristiques locales.
getdate Stocke dans un tableau les diffrentes composantes d'une date donne
sous la forme d'un timestamp Unix.
time Donne le timestamp Unix actuel.

- 16 - ENI Editions - All rigths reserved


mktime Cre un timestamp Unix partir des diffrentes composantes d'une date.
microtime Donne le timestamp Unix actuel accompagn du nombre de
microsecondes coules depuis la dernire seconde.
idate Donne les composantes d'une date fournie sous la forme d'un timestamp
Unix.

checkdate

Lafonction checkdatevrifiequetroisentiersreprsentantlejour,lemoisetl'annecorrespondentunedate
valide.

Syntaxe

boolen checkdate(entier mois, entier jour, entier anne)

mois Numrodumois(112)

jour Numrodujour(131)

anne Anne(032767)

checkdate retourne TRUE si la date construite avec les trois composantes est valide et FALSE dans le cas
contraire.Cettefonctiontientcomptedesannesbissextiles.

Exemple

<?php
$jour = 13; $mois = 8 ; $anne = 1994;
echo "$jour/$mois/$anne => ",
var_dump(checkdate($mois,$jour,$anne)),"<BR>";
$jour = 31; $mois = 9 ; $anne = 2001;
echo "$jour/$mois/$anne => ",
var_dump(checkdate($mois,$jour,$anne)),"<BR>";
$jour = 29; $mois = 2 ; $anne = 2000;
echo "$jour/$mois/$anne => ",
var_dump(checkdate($mois,$jour,$anne)),"<BR>";
$jour = 29; $mois = 2 ; $anne = 2001;
echo "$jour/$mois/$anne => ",
var_dump(checkdate($mois,$jour,$anne)),"<BR>";
$jour = 29; $mois = 2 ; $anne = 2004;
echo "$jour/$mois/$anne => ",
var_dump(checkdate($mois,$jour,$anne)),"<BR>";
?>

Rsultat

13/8/1994 => bool(true)


31/9/2001 => bool(false)
29/2/2000 => bool(true)
29/2/2001 => bool(false)
29/2/2004 => bool(true)

date

Lafonctionconvertitenchaneunedatedonnesouslaformed'untimestampUnix.

Syntaxe

chane date(chane format[, entier timestamp])

format Formatdeconversion

timestamp Timestampconvertir(pardfautletimestampactuel).

Leformatpeuttrespcifil'aidedescaractressuivants :

ENI Editions - All rigths reserved - 17 -


Caractre Signification
d Jour du mois, sur deux chiffres (01 31)
j Jour du mois, sur un ou deux chiffres (1 31)
m Numro du mois, sur deux chiffres (01 12)
n Numro du mois, sur un ou deux chiffres (1 12)
Y Anne sur quatre chiffres (2001 par exemple)
y Anne sur deux chiffres (01 par exemple)
h Heure, au format 12h, sur deux chiffres (01 12)
g Heure, au format 12h, sur un ou deux chiffres (1 12)
H Heure, au format 24h, sur deux chiffres (00 23)
G Heure, au format 24h, sur un ou deux chiffres (0 23)
i Minutes sur deux chiffres (00 59)
s Secondes sur deux chiffres (00 59)
z Jour de l'anne (0 365)
w Numro du jour de la semaine (0 = dimanche 6 = samedi)
a Symbole "am"/"pm" (minuscules)
A Symbole "AM"/"PM" (majuscules)
D Trois premires lettres du nom du jour de la semaine
l (" L " Nom du jour de la semaine (en anglais)
minuscule)
M Trois premires lettres du nom du mois (en anglais)
F Nom du mois (en anglais)
S Suffixe (en anglais) pour le numro du jour ("st" ou "nd" par exemple)
I (" i " 1 si l'heure d'hiver est active, 0 sinon
majuscule)
L 1 si l'anne est bissextile, 0 sinon
t Nombre de jours dans le mois donn (entre 28 et 31)
B Heure Internet Swatch (000 999)
r Format de date de la RFC 822 (par exemple, "Thu, 20 Sep 2001
15:47:00 +0200")
T Fuseau horaire de la machine
U Timestamp (!)
Z Dcalage horaire en secondes (entre -43 200 et 43 200)
c Date au format ISO 8601 (par exemple, "2004-03-
09T17:39:12+01:00")
O Dcalage horaire en heures (par exemple "+0100")
W Numro de la semaine dans l'anne, selon la norme ISO 9601

Encasdebesoin,cesdiffrentscaractrespeuventtrechappsavecunantislash(\).

Exemple

<?php
// sans deuxime paramtre = utilisation du timestamp courant
echo "Format long (anglais uniquement) : ",
date("l j F Y"),"<BR>";
echo "Date au format JJ/MM/AAAA : ",
date("d/m/Y"),"<BR>";
echo "Date au format J/M/AA : ",
date("j/n/y"),"<BR>";
echo "Heure : ",
date("H:i:s"),"<BR>";

- 18 - ENI Editions - All rigths reserved


echo "Utilisation du \ : ",
date("Nou\s \so\m\me\s \le d/m/Y."),"<BR>";
echo "Unix a ft sa milliardime seconde le ",
date("d/m/Y H:i:s",1000000000),"<BR>";
?>

Rsultat

Format long (anglais uniquement) : Tuesday 9 March 2004


Date au format JJ/MM/AAAA : 09/03/2004
Date au format J/M/AA : 9/3/04
Heure : 17:46:45
Utilisation du \ : Nous sommes le 09/03/2004.
Unix a ft sa milliardime seconde le 09/09/2001 03:46:40

strftime

La fonction strftime convertit en chane une date donne sous la forme d'un timestampUnix,enutilisantdes
caractristiqueslocales.

Syntaxe

chane strftime(chane format[, entier timestamp])

format Formatdeconversion

timestamp Timestampconvertir(pardfautletimestampactuel)

ladiffrencedelafonctiondate, strftimeutiliselescaractristiqueslinguistiqueslocales(cellesduserveur).

Leformatpeuttrespcifil'aidedescaractressuivants :

Caractre Signification
%d Numro du jour du mois, sur deux positions, complt par un zro
(01 31)
%m Numro du mois sur deux chiffres (01 12)
%y Anne sur deux chiffres (par exemple 01)
%Y Anne sur quatre chiffres (par exemple 2001)
%H Heure, au format 24h
%I (" i " Heure, au format 12h, sur deux chiffres (01 12)
majuscule)
%M Minutes sur deux chiffres (00 59)
%S Secondes sur deux chiffres (00 59)
%j Jour de l'anne sur trois chiffres (001 366)
%w Numro du jour de la semaine (0 = dimanche 6 = samedi)
%p Symbole "AM"/"PM" (majuscules)
%a Nom abrg du jour de la semaine
%A Nom complet du jour de la semaine
%b Nom abrg du mois
%B Nom complet du mois
%U Numro de semaine dans l'anne ; en considrant le premier
dimanche de l'anne comme le premier jour de la premire semaine
%W Numro de semaine dans l'anne, en considrant le premier lundi
de l'anne comme le premier jour de la premire semaine
%Z Fuseau horaire, ou nom ou abrviation
%c Format par dfaut pour la date et l'heure
%x Format par dfaut pour la date seule

ENI Editions - All rigths reserved - 19 -


%X Format par dfaut pour l'heure seule
%% Un caractre % littral
%C Numro du sicle sur deux chiffres
%D Identique %m/%d/%y
%e Numro du jour du mois, sur deux positions, complt par un
espace
%G Anne sur 4 chiffres correspondant au numro de la semaine selon
la norme ISO 8601 (voir %V)
%g Anne sur 2 chiffres correspondant au numro de la semaine selon
la norme ISO 8601 (voir %V)
%h Nom abrg du mois (identique %b)
%n Retour la ligne
%r Heure avec la notation AM/PM
%R Heure avec la notation 24 h
%t Tabulation
%T Identique %H:%M:%S
%u Numro du jour dans la semaine (1 = lundi)
%V Numro de la semaine dans l'anne selon la norme ISO 8601

Tous les symboles ne sont pas forcment supports sur toutes les plates-formes.

Les caractristiques linguistiques locales peuvent tre lues et modifies par l'intermdiaire de la fonction
setlocale.

Syntaxe

chane setlocale(mixte catgorie, chane langue)

catgorie

Fonctionnalit concerne par les caractristiques linguistiques locales et dfinie l'aide d'une des constantes
suivantes :
LC_COLLATE :comparaisondechaneaveclafonctionstrcoll ;
LC_CTYPE :classificationetconversions(fonctionstroupperparexemple)
LC_NUMERIC :sparateursdcimaux
LC_MONETARY:symbolemontaire(fonctionlocaleconv) ;
LC_TIME :formatsdedate(fonctionstrftime) ;
LC_ALL :touteslesprcdentes.

langue

Codedelalanguedevantgouvernerlafonctionnalitassocie.Extraitdesvaleurspossibles :
du :Hollande
fr :France
ge :Allemagne
it :Italie
ru :Russie
sp :Espagne
sw :Sude
uk :RoyaumeUni
us :tatsunis.

setlocale retourne la nouvelle valeur ou FALSE en cas d'erreur. Si le deuxime paramtre est gal zro,
setlocaleretournesimplementlavaleurcourante.

Exemple

- 20 - ENI Editions - All rigths reserved


<?php
echo "Date au format JJ/MM/AAAA : ",
strftime("%d/%m/%Y "),"<BR>";
echo "Date au format JJ/MM/AA : ",
strftime("%d/%m/%y"),"<BR>";
echo "Heure : ",
strftime("%H:%M:%S"),"<BR>";
setlocale(LC_ALL,"fr");
echo "Format long (franais) : ",
strftime("%A %d %B %Y"),"<BR>";
setlocale(LC_ALL,"uk");
echo "Format long (anglais) : ",
strftime("%A %d %B %Y"),"<BR>";
setlocale(LC_ALL,"ge");
echo "Format long (allemand) : ",
strftime("%A %d %B %Y"),"<BR>";
setlocale(LC_ALL,"sp");
echo "Format long (espagnol) : ",
strftime("%A %d %B %Y"),"<BR>";
?>

Rsultat

Date au format JJ/MM/AAAA : 09/03/2004


Date au format JJ/MM/AA : 09/03/04
Heure : 18:18:11
Format long (franais) : mardi 09 mars 2004
Format long (anglais) : Tuesday 09 March 2004
Format long (allemand) : Dienstag 09 Mrz 2004
Format long (espagnol) : martes 09 marzo 2004

getdate

Lafonction getdatestocke,dansuntableau,lesdiffrentescomposantesd'unedatedonnesouslaformed'un
timestampUnix.

Syntaxe

tableau getdate([entier timestamp])

timestamp Timestamputiliser(pardfautletimestampactuel).

Lafonctiongetdateretourneuntableauassociatifcomprenantlesclssuivantes :

Cl Valeur
seconds Secondes (0 59)
minutes Minutes (0 59)
hours Heures (0 24)
mday Numro du jour du mois
wday Numro du jour de la semaine (0 = dimanche 6 = samedi)
mon Numro du mois (1 12)
year Anne
yday Numro du jour dans l'anne (0 365)
weekday Nom du jour de la semaine
month Nom du mois
0 Le timestamp

Exemple

<?php
$date = getdate(); // maintenant
foreach($date as $cl => $valeur) {
echo "$cl => $valeur<BR>";
}

ENI Editions - All rigths reserved - 21 -


?>

Rsultat

seconds => 6
minutes => 31
hours => 18
mday => 9
wday => 2
mon => 3
year => 2004
yday => 68
weekday => Tuesday
month => March
0 => 1078853466

time

LafonctiontimedonneletimestampUnixactuel.

Syntaxe

entier time()

Exemple

<?php
$ts = time();
echo "timestamp Unix actuel = $ts";
?>

Rsultat

timestamp Unix actuel = 1078853608

mktime

LafonctionmktimecreuntimestampUnixpartirdesdiffrentescomposantesd'unedate.

Syntaxe

entier mktime([entier heure[, entier minutes[, entier secondes[, entier mois[, entier jour[,
entier anne]]]]]])

heure Heure(023)

minutes Minutes(059)

secondes Secondes(059)

moi Mois(112)

jour Jour(131)

anne Anne :suprieure1970oucompriseentre0et99,laplage069tanttraduiteen20002069etlaplage


7099en19701999.

Lesparamtresomisprennentleurvaleuractuelle.

La fonction mktime a la particularit intressante de corriger les valeurs incorrectes en effectuant un calcul de
dateintelligent.Exemples :

- Le 35/12/2001 sera corrig en 31/12/2001 + 4 jours = 04/01/2002.

- 22 - ENI Editions - All rigths reserved


- Le 30/14/2001 sera corrig en 30/12/2001 + 2 mois = 30/02/2002 qui luimme sera corrig en 28/02/2002 + 2 jours
= 02/03/2002.

Cefonctionnementesttrspratiquepourraliserdescalculssurlesdates.

Exemple

<?php
$ts = mktime();
echo "mktime() = maintenant = ",
date("d/m/Y - H:i:s",$ts),"<BR>";
$ts = mktime(1,0,0,1,1,1970);
echo "mktime(1,0,0,1,1,1970) = temps zro d'Unix = $ts<BR>";
$ts = mktime(0,0,0,1,1,2001);
echo "mktime(0,0,0,1,1,2001) = ",
date("d/m/Y - H:i:s",$ts),"<BR>";
$ts = mktime(0,0,0,12,31,2001);
echo "mktime(0,0,0,12,31,2001) = ",
date("d/m/Y - H:i:s",$ts),"<BR>";
$ts = mktime(0,0,0,09,20+100,2001);
echo "Dans 100 jours, nous serons le ",
date("d/m/Y",$ts),".<BR>";
$ts = mktime(1,0,0,1,1+20000,1970);
echo "Unix ftera son 20 000 me jour le ",
date("d/m/Y",$ts),".<BR>";
?>

Rsultat

mktime() = maintenant = 09/03/2004 - 18:36:20


mktime(1,0,0,1,1,1970) = temps zro d'Unix = 0
mktime(0,0,0,1,1,2001) = 01/01/2001 - 00:00:00
mktime(0,0,0,12,31,2001) = 31/12/2001 - 00:00:00
Dans 100 jours, nous serons le 30/03/2001.
Unix ftera son 20 000 e jour le 04/10/2024

microtime

LafonctionmicrotimeretourneletimestampUnixactuelaveclafractiondesecondesenmicrosecondes.

Syntaxe

mixte microtime([boolen type_rel])

type_rel Boolenindiquantsilafonctiondoitretournerunnombrerel.

Sans paramtre (ou si le paramtre est valu FALSE), la fonction retourne une chane donnant les
microsecondessuiviesd'unespaceetdu timestamp Unix actuel. Si le paramtre est valu TRUE, la fonction
retourneunnombrerel.Leparamtreatintroduitenversion5.

Exemple

<?php
// affichage de microtime sous la forme d'une chane
echo microtime()."<BR>";
// affichage de microtime sous la forme d'un rel
echo microtime(TRUE)."<BR>";
// pour ne conserver que les microsecondes, le plus
// simple est de transformer la chane en rel
echo (float) microtime()."<BR>";
?>

Rsultat

0.38789700 1078854985
1078854985.3879
0.387924

ENI Editions - All rigths reserved - 23 -


idate

Lafonctionidateretournelesdiffrentescomposantes(anne,mois,etc.)d'untimestampUnix.

Syntaxe

entier idate(caractre composante [,entier timestamp])

composante Caractreindiquantlacomposantesouhaite(voirciaprs).

timestamp Timestamputiliser(pardfautletimestampactuel).

Lafonctionretourneunentiercorrespondantlacomposantedemande.

Lacomposantepeuttrespcifiel'aided'undescaractressuivants :

Caractre Signification
U Le timestamp !
Y Anne sur 4 chiffres
z Jour de l'anne
y Anne sur 2 chiffres
m ou n Numro du mois
d ou j Numro du jour du mois
G Heure sur 24
g ou h Heure sur 12
i Minutes
s Secondes
t Nombre de jours dans le mois
L Anne bissextile
Z Dcalage horaire en secondes
B Heure Internet Swatch
I (" i " majuscule) Heure d't (1)/Heure d'hiver (0)
W Numro de semaine de l'anne

Exemple

<?php
// affichage de la date/heure courante pour contrle
setlocale(LC_ALL,"fr");
echo strftime("%A %d %B %Y - %H:%M:%S"),"<BR>";
// extraction de diffrentes composantes
$composantes = str_split('UYmdHisztwW');
foreach($composantes as $composante) {
echo "$composante = ",idate($composante),"<BR>";
}
?>

Rsultat

mardi 09 mars 2004 - 19:23:58


U = 1078856638
Y = 2004
m = 3
d = 9
H = 19
i = 23
s = 58
z = 68
t = 31
w = 2

- 24 - ENI Editions - All rigths reserved


W = 11

Gnrerunnombrealatoire

Les fonctions rand et srand permettent respectivement de gnrer des nombres alatoires et d'initialiser le
gnrateurdenombresalatoires.

Syntaxe

srand([entier valeur])
entier rand([entier min[, entier max]])

Valeur

Valeurutilisepourinitialiserlegnrateurdenombresalatoires.galeunevaleuralatoiresinonspcifie.

min
et max

Bornesdesnombresalatoiresgnrer
Valeurpardfautdemin=0
Valeurpardfautdemax=unevaleurdonneparlafonctiongetrandmax

La fonction rand retourne un nombre alatoire entier, compris entre la borne minimum et la borne maximum
incluses.

Depuis la version 4.2, il n'est plus ncessaire d'appeler la fonction srand avant la fonction rand cela est fait
automatiquement.Demme,depuiscetteversion,leparamtred'initialisationdesrandestoptionnel.

Exemple

<?php

// depuis la 4.2, le gnrateur de nombres alatoires


// peut tre appel directement
echo rand()."<BR>";
echo rand()."<BR>";
echo rand()."<BR>";

// avant la 4.2, il fallait d'abord initialiser le


// gnrateur l'aide de la fonction srand
// pour cela, il tait frquent de faire un calcul
// avec la fonction microtime

// ((float) microtime())*1000000 donne un nombre compris


// entre 0 et 999 999
srand(((float) microtime())*1000000);

// gnration de nombres alatoires


echo rand()."<BR>";
echo rand()."<BR>";
echo rand()."<BR>";

?>

Rsultat

29261
20738
18963
29332
4413
7474

ENI Editions - All rigths reserved - 25 -


L'oprateurd'affectationparvaleur

L'oprateurd'affectationestlesignegal(=).

Syntaxe

$variable = expression;

expressionpeuttreunevaleurlittraledetouttype(123, "Bonjour", TRUE...),uneautrevariableoutoute


expressioncombinantdesvaleurslittrales,desvariablesavecdesfonctionsetdesoprateurs.

Exemple

<?php
$nom = "Olivier";
$indice = 1;
?>

Aveccettesyntaxe,l'affectations'effectueparvaleur,c'estdirequelavaleurdel'expressionsituedroite
du signe gal est copie dans la variable mentionne gauche. Lors de l'affectation d'une variable dans une
autre,lamodificationultrieuredelapremirevariableestsanseffetsurlaseconde.

Exemple

<?php
// initialisation d'une variable
$x = 1;
// affectation de la variable $x dans la variable $y
$y = $x;
// modification de la variable $x
$x = 2;
// affichage du rsultat
echo "\$x = $x<BR>";
echo "\$y = $y<BR>";
?>

Rsultat

$x = 2
$y = 1

L'opration d'affectation est une expression qui possde une valeur gale la valeur affecte, et qui peut tre
utilise directement dans une autre expression. Par exemple, la valeur de l'expression $x=1 est 1,etilestlicite
d'crireuneinstructiondutype$y=($x=1)+2affectantlavaleur3$y.

Exemple

<?php
// affectation en une instruction de $x et $y
$y = ($x = 1) + 2;
// affichage du rsultat
echo "\$x = $x<BR>";
echo "\$y = $y<BR>";
?>

Rsultat

$x = 1
$y = 3

Cettetechniqueesttrspratiquemaispeutnuirelalisibilitducode.

Pour tous les oprateurs tudis dans ce chapitre, des espaces peuvent tre prsents autour de l'oprateur.

ENI Editions - All rigths reserved - 1-


- 2- ENI Editions - All rigths reserved
L'oprateurd'affectationparrfrence

DepuisPHP4,ilestpossiblederaliseruneaffectationparrfrenceenutilisantl'oprateur&.

Syntaxe

$variable2 = &$variable1;

Avec cette syntaxe, la valeur de la variable $variable1 n'est pas copie dans la variable $variable2. La
variable $variable2 fait rfrence la variable $variable1 les deux variables pointent vers la mme zone
mmoireetlamodificationd'unedesdeuxvariablesserpercutesurl'autre.

Exemple

<?php
// initialisation d'une variable
$nom = "Olivier";
// affectation dans une autre variable par rfrence
$patronyme = &$nom;
// affichage du rsultat
echo "<B>Initialement :</B><BR>";
echo "\$nom = $nom<BR>";
echo "\$patronyme = $patronyme<BR>";
// modification de premire variable
$nom = "Heurtel";
// affichage du rsultat
echo "Aprs modification de \$nom :</B><BR>";
echo "\$nom = $nom<BR>";
echo "\$patronyme = $patronyme<BR>";
// modification de premire variable
$patronyme = "Olivier";
// affichage du rsultat
echo "<B>Aprs modification de \$patronyme :</B><BR>";
echo "\$nom = $nom<BR>";
echo "\$patronyme = $patronyme<BR>";
?>

Rsultat

Initialement :
$nom = Olivier
$patronyme = Olivier
Aprs modification de $nom :
$nom = Heurtel
$patronyme = Heurtel
Aprs modification de $patronyme :
$nom = Olivier
$patronyme = Olivier

ENI Editions - All rigths reserved - 1-


Lesoprateursarithmtiques

Les oprateurs arithmtiques sont les suivants :

Opration Oprateur Exemple


($x=13 et $y=8)
Somme ++ echo $x + $y;
=> 21
Soustraction - echo $x - $y;
=> 5
Multiplication * echo $x * $y;
=> 104
Division / echo $x / $y;
=> 1.625
Modulo (reste de la division entire du % echo $x % $y;
premier oprande par le deuxime) => 5
Oppos - echo -$x;
=> -13
Princrmentation (incrmente la variable ++ avant l'oprande echo ++$x;
avant de retourner la valeur de la variable) => 14
Postincrmentation (incrmente la variable ++ aprs l'oprande echo $x++;
aprs avoir retourn la valeur de la variable) => 13
echo $x;
=> 14
Prdcrmentation (dcrmente la variable -- avant l'oprande echo --$x;
avant de retourner la valeur de la variable) => 12
Postdcrmentation (dcrmente la -- aprs l'oprande echo $x--;
variable aprs avoir retourn la valeur de la => 13
echo $x;
variable)
=> 12

ENI Editions - All rigths reserved - 1-


L'oprateurdechane

Leseuloprateurdechaneestl'oprateurdeconcatnation,galaupoint(.).

Syntaxe

chane1.chane2;

Cette syntaxe retourne une chane gale la premire chane immdiatement suivie de la deuxime aucun
sparateurn'estplacentrelesdeuxchanes.

Exemple

<?php
// utilisation de l'oprateur de concatnation sur plusieurs
// expressions littrales
echo "Olivier"." "."Heurtel"."<BR>";
// initialisation de deux variables
$prnom = "Olivier";
$nom = "Heurtel";
// utilisation de l'oprateur de concatnation avec des
// variables et des expression littrales
echo $prnom." ".$nom."<BR>";
// peut tre crit plus simplement en utilisant la
// substitution des variables
echo "$prnom $nom<BR>";
?>

Rsultat

Olivier Heurtel
Olivier Heurtel
Olivier Heurtel

ENI Editions - All rigths reserved - 1-


Lesoprateursdecomparaison

Lesoprateursdecomparaisonsontlessuivants :

Opration Oprateur Exemple


($x=13, $y=8, $z="8")
galit == $x == $y => FALSE
$y == $z => TRUE
galit et types === $x === $y => FALSE
identiques $y === $z => FALSE
Diffrent != $x != $y => TRUE
$y != $z => FALSE
Infrieur < $x < $y => FALSE
$y < $x => TRUE
$y < $z => FALSE
Infrieur ou gal <= $x <= $y => FALSE
$y <= $x => TRUE
$y <= $z => TRUE
Suprieur > $x > $y => TRUE
$y > $x => FALSE
$y > $z => FALSE
Suprieur ou gal >= $x >= $y => TRUE
$y >= $x => FALSE
$y >= $z => TRUE

Ne confondez pas l'oprateur d'affectation (=) avec l'oprateur de comparaison (==).

ENI Editions - All rigths reserved - 1-


Lesoprateurslogiques

Lesoprateurslogiquessontlessuivants :

Opration Oprateur(s) Exemple


Et logique and TRUE and TRUE => TRUE
&& TRUE and FALSE => FALSE
FALSE and FALSE => FALSE
Ou logique or TRUE or TRUE => TRUE
|| TRUE or FALSE => TRUE
FALSE or FALSE => FALSE
Ou logique exclusif xor TRUE xor TRUE => FALSE
(FALSE si les deux TRUE xor FALSE => TRUE
oprandes sont TRUE) FALSE xor FALSE => FALSE
Non logique ! ! TRUE => FALSE
! FALSE => TRUE

Les oprateurs and et && ainsi que or et || sont identiques mais n'ont pas la mme prcdence (cf. I
Prcdencedesoprateurs).

ENI Editions - All rigths reserved - 1-


L'oprateurternaire

Unautreoprateurconditionnel,l'oprateurternaire"?",fonctionnecommedanslelangage C.

Syntaxe

expression1?expression2:expression3

Cette instruction retourne la valeur de expression2 si expression1 est valu TRUE, et la valeur de
expression3,siexpression1estvaluFALSE.Si expression1n'estpasdetypeboolen,uneconversionest
effectueselonlesrglesdcritesdanslechapitre3.

Exemple

<?php
// affichage d'un message dpendant de la valeur de $nom
echo "Bonjour ".(empty($nom)?"inconnu":$nom)." ! <BR>";
// initialisation de la variable $nom
$nom = "Olivier";
// nouvelle tentative
echo "Bonjour ".(empty($nom)?"inconnu":$nom)." ! <BR>";
// autre mthode (moins lisible ?)
echo "Bonjour ".($nom?$nom:"inconnu")." ! <BR>";
?>

Rsultat

Bonjour inconnu !
Bonjour Olivier !
Bonjour Olivier !

Surledernierexemple,nousexploitonslefaitqu'unechanevideestvalue FALSEetunechanenonvide
TRUE.

ENI Editions - All rigths reserved - 1-


Lesoprateurscombins

Les oprateurs somme (+), diffrence (), multiplication (*), division (/), modulo (%) et concatnation (.)
peuventtrecombinsavecl'oprateurd'affectation(=)selonlasyntaxesuivante :

Syntaxe quivalent
$variable += expression $variable = $variable + expression
$variable -= expression $variable = $variable - expression
$variable *= expression $variable = $variable * expression
$variable /= expression $variable = $variable / expression
$variable %= expression $variable = $variable % expression
$variable .= expression $variable = $variable . expression

ENI Editions - All rigths reserved - 1-


Prcdencedesoprateurs

La prcdence des oprateurs dsigne l'ordre selon lequel les oprateurs sont traits dans une expression
complte.

Comme dans tous les langages, les parenthses peuvent tre utilises pour modifier l'ordre dans le traitement
desoprations.Danslapratique,n'hsitezpasutiliserlesparenthsespourvitertoutproblmeetamliorerla
lisibilitdesexpressions.

Laprcdencedesoprateursestlasuivante,dumoinsprioritaire(traitendernier)auplusprioritaire(traiten
premier) :

Oprateur

or

xor

and

= += = *= /= %= .=

?:

||

&&

== != ===

< <= > >=

+ .

* / %

! ++ -- (int) (double) (string) (array) (object)

ENI Editions - All rigths reserved - 1-


Lescontrlesconditionnels

If

Lastructuredecontrleifpermetuneexcutionconditionnelled'instructions.

Cettestructurepossdedeuxsyntaxes :

Premire syntaxe

if (condition_1) {
instructions_1;
[ } elseif (condition_2) {
instructions_2; ]
[ ... ]
[ } else {
instructions_n; ]
}

Deuxime syntaxe

if (condition_1) :
instructions_1;
[ elseif (condition_2) :
instructions_2; ]
[ ... ]
[ else :
instructions_n; ]
endif;

Leprincipedefonctionnementdelastructuredecontrleifestlesuivant :

- Si condition_1 est vraie alors les instructions instructions_1 sont excutes puis le contrle est pass aux
instructions qui suivent la structure de contrle. Par exemple, l'excution du programme se poursuit l'instruction qui
suit directement la fin de la structure de contrle.

- Si condition_1 n'est pas vraie, le processus est rpt pour les ventuels couples
condition_i/instructions_i suivants, introduits par le mot cl elseif.

- Si aucune condition n'est vraie, les ventuelles instructions instructions_n, introduites par le mot cl else sont
excutes puis le contrle est pass aux instructions qui suivent la structure de contrle.

Plusieursclauseselseifpeuventtreprsentes.

Silesexpressionsdfinissantlesconditionsnesontpasdetypeboolen,uneconversionesteffectueselonles
rglesvoquesdanslechapitre3.

Exemple

<?php
// structure if simple
if (empty($nom)) {
echo "Bonjour inconnu ! Je vais vous appeler Olivier.<BR>";
$nom = "Olivier";
}
// structure if / else
if (empty($nom)) {
echo "Bonjour inconnu !<BR>";
} else {
echo "Bonjour $nom !<BR>";
}
// structure if / elseif / else
if (empty($nom)) {
echo "Bonjour inconnu !<BR>";
} elseif (empty($ge)) {
echo "Bonjour $nom ! Je ne connais pas votre ge.<BR>";

ENI Editions - All rigths reserved - 1-


} else {
echo "Bonjour $nom ! Vous avez $ge ans.<BR>";
}
?>

Rsultat

Bonjour inconnu ! Je vais vous appeler Olivier.


Bonjour Olivier !
Bonjour Olivier ! Je ne connais pas votre ge.

L'crituredelastructureestparfaitementlibre toutpeuttrecritsuruneligne.

Exemple

<?php
if (empty($nom)) { $nom = "Olivier"; }
if (empty($nom)) { echo "Bonjour inconnu !<BR>"; }
else { echo "Bonjour $nom !<BR>"; }
?>

Rsultat

Bonjour Olivier !

L'important est d'adopter une convention d'criture en essayant de rendre le code le plus lisible possible
(notammentenemployantdesindentations).

La deuxime syntaxe est surtout utilise pour crire une structure de contrle sur plusieurs blocs PHP entre
lesquelsducodeHTMLestintercal.

Deuxime syntaxe (avec incorporation de code HTML)

<?php if (condition_1): ?>


code_HTML_1
[ <?php if elseif (condition_2): ?>
code_HTML_2 ]
[ ... ]
[ <?php if else: ?>
code_HTML_n ]
<?php if endif; ?>

Le principe d'analyse de la structure if - elseif - else est le mme qu'avec la premire structure, mais au
lieud'excuterdesinstructionsPHP,lemoteurincorporedanslersultatlecodeHTMLassocilacondition.

Exemple

<?php
$nom = "Olivier";
?>
<HTML>
<HEAD><TITLE>Accueil</TITLE></HEAD>
<BODY>
<?php if (empty($nom)) : // condition PHP ?>
<!-- Code HTML -->
Bonjour inconnu !<BR>
<?php elseif (empty($ge)) : // suite de la condition PHP ?>
<!-- Code HTML -->
Je connais votre <B><FONT COLOR="green">nom</FONT></B>
mais pas votre <B><FONT COLOR="red">ge</FONT></B>.<BR>
<?php else : // suite de la condition PHP ?>
<!-- Code HTML -->
Je connais votre <B><FONT COLOR="green">nom</FONT></B>
et votre <B><FONT COLOR="green">ge</FONT></B>,
mais je ne dirai rien !<BR>
<?php endif; // fin de la condition PHP ?>
</BODY>
</HTML>

- 2- ENI Editions - All rigths reserved


Rsultat

Je connais votre nom mais pas votre ge.

Cette syntaxe est rellement trs pratique pour raliser une construction conditionnelle d'une page HTML, en
vitantlalourdeurdel'utilisationd'unseulblocPHPgnranttoutlecodeHTMLavecl'instructionecho.

Switch

La structure de contrle switch, quivalente aux if - elseif multiples, est utilise pour la comparaison du
rsultatd'uneexpressionavecplusieursrsultats.

Cettestructurepossdedeuxsyntaxes :

Premire syntaxe

switch (expression) {
case expression_1:
instructions_1;
[break;]
[ case expression_2:
instructions_2;
[break;] ]
[ ... ]
[ default:
instructions_n;
[break;] ]
}

Deuxime syntaxe

switch (expression) :
case expression_1 :
instructions_1;
[break;]
[ case expression_2 :
instructions_2;
[break;] ]
[ ... ]
[ default :
instructions_n;
[break;] ]
endswitch;

Leprincipedefonctionnementdelastructuredecontrleswitchestlesuivant :

- Si expression est gal expression_i alors les instructions associes instructions_i sont excutes et les
comparaisons se poursuivent s'il n'y a pas d'instruction break.

- Si aucune galit n'est trouve, les ventuelles instructions instructions_n introduites par le mot cl default,
sont excutes.

Plusieursclausescasepeuventtreprsentes.

Lorsqu'une galit est vrifie et que les instructions associes sont excutes, l'instruction switch n'est pas
interrompueetlesexpressions casesuivantessontvalues.Pourinterromprel'excutiondel'instructionswitch
etl'valuationdesclausescase,ilfaututiliserl'instructionbreak(forcelasortiedelastructuredecontrle).

Exemple

<?php
// structure switch simple
switch ($nom) {
case "" :
echo "Bonjour inconnu !
Je vais vous appeler Olivier.<BR>";
$nom = "Olivier";

ENI Editions - All rigths reserved - 3-


case "Olivier" :
echo "Bonjour Matre $nom !<BR>";
default :
echo "Bonjour lve $nom !<BR>";
}
?>

Rsultat (si les erreurs de niveau E_NOTICE ne sont pas affiches)

Bonjour inconnu ! Je vais vous appeler Olivier.


Bonjour Matre Olivier !
Bonjour lve Olivier !

Nous voyons bien, sur cet exemple, que l'instruction switch n'est pas interrompue lorsqu'une expression case
estvrifie :

- La premire expression case est vrifie, cela provoque l'initialisation de $nom et l'valuation se poursuit.

- Ainsi, la deuxime expression case est vrifie, un message est affich et l'valuation se poursuit.

- Au final, l'expression default est, elle aussi, vrifie et un autre message est affich.

Sicefonctionnementn'estpassouhait,ilsuffitd'ajouterdesinstructionsbreakpourinterromprel'excutionde
l'instructionswitchlorsqu'uneexpressioncaseestvrifie.

Exemple

<?php
// structure switch simple
switch ($nom) {
case "" :
echo "Bonjour inconnu !
Je vais vous appeler Olivier.<BR>";
$nom = "Olivier";
break;
case "Olivier" :
echo "Bonjour Matre $nom !<BR>";
break;
default :
echo "Bonjour lve $nom !<BR>";
}
?>

Rsultat (si les erreurs de niveau E_NOTICE ne sont pas affiches)

Bonjour inconnu ! Je vais vous appeler Olivier.

Comme pour le if, la deuxime syntaxe permet d'imbriquer du code HTML dans une structure de contrle
switch.

Reprise deuxime syntaxe (avec incorporation de code HTML)

<?php switch (expression) :


case (expression_1) : ?
code_HTML_1
[ <?php case (condition_2) : ?>
code_HTML_2 ]
[ ... ]
[ <?php default : ?>
code_HTML_n ]
<?php endswitch; ?>

LepremiercasedoittrecritdansleblocPHPswitch.

Exemple

<?php

- 4- ENI Editions - All rigths reserved


$langue = "franais";
?>
<HTML>
<HEAD><TITLE>Accueil</TITLE></HEAD>
<BODY>
<?php switch ($langue) : // switch
case "anglais" : // premier case ?>
<!-- Code HTML -->
Hello
<B><FONT COLOR="red">my friend</FONT></B> !<BR>
<?php break; // break premier case ?>
<?php case "espagnol" : // deuxime case ?>
<!-- Code HTML -->
Buenos dias
<B><FONT COLOR="orange">amigo</FONT></B> !<BR>
<?php break; // break deuxime case ?>
<?php case "franais" : // troisime case ?>
<!-- Code HTML -->
Salut <B><FONT COLOR="blue">mon pote</FONT></B> !<BR>
<?php break; // break troisime case ?>
<?php default : // default ?>
<!-- Code HTML -->
<B><FONT COLOR="red">???????</FONT></B><BR>
<?php endswitch ; // fin du switch ?>
</BODY>
</HTML>

Rsultat

Salut mon pote !

ENI Editions - All rigths reserved - 5-


Lescontrlesitratifs

While

La structure de contrle while permet d'excuter en boucle une srie d'instructions tant qu'une condition est
vraie.

Commepourlesstructuresdecontrleconditionnelles,deuxsyntaxessontdisponibles.

Premire syntaxe

while (condition) {
instructions;
}

Deuxime syntaxe

while (condition):
instructions;
endwhile;

Leprincipedefonctionnementdelastructuredecontrlewhileestlesuivant :tantquelaconditioncondition
estvraie,lesinstructionsinstructionssontexcutes.
Si l'expression dfinissant la condition n'est pas de type boolen, une conversion est effectue selon les rgles
voquesdanslechapitre3.

Exemple

<?php
// initialiser une variable
$nom = "OLIVIER";
// dterminer le nombre de caractres de la variable
$longueur = strlen($nom);
// initialiser un indice
$indice = 0;
// tant que l'indice est infrieur la longueur de la chane
while ($indice < $longueur) {
// afficher le caractre correspondant l'indice suivi
// d'un saut de ligne
echo "$nom[$indice]<BR>";
// incrmenter l'indice
$indice++;
}
?>

Rsultat

O
L
I
V
I
E
R

Classiquement,cettestructureadoptelescomportementssuivants :

- Si la condition est fausse la premire itration, les instructions situes l'intrieur de la boucle ne sont jamais
excutes.

- Si la condition n'est jamais fausse, les instructions l'intrieur de la boucle sont excutes sans fin (pas tout fait
puisque le temps d'excution d'un script est limit par la directive de configuration max_execution_time.

Comme pour les structures conditionnelles, la deuxime syntaxe permet d'imbriquer du code HTML dans une
structuredecontrlewhile.

ENI Editions - All rigths reserved - 1-


<?php while (condition) : ?>
code_HTML
<?php endwhile; ?>

Reprise deuxime syntaxe (avec incorporation de code HTML)

<?php
$numro = 0;
$nombre = 5;
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<!-- Construction d'un formulaire HTML proposant $nombre
---- (5 sur cet exemple) zones de texte -->
<FORM>
Indiquez vos cinq comptences principales :<BR>
<?php while($numro++ <+$nombre) : // boucle PHP ?>
<!-- Code HTML -->
<INPUT TYPE="text" LENGTH="40"><BR>
<?php endwhile; // fin de la boucle PHP ?>
<INPUT TYPE="submit" VALUE = "OK">
</FORM>
</BODY>
</HTML>

Rsultat

Do...while

La structure de contrle do ... while permet d'excuter en boucle une srie d'instructions tant qu'une
conditionestvraie.

Contrairementauxautresstructuresdecontrle,uneseulesyntaxeestdisponible.

Syntaxe

do {
instructions;
} while (expression);

Le principe de fonctionnement de la structure de contrle do ... while est le suivant : tant que la condition
condition est vraie, les instructions instructions sont excutes. la diffrence de la structure while, la
condition est teste la fin de la boucle les instructions instructions sont donc forcment excutes au
moinsunefois.

Si l'expression dfinissant la condition n'est pas de type boolen, une conversion est effectue selon les rgles
voquesdanslechapitre3.

Exemple

<?php
// initialiser une variable
$nom = "OLIVIER";

- 2- ENI Editions - All rigths reserved


// dterminer le nombre de caractres de la variable
$longueur = strlen($nom);
// initialiser un indice
$indice = 0;
// tant que l'indice est infrieur la longueur de la chane
do {
// afficher le caractre correspondant l'indice suivi
// d'un saut de ligne
echo "$nom[$indice]<BR>";
// incrmenter l'indice
$indice++;
} while ($indice < $longueur);
?>

Rsultat

O
L
I
V
I
E
R

Surcetexemple,lesinstructionsdelabouclesontexcutesunefoismmesilachaneestvide.Ici,l'utilisation
d'unestructurewhileseraitsansdoutepluspertinente.

For

Lastructuredecontrlefor,commedanslelangageC,permetd'excuterdesinstructionsdemanireitrative,
encontrlantlesitrationsl'aidedetroisexpressions.

Deuxsyntaxessontdisponibles.

Premire syntaxe

for (expression1; expression2; expression3) {


instructions;
}

Deuxime syntaxe

for (expression1; expression2; expression3):


instructions;
endfor;

Leprincipedefonctionnementdecettestructuredecontrleestlesuivant :

- expression1 est excute une fois au dmarrage de la boucle.

- expression2 est excute, et le rsultat est valu comme boolen, avant chaque itration (dont la premire): si le
rsultat est valu TRUE, les instructions instructions sont excutes; si le rsultat est valu FALSE, la
boucle s'arrte et le contrle est pass la premire instruction qui suit la construction.

- expression3 est excute la fin de chaque itration.

Danslagrandemajoritdescas,lastructureforestemployedelamaniresuivante :

- expression1 initialise un compteur.

- expression2 teste la valeur du compteur.

- expression3 incrmente la valeur du compteur.

ENI Editions - All rigths reserved - 3-


Cetteutilisationpermetd'excuterdesinstructionsunnombredonndefois.

Exemple

<?php
// utilisation de la structure for pour parcourir un tableau
// indices entiers conscutifs
// initialisation du tableau
$couleurs = array("bleu","blanc","rouge");
// dtermination du nombre d'lments dans le tableau
$nombre = count($couleurs);
// boucle utilisant un indice $i qui dmarre 0 ($i = 0)
// qui est incrment d'une unit chaque itration ($i++) ;
// la boucle se poursuit tant que l'indice est infrieur au
// nombre d'lments prsents dans le tableau ($i < $nombre)
for ($i = 0; $i < $nombre; $i++) {
echo "$couleurs[$i]<BR>";
};
?>

Rsultat

bleu
blanc
rouge

Avecunpeud'habitude,ilestpossiblederaliserdestraitementsbeaucouppluscomplexes(audtrimentparfois
delalisibilitducode)l'aidedel'instructionfor(ventuellementutiliseseule).

Exemple

<?php
// tout se passe dans l'instruction for !
for
(
// premire itration : initialisation d'un indice $i 1
// et d'une variable $total 0
$i = 1,$total = 0;
// condition d'arrt de la boucle : $i = 5
$i <= 5;
// chaque itration : incrmentation de $total avec le
// valeur courante de $i puis stockage dans un tableau de
// la valeur courante de $i juste avant de l'incrmenter
$total += $i,$nombres[] = $i++
);
// la sortie de la boucle, le tableau contient la liste des
// cinq premiers entiers, et la variable $total la somme des
// cinq premiers entiers
// il ne reste plus qu' afficher tout cela ...
echo implode($nombres,"+")."=$total";
?>

Rsultat

1+2+3+4+5=15

De manire "classique", la deuxime syntaxe permet d'imbriquer du code HTML dans une structure de contrle
for :

Reprise deuxime syntaxe (avec incorporation de code html)

<?php for (expression1; expression2; expression3) : ?>


code_HTML
<?php endfor; ?>

Exemple

<?php
$nombre = 5;
?>

- 4- ENI Editions - All rigths reserved


<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<!-- Construction d'un formulaire HTML proposant $nombre
---- (5 sur cet exemple) zones de texte -->
<FORM>
Indiquez vos cinq comptences principales :<BR>
<?php for($numro = 1; $numro <= $nombre; $numro++) :
// boucle PHP ?>
<!-- Code HTML -->
<INPUT TYPE="text" LENGTH="40"><BR>
<?php endfor; // fin de la boucle PHP ?>
<INPUT TYPE="submit" VALUE = "OK">
</FORM>
</BODY>
</HTML>

Rsultat

Continue

L'instruction continue peut tre utilise dans toutes les structures de contrle itratives pour interrompre
l'itrationencoursetpasserl'itrationsuivante.

Syntaxe

continue [n];
continue [(n)];

L'instruction continueaccepteunparamtrequiindiquedecombiendeniveau(x)remontersidesstructuresde
contrleitrativessontimbriques.Pardfaut,l'instructioncontinueremonted'unniveau.

Exemple (sans utilisation de l'instruction continue)

<?php
// boucle qui affiche tous les nombres composs de deux
// chiffres compris entre 1 et 3
for ($premier = 1; $premier <= 3; $premier++) {
for ($deuxime = 1; $deuxime <= 3; $deuxime++) {
echo "$premier$deuxime ";
}
};
?>

Rsultat

11 12 13 21 22 23 31 32 33

Exemple (avec utilisation de l'instruction continue)

<?php
// boucle qui affiche tous les nombres composs de deux
// chiffres compris entre 1 et 3
for ($premier = 1; $premier <= 3; $premier++) {
for ($deuxime = 1; $deuxime <= 3; $deuxime++) {
if ($deuxime == 2) {

ENI Editions - All rigths reserved - 5-


// passer la suite si $deuxime = 2
continue; // = continue 1
}
echo "$premier$deuxime ";
}
};
?>

Rsultat

11 13 21 23 31 33

Plusaucunnombreprsentantun2endeuximechiffren'estaffich.

Exemple (avec utilisation de l'instruction continue paramtre "n" = 2)

<?php
// boucle qui affiche tous les nombres composs de deux
// chiffres compris entre 1 et 3
for ($premier = 1; $premier <= 3; $premier++) {
for ($deuxime = 1; $deuxime <= 3; $deuxime++) {
if ($deuxime == 2) {
// passer la suite de deux niveaux si $deuxime = 2
continue 2;
}
echo "$premier$deuxime ";
}
};
?>

Rsultat

11 21 31

Puisque le contrle passe la suite de la boucle principale lorsque le deuxime chiffre est gal 2, plus aucun
nombreprsentantun2,etmaintenantun3,endeuximechiffren'estaffich.

- 6- ENI Editions - All rigths reserved


Inclureunfichier

Fonctionnement

Les fonctions include, include_once, require et require_once permettent d'inclure un fichier dans un
scriptPHP.

Syntaxe

entier include(fichier)
entier include_once(fichier)
require(fichier)
require_once(fichier)

fichier Nomdufichierinclure(peuttreindiquavecuncheminabsoluourelatif).

Les fonctionsinclude etinclude_onceretournent1encasdesuccsetFALSEencasd'erreur.Lesfonctions


requireetrequire_oncen'ontpasdecodederetour.

En cas d'erreur, les fonctions include et include_once gnrent une simple erreur de niveau E_WARNING qui
n'interrompt pas l'excution du script. Ce n'est pas le cas des fonctions require et require_once qui
provoquentalorsuneerreurfataleinterrompantl'excutionduscript.

LefichierincluspeutcontenirducodeHTML,ducodePHPoulesdeux.S'iloffreducodePHP,cecodedoittre
crit entre les balises PHP habituelles. Le code HTML, prsent dans le fichier inclus, est intgr tel quel dans la
pageenvoyeaunavigateur,commes'iltaitdanslescriptappelant.LecodePHP,prsentdanslefichierinclus,
estexcutlencore,commes'iltaitdanslescriptappelant.

Lorsdel'inclusiondecodePHP,lesvariablesetconstantes,dfiniesdanslefichierinclussontutilisablesdansle
scriptappelantetrciproquement.Toutsepassecommes'iln'yavaitqu'unseulscriptaprsl'inclusion,etdonc,
uneportegalecescriptpourlesvariablesetconstantes.

Il est possible d'inclure plusieurs fichiers dans un script, ou d'imbriquer les inclusions (inclure un fichier qui lui
mmeinclutunfichierdansunautre).

Avec les fonctions include et require, le processus d'inclusion est rpt plusieurs fois si le mme fichier est
inclusplusieursfois.

Dans certains cas, cette situation peut tre indsirable et involontaire, notamment lorsqu'un fichier est inclus
unepremirefoisdirectementdansunscriptetunedeuximefoisindirectementparl'inclusiond'unautrefichier.

Ce comportement peut tre vit en utilisant les fonctions include_once et require_once qui garantissent
qu'unfichierneserainclusqu'unefois,mmes'ilestappelplusieursfois.

L'extension du fichier inclure est parfaitement libre. Il n'est notamment pas obligatoire d'utiliser l'extension .php pour inclure
du code PHP : le fichier inclus n'est pas directement excut par le moteur PHP (c'est le script appelant qui l'est). Pour les
fichiers inclus qui ne peuvent ou ne doivent pas tre excuts directement, il est alors possible d'utiliser une autre extension
(.inc par exemple).

Exemple Script principal

<?php
// dclaration d'une variable $x dans le script principal
$x = 1;
// inclusion d'un fichier
include("commun.inc");
// affichage de la variable $x
echo "Valeur de \$x dans le script principal : $x<BR>";
// affichage de la variable $y (dfinie dans le fichier
// inclus)
echo "Valeur de \$y dans le script principal : $y<BR>";
?>

ENI Editions - All rigths reserved - 1-


Fichier inclus commun.inc

<!-- Dmarrage du fichier d'inclusion en mode HTML (ouverture


---- d'une balise <B> qui est ferme la fin du fichier --
<B>Dbut du fichier commun.inc<BR>
<?php
// dclaration d'une variable $x dans le script principal
$y = 2;
// affichage de la variable $x (dfinie dans le script
// appelant)
echo "Valeur de \$x dans le fichier inclus : $x<BR>";
// affichage de la variable $y
echo "Valeur de \$y dans le fichier inclus : $y<BR>";
?>
Fin du fichier commun.inc</B><BR>

Rsultat de l'excution du script principal

Dbut du fichier commun.inc


Valeur de $x dans le fichier inclus : 1
Valeur de $y dans le fichier inclus : 2
Fin du fichier commun.inc
Valeur de $x dans le script principal : 1
Valeur de $y dans le script principal : 2

Exemple Script principal avec deux inclusions du fichier commun.inc

<?php
include("commun.inc");
$x = 1;
echo "Valeur de \$x dans le script principal : $x<BR>";
echo "Valeur de \$y dans le script principal : $y<BR>";
include("commun.inc");
?>

Rsultat de l'excution du script principal (si les erreurs de niveau E_NOTICE ne sont pas affiches)

Dbut du fichier commun.inc


Valeur de $x dans le fichier inclus :
Valeur de $y dans le fichier inclus : 2
Fin du fichier commun.inc
Valeur de $x dans le script principal : 1
Valeur de $y dans le script principal : 2
Dbut du fichier commun.inc
Valeur de $x dans le fichier inclus : 1
Valeur de $y dans le fichier inclus : 2
Fin du fichier commun.inc

Surcetexemple,lorsdelapremireinclusion,lavariable$xn'apasencoretdfiniedanslescriptprincipalet
donnedoncunevaleurvidelorsdel'affichage.

Exemple Script principal avec deux inclusions include_once du fichier commun.inc

<?php
include_once("commun.inc");
$x = 1;
echo "Valeur de \$x dans le script principal : $x<BR>";
echo "Valeur de \$y dans le script principal : $y<BR>";
include_once("commun.inc");
?>

Rsultat de l'excution du script principal (si les erreurs de niveau E_NOTICE ne sont pas affiches)

Dbut du fichier commun.inc


Valeur de $x dans le fichier inclus :
Valeur de $y dans le fichier inclus : 2
Fin du fichier commun.inc
Valeur de $x dans le script principal : 1
Valeur de $y dans le script principal : 2

La deuxime inclusion n'est pas effectue car le fichier a dj t inclus et l'inclusion est demande avec la

- 2- ENI Editions - All rigths reserved


fonctioninclude_once.

Dans le fichier php.ini, la directive include_path permet de dfinir des chemins de recherche pour l'inclusion des
fichiers.

Utilisation

Latechniqued'inclusionestpratiquepourdeuxgrandstypesd'utilisation :

- Inclure des dfinitions statiques: constantes, dfinitions de fonctions. Dans ce cas, il faut plutt utiliser les fonctions
include_once ou require_once afin d'viter une ventuelle double inclusion (qui provoquerait une erreur dans la
dfinition des fonctions).

- Inclure du code PHP ou HTML dynamique qui s'excute effectivement au moment de l'inclusion: section HTML
commune plusieurs pages (entte, pied de page) ou code commun plusieurs pages (bien que dans cette hypothse,
la dfinition d'une fonction soit plus pertinente). Dans ce cas, il faut plutt utiliser les fonctions include ou require
afin de garantir que l'inclusion se produit chaque appel.

La cration de fonctions personnalises est tudie dans le chapitre 6.

Exemple

- Fichier de dfinition de constantes (constantes.inc) :

<?php
// dfinition des constantes
// par exemple, le nom du site
DEFINE("NOM_SITE","monSite.com");
?>

- Fichier contenant le dbut de chaque page (dbut.inc) :

<?php
// inclusion du fichier des contantes
include_once("constantes.inc");
?>
<HTML>
<HEAD><TITLE><?php echo NOM_SITE; ?></TITLE></HEAD>
<BODY>

- Fichier contenant la fin de chaque page (fin.inc) :

</BODY>
</HTML>

- Script d'une page :

<?php
// inclusion du dbut de la page
include("dbut.inc");
?>
Contenu de la page ...
<?php
// inclusion de la fin de la page
include("fin.inc");
?>

Rsultat (source de la page dans le navigateur)

<HTML>
<HEAD><TITLE>monSite.com</TITLE></HEAD>
<BODY>
Contenu de la page ...
</BODY>
</HTML>

ENI Editions - All rigths reserved - 3-


- 4- ENI Editions - All rigths reserved
Sortird'unestructuredecontrle

L'instructionbreakpermetdesortird'unestructure for, while, foreach (cf. chapitre 3 D3.Manipulation)


ouswitch.

Syntaxe

break [n];
ou
break[(n)];

L'instruction break accepte un paramtre qui indique de combien de niveau(x) remonter si des structures de
contrlesontimbriques.Pardfaut,l'instructionbreakremonted'unniveau.

Exemple (avec utilisation de l'instruction break)

<?php
// boucle qui affiche tous les nombres compose de deux
// chiffres compris entre 1 et 3
for ($premier = 1; $premier <= 3; $premier++) {
for ($deuxime = 1; $deuxime <= 3; $deuxime++) {
if ($deuxime == 2) {
// interrompre la boucle courante si $deuxime = 2
break; // = break 1
}
echo "$premier$deuxime ";
}
};
?>

Rsultat

11 21 31

Plusaucunnombrecomprenantunchiffresuprieur2endeuximechiffren'estaffich.

Exemple (avec utilisation de l'instruction break paramtre "n" = 2)

<?php
// boucle qui affiche tous les nombres composs de deux
// chiffres compris entre 1 et 3
for ($premier = 1; $premier <= 3; $premier++) {
for ($deuxime = 1; $deuxime <= 3; $deuxime++) {
if ($deuxime == 2) {
// interrompre la boucle principale si $deuxime = 2
break 2;
}
echo "$premier$deuxime ";
}
};
?>

Rsultat

11

La boucle principale est interrompue ds qu'un chiffre 2 est rencontr en deuxime chiffre (soit pour le nombre
12) seullenombre11estdoncaffich.

ENI Editions - All rigths reserved - 1-


Interromprelescript

Les instructions exitetdiepermettentd'interromprel'excutionduscript(dieestunaliasd'exit).

Syntaxe

exit[(chane message)];
exit[(entier statut)];
die[(chane message)];
die[(entier statut)];

message Messageafficheravantd'interromprelescript.

statut Statutderetour(entierentre1et254).Depuislaversion4.2,cetteinformationn'estpasafficheavant
l'interruptionduscript.

Lescripts'interromptbrutalementetl'affichageestlaiss"enl'tat".LapageHTMLenvoyeaunavigateurpeut
donctreincohrenteouvide.

Sil'instructionoulafonctionsontappelesdansunfichierinclus,c'estlescriptprincipalquiestinterrompu.

Exemple (sans message)

<?php
// gnrer le dbut de la page
echo "Bonjour ";
// une condition n'est pas vrifie, interrompre le script
if (empty($nom)) {
exit(1); // pas de message ...;
}
// poursuivre la gnration de la page
echo $nom;
?>

Rsultat

Bonjour

Exemple (avec message)

<?php
// gnrer le dbut de la page
echo "Bonjour ";
// une condition n'est pas vrifie, interrompre le script
if (empty($nom)) {
exit("Utilisateur inconnu.
Impossible de continuer.</B>");
}
// poursuivre la gnration de la page
echo $nom;
?>

Rsultat

Bonjour Utilisateur inconnu. Impossible de continuer.

ENI Editions - All rigths reserved - 1-


Fonctions

Introduction

l'instar des diffrents langages de dveloppement, PHP offre la possibilit de dfinir ses propres fonctions
(appeles fonctions "utilisateur") avec tous les avantages associs (modularit, capitalisation...). Une fonction
est un ensemble d'instructions identifies par un nom, dont l'excution retourne une valeur et dont l'appel peut
tre utilis comme oprande dans une expression. Une procdure est un ensemble d'instructions identifies par
unnomquipeuttreappelcommeuneinstruction.

Dclarationetappel

Lemotclfunctionpermetd'introduireladfinitiond'unefonction.

Syntaxe

function nom_fonction([paramtre]) {
instructions;
}

nom_fonction Nomdelafonction(doitrespecterlesrglesdenommageprsentesdanslechapitreVue
d'ensembledePHP).

paramtre Paramtresventuelsdelafonctionexprimssousformed'unelistedevariables(cf.Paramtresci
aprs) :$paramtre1, $paramtre2, ...

instructions Ensembledesinstructionsquicomposentlafonction.

Silafonctionretourneunevaleur,ilestpossibled'utiliserl'instruction returnpourdfinirlavaleurderetourde
lafonction(cf.Valeurderetourciaprs).

LenomdelafonctionnedoitpastreunmotrservPHP(nomdefonctionnative,d'instruction)nitregalau
nomd'uneautrefonctionpralablementdfinie.

Une fonction utilisateur peut tre appele comme une fonction native de PHP : dans une affectation, dans une
comparaison...

Exemple

<?php
// fonction sans paramtre qui affiche " Bonjour ! "
// pas de valeur de retour
function afficher_bonjour() {
echo "Bonjour !<BR>";
}
// fonction avec 2 paramtres qui retourne le produit
// des deux paramtres
function produit($valeur1,$valeur2) {
return $valeur1 * $valeur2;
}
// utilisation de la fonction afficher_bonjour
afficher_bonjour();
// utilisations de la fonction produit
// - dans une affectation
$rsultat = produit(2,4);
echo "$rsultat<BR>";
// - dans une comparaison
if (produit(10,12) > 100) {
echo "Le rsultat est suprieur 100.<BR>";
}
// - dans une affectation et une comparaison (lisibilit ?)
if (($rsultat = produit(10,12)) > 100) {
echo "$rsultat est suprieur 100.<BR>";
}
?>

ENI Editions - All rigths reserved - 1-


Rsultat

Bonjour !
8
Le rsultat est suprieur 100.
120 est suprieur 100.

Dans le langage PHP, il n'existe pas proprement parler de procdure. Pour dfinir quelque chose d'quivalent une
procdure, il suffit de dfinir une fonction qui ne retourne pas de valeur et d'appeler la fonction comme s'il s'agissait d'une
instruction (comme la fonction afficher_bonjour par exemple).

Ilestpossibled'utiliserunefonctionavantdeladfinir.

Exemple

<?php
// utilisation de la fonction produit
echo produit(5,5);
// dfinition de la fonction produit
function produit($valeur1,$valeur2) {
return $valeur1 * $valeur2;
}
?>

Rsultat

25

Iln'yadoncaucunproblmepourdfinirdesfonctionsquis'appellententreelles.

Une fonction est utilisable uniquement dans le script o elle est dfinie. Pour l'employer dans plusieurs scripts, il faut, soit
recopier sa dfinition dans les diffrents scripts (vous perdez l'intrt de dfinir une fonction), soit la dfinir dans un fichier inclus
partout o la fonction est ncessaire.

Exemple

- Fichier fonctions.inc contenant des dfinitions de fonctions :

<?php
// dfinition de la fonction produit
function produit($valeur1,$valeur2) {
return $valeur1 * $valeur2;
}
?>

- Script utilisant les fonctions dfinies dans fonctions.inc :

<?php
// inclusion du fichier contenant la dfinition des fonctions
include("fonctions.inc");
// utilisation de la fonction produit
echo produit(5,5);
?>

Fonctionvariable

PHPproposeune"fonctionvariable"quipermetdestockerunnomdefonctiondansunevariableetd'appelerla
variable dans une instruction, comme si c'tait une fonction, avec la notation $variable(). Sur une telle
criture,PHPremplacelavariableparsavaleuretchercheexcuterlafonctioncorrespondante(quidoit,bien
entendu,exister).

Exemple

<?php
// fonction qui effectue un produit
function produit($valeur1,$valeur2) {

- 2- ENI Editions - All rigths reserved


return $valeur1 * $valeur2;
}
// fonction qui effectue une somme
function somme($valeur1,$valeur2) {
return $valeur1 + $valeur2;
}
// fonction qui effectue un calcul, le nom du calcul
//("somme" ou "produit") tant pass en paramtre
function calculer($opration,$valeur1,$valeur2) {
// $opration contient le nom de la fonction
// excuter => appel $opration()
return $opration($valeur1,$valeur2);
}
// utilisation de la fonction calculer
echo calculer("somme",3,5)."<BR>";
echo calculer("produit",3,5)."<BR>";
?>

Rsultat

8
15

Paramtres

Lesparamtresventuelsdelafonctionsontdfinissouslaformed'unelistedevariables.

Danscetroisimepoint,nousallonstudierlespossibilitssuivantes :

- dfinir une valeur par dfaut pour un paramtre ;

- passer un paramtre par rfrence ;

- utiliser une liste variable de paramtres (aussi appels arguments).

Valeurpardfaut

Ilestpossibled'indiquerqu'unparamtrepossdeunevaleurpardfautgrcelasyntaxesuivante :

$paramtre = expression littrale

La valeur par dfaut d'un paramtre doit tre une expression littrale et ne peut tre ni une variable, ni une
fonction,niuneexpressioncompose.

La valeur par dfaut est utilise comme valeur d'un paramtre lorsque la fonction est appele, sans mentionner
devaleurpourleparamtreenquestion.

Exemple

<?php

// dfinition de la fonction produit avec des valeurs


// par dfaut pour les paramtres
function produit($valeur1=1,$valeur2=2) {
return $valeur1 * $valeur2;
}
// appels
// - sans paramtre
echo "produit() = ".produit()."<BR>";
// - avec un seul paramtre = forcment le premier
echo "produit(3) = ".produit(3)."<BR>";
// - avec un seul paramtre = le deuxime ?
//echo "produit(,4) = ".produit(,4)."<BR>";
// interdit
// =><+>contournement ?
echo "produit(\"\",4) = ".produit("",4)."<BR>";
echo "produit(NULL,4) = ".produit(NULL,4)."<BR>";
?>

ENI Editions - All rigths reserved - 3-


Rsultat

produit() = 2
produit(3) = 6
produit("", 4) = 0
produit(NULL, 4) = 0

Ne pas donner de valeur un paramtre ayant une valeur par dfaut n'est possible qu'en partant de la droite.
Passer une valeur de "vide" ("" ou NULL) ne rsout pas le problme car la valeur en question est convertie par
PHPdansletypeadquat(icienentiergal0).

Exemples interdits de valeur par dfaut

function produit($valeur1,$valeur2=1+1)... // pas d'expression


function produit($valeur1,$valeur2=$x)... // pas de variable
function produit($valeur1,$valeur2=time())...// pas de fonction

Exemple autoris

define("UN",1); // dfinition d'une constante UN (=1)


...
function produit($valeur1=UN,$valeur2=UN)... // constante OK

Passer un nombre insuffisant de paramtres et ne pas avoir de valeur par dfaut gnre une erreur. Passer trop de paramtres
ne gnre pas d'erreur ; les paramtres en trop sont ignors.

Passageparrfrence

Par dfaut, le passage des paramtres s'effectue par valeur : c'est une copie de la valeur qui est passe la
fonction. En consquence, la modification des paramtres l'intrieur de la fonction n'a aucun effet sur les
valeursdanslescriptappelant.

Exemple

<?php
// dfinition d'une fonction qui prend un paramtre
function par_valeur($paramtre) {
// incrmentation du paramtre
$paramtre++;
// affichage du paramtre l'intrieur de la fonction
echo "\$paramtre = $paramtre<BR>";
}
// initialisation d'une variable
$x = 1;
// affichage de la variable avant l'appel la fonction
echo "\$x avant appel = $x<BR>";
// appel de la fonction en utilisant la variable comme valeur
// du paramtre
par_valeur($x);
// affichage de la variable aprs l'appel la fonction
echo "\$x aprs appel = $x<BR>";
?>

Rsultat

$x avant appel = 1
$paramtre = 2
$x aprs appel = 1

En cas de besoin, il est possible d'avoir un passage par rfrence en utilisant l'oprateur de rfrence & (cf.
chapitre Oprateurs L'oprateurd'affectationparrfrence)devantlenomduparamtredansladfinitionde
la fonction. Avec une telle dfinition, c'est une rfrence vers la variable (plus une copie) qui est passe la
fonction cettederniretravailledirectementsurlavariableduscriptappelant.

Exemple

<?php

- 4- ENI Editions - All rigths reserved


// dfinition d'une fonction qui prend un paramtre
function par_rfrence(&$paramtre) {
// incrmentation du paramtre
$paramtre++;
// affichage du paramtre l'intrieur de la fonction
echo "\$paramtre = $paramtre<BR>";
}
// initialisation d'une variable
$x = 1;
// affichage de la variable avant l'appel la fonction
echo "\$x avant appel = $x<BR>";
// appel de la fonction en utilisant la variable comme valeur
// du paramtre
par_rfrence($x);
// affichage de la variable aprs l'appel la fonction
echo "\$x aprs appel = <B>$x</B><BR>";
?>

Rsultat

$x avant appel = 1
$paramtre = 2
$x aprs appel = 2

Avec une telle dfinition, il n'est plus possible de passer une constante ou une expression comme valeur du
paramtre.

Exemples interdits

par_rfrence(2);
par_rfrence(1+1);
par_rfrence(UN); // UN = constante dfinie prcdemment

Listevariabledeparamtres

l'intrieurd'unefonction,ilestpossibled'utiliserlestroisfonctionsPHPsuivantes :

Fonction Rle
func_num_args Donne le nombre de paramtres passs la fonction.
func_get_args Retourne la liste des paramtres passs la fonction (dans un
tableau).
func_get_arg Retourne la valeur d'un paramtre dont le numro est prcis.

Syntaxe

entier func_num_args()
tableau func_get_args()
mixte func_get_arg(entier numro)

numro Numroduparamtredemand(0=premierparamtre).

l'aidedecesfonctionsnatives,ilestalorstrssimpled'crireunefonctionquiaccepteunnombrevariablede
paramtres.Lesprincipessontlessuivants :

- dclarer la fonction sans paramtre ;

- rcuprer, dans le corps de la fonction, les paramtres avec les fonctions func_get_args ou func_get_arg et les utiliser
(typiquement dans une boucle).

Exemple

<?php
// fonction qui effectue le produit de tous les paramtres
function produit() {
if (func_num_args() == 0) {

ENI Editions - All rigths reserved - 5-


// pas de paramtres => rsultat<+>= 0
$rsultat = 0;
} else {
// il y a des paramtres
// rcuprer les paramtres dans un tableau
$paramtres = func_get_args();
// initialiser le rsultat 1
$rsultat = 1;
// faire une boucle sur le tableau des paramtres
// pour multiplier le rsultat par le paramtre
foreach($paramtres as $paramtre) {
$rsultat *= $paramtre;
}
}
// retourner le rsultat
return $rsultat;
}
// appels
echo produit()."<BR>";
echo produit(1)."<BR>";
echo produit(1,2)."<BR>";
echo produit(1,2,3)."<BR>";
echo produit(1,2,3,4)."<BR>";
?>

Rsultat

0
1
2
6
24

Danslapratique,rienn'interditauxparamtresd'tredetypesdiffrents.

Par ailleurs, il est possible de dclarer explicitement les premiers paramtres et d'accepter ensuite une liste
variabledeparamtrescomplmentaires.Danscecas,lesparamtresexplicitementdclarssontreprisdansle
comptageetdanslalistedesparamtres.Ilconvientdoncdelesliminersoimmedutraitement.

Supposons, par exemple, que nous souhaitons disposer d'une fonction qui permet de stocker, dans un tableau
passenpremierparamtre,plusieurscouplescl/valeurpasssenparamtrescomplmentaires.

Exemple

la_fonction(tableau, cl1, valeur1, cl2, valeur2, ...)

Rsultat

Cl Valeur
cl1 valeur1
cl2 valeur2
...

Exemple

<?php
function affecte_tableau(&$tableau) {
// le premier paramtre (tableau alimenter) est
// explicitement dfini car il doit tre pass par
// rfrence (la fonction le modifie directement)
// rcuprer le nombre d'argument (tient compte
// de &$tableau)
$nombre_param = func_num_args();
if ($nombre_param < 2) {
// pas assez de paramtres => erreur (il doit y avoir au
// minimum 3 paramtres en tout, le tableau et un couple
// cl/valeur
$rsultat = "Pas assez de paramtres";

- 6- ENI Editions - All rigths reserved


} elseif ($nombre_param%2 == 0) {
// nombre de paramtres pair => erreur (le nombre de
// paramtres doit tre impair : un paramtre pour le
// tableau suivi de N fois deux paramtres pour les
// couples cl/valeur)
$rsultat = "Le nombre de paramtres
doit tre impair";
} else { // bon nombre de paramtres
// faire<+>une boucle pour parcourir les paramtres
// correspondant aux couples cl/valeur, i.e. en
// commenant au deuxime paramtre (numro = 1) et
// allant de deux en deux
for($i=1;$inombre_param;$i += 2) {
// le paramtre $i est la cl dans le tableau
// le paramtre $i+1 est la valeur associe
$tableau[func_get_arg($i)] = func_get_arg($i+1);
} // for
$rsultat = ""; // rsultat de la fonction (chane vide)
} // if
// retourner le rsultat
return $rsultat;
}
// utilisation de la fonction pour remplir un tableau
// donnant la capitale d'un pays
// premier appel (tout le monde peut se tromper)
affecte_tableau($capitales,"France","Lyon");
echo "<B>Capitales (premier appel)</B><BR>";
foreach ($capitales as $pays => $capitale) {
echo "$pays => $capitale<BR>";
}
// deuxime appel (corriger pour la France et complter)
affecte_tableau($capitales,"Espagne","Madrid",
"France","Paris","Italie","Rome");
echo "<B>Capitales (deuxime appel)</B><BR>";
foreach ($capitales as $pays => $capitale) {
echo "$pays => $capitale<BR>";
}
// autre exemple avec cl alphabtique et valeur numrique
affecte_tableau($stock,"CD",5,"Livre",10);
echo "<B>Stock</B><BR>";
foreach ($stock as $produit => $quantit) {
echo "$produit => $quantit<BR>";
}
?>

Rsultat

Capitales (premier appel)


France => Lyon
Capitales (deuxime appel)
France => Paris
Espagne => Madrid
Italie => Rome
Stock
CD => 5
Livre => 10

Pourtrerigoureux,ilfaudraitvrifierquelesclssontbienentiresoualphabtiques(parcontre,lavaleurpeut
treden'importequeltype,mmedutypetableau).

Valeurderetour

L'utilisationdel'instruction returnl'intrieurd'unefonction,permetdedfinirlavaleurderetourdelafonction
etdestoppersonexcution.

Syntaxe

return expression;

expression Expressiondontlersultatconstituelavaleurderetourdelafonction.

Lersultatd'unefonctionpeuttreden'importequeltype(chane,nombre,tableau...).

ENI Editions - All rigths reserved - 7-


Si plusieurs instructions return sont prsentes dans la fonction, c'est la premire rencontre dans le
droulementdesinstructionsquidfinitlavaleurderetouretprovoquel'interruptiondelafonction.

Exemple

<?php
// dfinition d'une fonction avec deux appels return
function valeur_retour($paramtre) {
if ($paramtre == 1) {
return "Premier return";
}
return "Deuxime return";
}
// appels la fonction
echo "valeur_retour(1) = ".valeur_retour(1)."<BR>";
echo "valeur_retour(0) = ".valeur_retour(0)."<BR>";
?>

Rsultat

valeur_retour(1) = Premier return


valeur_retour(0) = Deuxime return

Silafonctionneprsenteaucuneinstructionreturn(ousiaucuneinstructionreturnn'estexcute),lavaleur
deretourdelafonctionestNULL.

Considrationssurlesvariablesutilisesdanslesfonctions

Variablelocale

Lesvariablesutilisesl'intrieurd'unefonctionsontlocales :ellessontnondfiniesendehorsdelafonctionet
initialiseschaqueappeldelafonction.Ilenestdemmedesparamtresdelafonction.

Rciproquement, une variable dfinie en dehors de la fonction (dans le script appelant) n'est pas dfinie
l'intrieurdelafonction.

Exemple

<?php
// dfinition d'une fonction
function variable_locale() {
// initialisation de deux variables $x et $z l'intrieur
// de la fonction
$x<+>= 0;
$z = 3;
// affichage des variables $x, $y et $z
echo "Valeur de \$x dans la fonction = $x<BR>";
echo "Valeur de \$y dans la fonction = $y<BR>";
echo "Valeur de \$z dans la fonction = $z<BR>";
}
// initialisation de deux variables $x et $y dans le script
// appelant
$x = 1;
$y = 2;
// appel de la fonction
variable_locale();
// affichage des variables $x, $y et $z
echo "<P>";
echo "Valeur de \$x dans le script = $x<BR>";
echo "Valeur de \$y dans le script = $y<BR>";
echo "Valeur de \$z dans le script = $z<BR>";
?>

Rsultat (si les erreurs de niveau E_NOTICE ne sont pas affiches)

Valeur de $x dans la fonction = 0


Valeur de $y dans la fonction =
Valeur de $z dans la fonction = 3
Valeur de $x dans le script = 1

- 8- ENI Editions - All rigths reserved


Valeur de $y dans le script = 2
Valeur de $z dans le script =

Cetexempleillustrelespointssuivants :

- La variable $x de la fonction et celle du script sont deux variables diffrentes.

- La variable $y dfinie dans le script n'existe pas dans la fonction.

- La variable $z dfinie dans la fonction n'existe pas dans le script.

Variableglobale

PHP propose une notion de variable globale pour accder, dans une fonction, aux variables dfinies dans le
contexteduscriptappelant.

Pour cela, l'intrieur de la fonction, il faut dclarer les variables globales que la fonction utilise avec
l'instructionglobal.

Syntaxe

global $variable[, ...];

$variable Variableduscriptappelantquelafonctionsouhaiteutiliser.Plusieursvariablespeuventtre
mentionnes,enlessparantparunevirgule.

Exemple

<?php
// dfinition d'une fonction
function variable_globale() {
// dfinition des variables globales (ici $x)
global $x;
// affichage de $x au dbut de la fonction
echo "Valeur de \$x au dbut de la fonction = $x<BR>";
// modification de $x et initialisation de $z l'intrieur
// de la fonction
$x = 0;
$z = 3;
// affichage des variables $x, $y et $z
echo "Valeur de \$x la fin de la fonction = $x<BR>";
echo "Valeur de \$y dans la fonction = $y<BR>";
echo "Valeur de \$z dans la fonction = $z<BR>";
}
// initialisation de deux variables $x et $y dans le script
// appelant
$x = 1;
$y = 2;
// appel de la fonction
variable_globale();
// affichage des variables $x, $y et $z
echo "<P>";

echo "Valeur de \$x dans le script = $x<BR>";


echo "Valeur de \$y dans le script = $y<BR>";
echo "Valeur de \$z dans le script = $z<BR>";
?>

Rsultat (si les erreurs de niveau E_NOTICE ne sont pas affiches)

Valeur de $x au dbut de la fonction = 1


Valeur de $x la fin de la fonction = 0
Valeur de $y dans la fonction =
Valeur de $z dans la fonction = 3

Valeur de $x dans le script = 0


Valeur de $y dans le script = 2
Valeur de $z dans le script =

ENI Editions - All rigths reserved - 9-


la diffrence de l'exemple initial, la variable $x est maintenant dfinie l'entre de la fonction et sa
modificationdanslafonctionchangelavaleurdanslescriptappelant :c'estlammevariablequiestutilise.

Il est possible, sans dclaration, d'accder aux variables globales l'intrieur d'une fonction, en utilisant un
tableau associatif $GLOBALS gr par PHP. Dans ce tableau associatif, la cl est gale au nom de la variable
globale(sansle$),etlavaleur,lavaleurdelavariableglobale.

Exemple

<?php
// dfinition d'une fonction
function variable_globale() {
// affichage de variables globales en utilisant le tableau
// $GLOBALS
echo "Valeur de \$x au dbut de la fonction =
$GLOBALS[x]<BR>";
echo "Valeur de \$y au dbut de la fonction =
$GLOBALS[y]<BR>";
// modification de variables globales en utilisant le tableau
$GLOBALS["x"]++;
$GLOBALS["y"]++;
}
// initialisation de deux variables $x et $y dans le script
// appelant
$x = 1;
$y = 2;
// appel de la fonction
variable_globale();
// affichage des variables $x, $y et $z
echo "<P>";
echo "Valeur de \$x dans le script = $x<BR>";
echo "Valeur de \$y dans le script = $y<BR>";
?>

Rsultat

Valeur de $x au dbut de la fonction = 1


Valeur de $y au dbut de la fonction = 2
Valeur de $x aprs dans le script = 2
Valeur de $y aprs dans le script = 3

Un paramtre d'une fonction se comporte comme une variable locale la fonction, sauf, s'il est pass par rfrence, auquel
cas, il est quivalent une variable globale.

Variablestatique

Pardfaut,lesvariableslocalesd'unefonctionsontrinitialiseschaqueappeldelafonction.

L'instruction static permet de dfinir des variables locales statiques qui ont pour proprit de conserver leur
valeurd'unappell'autredelafonction,pendantladureduscript.

Syntaxe

static $variable = expression_littrale[, ...];

$variable

Variableconcerne.

expression_littrale

Valeur initiale affecte la variable lors du premier appel la fonction l'intrieur du script. Seules les
expressionslittralesetlesconstantessontacceptes lesexpressionscomposesoulesfonctionsnesontpas
autorises.

Exemple

- 10 - ENI Editions - All rigths reserved


<?php
// dfinition d'une fonction
function variable_statique() {
// dfinition d'une variable statique
static $variable_statique = 0;
// initialisation d'une autre variable
$autre_variable = 0;
// affichage des deux variables
echo "\$variable_statique = $variable_statique <BR>";
echo "\$autre_variable = $autre_variable<BR>";
// incrmentation des deux variables
$variable_statique++;
$autre_variable++;
}
// premier appel de la fonction
echo "<B>Premier appel de la fonction :</B><BR>";
variable_statique();
// autres instructions ...
// deuxime appel de la fonction
echo "<B>Deuxime appel de la fonction<+>:</B><BR>";
variable_statique();
// autres instructions ...
// troisime appel de la fonction
echo "<B>Troisme appel de la fonction :</B><BR>";
variable_statique();
?>

Rsultat

Premier appel de la fonction :


$variable_statique = 0
$autre_variable = 0
Deuxime appel de la fonction :
$variable_statique = 1
$autre_variable = 0
Troisime appel de la fonction :
$variable_statique = 2
$autre_variable = 0

Cet exemple montre que la valeur de $variable_statique est bien conserve d'un appel l'autre, le premier
appel permettant de l'initialiser. Par contre, la variable $autre_variable est remise 0 chaque appel de la
fonction.

La valeur n'est conserve que pendant la dure du script : lorsque ce dernier se termine, la valeur est perdue et, au prochain
appel du script, la variable statique est rinitialise.

Lesconstantesetlesfonctions

Dans le chapitre Constantes, variables, types et tableaux, nous avons observ que la porte des constantes
taitlescriptdanslequelellessontdfinies.

la diffrence des variables, cette porte s'tend aux fonctions appeles dans le script : une constante peut
treutilisel'intrieurdelafonctionsansqu'ellesoitdclareglobale.

Rciproquement, une constante dfinie dans une fonction peut tre utilise dans un script, aprs appel de la
fonction.

Exemple

<?php
// dfinition d'une constante dans le script
define("CONSTANTE_SCRIPT","constante script");
// dfinition d'une fonction
function constante() {
// qui dfinit une constante
define("CONSTANTE_FONCTION","constante fonction");
// qui affiche une constante du script appelant
echo "Dans la fonction, CONSTANTE_SCRIPT = ".
CONSTANTE_SCRIPT."<BR>";
}
// appel de la fonction

ENI Editions - All rigths reserved - 11 -


constante();
// affichage de la constante dfinie dans la fonction
echo "Dans le script, CONSTANTE_ FONCTION = ".
CONSTANTE_FONCTION."<BR>";
?>

Rsultat

Dans la fonction, CONSTANTE_SCRIPT = constante script


Dans le script, CONSTANTE_ FONCTION = constante fonction

Rcursivit

l'instar de nombreux langages, PHP autorise la rcursivit, c'estdire la possibilit pour une fonction de
s'appelerellemme.

Pour illustrer cette notion, nous allons crire une fonction gnrique qui permet d'afficher le contenu d'un
tableau,ventuellementmultidimensionnel.

Exemple

<?php
function afficher_tableau($tableau,$titre="",$niveau=0) {
// Paramtres
// - $tableau = tableau dont il faut afficher le contenu
// - $titre = titre afficher au dessus du contenu
// - $niveau = niveau d'affichage
// s'il y a un titre, l'afficher
if ($titre != "") {
echo "<P><B>$titre</B><BR>\n";
}
// tester s'il y a des donnes
if (isset($tableau)) { // il y a des donnes
// parcourir le tableau pass en paramtre
reset ($tableau);
while (list ($cle, $valeur) = each ($tableau)) {
// afficher la cl (avec indentation fonction
// du niveau)
echo
str_pad("",12*$niveau, "&nbsp;").
htmlentities($cle)." = ";
// afficher la valeur
if (is_array($valeur)) { // c'est un tableau ...
// mettre une balise <BR>
echo "<BR>";
// et appeler rcursivement afficher_tableau pour
// afficher le tableau en question (sans titre et au
// niveau suprieur pour l'indentation)
afficher_tableau($valeur,"",$niveau+1);
} else { // c'est une valeur scalaire
// afficher la valeur
echo htmlentities($valeur)."<BR>";
}
}
} else {<+>// pas de donnes
// mettre une simple balise <BR>
echo "<BR>\n";
}
}
// Afficher un tableau de couleurs
$couleurs = array("Bleu","Blanc","Rouge");
afficher_tableau($couleurs,"Couleurs");
// Afficher un tableau de pays
$pays = array("FR" => "France","IT" => "Italie");
afficher_tableau($pays,"Pays");
// Afficher un tableau deux dimensions (couleurs et pays)
$cp = array("couleurs" => $couleurs,"pays" => $pays);
afficher_tableau($cp,"Couleurs & Pays");
?>

Rsultat

Couleurs

- 12 - ENI Editions - All rigths reserved


0 = Bleu
1 = Blanc
2 = Rouge
Pays
FR = France
IT = Italie
Couleurs & Pays
couleurs =
0 = Bleu
1 = Blanc
2 = Rouge
pays =
FR = France
IT = Italie

Pour tre rigoureux, il faudrait vrifier que la variable passe initialement en premier paramtre est bien un
tableau.

Nousallonsutilisercettefonctionplusieursreprisesdanscetouvrage,partantdel'hypothsequ'ellefaitpartie
d'unjeudefonctionsgnriquesdfiniesdansunfichierquiestinclusdanslescriptencasdebesoin.

ENI Editions - All rigths reserved - 13 -


Classes

Concept

Enversion5,lagestiondesobjetsdansPHPatcompltementrcriteafind'offrirdemeilleuresperformances
etplusdefonctionnalits.

PHPproposemaintenantdesfonctionnalitsclassiquesdeprogrammationorienteobjet :

- dfinition de classe ;

- utilisation de mthodes constructeur et destructeur ;

- notions d'attribut ou de mthode public, priv, protg ;

- hritage ;

- notions de classe ou mthode abstraite, de classe ou mthode finale, d'interface, d'attribut ou mthode statique (de classe) ;

- exceptions.

Une classe est un type composite regroupant des variables (appeles attributs de la classe) et des fonctions
(appeles mthodes de la classe). En soi, une classe ne contient pas de donnes c'est juste un modle, une
dfinition.

partir de la classe, il est possible de dfinir ("instancier") des objets qui ont la structure de la classe et qui,
eux,contiennentdesdonnes.

Dans cette partie, nous allons prsenter les fonctionnalits de base les plus couramment utilises : c'est une
introduction pratique aux fonctionnalits objet de PHP. Pour plus d'informations, reportezvous la
documentationdePHP.

Dfiniruneclasse

Lemotclclasspermetd'introduireladfinitiond'uneclasse.

Syntaxe

class nom_classe {
// dfinition des attributs
[
public | private | protected $attribut [= expression_littrale];
...
]
// dfinition des mthodes
[
[public | private | protected] function mthode() {
...
}
...
]
}

nom_classe

Nomdelaclasse(doitrespecterlesrglesdenommageprsentesdanslechapitreVued'ensembledePHP).

$attribut

Nomd'unevariablecorrespondantunattributdelaclasse.

expression_litrale

ENI Editions - All rigths reserved - 1-


Valeur initiale de l'attribut. Seules les expressions littrales et les constantes sont acceptes les expressions
composesoulesfonctionsnesontpasautorises.

mthode

Dfinitiond'unefonctioncorrespondantunedesmthodesdelaclasse.


Lavisibilitdesattributsetdesmthodesestdfinieparundesmotsclssuivants :

public

L'attributoulamthodesontpublicsetl'onnepeutyaccderdel'extrieurdelaclasse.

private

L'attributoulamthodesontprivsetl'onnepeutyaccderquedel'intrieurdelaclasse.

protected

L'attribut ou la mthode sont protgs et l'on ne peut y accder que de l'intrieur de la classe ou des classes
drivesdelaclasse(voirlanotiond'hritage).


Pardfaut,unemthodeestpublique.Parcontre,lavisibilitdel'attributdoittrespcifie.

Ces variantes ont t introduites en version 5. En version 4, les attributs et mthodes sont obligatoirement
publics et le mot clvar (quivalent public) est utilis pour introduire la dfinition d'un attribut (pas de mot
clpourlesmthodes).

Les mthodes sont dfinies comme des fonctions utilisateur classiques (avec paramtres, instruction
return ...),mais,l'intrieurdelaclasse.Unemthoded'uneclassepeutavoirlemmenomqu'unefonction
utilisateurouqu'uneautremthoded'uneautreclasse.

Une des mthodes peut porter le mme nom que la classe dans laquelle elle est dfinie. Cette mthode
particulire, nomme mthode constructeur, est automatiquement appele la cration ("instanciation") d'un
nouvelobjet.Gnralement,cettemthodeestutilisepourinitialiserdesattributsquinepeuventl'treparune
simple expression littrale. En version 5, la mthode constructeur d'une classe peut tre nomme de manire
unifie __construct. Cette mthode de nommage est conseille car elle facilite l'appel de la mthode
constructeur d'une classe parent dans une classe drive (voir la notion d'hritage). En premier, PHP recherche
toujours une mthode nomme __construct s'il n'en trouve pas, il recherche une mthode portant le mme
nomquelaclasse.

Encomplment,enversion5,ilestpossibledespcifierunemthodedestructeurnomme __destruct(pasde
paramtre). Cette mthode destructeur est automatiquement appele lorsque la dernire rfrence un objet
estsupprime.Cettemthodepeuttreutilisepourlibrerdesressourcesutilisesparl'objet(dutypefichier,
informationsdansunebasededonnes,etc.).

Enfin,toujoursenversion5,ilestpossibledespcifierunemthodenomme__toString(pasdeparamtre)qui
permet de convertir un objet en chane. Cette mthode est automatiquement appele chaque fois que l'objet
est utilis dans un contexte o PHP attend une chane (par exemple dans un echo). Cette mthode doit
retournerunechanedanslaquellevouspouvezintgrerlesinformationsquevoussouhaitezsurl'objet.

l'intrieur des mthodes, l'objet courant (ou instance courante) peut tre rfrenc par la variable $this
pouraccderauxattributsouauxmthodes,ilsuffitd'utiliserl'oprateur >suividunomdel'attributoudunom
delamthode,derrirelenomdelavariable$this.

Syntaxe

$this->attribut
$this->mthode([valeur[, ...]])

- 2- ENI Editions - All rigths reserved


Lesigne$portesurlenomdelavariablethis,passurlenomdel'attribut.

Exemple

<?php
// dfinition d'une classe destine stocker des informations
// sur un utilisateur
class utilisateur {
// dfinition des attributs
public $nom; // nom de l'utilisateur
public $prnom; // prnom de l'utilisateur
public $langue = "fr"; // langue de l'utilisateur
// franais par dfaut
private $timestamp; // date/heure de cration
// attribut priv
// dfinition des mthodes
// - mthode constructeur
public function __construct($prnom,$nom) {
// initialiser le nom et le prnom
// avec les valeurs passes en paramtre
$this->prnom = $prnom;
$this->nom = $nom;
// initialiser le timestamp avec la fonction time()
$this->timestamp = time();
}
// - mthode destructeur
public function __destruct() {
// se contente d'afficher un message
echo "Suppression de $this-nom/B";
}
// - mthode de conversion de l'objet en chane
public function __toString() {
// retourne juste le nom et le prnom
return "__toString = $this-nom - $this-prnom";
}
// - mthode qui modifie la langue de l'utilisateur
public function langue($langue) {
$this->langue = $langue;
}
// - mthode (prive) qui met en forme la date/heure
// de cration de l'utilisateur
private function miseEnFormeTimestamp() {
setlocale(LC_TIME,$this-langue);
return strftime("%c", $this-timestamp);
}
// - mthode qui donne des informations sur l'utilisateur
public function informations() {
$cration = $this-miseEnFormeTimestamp();
return "$this->prnom $this->nom - $cration";
}
}
?>

Une classe est utilisable uniquement dans le script o elle est dfinie. Pour pouvoir l'employer dans plusieurs scripts, il faut,
soit recopier sa dfinition dans les diffrents scripts (vous perdez l'intrt de la dfinition d'une classe), soit la dfinir dans un
fichier qui est inclus partout o la classe est utilise.

Instancieruneclasse

Instancier une classe signifie crer un objet bas sur la dfinition de la classe. Dans une certaine mesure, cela
revientdfinirunevariableayantcomme"type",laclasse.

L'instanciations'effectuegrcel'oprateurnew.

Syntaxe

$nom_objet = new nom_classe[(valeur[, ...])]

$nom_objet

Variabledestinestockerl'objet.

ENI Editions - All rigths reserved - 3-


nom_classe

Nomdelaclassequisertde"modle"l'objet.

valeur

Paramtreventuelpasslamthodeconstructeurdelaclasseappelelorsdelacrationdel'objet.


Aprscrationdel'objet,lesattributsetmthodespublicsdel'objetpeuventtreatteintsavecl'oprateur >,
surlavariable$nom_objet,commeaveclavariable$this.

Il n'y a pas de protection des attributs publics des objets ; ils peuvent tre manipuls directement.

Exemple

<?php
// inclusion du fichier qui contient la dfinition de la
// classe utilisateur prsente prcdemment
include("classes.inc");
// instanciation d'un objet
$moi = new utilisateur("Olivier","Heurtel");
// la variable $moi contient maintenant un objet
// bas sur la classe utilisateur
// les mthodes sont accessibles par l'oprateur ->
// utilisation des mthodes de l'objet
echo "$moi->informations()."<BR>";
$moi->langue("us"); //modification de la langue
echo $moi->informations()."<BR>";
// ou directement des attributs publics
$moi->nom = strtoupper($moi->nom);
echo $moi->nom."<BR>";
// affichage direct de l'objet = utilisation de __toString
echo $moi."<BR>";
// tentative d'accs un attribut priv = erreur
echo $moi->timestamp;
?>

Rsultat

Olivier Heurtel - 10/03/2004 15:37:21


Olivier Heurtel - 03/10/2004 03:37:21 PM
HEURTEL
__toString = HEURTEL - Olivier
Fatal error: Cannot access private property utilisateur::$timestamp in d:\scripts
php\index.php on line 20

Suppression de HEURTEL

Notez le message d'erreur sur la tentative d'accs l'attribut priv $timestamp et le message final
correspondantl'appelautomatiquedelamthodedestructeur.

Les variables objet peuvent tre substitues comme les autres (cf. chapitre Constantes, variables, types et
tableauxTypesdedonnes),dansleschanesdecaractresdlimitespardesguillemetsdoubles.

Exemple

<?php
// inclusion du fichier qui contient la dfinition de la
// classe utilisateur prsente prcdemment
include("classes.inc");
// instanciation d'un objet
$moi = new utilisateur("Olivier","Heurtel");
// affichage
echo "\$moi->nom = $moi->nom";
?>

Rsultat

- 4- ENI Editions - All rigths reserved


$moi->nom = Heurtel
Suppression de HEURTEL

Encasdebesoin,lesaccoladespeuventtreutilisespourdlimiterlavariablel'intrieurdelachane.

Les rgles de porte et de dure de vie des variables s'appliquent aux objets (cf. chapitre Constantes, variables, types et
tableaux - Porte et dure de vie).

Hritage

Ilestpossiblededfinirunenouvelleclassequihrited'uneclasseexistanteaveclemotclextends.

Syntaxe

class nom_classe extends nom_classe_de_base{


// dfinition des attributs supplmentaires
[
public | private | protected $attribut [= expression_littrale];
...
]
// dfinition des mthodes supplmentaires
[
public | private | protected function mthode() {
...
}
...
]
}

Lasignificationdesdiffrentslmentsestlammequepourladfinitiond'uneclasse.

Lanouvelleclassecreestappeleclassefilleetlaclassedebase(quiaservide"moule"cettecration)est
nommeclassemre.

La nouvelle classe possde implicitement les attributs et mthodes de la classe de base et peut en dfinir de
nouveaux, notamment une classe constructeur nomme __construct. Si la classe fille n'a pas de mthode
constructeur, c'est la mthode constructeur de la classe mre qui est appele lors de l'instanciation d'un objet
surlaclassefille.

Quand la mthode constructeur existe dans la classe fille, il n'y a pas d'appel automatique la mthode
constructeur de la classe mre : si ncessaire, il faut l'appeler explicitement en utilisant parent::__construct
().

Exemple

<?php
// dfinition d'une classe de base
class utilisateur {
// dfinition des attributs
public $nom; // nom de l'utilisateur
public $prnom; // prnom de l'utilisateur
// dfinition des mthodes
// - mthode constructeur
public function __construct($prnom,$nom) {
// initialiser le nom et le prnom
// avec les valeurs passes en paramtre
$this->prnom = $prnom;
$this->nom = $nom;
}
// - mthode qui donne les informations sur l'utilisateur
public function informations() {
return "$this->prnom $this->nom";
}
}
// dfinition d'une classe qui hrite de la premire
class utilisateur_couleur extends utilisateur{
// dfinition des attributs complmentaires
public $couleurs; // couleurs prfres de l'utilisateur

ENI Editions - All rigths reserved - 5-


// dfinition des mthodes complmentaires
// - mthode constructeur
public function __construct($prnom,$couleurs) {
// appel au constructeur de la classe mre
// pour la premire partie de l'initialisation
parent::__construct ($prnom,"X");
// initialisation spcifique complmentaire
$this->couleurs = explode(",",$couleurs);
}
// - liste des couleurs prfres de l'utilisateur
public function couleurs() {
return implode(",",$this->couleurs);
}
}
// instanciation d'un objet sur la classe fille
$moi = new utilisateur_couleur("Olivier","bleu,blanc,rouge");
// utilisation des mthodes
// - de la classe mre
echo $moi->informations()."<BR>"; // existe par hritage
// - de la classe fille
echo $moi->couleurs()."<BR>"; // existe dans la classe
?>

Rsultat

Olivier X
bleu,blanc,rouge

Dans une classe fille, il est possible de redclarer une mthode ou un attribut qui existe dans la classe mre. Dans ce cas,
l'oprateur parent:: peut tre utilis pour faire rfrence explicitement aux attributs (parent::attribut) ou mthodes
(parent::mthode()) de la classe mre et lever l'ambigut du nommage (cet oprateur peut tre utilis mme s'il n'y a pas
d'ambigut).

Autresfonctionnalitssurlesclasses

Lesdiffrentesfonctionnalitsprsentesdanscettesectiononttintroduitesenversion5.

Classeoumthodeabstraite

Une classe abstraite est une classe qui ne peut pas tre instancie (pas de cration d'objet sur la classe). Par
contre,unetelleclassepeutservirdebaseladfinitiond'uneclassefillequipourratreinstancie(saufsielle
estellemmeabstraite).

Une mthode abstraite est une mthode qui est dfinie dans une classe (ellemme obligatoirement abstraite)
mais pas implmente (le code de la mthode n'est pas prsent). Une telle mthode pourra tre implmente
dansuneclassefille.

Entermedesyntaxe,ilsuffitdemettrelemotclabstractdevantladfinitiondelaclasseoudelamthode.

Uneclassefillequin'implmentepastouteslesmthodesabstraitesdelaclassemreestimplicitementabstraite
(mmesilemotclabstractn'estpasprsent).

Exemple

<?php
// dfinition d'une classe abstraite
abstract class classeMre {
// attribut protg
protected $x;
// deux mthodes pour accder l'attribut protg
// - pour lire
public function get() {
return "GET = $this->x";
}
// - pour crire
// > mthode abstraite
abstract public function put();
}
// dfinition d'une classe fille qui hrite de la classe mre
class classeFille extends classeMre {

- 6- ENI Editions - All rigths reserved


// implmentation de la mthode d'criture
public function put($valeur) {
$this->x = $valeur;
}
}
// dfinition d'une autre classe fille qui hrite de la classe mre
class classeFilleBis extends classeMre {
// implmentation d'une autre mthode d'criture
public function put($valeur1,$valeur2) {
$this->x = $valeur1+$valeur2;
}
}
// utilisation de la premire classe fille
$objet = new classeFille();
$objet->put(123);
echo $objet->get(),"<BR>";
// utilisation de la deuxime classe fille
$objet = new classeFilleBis();
$objet->put(123,456);
echo $objet->get(),"<BR>";
?>

Rsultat

GET = 123
GET = 579

Classeoumthodefinale

Onnepeuthriterd'uneclassefinale.

Unemthodefinalenepeutpastreredfiniedansuneclassefille.

Entermedesyntaxe,ilsuffitdemettrelemotclfinaldevantladfinitiondelaclasseoudelamthode.

Exemple 1

<?php
// dfinition d'une classe mre avec une mthode finale
class classeMre {
final public function mthodeFinale() {
echo "Mthode finale dans la classe mre";
}
}
// dfinition d'une classe fille qui hrite de la classe mre
class classeFille extends classeMre {
// tentative de modification de la classe finale
public function mthodeFinale() {
echo "Mthode finale dans la classe fille";
}
}
?>

Rsultat

Fatal error: Cannot override final method


classeMre::mthodeFinale() in d:\scripts php\index.php on line 14

Exemple 2

<?php
// dfinition d'une classe mre finale
final class classeMre {
public $x;
}
// tentative de dfinition d'une classe fille qui hrite
// de la classe mre
class classeFille extends classeMre {
public $y;
}
?>

ENI Editions - All rigths reserved - 7-


Rsultat

Fatal error: Class classeFille may not inherit from final class
(classeMre) in d:\scripts php\index.php on line 10

Interface

Une interface est une classe qui ne contient que des spcifications de mthodes sans implmentations. Une
interfacenecontientpasd'attributnonplus.

D'autres classes peuvent tre ensuite dfinies et implmenter une ou plusieurs interfaces, c'estdire
implmenterlesmthodesd'uneouplusieursinterfaces.

Syntaxe de dfinition d'une interface

interface nom_interface {
// dfinition des mthodes
[public] function mthode();
...
}

nom_interface

Nomdel'interface(doitrespecterlesrglesdenommageprsentesdanslechapitreVued'ensembledePHP).

mthode

Spcificationd'unemthodedel'interface.


Lesmthodesd'uneinterfacesontforcmentpubliques lemotclpublicpeuttreomis.

Il est possible de dfinir une nouvelle classe qui implmente une ou plusieurs interfaces avec le mot cl
implements.

Syntaxe

class nom_classe implements nom_interface1,nom_interface2,... {


...
}

Une telle classe doit implmenter les diffrentes mthodes des interfaces qu'elle implmente. Si l'une des
mthodesdesinterfacesn'estpasimplmente,laclassedoittredclareabstraite.

Exemple

<?php
// dfinition de deux interfaces
interface lecture {
function get();
}
interface criture {
function put();
}
// dfinition d'une classe qui implmente les deux interfaces
class uneClasse implements lecture,criture {
// dfinition d'un attribut quelconque
private $x;
// implmentation de la mthode de lecture
public function get() {
return $this->x;
}
// implmentation de la mthode d'criture
public function put($valeur) {
$this->x = $valeur;
}
}

- 8- ENI Editions - All rigths reserved


?>

AttributoumthodestatiqueConstantedeclasse

Un attribut ou une mthode statique est utilisable directement sans instanciation pralable d'un objet. On parle
aussid'attributoudemthodedeclasse.

Pour dfinir un attribut ou une mthode statique, il suffit de placer le mot cl static devant la dfinition de
l'attributoudelamthode.

Pour rfrencer un attribut ou une mthode statique, il faut utiliser la syntaxe nom_classe::$nom_attribut ou
nom_classe::nom_mthode().

Une constante de classe est une constante dfinie dans une classe utilisable directement sans instanciation
pralabled'unobjet(commeunattributdeclasse,maisconstant).

Syntaxe de dfinition d'une constante de classe

const nom_constante = valeur;

nom_constante

Nomdelaconstante.

valeur

Valeurdelaconstante.


Uneconstantedeclasseestimplicitementpublique.

Pourrfrenceruneconstantedeclasse,ilfaututiliserlasyntaxenom_classe::nom_constante.

Exemple

<?php
// dfinition d'une classe
class uneClasse {
// attribut priv quelconque
private $x;
// attribut priv statique pour stocker
// le nombre d'objets instancis
static private $nombre = 0;
// constante de classe pour dfinir une valeur
// par dfaut
const DEFAUT = "X";
// fonction publique statique qui retourne le
// nombre d'objets
static public function nombreObjets() {
return uneClasse::$nombre;
}
// mthode constructeur
// - rcuprer la valeur de l'attribut (valeur par dfaut
// = la constante de classe)
// - incrmenter le nombre d'objets
public function __construct($valeur = uneClasse::DEFAUT) {
$this->x = $valeur;
uneClasse::$nombre++;
echo "Cration de l'objet : $this->x<BR>";
}
// mthode destructeur
// - dcrmenter le nombre d'objets
public function __destruct() {
uneClasse::$nombre--;
echo "Suppression de l'objet : $this->x<BR>";
}
}
// crer deux objets
$inconnu = new uneClasse();

ENI Editions - All rigths reserved - 9-


$abc = new uneClasse ("ABC");
// afficher le nombre d'objets
echo uneClasse::nombreObjets()," objet(s)<BR>";
// "supprimer" un objet
unset($inconnu);
// afficher le nombre d'objets
echo uneClasse::nombreObjets()," objet(s)<BR>";
?>

Rsultat

Cration de l'objet : X
Cration de l'objet : ABC
2 objet(s)
Suppression de l'objet : X
1 objet(s)
Suppression de l'objet : ABC

Exceptions

Les langages de programmation objet comme C++ et Java utilisent la notion d'exception pour grer les erreurs.
CettefonctionnalitatintroduitedanslagestiondesobjetsdePHPenversion5.

Le principe consiste inclure le code susceptible de gnrer des erreurs dans un bloc try et lui associer un
bloccatchdestinintercepterleserreursetlestraiter :

Structure gnrale

try {
// code susceptible de gnrer des erreurs
...
} catch (Exception $e) {
// code destin traiter les erreurs
...
}

LaclasseExceptionestuneclassequicontientnotammentlesmthodessuivantes :

__construct

Mthodeconstructeuracceptantdeuxparamtres :unmessaged'erreuretuncoded'erreur(optionnel).

getMessage

Mthodepermettantdercuprerlemessaged'erreur.

getCode

Mthodepermettantdercuprerlecoded'erreur.


l'intrieur du bloc try, une exception peut tre leve par une instruction du type throw new Exception
(message[,code]). Dans le bloc catch, les mthodes getMessage et getCode permettent de rcuprer des
informations sur l'erreur et de la traiter. En cas d'exception dans un bloc try, le traitement se branche
directementdanslebloccatch :lerestedubloctryn'estpasexcut.

Exemple

<?php
// dfinition d'une classe
class uneClasse {
// un attribut quelconque
private $x;
// mthode constructeur
public function __construct($valeur) {
$this->x = $valeur;
}
// mthode qui effectue une action quelconque

- 10 - ENI Editions - All rigths reserved


public<+>function action() {
// pour une raison donne l'action est interdite
// si l'attribut est ngatif : une exception est leve
if ($this->x < 0) {
throw new Exception("Action interdite",123);
}
}
}
// crer deux objets
$objet = new uneClasse(1);
try {
echo "Objet 1 : ";
$objet->action(); // ne va pas lever d'exception
echo "OK<BR>";
} catch (Exception $e) {
echo "ERREUR ",$e->getCode()," - ",$e->getMessage(),"<BR>";
}
$objet = new uneClasse(-1);
try {
echo "Objet 2 : ";
$objet->action(); // va lever une exception
echo "OK<BR>";
} catch (Exception $e) {
echo "ERREUR ",$e->getCode()," - ",$e->getMessage(),"<BR>";
}
?>

Rsultat

Objet 1 : OK
Objet 2 : ERREUR 123 - Action interdite

ENI Editions - All rigths reserved - 11 -


Vued'ensemble

Petitrappelsurlesformulaires

Le formulaire est un outil de base indispensable pour les sites Web dynamiques puisqu'il permet l'utilisateur de
saisirdesinformationsetdoncd'interagiraveclesite.

UnformulaireHTMLestdfinientrelesbalises<FORM>et</FORM>.

Syntaxe

<FORM
[ ACTION="url_de_traitement" ]
[ METHOD="GET"|"POST" ]
[ NAME="nom_formulaire" ]
>
...
</FORM>

Lesoptionsdelabalise<FORM>sontlessuivantes :

ACTION

URL relative ou absolue (Uniform Resource Locator), qui va traiter le formulaire, en ce qui nous concerne, un
scriptPHP.Sirienn'estspcifi,lammeURLquelapageestutilise.

METHOD

Modedetransmissionversleserveurdesinformationssaisiesdansleformulaire.
GET(valeurpardfaut) :lesdonnesduformulairesonttransmisesdansl'URL.
POST :lesdonnesduformulairesonttransmisesdanslecorpsdelarequte.

NAME

Nom du formulaire. Si la page HTML contient plusieurs formulaires, le nom permet de les diffrencier. En ce qui
nous concerne, ce nom ne prsente pas d'intrt car il n'est pas rcupr dans le script de traitement du
formulaire.Parcontre,ilpeuttreutilisctclient,enJavaScriptparexemple.


Entre les balises <FORM> et </FORM>, il est possible de placer des balises <INPUT>, <SELECT> ou <TEXTAREA>
pourdfinirdeszonesdesaisies.

Exemple (formulaire HTML complet)

<FORM>
Nom :
<INPUT TYPE="text" NAME="nom" VALUE=""
SIZE="20" MAXLENGTH="20">
Mot de passe :
<INPUT TYPE="password" NAME="mot_de_passe" VALUE=""
SIZE="20" MAXLENGTH="20">
<BR>Sexe :
<INPUT TYPE="radio" NAME="sexe" VALUE="M"> Masculin
<INPUT TYPE="radio" NAME="sexe" VALUE="F"> Fminin
<INPUT TYPE="radio" NAME="sexe" VALUE="?"
CHECKED> Ne sait pas
<BR>Photo :
<INPUT TYPE="file" NAME="photo" VALUE="" SIZE="50">
<BR>Couleurs prfres :
<INPUT TYPE="checkbox" NAME="bleu"> Bleu
<INPUT TYPE="checkbox" NAME="blanc"> Blanc
<INPUT TYPE="checkbox" NAME="rouge"> Rouge
<INPUT TYPE="checkbox" NAME="nesaitpas" CHECKED> Ne sait pas
<BR>Langue :
<SELECT NAME="langue">
<OPTION VALUE="E">Espagnol
<OPTION SELECTED VALUE="F">Franais

ENI Editions - All rigths reserved - 1-


<OPTION VALUE="I">Italien
</SELECT>
<BR>Fruits prfrs :<BR>
<SELECT NAME="fruits" MULTIPLE SIZE="8">
<OPTION VALUE="A">Abricots
<OPTION VALUE="C">Cerises
<OPTION VALUE="F">Fraises
<OPTION VALUE="P">Pches
<OPTION SELECTED VALUE="?">Ne sait pas
</SELECT>
<BR>Commentaire :<BR>
<TEXTAREA NAME="commentaire" ROWS="4" COLS="50"></TEXTAREA>
<BR>
<INPUT TYPE="hidden" NAME="invisible" VALUE="123"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
<INPUT TYPE="image" NAME="valider"
SRC="valider.gif" WIDTH="23" HEIGHT="34">
<INPUT TYPE="reset" NAME="effacer" VALUE="Effacer">
<INPUT TYPE="button" NAME="action" VALUE="Ne fait rien">
</FORM>

InteractionentreunformulaireetunscriptPHP

PHPpeutintervenirdeuxendroitsparrapportauformulaire :

- pour la construction du formulaire, si ce dernier doit contenir des informations dynamiques ;

- pour le traitement du formulaire (c'estdire des donnes saisies par l'utilisateur dans le formulaire).

TroisgrandesmthodessontutilisablespourfaireinteragirunformulaireetunscriptPHP :

- placer le formulaire dans un document HTML "pur" (.htm ou .html), le formulaire ne contient alors aucun lment
dynamique, et indiquer le nom du script PHP qui doit traiter le formulaire dans l'option ACTION de la balise <FORM> ;

- placer le formulaire dans un script PHP (par exemple, pour construire une partie du formulaire dynamiquement) et faire
traiter le formulaire par un autre script PHP (mentionn dans l'option ACTION de la balise <FORM>) ;

- 2- ENI Editions - All rigths reserved


- placer le formulaire dans un script PHP (par exemple, pour construire une partie du formulaire dynamiquement), et le
faire traiter par le mme script PHP (mentionn dans l'option ACTION de la balise <FORM> ou appel par dfaut si
cette option n'est pas prsente).

Exemple (premire mthode)

Document HTML saisie.htm

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="traitement.php" METHOD="POST">
Nom : <INPUT TYPE="text" NAME="nom" VALUE=""><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

Script PHP traitement.php

<?php
/* A faire ...
- rcuprer les informations saisies
- faire le traitement
- afficher une nouvelle page
*/
?>

Par ailleurs, sur une autre page, un lien (Saisie par exemple) peut tre insr pour appeler le formulaire de
saisie :

<A HREF="saisie.htm">Saisie</A>

Rsultat

- Affichage initial du formulaire :

- Saisie d'une information :

- Le rsultat du clic sur le bouton OK est une page vide car, pour l'instant, le script de traitement ne fait rien.

Exemple (deuxime mthode)

Document PHP saisie.php

UnpeudecodePHP(engras)estutilispourgnrerlapartiedynamiqueduformulaire.

<?php
// inclure un fichier qui contient des dfinitions de
// constantes, dont le titre de la page (TITRE_PAGE_SAISIE)
require("constantes.inc");
// initialisation d'une variable qui contient la valeur
// initiale de la zone de saisie (dans la pratique, cette
// valeur vient sans doute d'ailleurs et n'est pas code
// en dur)

ENI Editions - All rigths reserved - 3-


$nom = "X";
// dans le code HTML qui suit, inclusion de deux petits
// bouts de code PHP pour afficher respectivement le titre
// de la page et la valeur initiale de la zone de saisie
?>
<HTML>
<HEAD><TITLE><?php echo TITRE_PAGE_SAISIE ?></TITLE></HEAD>
<BODY>
<FORM ACTION="traitement.php" METHOD="POST">
Nom : <INPUT TYPE="text" NAME="nom"
VALUE="<?php echo $nom ?>"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

Script PHP traitement.php

<?php
/* A faire ...
- rcuprer les informations saisies
- faire le traitement
- afficher une nouvelle page
*/
?>

Par ailleurs, sur une autre page, un lien (Saisie par exemple) peut tre insr pour appeler le formulaire de
saisie :

<A HREF="saisie.php">Saisie</A>

Rsultat

- Affichage initial du formulaire (une valeur initiale dynamique est propose pour la zone de saisie) :

- Saisie d'une information :

- Le rsultat du clic sur le bouton OK est une page vide car, pour l'instant, le script de traitement ne fait rien.

Exemple (troisime mthode)

Document PHP saisie.php

C'estlemmescriptqueprcdemment,danslequelnousavonssimplementchangl'optionACTIONdelabalise
<FORM> pour indiquer que le formulaire doit tre trait par le mme script saisie.php (ne pas mettre d'option
ACTIONauraitlemmeeffet).

<?php
// inclure un fichier qui contient des dfinitions de
// constantes, dont le titre de la page (TITRE_PAGE_SAISIE)
require("constantes.inc");
// initialisation d'une variable qui contient la valeur
// initiale de la zone de saisie (dans la pratique, cette
// valeur vient sans doute d'ailleurs et n'est pas code en dur)
$nom = "X";
// dans le code HTML qui suit, inclusion de deux petits
// bouts de code PHP pour afficher respectivement le titre
// de la page et la valeur initiale de la zone de saisie

- 4- ENI Editions - All rigths reserved


?>
<HTML>
<HEAD><TITLE><?php echo TITRE_PAGE_SAISIE ?></TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Nom : <INPUT TYPE="text" NAME="nom"
VALUE="<?php echo $nom ?>"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

Par ailleurs, sur une autre page, un lien (Saisie par exemple) peut tre insr pour appeler le formulaire de
saisie :

<A HREF="saisie.php">Saisie</A>

Rsultat

- Affichage initial du formulaire (une valeur initiale dynamique est propose pour la zone de saisie) :

- Saisie d'une information :

- Le rsultat du clic sur le bouton OK est la mme page de nouveau affiche, car, pour l'instant, le script de traitement
ne fait rien de plus.

Que s'estil pass?

Le script saisie.php a t appel de nouveau, par le clic sur le bouton OK il s'est donc excut comme lors
de son premier appel (lien Saisie). Comme le code ne fait rien, pour l'instant, afin de traiter le formulaire, il
s'affiche comme initialement. Utiliser le mme script pour l'affichage initial et le traitement ncessite d'tre en
mesuredefaireladiffrenceentrelesdeuxtypesd'appels(cf.B2.Lesdiffrentstypesdezones).

Quechoisir ?

Lechoixdetelleoutellemthodedpenddelacomplexitdusiteetdesprfrencesdechacun.

Quelquesconsidrationsgnrales :

- Sparer la page HTML (ou le script PHP qui gnre le formulaire) du script PHP prsente un inconvnient au niveau de
la maintenance: si des modifications sont apportes au formulaire, il y a deux fichiers modifier (avec des risques
d'erreur, d'oubli...).

- Inversement, si le formulaire n'a aucune partie dynamique, l'crire dans un fichier HTML spar du script PHP qui le
traite, permet de bien sparer l'interface utilisateur (la couche "prsentation") du traitement.

- Dans la pratique, pour faciliter la maintenance, il est souhaitable de dfinir certaines valeurs prsentes plusieurs

ENI Editions - All rigths reserved - 5-


reprises (nom de socit par exemple) dans des constantes ou des variables et d'utiliser ces constantes/variables dans
les pages: toutes les pages deviennent un peu dynamiques et la troisime mthode parat optimale.

Dans la suite de ce chapitre, nous allons rentrer dans le dtail du traitement du formulaire en PHP, en utilisant
desexemplesconstruitssurlemodledelatroisimemthode.

- 6- ENI Editions - All rigths reserved


Rcuprerlesdonnessaisiesdansleformulaire

Principe

ladiffrencedesscriptsCGI,iln'yapasbesoinderaliserdesanalysescomplexesdechanesdecaractres
("parser")pourrcuprerlesvaleurssaisiesparl'utilisateur. cesvaleursvonttrercupresdirectement(ou
presque,selonlaconfigurationdePHP).

Premiremthode

Par dfaut, toutes les zones de formulaire sont automatiquement enregistres dans le script PHP qui traite le
formulaire,dansuntableauassociatif $_POSTpourlesformulairesPOST et$_GETpourlesformulairesGET :lacl
du tableau est gale au nom de la zone dans le formulaire (option NAME de la balise <INPUT>, <SELECT> ou
<TEXTAREA>) et la valeur gale la valeur saisie dans la zone. Ces informations sont aussi disponibles dans le
tableau associatif $_REQUEST qui regroupe le contenu des tableaux $_GET et $_POST (et nous le verrons plus
tarddutableau$_COOKIEquicontientdesinformationssurlescookies).

Exemple

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<?php
// initialisation de deux variables destines rcuprer
// l'information souhaite dans les tableaux $_POST
// et $_REQUEST
$nom_POST = "";
$nom_REQUEST = "";
// pour les deux tableaux :
// - tester si le tableau contient une valeur associe la
// cl portant le mme nom que la zone de saisie du
// formulaire
// - si oui, rcuprer cette valeur dans une variable et
// l'afficher
if ( isset($_POST["nom"]) ) {
$nom_POST = $_POST["nom"];
echo "\$_POST -> $nom_POST<BR>";
}
if ( isset($_REQUEST["nom"]) ) {
$nom_REQUEST = $_REQUEST["nom"];
echo "\$_REQUEST -> $nom_REQUEST<BR>";
}
// ensuite, affichage du formulaire : c'est du HTML
// noter l'utilisation de la variable $nom_POST dans un petit
// bloc PHP pour initialiser la zone de saisie
?>
<FORM ACTION="saisie.php" METHOD="POST">
Nom : <INPUT TYPE="text" NAME="nom"
VALUE="<?php echo $nom_POST?>"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

Rsultat

- Affichage initial du formulaire :

- Saisie d'une valeur :

ENI Editions - All rigths reserved - 1-


- Rsultat du clic sur le bouton OK :

Lors du premier appel, les tableaux $_POST et $_REQUEST ne contiennent pas de valeur associe une cl
portantlemmenomquelazonedeformulaire :rienn'estaffich,nienhaut,nidanslazonedesaisie.
Aprs saisie d'une valeur et clic sur le bouton OK, le script est de nouveau appel : cette fois, les tableaux
$_POST et$_REQUESTcontiennentunevaleurassocielaclportantlemmenomquelazonedeformulaire
la valeur saisie. Cette valeur saisie est afiche en haut, mais aussi dans la zone de saisie. S'il n'y avait pas
d'instructionecho $nom_POSTdansl'optionVALUE,lavaleursaisieneseraitpasraffichedanslazone.
Siunautrescripttaitappelpourtraiterleformulaire,lesinformationsseraientdisponiblesdelammemanire.

Exemple de (script traitement.php)

<?php
// initialisation de deux variables destines rcuprer
// l'information souhaite dans les tableaux $_POST
// et $_REQUEST
$nom_POST = "";
$nom_REQUEST = "";
// pour les deux tableaux :
// - tester si le tableau contient une valeur associe la
// cl portant le mme nom que la zone de saisie du
// formulaire
// - si oui, rcuprer cette valeur dans une variable et
// l'afficher
if ( isset($_POST["nom"]) ) {
$nom_POST = $_POST["nom"];
echo "\$_POST -> $nom_POST<BR>";
}
if ( isset($_REQUEST["nom"]) ) {
$nom_REQUEST = $_REQUEST["nom"];
echo "\$_REQUEST -> $nom_REQUEST<BR>";
}
?>

Rsultat

Les tableaux $_GET, $_POST et $_REQUEST sont apparus en version 4.1. Avant la version 4.1, $_GET et $_POST
s'appelaient $HTTP_GET_VARS et $HTTP_POST_VARS, et $_REQUEST n'avait pas d'quivalent. Pour des raisons de
compatibilit ascendante, ces variables "longues" sont toujours disponibles condition de positionner la directive de
configuration register_long_array on (off par dfaut). Cette directive de configuration est apparue en version 5 ; entre
la version 4.1 et la version 5, les variables longues taient disponibles par dfaut. Avant la version 4.0.3, il fallait que la directive
de configuration track_vars soit on pour que les tableaux $HTTP_GET_VARS et $HTTP_POST_VARS soient disponibles ;
depuis la version 4.0.3, cette directive est toujours on et les tableaux sont donc toujours disponibles.

Deuximemthode

Les informations saisies dans le formulaire peuvent tre automatiquement importes dans des variables PHP
grcelafonctionimport_request_variables.

- 2- ENI Editions - All rigths reserved


Syntaxe

import_request_variables(chane types,chane prfixe)

types

Typed'informationdsire :
Goug :informationsenvoyesparlamthodeGET
Poup :informationsenvoyesparlamthodePOST
Couc :informationsenvoyesparuncookie(cf.chapitreGrerlessessionsUtiliserdescookies).

prfixe

Prfixeajouterdevantlenomdelavariable.


Lorsque cette fonction est appele dans le script de traitement d'un formulaire, PHP va crer une variable pour
chaque zone du formulaire : le nom de la variable est gal au nom de la zone dans le formulaire prcd du
prfixe,etlavaleurdelavariableestgalelavaleursaisiedansleformulaire.

LeprfixeestoptionnelmaisuneerreurdeniveauE_NOTICEestgnres'iln'estpasrenseign.

Vouspouvezutiliserunecombinaisondesdiffrenteslettresdetypespourimporterenunefoisdesinformations
d'origine diffrente. Par exemple, spcifier PG permet de rcuprer les informations envoyes par une mthode
POSTouunemthodeGET.

Exemple

<?php
// importer les informations du formulaire
// - mthode POST
// - prfixe form_
import_request_variables("P","form_");
// tester si la variable $form_nom existe
if ( isset($form_nom) ) {
// si oui, l'afficher
echo "\$form_nom = $form_nom<BR>";
} else {
// si non, l'initialiser
$form_nom = "";
}
// ensuite, affichage du formulaire : c'est du HTML
// noter l'utilisation de la variable $form_nom dans un petit
// bloc PHP pour initialiser la zone de saisie
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Nom : <INPUT TYPE="text" NAME="nom"
VALUE="<?php echo $form_nom?>"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

Rsultat

- Affichage initial du formulaire :

- Saisie d'une valeur :

ENI Editions - All rigths reserved - 3-


- Rsultat du clic sur le bouton OK :

Le fonctionnement est identique celui du premier exemple. Lors du premier appel, aucune variable n'est
importe dans le script (le formulaire n'a pas encore t affich). Lors du deuxime appel (traitement du
formulaire),unevariable$form_nomestbiencredanslescriptaveclavaleursaisie.

La fonction import_request_variables est apparue en version 4.1.

Troisimemthode(nonrecommande)

Latroisimemthodeestnonrecommandecarelleestdpendanted'unedirectivedeconfigurationetellepeut
poserdesproblmesdeperformanceetdescurit.Elleestnanmoinsprsentebrivementdanscettepartie
carvouspouvezlarencontrerdansducodePHP"ancien"(venantdelaversion3parexemple).

Si la directive de configuration register_globals est on, toutes les zones de formulaire sont automatiquement enregistres
dans des variables dans le script PHP qui traite le formulaire. Les variables hritent du nom (option NAME de la balise <INPUT>, <SELECT>
ou <TEXTAREA>) de la zone correspondante du formulaire. Ce comportement est valable quelle que soit la mthode (GET ou POST).

Exemple

<?php
// tester s'il existe une variable portant le mme nom
// que la zone de saisie du formulaire
if ( isset($nom) ) {
// si oui, l'afficher
echo "\$nom = $nom<BR>";
} else {
// si non, l'initialiser
$nom = "";
}
// ensuite, affichage du formulaire : c'est du HTML
// noter l'utilisation de la variable $nom dans un petit
//<+>bloc PHP pour initialiser la zone de saisie
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Nom : <INPUT TYPE="text" NAME="nom"
VALUE="<?php echo $nom ?>"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

Rsultat (si register_globals = on dans php.ini)

- Affichage initial du formulaire :

- 4- ENI Editions - All rigths reserved


- Saisie d'une valeur :

- Rsultat du clic sur le bouton OK :

Le fonctionnement est identique celui des deux exemples prcdents. Lors du premier appel, la variable $nom
n'existe pas : rien n'est affich, ni en haut, ni dans la zone de saisie. Aprs saisie d'une valeur et clic sur le
boutonOK,lescriptestdenouveauappel :cettefois,lavariable$nomestdfinieetcontientlavaleursaisie.

Siladirectivedeconfigurationregister_globalsestoff,lesvariablesdeformulairenesontpascres.

Depuis la version 4.2, la directive register_globals est par dfaut off et cette mthode ne peut pas tre utilise sans
intervention dans le fichier php.ini.

Quechoisir ?

Unedesdeuxpremiresmthodes.

Les volutions successives de PHP vont dans le sens d'une utilisation des tableaux $_POST ou $_GET, ou de la
fonctionimport_request_variables.Dansunefutureversion,ladirectivedeconfigurationregister_globals
seradfinitivementpasse offetneserapasmodifiabledanslefichierphp.ini.Dansunetellehypothse,la
troisimemthodeneseraplusdisponible.

Les auteurs de PHP conseillent vivement d'utiliser l'une des deux premires mthodes pour des raisons de
scurit : en interrogeant le tableau adquat, ou en important explicitement les variables, on est certain que
l'information vient bien de l'endroit prvu et qu'il n'y a pas eu substitution par un utilisateur ventuellement mal
intentionn(cf.chapitreGrerlessessions).

Lesdeuxscriptssuivantsprsententunemanireclassiquedercuprerlesvaleurssaisiesdansunformulaireen
utilisantlesdeuxmthodes.

Utilisation d'un tableau $_*

<?php
// rcupration dans des variables PHP des valeurs
// saisies dans le formulaire en utilisant un
// tableau $_* ($_POST ici)
$form_nom = (isset($_POST["nom"]))?$_POST["nom"]:"";
$form_prnom = (isset($_POST["prnom"]))?$_POST["prnom"]:"";
// etc. pour chaque zone
// ensuite, on utilise les variables dans les traitements
// et ventuellement dans le raffichage du formulaire
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Nom : <INPUT TYPE="text" NAME="nom"
VALUE="<?php echo $form_nom?>"><BR>
Prnom : <INPUT TYPE="text" NAME="prnom"
VALUE="<?php echo $form_prnom?>"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

ENI Editions - All rigths reserved - 5-


Utilisation de la fonction import_request_variables

<?php
// importation dans des variables PHP des valeurs
// saisies dans le formulaire
import_request_variables("P","form_");
// si les variables attendues n'existent pas, les initialiser
if (! isset($form_nom)) $form_nom = "";
if (! isset($form_prnom)) $form_prnom = "";
// etc. pour chaque zone
// ensuite, on utilise les variables dans les traitements
// et ventuellement dans le raffichage du formulaire
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Nom : <INPUT TYPE="text" NAME="nom"
VALUE="<?php echo $form_nom?>"><BR>
Prnom : <INPUT TYPE="text" NAME="prnom"
VALUE="<?php echo $form_prnom?>"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

Danslasuitedecechapitre,nousutiliseronsdesformulairesPOSTetl'uneoul'autredesmthodes.

Quesepassetilsideuxzonesportentlemmenom ?

C'esttoutsimplementladernirezonerencontredansleformulairequifixelavaleur.

Exemple

<FORM ACTION="saisie.php" METHOD="POST">


Nom : <INPUT TYPE="text" NAME="nom"><BR>
Prnom : <INPUT TYPE="text" NAME="nom"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>

La saisie de HEURTELdanslapremirezoneetdeOlivierdansladeuxime,donneuneseulevariable $nom ou


$_POST["nom"]aveclavaleurOlivier.

Quesepassetils'ilyadeuxformulairesdanslapageHTML ?

Lesvariablesnesontcresetrenseignesquepourleformulairequiatvalid.

Exemple

Page saisie.htm

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Nom 1 : <INPUT TYPE="text" NAME="nom1"><BR>
<INPUT TYPE="submit" NAME="OK1" VALUE="OK1">
</FORM>
<FORM ACTION="saisie.php" METHOD="POST">
Nom 2 : <INPUT TYPE="text" NAME="nom2"><BR>
<INPUT TYPE="submit" NAME="OK2" VALUE="OK2">
</FORM>
</BODY>
</HTML>

Script de traitement saisie.php

<?php
$nom1 = (isset($_POST["nom1"]))?$_POST["nom1"]:"";

- 6- ENI Editions - All rigths reserved


$nom2 = (isset($_POST["nom2"]))?$_POST["nom2"]:"";
echo "nom1 = $nom1<BR>";
echo "nom2 = $nom2<BR>";
?>

Rsultat

- Affichage initial du formulaire puis saisie de valeurs :

- Rsultat aprs un clic sur le bouton OK1 :

nom1 = Olivier
nom2 =

Utilisationd'untableaupourrcuprerleszonessaisies

Il est possible d'utiliser une notation de type tableau dans l'option NAME des balises <INPUT>, <SELECT> et
<TEXTAREA>.

Exemple

<FORM ACTION="saisie.php" METHOD="POST">


Nom : <INPUT TYPE="text" NAME="saisie[]"><BR>
Prnom : <INPUT TYPE="text" NAME="saisie[]"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>

LasaisiedeHEURTELdanslapremirezoneetdeOlivierdansladeuxime,donneuneseulevariable$saisie,
detypetableau,quicontientleslignessuivantes :

Cl Valeur
0 HEURTEL
1 Olivier

PHPremplitletableauenajoutantunelignepourchaquezone,avecunindiceentierconscutifcommenant0
(commepourlanotation[]tudiedanslechapitreConstantes,variables,typesettableaux).

Cettetechniqueestintressante,mais,danslecode,ilfautsavoirquel'indice0correspondaunometl'indice1
auprnom.Parailleurs,unproblmepeutseprsentersil'ordredeszoneschange.

Pour amliorer cette technique, il est possible de fixer soimme la cl, soit avec un numro, soit avec une
chanedecaractres.

Exemple

<FORM ACTION="saisie.php" METHOD="POST">


Nom : <INPUT TYPE="text" NAME="saisie[1]"><BR>
Prnom : <INPUT TYPE="text" NAME="saisie[2]"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>

La saisie de HEURTEL dans la premire zone et de Olivier dans la deuxime, donne le rsultat suivant dans le
tableau$saisie :

ENI Editions - All rigths reserved - 7-


Cl Valeur
1 HEURTEL
2 Olivier

Exemple

<FORM ACTION="saisie.php" METHOD="POST">


Nom : <INPUT TYPE="text" NAME="saisie[nom]"><BR>
Prnom : <INPUT TYPE="text" NAME="saisie[prnom]"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>

La saisie de HEURTEL dans la premire zone et de Olivier dans la deuxime, donne le rsultat suivant dans le
tableau$saisie :

Cl Valeur
nom HEURTEL
prnom Olivier

Nousverronsultrieurementd'autressituationsocetypedenotationestobligatoire.

Lesdiffrentstypesdezones

PrenonsnotreformulairecompletdedpartetvoyonslesinformationsrcupresdanslescriptPHP.

Exemple Script saisie.htm

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="traitement.php" METHOD="POST">
Nom :
<INPUT TYPE="text" NAME="nom" VALUE=""
SIZE="20" MAXLENGTH="20">
Mot de passe :
<INPUT TYPE="password" NAME="mot_de_passe" VALUE=""
SIZE="20" MAXLENGTH="20">
<BR>Sexe :
<INPUT TYPE="radio" NAME="sexe" VALUE="M"> Masculin
<INPUT TYPE="radio" NAME="sexe" VALUE="F"> Fminin
<INPUT TYPE="radio" NAME="sexe" VALUE="?"
CHECKED> Ne sait pas
<BR>Photo :
<INPUT TYPE="file" NAME="photo" VALUE="" SIZE="50">
<BR>Couleurs prfres :
<INPUT TYPE="checkbox" NAME="bleu"> Bleu
<INPUT TYPE="checkbox" NAME="blanc"> Blanc
<INPUT TYPE="checkbox" NAME="rouge"> Rouge
<INPUT TYPE="checkbox" NAME="nesaitpas" CHECKED> Ne sait pas
<BR>Langue :
<SELECT NAME="langue">
<OPTION VALUE="E">Espagnol
<OPTION SELECTED VALUE="F">Franais
<OPTION VALUE="I">Italien
</SELECT>
<BR>Fruits prfrs :<BR>
<SELECT NAME="fruits" MULTIPLE SIZE="8">
<OPTION VALUE="A">Abricots
<OPTION VALUE="C">Cerises
<OPTION VALUE="F">Fraises
<OPTION VALUE="P">Pches
<OPTION SELECTED VALUE="?">Ne sait pas
</SELECT>
<BR>Commentaire :<BR>
<TEXTAREA NAME="commentaire" ROWS="4" COLS="50"></TEXTAREA>
<BR>
<INPUT TYPE="hidden" NAME="invisible" VALUE="123"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
<INPUT TYPE="image" NAME="valider"

- 8- ENI Editions - All rigths reserved


SRC="valider.gif" WIDTH="23" HEIGHT="34">
<INPUT TYPE="reset" NAME="effacer" VALUE="Effacer">
<INPUT TYPE="button" NAME="action" VALUE="Ne fait rien">
</FORM>
</BODY>
</HTML>

Script traitement.php

<?php
// inclusion d'un fichier contenant des fonctions gnriques
// (dont la fonction afficher_tableau dfinie dans le chapitre Fonctions et classes)
include("fonctions.inc") ;
afficher_tableau($_POST,"\$_POST :");
?>

Rsultat

- Affichage initial et saisie de diffrentes valeurs :

- Rsultat du clic sur le bouton OK (affichage du contenu de $_POST) :

$_POST :
nom = HEURTEL
mot_de_passe = olivier
sexe = M
photo = D:\Photos\identit.jpg
bleu = on
rouge = on
langue = F
fruits = F
commentaire = Consultant en systme d'information
invisible = 123
OK = OK

Zonecontenantdutexte

Pour les zones comprenant du texte, c'estdire les zones <INPUT> de type text (nom), password
(mot_de_passe), file (photo) et hidden (invisible), ainsi que pour la zone <TEXTAREA> (commentaire), les

ENI Editions - All rigths reserved - 9-


variablesassociescontiennentletextesaisi.

Pour l'instant, avec la zone de type file, nous avons juste rcupr le nom du fichier, mais pas le fichier lui-mme (cf.
chapitre Gestion des fichiers).

Groupedeboutonsradio

Pouravoirungroupedeboutonsradio,leszonesdoiventporterlemmenom.

Pourungroupedeboutonsradio,c'estdirepourdeszones<INPUT> detype radio (sexedansl'exempleci


aprs), la variable associe contient la valeur contenue dans l'option VALUE de la balise INPUT du bouton
slectionn.

Exemple

<INPUT TYPE="radio" NAME="sexe" VALUE="M"> Masculin


<INPUT TYPE="radio" NAME="sexe" VALUE="F"> Fminin
<INPUT TYPE="radio" NAME="sexe" VALUE="?"
CHECKED> Ne sait pas

Rsultat

$_POST :
sexe = M

Sil'optionVALUEestabsente,lavaleurpardfauteston.

Exemple

<INPUT TYPE="radio" NAME="sexe"> Masculin


<INPUT TYPE="radio" NAME="sexe"> Fminin
<INPUT TYPE="radio" NAME="sexe"
CHECKED> Ne sait pas

Rsultat

$_POST :
sexe = on

Avec le groupe de boutons radio, ne pas mettre d'option VALUE est gnant puisqu'il est alors impossible de
connatrel'optionslectionne.Danslapratique,ilfautmettrel'optionVALUE.

Casecocher

Pour des cases cocher, c'estdire pour des zones <INPUT> de type checkbox (sexe), la variable associe
contientlavaleurcontenuedansl'option VALUE de la baliseINPUT si l'option VALUEestabsente,lavaleurpar
dfauteston.Danslesdeuxcas,lavariableassocieestdfinieuniquementpourlescasescoches.

Exemple

<INPUT TYPE="checkbox" NAME="bleu"> Bleu


<INPUT TYPE="checkbox" NAME="blanc"> Blanc
<INPUT TYPE="checkbox" NAME="rouge"> Rouge
<INPUT TYPE="checkbox" NAME="nesaitpas" CHECKED> Ne sait pas

- 10 - ENI Editions - All rigths reserved


Rsultat

$_POST :
bleu = on
rouge = on

Autre exemple

<INPUT TYPE="checkbox" NAME="bleu" VALUE="b"> Bleu


<INPUT TYPE="checkbox" NAME="blanc"> Blanc
<INPUT TYPE="checkbox" NAME="rouge"> Rouge
<INPUT TYPE="checkbox" NAME="nesaitpas" CHECKED> Ne sait pas

Rsultat

$_POST :
bleu = b
rouge = on

Avec la case cocher, l'option VALUE a gnralement moins d'importance, car il est possible de dterminer
qu'unecaseestcocheuniquementparlefaitquelavariableassocieaunevaleur(peuimportecettevaleur).

Danslecode,sivoussouhaitezrcuprerl'informationcorrespondantesouslaformed'unboolen,vouspouvez
crireuneinstructiondustyle:

$nom_case = isset($_POST["nom_case"])?TRUE:FALSE;

Plusieursapprochessontpossiblesvisvisdelavaleurdel'optionVALUE :

- L'option VALUE utilise la valeur souhaite au niveau de la logique applicative dans le cas o la case est coche (1,
oui ...), sachant que, si la case n'est pas coche, la variable n'existe pas.

- L'option VALUE est omise et le code interprte l'existence de la variable selon les besoins de la logique applicative.

Parcontre,ilestimportantquelesnomsdeszonessoientdiffrents.

Exemple

<INPUT TYPE="checkbox" NAME="couleur"> Bleu


<INPUT TYPE="checkbox" NAME="couleur"> Blanc
<INPUT TYPE="checkbox" NAME="couleur"> Rouge
<INPUT TYPE="checkbox" NAME="couleur" CHECKED> Ne sait pas

Rsultat

$_POST :
couleur = on

Autre exemple

<INPUT TYPE="checkbox" NAME="couleur" VALUE="bleu"> Bleu


<INPUT TYPE="checkbox" NAME="couleur" VALUE="blanc"> Blanc
<INPUT TYPE="checkbox" NAME="couleur" VALUE="rouge"> Rouge
<INPUT TYPE="checkbox" NAME="couleur" VALUE="?" CHECKED>
Ne sait pas

ENI Editions - All rigths reserved - 11 -


Rsultat

$_POST :
couleur = rouge

Noussommesdanslecasoplusieurszonesportentlemmenom c'estalorsladernirerencontrequifixela
valeur.

Parcontre,ilestenvisageabled'utiliseruntableaupournepasavoirunevariableparcasecocher.

Exemple

<INPUT TYPE="checkbox" NAME="couleur[]"> Bleu


<INPUT TYPE="checkbox" NAME="couleur[]"> Blanc
<INPUT TYPE="checkbox" NAME="couleur[]"> Rouge
<INPUT TYPE="checkbox" NAME="couleur[]" CHECKED>
Ne sait pas

Rsultat

$_POST :
couleur =
0 = on
1 = on

PHP ne met une ligne dans le tableau que lorsque la case est coche, en attribuant des indices entiers
conscutifscommenant0.Decefait,cesindicesnecorrespondentpaslapositiondelacasecocheparmi
l'ensembledescases.SansoptionVALUE,ilestimpossiblededterminerlescasescoches.

Solution: utiliser l'option VALUE

<INPUT TYPE="checkbox" NAME="couleur[]" VALUE="bleu"> Bleu


<INPUT TYPE="checkbox" NAME="couleur[]" VALUE="blanc"> Blanc
<INPUT TYPE="checkbox" NAME="couleur[]" VALUE="rouge"> Rouge
<INPUT TYPE="checkbox" NAME="couleur[]" VALUE="?" CHECKED>
Ne sait pas

Rsultat

$_POST :
couleur =
0 = bleu
1 = rouge

C'estmieux,onsaitcequiatcoch.

Autre solution: mettre soimme un indice et ne pas mettre d'option VALUE

<INPUT TYPE="checkbox" NAME="couleur[1]"> Bleu


<INPUT TYPE="checkbox" NAME="couleur[2]"> Blanc
<INPUT TYPE="checkbox" NAME="couleur[3]"> Rouge
<INPUT TYPE="checkbox" NAME="couleur[4]" CHECKED>
Ne sait pas

Rsultat

- 12 - ENI Editions - All rigths reserved


$_POST :
couleur =
1 = on
3 = on

Variante:utiliser un tableau associatif (plus lisible dans le code)

<INPUT TYPE="checkbox" NAME="couleur[bleu]"> Bleu


<INPUT TYPE="checkbox" NAME="couleur[blanc]"> Blanc
<INPUT TYPE="checkbox" NAME="couleur[rouge]"> Rouge
<INPUT TYPE="checkbox" NAME="couleur[nesaitpas]" CHECKED>
Ne sait pas

Rsultat

$_POST :
couleur =
bleu = on
rouge = on

Siuntableauestutilispourl'ensembleduformulaire,unedessolutionslespluslisiblesestlasuivante :

<INPUT TYPE="checkbox" NAME="saisie[couleur][bleu]"> Bleu


<INPUT TYPE="checkbox" NAME="saisie[couleur][blanc]"> Blanc
<INPUT TYPE="checkbox" NAME="saisie[couleur][rouge]"> Rouge
<INPUT TYPE="checkbox" NAME="saisie[couleur][nesaitpas]"
CHECKED> Ne sait pas

Rsultat

$_POST :
saisie =
couleurs =
bleu = on
rouge = on
ou
<INPUT TYPE="checkbox" NAME="saisie[couleur][]"
VALUE="bleu"> Bleu
<INPUT TYPE="checkbox" NAME="saisie[couleur][]"
VALUE="blanc"> Blanc
<INPUT TYPE="checkbox" NAME="saisie[couleur][]"
VALUE="rouge"> Rouge
<INPUT TYPE="checkbox" NAME="saisie[couleur][]"
VALUE=" ?" CHECKED> Ne sait pas

Rsultat

$_POST :
saisie =
couleurs =
0 = bleu
1 = rouge

Listeslectionunique

Pour les listes slection unique, c'estdire pour une zone <SELECT> sans option MULTIPLE (langue dans
l'exemple suivant), la variable associe contient la valeur contenue dans l'option VALUE de la balise <OPTION>,
ou,s'iln'yapasd'optionVALUE,lavaleuraffichedanslaliste(c'estdirederrirelabalise<OPTION>).

ENI Editions - All rigths reserved - 13 -


Exemple (avec option VALUE)

<SELECT NAME="langue">
<OPTION VALUE="E">Espagnol
<OPTION SELECTED VALUE="F">Franais
<OPTION VALUE="I">Italien
</SELECT>

Rsultat

$_POST :
langue = F

Exemple (sans option VALUE)

<SELECT NAME="langue">
<OPTION>Espagnol
<OPTION SELECTED>Franais
<OPTION>Italien
</SELECT>

Rsultat

$_POST :
langue = Franais

L'une ou l'autre des possibilits peut tre choisie en fonction des besoins de la logique applicative. Souvent,
l'option VALUE est utilise pour mettre un code qui sera stock dans la base la place de la valeur affiche.
Cetteapprocheprsenteuninconvnient :lapartieinterfaceutilisateur(coucheprsentation)doitconnatreles
codes, ce qui n'est pas une bonne ide. La solution optimale consiste gnrer dynamiquement le formulaire
partirdelabase.

Listeslectionmultiple

Pour les listes slection multiple, c'estdire pour une zone <SELECT> avec option MULTIPLE (fruits dans
l'exemple ciaprs), la variable associe contient la valeur contenue dans l'option VALUE de la balise <OPTION>,
ou, s'il n'y a pas d'option VALUE, la valeur affiche dans la liste (c'estdire derrire la balise <OPTION>).
Attention, ceci est valable uniquement pour la dernire option slectionne, si la variable est une variable
scalaire.

Exemple

<SELECT NAME="fruits" MULTIPLE SIZE="8">


<OPTION VALUE="A">Abricots
<OPTION VALUE="C">Cerises
<OPTION VALUE="F">Fraises
<OPTION VALUE="P">Pches
<OPTION SELECTED VALUE="?">Ne sait pas
</SELECT>

- 14 - ENI Editions - All rigths reserved


Rsultat

$_POST :
fruits = F

Lasolutionconsisteutiliseruntableau.

Exemple

<SELECT NAME="fruits[]" MULTIPLE SIZE="8">


<OPTION VALUE="A">Abricots
<OPTION VALUE="C">Cerises
<OPTION VALUE="F">Fraises
<OPTION VALUE="P">Pches
<OPTION SELECTED VALUE="?">Ne sait pas
</SELECT>

Rsultat

$_POST :
fruits =
0 = A
1 = F

Comme nous l'avons dj vu avec la case cocher, PHP remplit le tableau avec une ligne pour chaque option
slectionne et numrote luimme les lignes. Dans le cas de la liste slection multiple, ce mode de
fonctionnementneposepasdeproblme.

Exemple (sans option VALUE)

<SELECT NAME="fruits[]" MULTIPLE SIZE="8">


<OPTION>Abricots
<OPTION>Cerises
<OPTION>Fraises
<OPTION>Pches
<OPTION SELECTED>Ne sait pas
</SELECT>

ENI Editions - All rigths reserved - 15 -


Rsultat

$_POST :
fruits =
0 = Abricots
1 = Fraises

L'une ou l'autre des possibilits peut tre choisie en fonction des besoins de la logique applicative (mmes
principesquepourlalisteslectionunique).

Exemple : (cas o un tableau est utilis pour l'ensemble du formulaire):

<SELECT NAME="saisie[fruits][]" MULTIPLE SIZE="8">


<OPTION>Abricots
<OPTION>Cerises
<OPTION>Fraises
<OPTION>Pches
<OPTION SELECTED>Ne sait pas
</SELECT>

Rsultat

$_POST :
saisie =
fruits =
0 = Abricots
1 = Fraises

Boutondevalidation

Pour un bouton de validation, c'estdire pour une zone <INPUT> de type submit (OK sur l'exemple ciaprs),
PHP cre une variable portant le nom du bouton (option NAME) et ayant comme valeur celle de l'option VALUE,
uniquementsileboutonestcliqu.

Exemple

<INPUT TYPE="submit" NAME="OK" VALUE="OK">

Rsultat (si le bouton est cliqu)

$_POST :
OK = OK

- 16 - ENI Editions - All rigths reserved


Autre exemple

<INPUT TYPE="submit" NAME="soumettre" VALUE="OK">

Rsultat (si le bouton est cliqu)

$_POST :
soumettre = OK

Sileboutonneportepasdenom,aucunevariablen'estcre.Cen'estpasgravesi :

- Il n'est pas ncessaire de savoir comment le script est appel (affichage initial ou traitement du formulaire).

- Il n'y a qu'un seul bouton de validation.

Danslesautrescas,ilfautnommerle(s)bouton(s).

Le script suivant montre comment faire la diffrence entre l'appel du script pour affichage initial et l'appel du
scriptpourtraitementduformulaire(cf.2.InteractionentreunformulaireetunscriptPHP,troisimemthode).

Exemple :

<?php
// inclure un fichier qui contient des dfinitions de
// constantes, dont le titre de la page (TITRE_PAGE_SAISIE)
require("constantes.inc");
// Tester comment le script est appel
if (isset($_POST["OK"])) {
// une ligne existe dans la variable $_POST
// correspondant au bouton nomm " OK " = le script
// est appel sur la validation du formulaire
// => traiter le formulaire
// gnralement, commencer par rcuprer les valeurs saisies
$nom = $_POST["nom"];
} else {
// le script n'est pas appel par le clic sur le bouton OK
// s'il n'y pas d'autre bouton "submit", le script est
// donc appel pour l'affichage initial
// => initialiser le formulaire
$nom = "X"; // par exemple
}
// dans le code HTML qui suit, inclusion de deux petits
//bouts de code PHP pour afficher respectivement le titre
// de la page et la valeur initiale de la zone de saisie
?>
<HTML>
<HEAD><TITLE><?php echo TITRE_PAGE_SAISIE ?></TITLE></HEAD>
<BODY>
<FORM ACTION="traitement.php" METHOD="POST">
Nom : <INPUT TYPE="text" NAME="nom"
VALUE="<?php echo $nom ?>"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

Aveccescript,ladonnesaisieestbienraffichedansleformulaire.

Un problme se pose si le formulaire possde une seule zone de texte, aucun bouton et que l'utilisateur tape
ENTER ou RETURN. Dans ce cas, le formulaire est bien soumis mais il n'existe pas de bouton de validation pour
raliser le test dans le script PHP. La solution consiste tester si la variable $_* est vide ou pas (avec empty
maispasissetcarletableauexistetoujours).

Un problme similaire mais plus inattendu se pose si le formulaire prsente un bouton de validation, une seule
zone<INPUT>detypetext oufileetn'importequelautretypedezone(saufuneautrezone<INPUT>detype
text ou file). Dans ce cas, si l'utilisateur tape ENTER ou RETURN, alors qu'il est en train de saisir une
information dans la zone <INPUT> de type text ou file, le formulaire est bien soumis mais le bouton de
validation n'est pas considr comme cliqu : aucune variable ne lui est associe dans le formulaire. La solution

ENI Editions - All rigths reserved - 17 -


estlammequedanslecasprcdent.

Si le formulaire contient deux boutons de validation nomms diffremment (option NAME), le premier OK et le
deuximeannuler,ilestpossiblededterminerdansquelcontextelescriptestappel.

Exemple

// Tester comment le script est appel


if (isset($_POST["OK"])) {
// bouton OK
} elsif (isset($_POST["annuler"])) {
// bouton Annuler
} else {
// affichage initial
}

Si le formulaire contient deux boutons de validation portant le mme nom (option NAME="soumettre" par
exemple), mais des valeurs (option VALUE) diffrentes, le premier OK et le deuxime Annuler, il est possible de
dterminerdansquelcontextelescriptestappeldelamaniresuivante.

Exemple

// Tester comment le script est appel


if ( isset($_POST["soumettre"]) ) {
// traitement du formulaire
if ($_POST ["soumettre"] == "OK") {
// bouton OK
} elseif ($_POST ["soumettre"] == "Annuler") {
// bouton Annuler
}
} else {
// affichage initial
}

Boutonimage

Pourunboutonimage,c'estdirepourunezone<INPUT>detypeimage (exemplevaliderciaprs),PHPcre
deux variables portant le nom du bouton (option NAME) suivi de _x et _y et donnant la position relative, en
pixels,duclicparrapportl'anglesituenhautgauchedel'image(uniquementsil'imageestclique).

Exemple

<INPUT TYPE="image" NAME="valider" SRC="valider.gif">

Rsultat si l'image est clique

$_POST :
valider_x = 5
valider_y = 8

Sileboutonneportepasdenom,lesdeuxvariablessontappelesxety.

Exemple

<INPUT TYPE="image" SRC="valider.gif">

Rsultat si l'image est clique

$_POST :
x = 5
y = 8

Ilestalorspossibledetraiterlapositionduclicsielleestsignificativedupointdevuedelalogiqueapplicative.

Siplusieursboutonsimagesontprsentsdansleformulaire,ilestpossiblededterminerquelboutonaprovoqu
lasoumissionduformulaire.

- 18 - ENI Editions - All rigths reserved


Exemple

// Tester comment le script est appel


if (isset($_POST["valider_x"])) {
// bouton Valider
} else ...

Bouton"reset"ou"button"

Un clic sur des boutons correspondant des zones <INPUT> de type reset ou button ne provoque pas la
soumission du formulaire, ni l'appel du script de traitement. Ces boutons permettent de faire une simple action
ctnavigateur(enJavaScriptparexemple).

Synthse

Ilfautprendrel'habitudedebiendsigner(option NAME)toutesleszonesduformulaireavecdesnomsdistincts
oud'utiliserunnommagedetypetableau,pluttassociatif,pourfaciliterlamaintenanceetlalisibilitducode.

Pourlesgroupesdeboutonsradio,ilfautmettreuneoptionVALUEdistinctechaquebouton.

Pourlescasescocher,ilfautemployerdesnomsdistincts(option NAME),et/oudesvaleursdistinctes(option
VALUE), pour tre certain de pouvoir faire la diffrence l'arrive en cas d'utilisation d'un tableau, ne laissez
pasPHPeffectuerlanumrotation(pasde[]).

Pourleslistesslectionmultiple,ilfaututiliserunnommagedetypetableaupourpouvoirrcuprerlalistedes
valeursslectionnes employezl'option VALUEpourrcuprerunevaleurdiffrentedecellequiapparatdansla
liste.

Demme,Ilfautnommerle(s)bouton(s)devalidationpourtreenmesuredesavoircommentlescriptPHPest
appel. Si plusieurs boutons sont utiliss, il est possible d'employer le mme nom du moment que les valeurs
(optionVALUE)sontdiffrentes.

Exemple

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="traitement.php" METHOD="POST">
Nom :
<INPUT TYPE="text" NAME="nom" VALUE=""
SIZE="20" MAXLENGTH="20">
Mot de passe :
<INPUT TYPE="password" NAME="mot_de_passe" VALUE=""
SIZE="20" MAXLENGTH="20">
<BR>Sexe :
<INPUT TYPE="radio" NAME="sexe" VALUE="M"> Masculin
<INPUT TYPE="radio" NAME="sexe" VALUE="F"> Fminin
<INPUT TYPE="radio" NAME="sexe" VALUE="?"
CHECKED> Ne sait pas
<BR>Photo :
<INPUT TYPE="file" NAME="photo" VALUE="" SIZE="50">
<BR>Couleurs prfres :
<INPUT TYPE="checkbox" NAME="couleurs[bleu]"> Bleu
<INPUT TYPE="checkbox" NAME="couleurs[blanc]"> Blanc
<INPUT TYPE="checkbox" NAME="couleurs[rouge]"> Rouge
<INPUT TYPE="checkbox" NAME="couleurs[nesaitpas]" CHECKED>
Ne sait pas
<BR>Langue :
<SELECT NAME="langue">
<OPTION VALUE="E">Espagnol
<OPTION SELECTED VALUE="F">Franais
<OPTION VALUE="I">Italien
</SELECT>
<BR>Fruits prfrs :<BR>
<SELECT NAME="fruits[]" MULTIPLE SIZE="8">
<OPTION VALUE="A">Abricots
<OPTION VALUE="C">Cerises
<OPTION VALUE="F">Fraises
<OPTION VALUE="P">Pches

ENI Editions - All rigths reserved - 19 -


<OPTION SELECTED VALUE="?">Ne sait pas
</SELECT>
<BR>Commentaire :<BR>
<TEXTAREA NAME="commentaire" ROWS="4" COLS="50"></TEXTAREA>
<BR>
<INPUT TYPE="hidden" NAME="invisible" VALUE="123"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
<INPUT TYPE="image" NAME="valider"
SRC="valider.gif" WIDTH="23" HEIGHT="34">
<INPUT TYPE="reset" NAME="effacer" VALUE="Effacer">
<INPUT TYPE="button" NAME="action" VALUE="Ne fait rien">
</FORM>
</BODY>
</HTML>

Rsultat

Rsultat

$_POST :
nom = HEURTEL
mot_de_passe = olivier
sexe = M
photo = D:\Photos\identit.jpg
couleurs =
bleu = on
rouge = on
langue = F
fruits =
0 = A
1 = F
commentaire = Consultant en systme d'information
invisible = 123
OK = OK

Mme exemple avec un tableau

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="traitement.php" METHOD="POST">
Nom :

- 20 - ENI Editions - All rigths reserved


<INPUT TYPE="text" NAME="saisie[nom]" VALUE=""
SIZE="20" MAXLENGTH="20">
Mot de passe :
<INPUT TYPE="password" NAME="saisie[mot_de_passe]" VALUE=""
SIZE="20" MAXLENGTH="20">
<BR>Sexe :
<INPUT TYPE="radio" NAME="saisie[sexe]" VALUE="M"> Masculin
<INPUT TYPE="radio" NAME="saisie[sexe]" VALUE="F"> Fminin
<INPUT TYPE="radio" NAME="saisie[sexe]" VALUE="?"
CHECKED> Ne sait pas
<BR>Photo :
<INPUT TYPE="file" NAME="saisie[photo]" VALUE="" SIZE="50">
<BR>Couleurs prfres :
<INPUT TYPE="checkbox" NAME="saisie[couleurs][bleu]"> Bleu
<INPUT TYPE="checkbox" NAME="saisie[couleurs][blanc]"> Blanc
<INPUT TYPE="checkbox" NAME="saisie[couleurs][rouge]"> Rouge
<INPUT TYPE="checkbox" NAME="saisie[couleurs][nesaitpas]"
CHECKED> Ne sait pas
<BR>Langue :
<SELECT NAME="saisie[langue]">
<OPTION VALUE="E">Espagnol
<OPTION SELECTED VALUE="F">Franais
<OPTION VALUE="I">Italien
</SELECT>
<BR>Fruits prfrs :<BR>
<SELECT NAME="saisie[fruits][]" MULTIPLE SIZE="8">
<OPTION VALUE="A">Abricots
<OPTION VALUE="C">Cerises
<OPTION VALUE="F">Fraises
<OPTION VALUE="P">Pches
<OPTION SELECTED VALUE="?">Ne sait pas
</SELECT>
<BR>Commentaire :<BR>
<TEXTAREA NAME="saisie[commentaire]" ROWS="4" COLS="50"></TEXTAREA>
<BR>
<INPUT TYPE="hidden" NAME="saisie[invisible]"
VALUE="123"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
<INPUT TYPE="image" NAME="valider"
SRC="valider.gif" WIDTH="23" HEIGHT="34">
<INPUT TYPE="reset" NAME="effacer" VALUE="Effacer">
<INPUT TYPE="button" NAME="action" VALUE="Ne fait rien">
</FORM>
</BODY>
</HTML>

Rsultat

$_POST :
saisie =
nom = HEURTEL
mot_de_passe = olivier
sexe = M
photo = D:\Photos\identit.gif
couleurs =
bleu = on
rouge = on
langue = F
fruits =
0 = A
1 = F
commentaire = Consultant en systme d'information
invisible = 123
OK = OK

ENI Editions - All rigths reserved - 21 -


Construireunformulairedynamiquement

Comme tout le reste de la page, tout ou partie d'un formulaire peut tre construit dynamiquement. Trois cas
sontabordsdanscettesection :

- gnrer la totalit du formulaire ;

- gnrer des valeurs initiales dans les zones de saisie ;

- gnrer une liste d'options.

Gnrerlatotalitduformulaire

Exemple

<?php
echo "<FORM ACTION=\"saisie.php\" METHOD=\"POST\">";
echo "Nom : <INPUT TYPE=\"text\" NAME=\"nom\"><BR>";
echo "<INPUT TYPE=\"submit\" NAME=\"OK\" VALUE=\"OK\">";
echo "</FORM>";
?>

Cetexempleneprsentepasungrandintrtcariln'yariendevraimentdynamiquedansleformulaire :autant
mettrelecodeHTMLdirectement,c'estpluslisible.

Unetelleapprochepeutnanmoinstrepratiques'ilexisteunedescriptionduformulairesousuneformeousous
uneautre.

En effet, dans l'exemple suivant, nous supposons que nous rcuprons (dans un fichier, dans une base...) une
description du formulaire sous la forme d'un tableau deux dimensions : chaque ligne du tableau contient une
descriptiondelazonesouslaformed'untableauavecletitre,letype,lenometlavaleur.

Exemple :

<?php
// tableau contenant la description du formulaire
$formulaire = array(
array("Nom : ","text","nom","HEURTEL"),
array("","submit","OK","OK") );
// gnration d'un formulaire l'aide d'une boucle sur le tableau
echo "<FORM ACTION=\"saisie.php\" METHOD=\"POST\">\n";
foreach($formulaire as $zone) {
echo "$zone[0]<INPUT TYPE=\"$zone[1]\"
NAME=\"$zone[2]\" VALUE=\"$zone[3]\"><BR>\n";
}
echo "</FORM>\n";
?>

Rsultat dans le source du navigateur

<FORM ACTION="saisie.php" METHOD="POST">


Nom : <INPUT TYPE="text" NAME="nom" VALUE="HEURTEL"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK"><BR>
</FORM>

Notez la prsence des squences \n, dans le code PHP, qui permettent d'avoir des retours la ligne dans le
sourcedelapage.

Gnrerdesvaleursinitialesdansleszonesdesaisie

Nousavonsdjtudicettepossibilitdansdiffrentsexemples.

Exemple

ENI Editions - All rigths reserved - 1-


<FORM ACTION="saisie.php" METHOD="POST">
Nom : <INPUT TYPE="text" NAME="nom"
VALUE="<?php echo $nom ?>"><BR>
<INPUT TYPE="submit"NAME="OK" VALUE="OK">
</FORM>

Ici,noussupposonsque$nomestunevariableinitialiseparailleursdanslescriptPHP.

Gnrerunelisted'options

Du code PHP peut tre utilis pour gnrer des listes d'options, soit dans une zone <SELECT> (liste slection
unique ou multiple), soit dans une zone <INPUT> de type radio (groupe de boutons radio), soit dans une zone
<INPUT>detypecheckbox(casecocher).

Les donnes affiches proviennent trs souvent d'une base de donnes et il est intressant de pouvoir
construirecettezoneduformulairedynamiquementpartirdesdonnesextraitesdelabase.

Exemple avec une liste slection multiple

<?php
// liste des fruits afficher dans la liste, sous la forme d'un tableau
// associatif donnant le code du fruit (cl du tableau) et l'intitul
// du fruit ; nous verrons ultrieurement comment rcuprer ces informations
// dans une base
$fruits_du_march = array(
"A" => "Abricots",
"C" => "Cerises",
"F" => "Fraises",
"P" => "Pches",
"?" => "Ne sait pas");
// liste des fruits prfrs de l'utilisateur, sous la
// forme d'un tableau donnant le code des fruits concerns
// l encore, cette information pourra venir d'une base ou d'un autre cran
$fruits_prfrs = array("A","F");
?>
<!-- construction du formulaire -->
<FORM ACTION="saisie.php" METHOD="POST">
Fruits prfrs :<BR>
<SELECT NAME="fruits[]" MULTIPLE SIZE="8">
<?php
// code PHP gnrant la partie dynamique du formulaire
// parcourir la liste afficher et rcuprer le code et l'intitul
foreach($fruits_du_march as $code => $intitul) {
// dterminer si la ligne doit tre slectionne
// - oui si le code figure dans la liste des fruits
// prfrs de l'utilisateur => recherche de $code
// dans $fruits_prfrs avec la fonction in_array
// - si c'est le cas, mettre la clause SELECTED dans
// la balise OPTION, sinon ne rien mettre
$slection = in_array($code,$fruits_prfrs)?
"SELECTED":"";
// gnrer la balise OPTION avec la variable $code pour
// l'option VALUE, la variable $slection pour
// l'indication de slection et la variable $intitul
// pour le texte affich dans la liste
echo "<OPTION VALUE=\"$code\" $slection>$intitul\n";
}
?>
</SELECT>
<INPUT TYPE="submit" NAME="OK" VALUE="OK"><BR>
</FORM>

Rsultat l'cran (affichage initial)

- 2- ENI Editions - All rigths reserved


Rsultat dans le source du navigateur

<!-- construction du formulaire -->


<FORM ACTION="saisie.php" METHOD="POST">
Fruits prfrs :<BR>
<SELECT NAME="fruits[]" MULTIPLE SIZE="8">
<OPTION VALUE="A" SELECTED>Abricots
<OPTION VALUE="C" >Cerises
<OPTION VALUE="F" SELECTED>Fraises
<OPTION VALUE="P" >Pches
<OPTION VALUE="?" >Ne sait pas
</SELECT>
<INPUT TYPE="submit" NAME="OK" VALUE="OK"><BR>
</FORM>

Cetexempleesttrsfacileadaptersil'optionVALUEn'estpasutilise.

Exemple avec une liste slection unique

<?php
// liste des langues afficher dans la liste, sous la
// forme d'un tableau associatif donnant le code de
// la langue (cl du tableau) et l'intitul de la langue
$langues_disponibles = array(
"E" => "Espagnol",
"F" => "Franais",
"I" => "Italien");
// code de la langue de l'utilisateur
$langue = "F";
?>
<!-- construction du formulaire -->
<FORM ACTION="saisie.php" METHOD="POST">
Langue :<BR>
<SELECT NAME="langue">
<?php
// code PHP gnrant la partie dynamique du formulaire
// parcourir la liste afficher et rcuprer le code
// et l'intitul
foreach($langues_disponibles as $code => $intitul) {
// dterminer si la ligne doit tre slectionne
// - oui si le code est gal au code de la langue de
// l'utilisateur
// - si c'est le cas, mettre la clause SELECTED dans
// la balise OPTION, sinon ne rien mettre
$slection = ($code == $langue)?"SELECTED":"";
// gnrer la balise OPTION avec la variable $code pour
// l'option VALUE, la variable $slection pour
// l'indication de slection et la variable $intitul
// pour le texte affich dans la liste
echo "<OPTION VALUE=\"$code\" $slection>$intitul\n";
}
?>
</SELECT>
<INPUT TYPE="submit" NAME="OK" VALUE="OK"><BR>
</FORM>

Rsultat l'cran (affichage initial)

ENI Editions - All rigths reserved - 3-


Rsultat dans le source du navigateur

<!-- construction du formulaire -->


<FORM ACTION="saisie.php" METHOD="POST">
Langue :<BR>
<SELECT NAME="langue">
<OPTION VALUE="E" >Espagnol
<OPTION VALUE="F" SELECTED>Franais
<OPTION VALUE="I" >Italien
</SELECT>
<INPUT TYPE="submit" NAME="OK" VALUE="OK"><BR>
</FORM>

Des techniques similaires peuvent tre utilises pour construire une liste de cases cocher, un groupe de
boutonsradio...

- 4- ENI Editions - All rigths reserved


Contrlerlesdonnessaisies

Vued'ensemble

Danslapremirepartiedecechapitre,nousavonsvucommentrcuprerlesdonnessaisies.

Ensuite, il faut vrifier que les donnes saisies sont correctes, c'estdire qu'elles respectent les rgles de
gestiondfiniespourl'application.

L'objectif de cette partie est de vous fournir quelques pistes sur les techniques couramment utilises en PHP
pour cette vrification. Une autre approche possible consiste raliser un contrle en JavaScript dans le
navigateur,l'intrttantd'viterunalleretretouravecleserveur.

Pour illustrer les diffrents cas, nous allons utiliser le formulaire suivant, qui ne contient volontairement aucune
valeurpardfaut(notezlecasdelalanguepourlaquellelapremireoptionestunelignevide).

Exemple

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="traitement.php" METHOD="POST">
Nom :
<INPUT TYPE="text" NAME="nom" VALUE=""
SIZE="20" MAXLENGTH="20">
Mot de passe :
<INPUT TYPE="password" NAME="mot_de_passe" VALUE=""
SIZE="20" MAXLENGTH="20">
<BR>Date de naissance (JJ/MM/AAAA) :
<INPUT TYPE="text" NAME="date_naissance" VALUE=""
SIZE="10" MAXLENGTH="10">
<BR>Sexe :
<INPUT TYPE="radio" NAME="sexe" VALUE="M"> Masculin
<INPUT TYPE="radio" NAME="sexe" VALUE="F"> Fminin
<BR>Couleurs prfres :
<INPUT TYPE="checkbox" NAME="couleurs[bleu]"> Bleu
<INPUT TYPE="checkbox" NAME="couleurs[blanc]"> Blanc
<INPUT TYPE="checkbox" NAME="couleurs[rouge]"> Rouge
<BR>Langue :
<SELECT NAME="langue">
<OPTION>
<OPTION VALUE="E">Espagnol
<OPTION VALUE="F">Franais
<OPTION VALUE="I">Italien
</SELECT>
<BR>Fruits prfrs :<BR>
<SELECT NAME="fruits[]" MULTIPLE SIZE="8">
<OPTION VALUE="A">Abricots
<OPTION VALUE="C">Cerises
<OPTION VALUE="F">Fraises
<OPTION VALUE="P">Pches
</SELECT>
<BR>Commentaire :<BR>
<TEXTAREA NAME="commentaire" ROWS="4" COLS="50"></TEXTAREA>
<BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

Rsultat

ENI Editions - All rigths reserved - 1-


Dansunepremirepartieduscripttraitement.php,lesvaleurssaisiessontrcupresdelamaniresuivante :

<?php
$nom = $_POST["nom"];
$mot_de_passe = $_POST["mot_de_passe"];
$date_naissance = $_POST["date_naissance"];
$sexe = $_POST["sexe"];
$couleurs = $_POST["couleurs"]; // tableau
$langue = $_POST["langue"];
$fruits = $_POST["fruits"]; // tableau
$commentaire = $_POST["commentaire"];
echo "\$nom = $nom<BR>";
echo "\$mot_de_passe = $mot_de_passe<BR>";
echo "\$date_naissance = $date_naissance<BR>";
echo "\$sexe = $sexe<BR>";
echo "\$couleurs = $couleurs<BR>";
echo "\$langue = $langue<BR>";
echo "\$fruits = $fruits<BR>";
echo "\$commentaire = $commentaire<BR>";
?>

Vrificationsclassiques

Nettoyagedesespacesquitranent

Pourleszonesensaisielibre(<INPUT>detypetext ou password, <TEXTAREA>),lafonction trim(cf.chapitre


Constantes, variables, types et tableaux Manipulation des chanes de caractres) peut tre utilise pour
supprimerles"blancs"indsirablesendbutet/ouenfindechane.

Exemple

$nom = trim($_POST["nom"]);
$mot_de_passe = trim($_POST["mot_de_passe"]);
$date_naissance = trim($_POST["date_naissance"]);
$commentaire = trim($_POST["commentaire"]);

Zonesobligatoires

Leformulaireprcdent,surunesaisievide,donnelersultatsuivant :

$nom =
$mot_de_passe =

- 2- ENI Editions - All rigths reserved


$date_naissance =
$sexe =
$couleurs =
$langue =
$fruits =
$commentaire =

Testersiunezoneobligatoireestsaisieservletrssimple :ilsuffitdetestersilavariableassociecontient
unevaleur.

Exemple

if ($variable == "") {
// $variable est non saisi, faire quelque chose
}

Il peut aussi tre tentant de raliser un test du type if (! $variable) en se souvenant qu'une chane vide est
quivalente FALSE. Cette approche n'est gnralement pas fiable, car une valeur saisie gale 0 sera aussi
considrecommemauvaise(car0estaussiquivalentFALSE).

Longueurmaximumd'unechane

Pour les zones en saisie libre, la longueur des informations saisies peut tre contrle avec la fonction strlen
(cf.Constantes,variables,typesettableauxManipulationdeschanesdecaractres).

Exemple

if (strlen($variable) > limite) {


// $variable est trop long, faire quelque chose
}

L'option MAXLENGTH de la balise INPUT permet un contrle complmentaire au moment de la saisie (c'est le
navigateurquis'encharge).

CaractresautorisspourunechaneFormat

Encasdebesoin,l'utilisationdesexpressionsrgulires(cf.chapitreConstantes,variables,typesettableaux
Manipulationdeschanesdecaractres)permetdecontrlertrsfacilementqueseulscertainscaractressont
prsentsetventuellementquelachanesaisierespecteunformatspcifique.

titre d'exemple, supposons que le mot de passe doit vrifier la rgle suivante : commencer par une lettre,
suiviedelettres,dechiffresoudescaractres_#*$avecunelongueurminimalede4.

Exemple

if (! eregi("^[a-z][a-z0-9_#*$]{3,}",$mot_de_passe)) {
// Mot de passe non valide
}

Quelquesexplicationssurl'expressionrgulireutilise(^[a-z][a-z0-9_#*$]{3,}) :

- eregi autoris indiffremment les majuscules et minuscules

- ^ = commence par ...

- [a-z] = une lettre entre a et z (ou A et Z car eregi est utilise) ...

- [a-z0-9_#*$]{3,} = suivi d'au moins 3 ({3,}) caractres parmi ceux indiqus: a z (et donc A Z), 0 9 et les
caractres _#*$.

D'autresexemplessontprsentsdanslasuitedecettepartieaveclesdatesetlesnombres.

Validitd'unedatePlagedevaleurs

ENI Editions - All rigths reserved - 3-


Gnralement,deuxvrificationsdoiventtreralisessurunedate :

- respect d'un format (JJ/MM/AAAA par exemple) ;

- validit (pas de 32/13/2001).

Lavrificationdurespectduformatetdescaractresautorissesttrssimpleavecuneexpressionrgulire.

Exemple

if (! ereg("^[0-9]{1,2}/[0-9]{1,2}/[0-9]{4}$",
$date_naissance)) {
// mauvais format pour la date
}

Quelquesexplicationssurl'expressionrgulireutilise(^([0-9]{1,2})/
([0-9]{1,2})/([0-9]{4})$) :

- ^ = commence par ...

- [0-9]{1,2} = un ou deux chiffres ...

- / = suivi du caractre "/" ...

- [0-9]{1,2} = un ou deux chiffres ...

- / = suivi du caractre "/" ...

- [0-9]{4} = suivi de quatre chiffres ...

- $ = suivi de ... rien du tout La chane doit se terminer immdiatement.

Pour vrifier la validit de la date, il est possible d'utiliser la fonction checkdate (cf. chapitre Constantes,
variables,typesettableauxManipulationdesdates).

Dansunpremiertemps,ilfautrcuprerlescomposantesdeladatesaisie.Plusieurssolutionssontutilisables :

- avec la fonction explode :

$jma = explode("/",$date_naissance);
// $jma[0] contient le jour
// $jma[1] contient le mois
// $jma[2] contient l'anne
if (! checkdate($jma[1],$jma[0],$jma[2])) {
// date non valide
}

- variante avec les fonctions explode et list :

list($jour,$mois,$anne) = explode("/",$date_naissance);
// rcupration des composantes dans des variables indpendantes
if (! checkdate($mois,$jour,$anne)) {
// date non valide
}

- avec le troisime paramtre de la fonction ereg qui permet de rcuprer des portions de la chane, et cela
directement dans le test de conformit du format :

if (! ereg("^([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})$",
$date_naissance,$jma)) {
// mauvais format pour la date

- 4- ENI Editions - All rigths reserved


} else {
// bon format pour la date
// $jma contient les diffrentes composantes avec des
// indices diffrents par rapport l'exemple prcdent
// $jma[1] contient le jour
// $jma[2] contient le mois
// $jma[3] contient l'anne
if (! checkdate($jma[2],$jma[1],$jma[3])) {
// date non valide
}
}

Pour tester la plage de valeurs, le plus simple est de faire une comparaison numrique (ou alphabtique) sur un
nombre(ouunechane)construitsurlaformeAAAAMMJJ (20010828pourle28/08/2001).

Exemple

// rcuprer les composantes de la date


list($jour,$mois,$anne) = explode("/",$date_naissance);
// contruire une chane au format AAAAMMJJ
$AAAAMMJJ = sprintf("%04d%02d%02d",$anne,$mois,$jour);
// dfinir les dates mini et maxi selon le mme format
$date_mini = "19000101"; // 01/01/1900
$date_maxi = date("Ymd"); // date du jour
// comparer
if ($AAAAMMJJ < $date_mini or $AAAAMMJJ > $date_maxi) {
// date hors de la plage autorise
}

Validitd'unnombrePlagedevaleurs

Plusieurstechniquespeuventtreutilisespourvrifierqu'unnombreestbienform :

- les expressions rgulires ;

- la fonction is_numeric ;

- la conversion de la saisie et le test du rsultat obtenu.

Exemple avec les expressions rgulires

// vrifier qu'une saisie est un nombre entier


ereg("^\-?[0-9]+$",$variable)
// vrifier qu'une saisie est un nombre entier et contrler
// le nombre de chiffres (entre 1 et 3 par exemple)
ereg("^[0-9]{1,3}$",$variable)
// vrifier qu'une saisie est un nombre dcimal (sur cet
// exemple la virgule et le point sont accepts comme sparateur dcimal)
ereg("^\-?[0-9]*[\.|,]?[0-9]*$",$variable)
// autorise .1, -.1 mais aussi -., - et .
// possible dans ce cas de forcer la saisie d'un chiffre avant la virgule
ereg("^\-?[0-9]+[\.|,]?[0-9]*$",$variable)
// plus de problme avec -., - et . mais .1 et -.1 ne
// sont plus autoriss non plus
// ventuellement, combiner le premier test avec un deuxime
// qui vrifie que $variable n'est pas gal -, -. ni .
ereg("^\-?[0-9]*[\.|,]?[0-9]*$",$variable)
and !in_array($variable,array("-","-.","."))

Pourlaplagedevaleurs,unsimpletestdutypesuivantsuffit.

Exemple

if ($variable < minimum or $variable > maximum) {


// $variable en dehors de la plage autorise
}

Validitd'uneadresseemail

ENI Editions - All rigths reserved - 5-


L encore, les expressions rgulires vont tre utiles. Ce sujet a fait l'objet de beaucoup d'tudes et de
nombreusessolutionspeuventtretrouvessurInternet.

Unedesmeilleuressolutionssembletrelasuivante :

eregi("^[0-9a-z]([-_.]?[0-9a-z])*@
[0-9a-z]([-.]?[0-9a-z])*\.[a-z]{2,3}$",$adresse)

Quelquesexplicationssurl'expressionrgulireutilise :

- eregi autorise indiffremment les majuscules et les minuscules.

- ^ = commence par ...

- [0-9a-z] = une lettre ou un chiffre ...

- ([-_.]?[0-9a-z])* = suivi d'une ou plusieurs squences commenant chacune optionnellement par un tiret, un
soulign ou un point suivi de lettre ou de chiffres...

- @@ = suivi d'un @.

- [0-9a-z] = suivi d'une lettre ou d'un chiffre...

- ([-.]?[0-9a-z])* = suivi d'une ou plusieurs squences commenant chacune optionnellement par un tiret ou un
point suivi de lettres ou de chiffres.

- \. = suivi d'un point...

- [a-z]{2,3} = suivi de deux ou trois lettres...

- $ = suivi de ... rien du tout. La chane doit se terminer.

L'expression rgulire permet de vrifier que l'adresse est syntaxiquement correcte, mais pas de contrler qu'elle existe
rellement.

- 6- ENI Editions - All rigths reserved


Lesproblmessurlesdonnessaisies

Lafonctionnalitde"magicquotes"

PHPproposeunefonctionnalit,appele"magicquotes",dontl'objectifprincipalestdersoudreunproblmeli
l'enregistrement des donnes dans une base de donnes en effectuant un encodage sur les donnes saisies
dansunformulaire.
Cettefonctionnalitpeutrapidementdeveniruncassettesielleestmalpriseencompte.

Dequois'agitil ?

Siladirectivedeconfigurationmagic_quotes_gpceston,touteslesdonnesarrivantparunemthodeGETou
POST (ou encore, nous le verrons plus tard, par un cookie) sont automatiquement encodes avec un antislash
(\)devantlescaractresapostrophe('),guillemet(")etbiensrantislash(\).

Le suffixe gpc de la directive correspond Get, Post et Cookie.

ConsidronslescriptPHPsaisie.phpsuivantquisecontented'afficherunezonedesaisiepuis,derafficherla
valeursaisiedanslazoneduformulaireetdirectementdanslapage.

Exemple

<?php
// rcuprer la donnes saisie
$saisie = isset($_POST["saisie"])?$_POST["saisie"]:"";
// la rafficher ensuite dans la zone de saisie et directement dans la page...
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Saisie : <INPUT TYPE="text" NAME="saisie"
VALUE="<?php echo $saisie; ?>"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<?php
echo $saisie;
?>
</BODY>
</HTML>

Rsultat

- Affichage initial :

- Saisie d'une valeur :

- Rsultat aprs un clic sur le bouton OK si magic_quotes_gpc = on :

- Rsultat aprs un clic sur le bouton OK si magic_quotes_gpc = off :

ENI Editions - All rigths reserved - 1-


- Saisie d'une autre valeur (prsentant un ") :

- Rsultat aprs un clic sur le bouton OK si magic_quotes_gpc = on :

Dans ce dernier cas, le problme de raffichage dans la zone de saisie n'est pas li la fonctionnalit "magic
quotes" mais un autre problme abord dans le prochain point (cf. 2. Autres problmes sur les donnes
saisies).

Ce principe d'encodage "magic quotes" est effectivement intressant, notamment devant l'apostrophe, si les
donnes sont destines tre enregistres dans une base SQL (Struc tured Query Language). En effet, en
SQL,ledlimiteurdechanedecaractresestl'apostrophe siunerequteenvoielachane'c'est l't'la
base,cettedernirevainterprter 'c'commeunechaneetnesaurapasquoifairedureste(est l't') :un
messaged'erreurseraretournparlabase.

Pourrglerceproblme,ilfautindiquerlabasequelesapostrophesl'intrieurdelachanenesontpasdes
dlimiteurs de la chane, gnralement en les faisant prcder d'un caractre "magique" ("d'chappement") : \
pour MySQL ou apostrophe (') pour d'autres bases comme Oracle, Sybase ou Microsoft SQL Server. Les bonnes
valeurs envoyer sont donc 'c\'est l\'t' pour MySQL ou 'c''est l''t' pour d'autres bases de
donnes.

La fonctionnalit "magic quotes" est intressante si la donne saisie est destine tre enregistre dans une
base MySQL (l'encodage est automatique), mais pose des problmes si la donne saisie est destine tre
enregistredansunebaseOracleouSQLServer(l'encodagen'estpaslebon)ousimplementaffichedansune
pageHTML(l'encodageestinutile).

Du point de vue du caractre d'chappement utiliser, PHP propose la directive magic_quotes_sybase si


cettedirectiveeston,PHPutiliselecaractred'chappementapostrophe(')laplaceducaractreantislash
(\).Deplus,danscecas,seullecaractreapostrophe(')estchapp(lesautrescaractresneposentpasde
problme).Aveccettenouvelledirective,notreproblmed'enregistrementdansunebaseOracle,SQLServerou
Sybaseestrsolu.

Danslapratique,cettefonctionnalit"magicquotes"posedeuxproblmes :

- Si la donne est la fois destine tre affiche dans la page et enregistre dans une base, il y a un problme: avec
l'affichage si "magic quotes" est actif, avec l'enregis trement dans la base si "magic quotes" est inactif.

- Le dveloppeur ne matrise pas forcment la configuration de PHP dans l'environnement d'exploitation: il peut donc
crire du code qui fonctionne dans son environnement de dveloppement (avec une certaine configuration de "magic
quotes"), mais qui risque de ne plus fonctionner dans l'environnement d'exploitation o la configuration est peuttre
diffrente.

Nous allons donc voir comment grer correctement cette fonctionnalit et crire un code indpendant de la
configuration.

Pour grer les besoins contradictoires de l'affichage et de l'enregistrement dans la base, PHP propose deux

- 2- ENI Editions - All rigths reserved


fonctionsencomplment :addslashesetstripslashes.

Lafonctionaddslashesprendenparamtreunechanedecaractresetretournecettechaneenajoutantun\
devant les caractres ', " et \ (si magic_quotes_sybase est off) ou le ' devant ' (si magic_quotes_sybase
eston).

Lafonctionstripslashesprendenparamtreunechanedecaractresetretournecettechaneensupprimant
le \ devant les caractres ', " et \ (si magic_quotes_sybase est off) ou le ' devant ' (si
magic_quotes_sybaseeston).

Exemple

<?php
echo addslashes("c'est l't")."<BR>";
echo stripslashes("c\'est l\'t")."<BR>";
?>

Rsultat (en supposant que magic_quotes_sybase = off)

c\'est l\'t
c'est l't

Cesfonctionsvonttreutilesdanslesdeuxcassuivants :

- Si vous avez une donne dans une variable, qui n'a pas dj t encode, et que cette donne doive tre enregistre
dans la base, il est conseill d'appeler addslashes pour effectuer l'encodage adapt.

- Si vous avez une donne dans une variable, qui a t encode (manuellement ou automatiquement), et que vous
souhaitiez l'afficher dans une page HTML, il faut appeler stripslashes pour enlever l'encodage.

Il ne faut pas appeler addslashes ou stripslashes au hasard sur des variables dj encodes en ce qui concerne
addslashes ou non encodes en ce qui concerne stripslashes.

Exemple

<?php
// utilisation de la fonction addslashes sur une donne dj encode
echo addslashes("c\'est l\'t")."<BR>";
// utilisation de la fonction stripslashes sur une donne non encode
echo stripslashes("c'est l't")."<BR>";
// pas grave
echo stripslashes("d:\photos\identit.gif")."<BR>";
// mauvais
?>

Rsultat (en supposant que magic_quotes_sybase = off)

c\\\'est l\\\'t
c'est l't
d:photosidentit.gif

Il est donc important de ne pas appeler addslashes systmatiquement avant un enregistrement dans la base,
oustripslashessystmatiquementavantunaffichagedansunepageHTML.Ilfautsavoird'ovientladonne
etsielleestounondjencodeparlafonctionnalit"magicquotes".

IlexistedeuxsituationssimplessivousmatrisezlaconfigurationdePHP :

- Vous tes certain que magic_quotes_gpc = off : dans ce cas, vous pouvez afficher les donnes issues des
formulaires sans soucis (pas besoin de la fonction stripslashes) et devez appeler addslashes avant tout
enregistrement dans la base.

- Vous tes certain que magic_quotes_gpc = on et que magic_quotes_sybase est adapt la base que vous
utilisez (off pour MySQL ou on pour Oracle, Sybase ou Microsoft SQL Server): dans ce cas, vous devez appeler

ENI Editions - All rigths reserved - 3-


stripslashes avant tout affichage des donnes issues des formulaires mais vous pouvez les enregistrer
directement dans la base (pas besoin de la fonction addslashes). Par contre, un problme peut se poser pour des
donnes qui ne viennent pas d'un formulaire.

En effet, si vous initialisez une variable du type $valeur = "c'est l't", cette variable vacontenir une
information qui n'a pas subi l'encodage automatique de la fonctionnalit "magic quotes"; un moment ou un autre, il
faudra encoder la donne avec addslashes si elle doit tre enregistre dans la base...

Gestionintelligenteetportable

SivousnematrisezpaslaconfigurationdePHPetquevoussouhaitiezavoiruncodeportable,ilfautprocder
autrement.

Voicilasolutionlaplussimple :

- Dcider une fois pour toutes que toute variable PHP contient une donne qui est soit encode, soit non encode; la
version "toute variable PHP contient une donne non encode" est prconise.

- Faire le traitement ncessaire, lors de l'affectation d'une variable par une donne qui vient de l'extrieur pour s'assurer
qu'elle ne contient pas d'encodage "magic quotes".

- Ne rien faire visvis de l'encodage "magic quotes" (les variables ne contiennent pas de caractre \ superflu) lors de
l'affichage d'une variable dans une page HTML (directement ou dans un formulaire).

- Faire l'encodage ncessaire lors de l'enregistrement d'une variable dans une base.

Leschmasuivantprsentelessourcesdedonnesextrieuresqu'ilvafalloirgreraumomentdel'alimentation
desvariables :

Nousavonsdjvuquetoutcequivenaitd'unformulaire(mthode GET ouPOST), d'uneURL (mthodeGET) ou


d'un cookie, et que nous allons dsormais appeler donne GPC, tait sous l'influence de la directive
magic_quotes_gpc(cf.chapitreGrerlessessionspourl'URLetlesCookies) :aumomentdel'alimentationd'une
variable partir d'une de ces sources, pour respecter notre principe de fonctionnement, il faut enlever
l'encodage"magicquotes",si"magicquotes"estactif,etnerienfairesi"magicquotes"estdsactiv.

Un tel traitement est possible grce la fonctionget_magic_quotes_gpc qui retourne 1 (quivalent TRUE) si
lafonctionnalit"magicquotes"estactiveet0(quivalentFALSE)sinon.

Ilestdoncpossibled'crireunefonctionquiserasystmatiquementappelelorsdelarcuprationd'unedonne
GPCpourenleverl'encodage"magicquotes"sicedernierestactif.

Exemple

<?php
function supprimer_encodage_MQ($valeur) {
// si magic quotes est actif, retourner
// la valeur aprs suppression de l'encodage
// (=> appel stripslashes), sinon, retourner

- 4- ENI Editions - All rigths reserved


// la valeur
return (get_magic_quotes_gpc())?
stripslashes($valeur):$valeur;
}
?>

Appeler uniquement cette fonction sur des donnes GPC pour ne pas risquer d'enlever des caractres d'chappement qui ne
sont pas lis un encodage "magic quotes".

Larcuprationdesdonnesd'unformulaireprendalorslastructuresuivante :

<?php
// inclusion du fichier qui contient les dfinitions de nos
// fonctions gnrales
include("fonctions.inc");
// rcupration des valeurs saisies dans le formulaire
$nom = supprimer_encodage_MQ(trim($_POST["nom"]));
$mot_de_passe = supprimer_encodage_MQ(
trim($_POST["mot_de_passe"]));
$date_naissance = supprimer_encodage_MQ(
trim($_POST["date_naissance"]));
// ...
?>

Pourleszonesquinesontpasensaisielibre(listeslectionuniqueoumultiple,groupedeboutonsradio,cases
cocher),iln'estpasforcmentncessaired'appelerlafonctioncarladonneretourneestmatriseetvous
pouvez faire en sorte qu'elle ne contienne pas d'apostrophe dans le doute, appelezla systmatiquement (en
l'adaptantaucasolavariableestuntableau).

Ilesttrssimpled'crireunefonctiongnriquequiregroupel'appeltrimetsupprimer_encodage_MQ.

Exemple

<?php
function supprimer_encodage_MQ($valeur) {
// si magic quotes est actif, retourner
// la valeur aprs suppression de l'encodage
// (=> appel stripslashes), sinon, retourner la valeur
return (get_magic_quotes_gpc())?
stripslashes($valeur):$valeur;
}
function valeur_saisie($valeur) {
return supprimer_encodage_MQ (trim($valeur));
}
$nom = valeur_saisie($_POST["nom"]);
// ...
?>

Nous allons voir dans les chapitres Accder aux bases de donnes et Gestion des fichiers que les donnes en
provenance d'une base de donnes ou d'un fichier sont sous l'influence d'une autre directive, appele
magic_quotes_runtime,quiaunfonctionnementidentiquemagic_quotes_gpcetdoncunmodedetraitement
proche.

Pour l'enregistrement dans la base, nous verrons dans le chapitre Accder aux bases de donnes comment
traiterdemaniregnriquelesdonnesavantdelesenvoyerlabasepourviterlesproblmes.

Autresproblmessurlesdonnessaisies

Danslepointprcdent,nousavonsabordunproblmed'affichagedansunezonedeformulairesuitelasaisie
d'unguillemet(").

Rappel

ENI Editions - All rigths reserved - 5-


Rsultat du source de la page dans le navigateur:

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Saisie : <INPUT TYPE="text" NAME="saisie"
VALUE="il dit : \"bonjour !\""><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
il dit : \"bonjour !\"
</BODY>
</HTML>

EnHTML,danslesoptionsdesbalises(VALUE, NAME...),ledlimiteurdechaneestleguillemetetlecaractre\
n'est pas un caractre d'chappement : dans l'option VALUE="il dit : \"bonjour !\"", la squence "il
dit : \"estconsidrecommelavaleurdel'optionetlerestedelachaneestignor.

Autre exemple (saisie posant un problme):

LasaisieOlivier <B>HeurteldonnelemotHeurtelengraslorsdel'affichagedanslapageHTML.

Rsultat du source de la page dans le navigateur:

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Saisie : <INPUT TYPE="text" NAME="saisie"
VALUE="Olivier <B>Heurtel"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
Olivier <B>Heurtel
</BODY>
</HTML>

Lasquence <B>saisieparl'utilisateurseretrouvetellequelledanslesourcedelapageetestdoncinterprte
parlenavigateurcommelabalisedemiseengras.

Autre exemple (saisie posant un problme):

- 6- ENI Editions - All rigths reserved


Unesaisiesurplusieurslignesdanslazone<TEXTAREA>estbienraffichetellequelledanslazonemaissansles
sautsdelignedanslapageHTML.

Rsultat du source de la page dans le navigateur:

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Saisie :<BR>
<TEXTAREA NAME="saisie" COLS="40" ROWS="6">Premire ligne.
Deuxime ligne.
Troisime ligne.</TEXTAREA><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
Premire ligne.
Deuxime ligne.
Troisime ligne.
</BODY>
</HTML>

Le texte est bien prsent avec des sauts de lignes dans le source de la page, mais le saut de ligne, en dehors
d'unezone<TEXTAREA>,n'estpasinterprtparlenavigateur :ilfautmettreunebalise<BR>.

Nous voyons donc apparatre trois problmes relatifs l'affichage dans la page HTML de donnes saisies par
l'utilisateur :

- prsence du caractre guillemet qui peut poser un problme lors de l'utilisation de la donne dans un formulaire (option
VALUE) ;

- prsence de balises HTML valides qui sont interprtes comme telles par le navigateur ;

- non prise en compte des sauts de lignes prsents dans un texte.

Ledeuxime"problme"peutprsenterunintrtsivoussouhaitezoffrirlapossibilitunutilisateuravancde
saisiruntexteavecunpeudemiseenformepourunaffichageultrieurdansunepage.

Pourrsoudrecestroisproblmes,PHPproposequatrefonctions : htmlspecialchars,htmlentities, nl2bret


strip_tags.

Lafonctionhtmlspecialcharsprendunechanedecaractresetlaretourneenremplaantcertainscaractres
parleurquivalentHTML :

Syntaxe

chane htmlspecialchars(chane texte [, entier option [, chane jeu]])

texte

Chanetraiter.

ENI Editions - All rigths reserved - 7-


option

Fonctionnementvisvisdescaractresguillemets(")etapostrophe(').

jeu

Jeudecaractresutiliserpourlaconversion.


Lescaractresconvertissontlessuivants :

Entre Sortie
& &amp;
" &quot;
' &#039;
< &lt;
> &gt;

Le deuxime paramtre permet de prciser le fonctionnement visvis des caractres guillemets (") et
apostrophe(') :

Valeur Comportement
ENT_COMPAT Conversion du guillemet mais pas de l'apostrophe (par dfaut)
ENT_NOQUOTES Aucune conversion
ENT_QUOTES Conversion des deux caractres

Le troisime paramtre permet de dfinir le jeu de caractres utiliser pour la conversion : ISO-8859-1 (par
dfaut),ISO-8859-15,UTF-8,etc.

Lafonctionhtmlentitiesprsenteuncomportementidentiqueceluidehtmlspecialcharsmaispourtousles
caractresayantunquivalentenHTML(caractresaccentusnotamment).

Syntaxe

chane htmlentities (chane texte [, entier option [, chane jeu]]

texte

Chanetraiter.

option

Fonctionnementvisvisdescaractresguillemets(")etapostrophe(').

jeu

Jeudecaractresutiliserpourlaconversion.


Lesdeuximeettroisimeparamtresontlammesignificationquepourlafonctionhtmlspecialchars.

Lafonctionnl2brprendunechaneetretournecettechaneaprsavoirinsrunebaliseHMTLdesautdeligne
devantchaquesautdeligne :labaliseest <br /><(compatibilitXHTML)partirdelaversion4.0.5dePHPet
<br> avant.

Syntaxe

- 8- ENI Editions - All rigths reserved


chane n12br (chane texte)

texte

Chanetraiter.


Enfin, la fonction strip_tags prend une chane de caractres et la retourne aprs avoir supprim toutes les
balisesHTMLqu'ellecontient.

Syntaxe

chane strip_tags (chane texte[, chane balises_autorises])

texte

Chanetraiter.

balises_autorises

Listedesbalisesconserverdanslachane.


Undeuximeparamtrepermetd'indiquerlesbalisesconserver.

Exemple

<?php
echo "// premier texte<BR>\n";
$texte = "Olivier & Co. a dclar : \"c'est l't !\"";
echo $texte."<BR>\n";
echo "// htmlspecialchars<BR>\n";
echo "// - guillemet uniquement<BR>\n";
echo htmlspecialchars($texte,ENT_COMPAT)."<BR>\n";
echo "// - ni guillemet ni apostrophe<BR>\n";
echo htmlspecialchars($texte,ENT_NOQUOTES)."<BR>\n";
echo "// - guillemet et apostrophe<BR>\n";
echo htmlspecialchars($texte,ENT_QUOTES)."<BR>\n";
echo "// htmlsentities<BR>\n";
echo "// - guillemet et apostrophe<BR>\n";
echo htmlentities($texte,ENT_QUOTES)."<BR><BR>\n";
echo "// deuxime texte<BR>\n";
$texte = "<B>Olivier</B> & <U>Co.</U> <TT>a dclar</TT> :
<I>c'est l't !</I>";
echo $texte."<BR>\n";
echo "// strip_tags<BR>\n";
echo "// - toutes les balises<BR>\n";
echo strip_tags($texte)."<BR>\n";
echo "// - conserver &lt;B&gt; et &lt;I&gt;<BR>\n";
echo strip_tags($texte,"<B><I>")."<BR><BR>\n";
echo "// troisime texte (avec sauts de ligne)<BR>\n";
$texte = "Premire ligne.\nDeuxime ligne.\n";
echo $texte."<BR>\n";
echo "// nl2br<BR>\n";
echo nl2br($texte)."<BR>\n";
?>

Rsultat

ENI Editions - All rigths reserved - 9-


Pourlesfonctionsstrip_tagsetnl2br,lecomportementestvisibledanslenavigateur.

Par contre, les substitutions opres par les fonctions htmlentities et htmlspecialschars sont surtout
visiblesdanslesource.

Rsultat du source HTML de la page (les lments concerns sont en gras)

// premier texte<BR>
Olivier & Co. a dclar : "c'est l't !"<BR>
// htmlspecialchars<BR>
// - guillemet uniquement<BR>
Olivier &amp; Co. a dclar : &quot;c'est l't !&quot;<BR>
// - ni guillemet ni apostrophe<BR>
Olivier &amp; Co. a dclar : "c'est l't !"<BR>
// - guillemet et apostrophe<BR>
Olivier &amp; Co. a dclar : &quot;c&#039;est l&#039;t !&quot;<BR>
// htmlsentities<BR>
// - guillemet et apostrophe<BR>
Olivier &amp; Co. a d&eacute;clar&eacute;&nbsp;: &quot;c&#039;est l&#039;
&eacute;t&eacute;&nbsp;!&quot;<BR><BR>
// deuxime texte<BR>
<B>Olivier</B> & <U>Co.</U> <TT>a dclar</TT> :
<I>c'est l't !</I><BR>
// strip_tags<BR>
// - toutes les balises<BR>
Olivier & Co. a dclar :
c'est l't !<BR>
// - conserver &lt;B&gt; et &lt;I&gt;<BR>
<B>Olivier</B> & Co. a dclar :
<I>c'est l't !</I><BR><BR>
// troisime texte (avec sauts de ligne)<BR>
Premire ligne.
Deuxime ligne.
<BR>
// nl2br<BR>
Premire ligne.<br />
Deuxime ligne.<br />
<BR>

Cesfonctionsvontdoncpermettredegrerlesdiffrentsproblmesvoqusprcdemment.
Pour viter tout problme d'affichage dans le navigateur, il est conseill d'effectuer une transformation des
donnesavantoudansl'instructionecho.

Exemple (script o les donnes sont raffiches sans prcaution)

<?php
// inclusion du script contenant la fonction valeur_saisie

- 10 - ENI Editions - All rigths reserved


// dfinie dans le paragraphe a)
include("fonctions.inc");
// rcuprer les donnes saisies
if ( isset($_POST["OK"]) ) {
$saisie1 = valeur_saisie($_POST["saisie1"]);
$saisie2 = valeur_saisie($_POST["saisie2"]);
} else {
$saisie1 = "";
$saisie2 = "";
}
// les rafficher ensuite dans le formulaire et
// directement dans la page...
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Saisie 1 : <INPUT TYPE="text" NAME="saisie1"
VALUE="<?php echo $saisie1; ?>"><BR>
Saisie 2 :<BR>
<TEXTAREA NAME="saisie2" COLS="40" ROWS="6"><?php echo $saisie2; ?>
</TEXTAREA><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<?php
echo $saisie1."<BR>\n";
echo $saisie2."<BR>\n";
?>
</BODY>
</HTML>

Avec saisie

Rsultat (avec les problmes dj rencontrs)

Correction

<?php
// inclusion du script contenant la fonction valeur_saisie
// dfinie dans le point 1. La fonctionnalit de "magic quotes"
include("fonctions.inc");

ENI Editions - All rigths reserved - 11 -


// rcuprer les donnes saisies
if ( isset($_POST["OK"]) ) {
$saisie1 = valeur_saisie($_POST["saisie1"]);
$saisie2 = valeur_saisie($_POST["saisie2"]);
} else {
$saisie1 = "";
$saisie2 = "";
}
// les rafficher ensuite dans le formulaire et directement dans la page...
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Saisie 1 : <INPUT TYPE="text" NAME="saisie1"
VALUE="<?php echo htmlentities($saisie1); ?>"><BR>
Saisie 2 :<BR>
<TEXTAREA NAME="saisie2" COLS="40" ROWS="6"><?php echo
htmlentities($saisie2); ?></TEXTAREA><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<?php
echo htmlentities($saisie1)."<BR>\n";
echo nl2br(htmlentities($saisie2))."<BR>\n";
?>
</BODY>
</HTML>

Rsultat

Aveccetteapproche,lasaisieestrestituetellequelle :sil'utilisateurasaisiunebalise,illaretrouve(celleci
n'estpasinterprteparlenavigateur).

Une autre approche possible pour les balises consiste les supprimer (notamment lors de la rcupration de la
donnesaisie).

Exemple

<?php
// inclusion du script contenant la fonction valeur_saisie
// dfinie dans le point 1. La fonctionnalit de "magic quotes"
include("fonctions.inc");
// rcuprer les donnes saisies sans les balises
if ( isset($_POST["OK"]) ) {
$saisie1 = valeur_saisie(
strip_tags($_POST["saisie1"]));
$saisie2 = valeur_saisie (
strip_tags($_POST["saisie2"]));
} else {
$saisie1 = "";
$saisie2 = "";
}
// les rafficher ensuite dans le formulaire et directement dans la page...
?>

- 12 - ENI Editions - All rigths reserved


<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Saisie 1 : <INPUT TYPE="text" NAME="saisie1"
VALUE="<?php echo htmlentities($saisie1); ?>"><BR>
Saisie 2 :<BR>
<TEXTAREA NAME="saisie2" COLS="40" ROWS="6"><?php echo htmlentities
($saisie2); ?></TEXTAREA><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<?php
echo htmlentities($saisie1)."<BR>\n";
echo nl2br(htmlentities($saisie2))."<BR>\n";
?>
</BODY>
</HTML>

Rsultat (sur la mme saisie que prcdemment)

La fonction nl2br doit tre appele aprs les fonctions htmlentities ou htmlspecialchar. Dans le cas contraire, la
balise <BR> ajoute par nl2br est encode (&lt;BR&gt;) avant d'tre insre dans le source de la page et n'est donc pas
interprte par le navigateur (le texte <BR> apparat dans la page affiche).
La fonction nl2br ne doit pas tre appele pour du texte destin une zone <TEXT-AREA> (sous peine, l encore, d'avoir le
texte <BR> dans la zone).

Synthse

Lagestiondesformulaires,avecl'affichageet/oul'enregistrementdesdonnessaisies,peutrapidementdevenir
uncassettecomptetenudesdiffrentsproblmespotentielsetdesdirectivesdeconfigurationassocies.

Nanmoins,avecunpeuderigueuretdeuxoutroisfonctionscritesunefoispourtoutes,cettegestionpeutse
fairesanssoucis.

Lastratgieprconiseestrsumeparleschmasuivant :

ENI Editions - All rigths reserved - 13 -


Lecasdesbasesdedonnes,desURL,cookiesetfichiersesttraitendtaildansleschapitresultrieurs.

Exemple de fonctions permettant de supprimer l'encodage ventuel li la fonctionnalit "magic quotes":

<?php
function supprimer_encodage_MQ($valeur) {
// si magic quotes est actif, retourner la valeur aprs suppression
// de l'encodage (=> appel stripslashes), sinon, retourner la valeur
return (get_magic_quotes_gpc())?
stripslashes($valeur):$valeur;
}
function valeur_saisie($valeur) {
return supprimer_encodage_MQ (trim($valeur));
}
?>

Une variante possible consiste supprimer les balises saisies par l'utilisateur dans ce cas, il suffit d'appeler la
fonctionstrip_tagsenplus.

Exemple de fonctions permettant d'afficher en scurit une donne dans une page HTML

<?php
function vers_formulaire($valeur) {
// affichage dans un formulaire
// encoder tous les caractres HTML spciaux
// - ENT_QUOTES : dont " et '
return htmlentities($valeur,ENT_QUOTES);
}
function vers_page($valeur) {
// affichage direct dans une page
// 1. encoder tous les caractres HTML spciaux
// - ENT_QUOTES : dont " et '
// 2. transformer les sauts de ligne en <BR>
return nl2br(htmlentities($valeur,ENT_QUOTES));
}
?>

Exemple d'utilisation sur une zone

<?php
// inclusion du script contenant les fonctions dfinies prcdemment
include("fonctions.inc");
// rcuprer la donne saisie
$saisie = isset($_POST["saisie"])?valeur_saisie($_POST["saisie"]):"";
// la rafficher ensuite dans le formulaire et directement dans la page...
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>

- 14 - ENI Editions - All rigths reserved


<FORM ACTION="saisie.php" METHOD="POST">
Saisie : <INPUT TYPE="text" NAME="saisie"
VALUE="<?php echo vers_formulaire($saisie); ?>"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<?php
echo vers_page($saisie)."<BR>\n";
?>
</BODY>
</HTML>

ENI Editions - All rigths reserved - 15 -


Allersuruneautrepagelafindutraitement

lafindutraitementduformulaire,ilpeuttrencessaired'afficheruneautrepage,lasituationpouvantvarier
selonqueleformulaireesttraitparlescriptquil'afficheouparunscriptindpendant.

Variantes possibles:

Redirigerl'utilisateurversuneautrepageencoursdescriptestpossibleenutilisantlafonctionheader.

LafonctionheaderpermetdespcifierunechanequiestenvoyecommeentteHTTPaveclapageHTML.

Nousallonsutiliserl'enttelocationquiredirigelarequteversuneautreadresse.

Syntaxe de la directive location

location: URL absolue ou relative

Syntaxe avec la fonction header

header("location: URL absolue ou relative")

Exemples

// redirection vers un script PHP situ au mme niveau


header("location: erreur.php");
// redirection vers une page HTML situe un sous-niveau
header("location: ./erreur/saisie.htm");
// redirection vers un autre site
header("location: http://www.olivier-heurtel.fr");

Exemple simple d'utilisation sur un script info.php

<?php
// affecter une valeur $nom si un nombre tir alatoirement
// entre 0 et 1 est gal 1
$nom = (rand(0,1)==1)?"Olivier":"";
// tester si $nom est renseign
if ($nom == "") {
// la variable $nom est vide, ce n'est pas normal
// => rediriger l'utilisateur vers une page d'erreur
header("location: erreur.htm");
// interrompre l'excution de ce script
exit;
}
// la variable $nom n'est pas vide, laisser le script se poursuivre
$message = "Bonjour $nom !"; // prparer un message
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<?php
// afficher le message

ENI Editions - All rigths reserved - 1-


echo $message;
?>
</BODY>
</HTML>

Avec page erreur.htm

<HTML>
<HEAD><TITLE>Erreur</TITLE></HEAD>
<BODY>
Le site est actuellement indisponible ; essayez plus tard.<BR>
Merci de votre comprhension.<BR>
<!-- Lien pour une nouvelle tentative -->
<A HREF="info.php">Essayer de nouveau</A>
</BODY>
</HTML>

Statistiquement,unefoissurdeux,l'appelduscriptinfo.phpdonnelersultatsuivant :

Bonjour Olivier !

Etdonc,unefoissurdeux,lesuivant :

Le site est actuellement indisponible ; essayez plus tard.


Merci de votre comprhension.
Essayer de nouveau

La fonction header doit tre appele avant toute instruction (PHP ou HTML) qui a pour effet de commencer construire la
page HTML (c'est en quelque sorte trop tard pour l'en-tte). Un simple espace, dans le script, ou dans un script inclus
(require ou include) provoque la mme erreur.

Exemple d'appel la fonction header qui gnre une erreur

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<?php
// affecter une valeur $nom si un nombre tir alatoirement
// entre 0 et 1 est gal 1
$nom = (rand(0,1)==1)?"Olivier":"";
// tester si $nom est renseign
if ($nom == "") {
// la variable $nom est vide, ce n'est pas normal
// => rediriger l'utilisateur vers une page d'erreur
header("location: erreur.htm");
// interrompre l'excution de ce script
exit;
}
// la variable $nom n'est pas vide, laisser le script se poursuivre
echo "Bonjour $nom !"; // afficher un message
?>
</BODY>
</HTML>

Rsultat

Warning: Cannot modify header information - headers already sent by (output started at
d:\scripts php\info.php:5) in d:\scripts php\info.php on line 15

Si la fonctionnalit de mise en buffer de la page est active avec la directive de configuration output_buffering, le rsultat
du script n'est pas envoy au fur et mesure mais plac dans un buffer puis envoy d'un seul coup la fin (ou par morceaux si
le buffer est limit en taille). Dans ce cas, il est possible d'utiliser la fonction header sans provoquer d'erreur alors que le script
a commenc construire la page.

PHPproposed'autresfonctionsrelativesauxenttes :

- headers_list: liste des enttes de la rponse (version 5).

- header_sent: permet de tester si les enttes ont dj t envoys.

- 2- ENI Editions - All rigths reserved


- get_headers: liste des enttes renvoys par un serveur, pour une URL donne (version 5).

Premierexempledelogiqued'enchanement

Un script saisie.php assure l'affichage initial du formulaire et son traitement. En cas d'erreur, le formulaire est
propos de nouveau pour correction (avec les valeurs saisies), accompagn d'un message d'erreur. En cas de
succsdutraitement,uneautrepageestappele.

<?php
// inclure un fichier qui contient des dfinitions de
// constantes, dont le titre de la page (TITRE_PAGE_SAISIE)
require("constantes.inc");
// inclure un fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// tester comment le script est appel
if (isset($_POST["OK"])) {
// traitement du formulaire ...
// rcuprer les valeurs saisies
$nom = valeur_saisie($_POST["nom"]);
$mail = valeur_saisie($_POST["mail"]);
// initialiser la variable du message
$message = "";
// contrler les valeurs saisies
if ($nom == "")
{ $message .= "Le nom est obligatoire.\n"; }
if ($mail == "")
{ $message .= "Le mail est obligatoire.\n"; }
if (! eregi("^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]
([-.]?[0-9a-z])*\.[a-z]{2,3}$",$mail))
{ $message .= "Le mail n'est pas valide.\n"; }
// tester s'il y a des erreurs
if ($message == "") {
// pas d'erreur
// enregistrer les informations quelque part
// et rediriger l'utilisateur vers une page d'accueil
header("location: accueil.php");
// interrompre l'excution du script
exit;
} else {
// erreur
// prparer le message pour l'affichage
$message = vers_page($message);
}
} else {
// affichage initial ...
// sur cet exemple simple, juste initialiser
// les variables
$nom = "";
$mail = "";
$message = "";
}
// dans le code HTML qui suit, inclusion de quatre petits
// bouts de code PHP pour afficher respectivement le titre
// de la page, la valeur des zones de saisie et le message
?>
<HTML>
<HEAD><TITLE><?php echo TITRE_PAGE_SAISIE ?></TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Veuillez saisir les informations suivantes
pour vous inscrire<BR><BR>
Nom : <INPUT TYPE="text" NAME="nom"
VALUE="<?php echo vers_formulaire($nom); ?>"><BR>
Mail : <INPUT TYPE="text" NAME="mail"
VALUE="<?php echo vers_formulaire($mail); ?>"><BR><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Deuximeexempledelogiqued'enchanement

Un script saisie.htm assure l'affichage initial du formulaire et un script traitement.php le traitement. En cas

ENI Editions - All rigths reserved - 3-


d'chec, un message d'erreur est affich et l'utilisateur est invit revenir en arrire. En cas de succs du
traitement,uneautrepageestaffiche.

Script saisie.htm

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="traitement.php" METHOD="POST">
Veuillez saisir les informations suivantes
pour vous inscrire<BR><BR>
Nom : <INPUT TYPE="text" NAME="nom" VALUE=""><BR>
Mail : <INPUT TYPE="text" NAME="mail" VALUE=""><BR><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

Script traitement.php

<?php
// inclure un fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// traitement du formulaire ...
// rcuprer les valeurs saisies
$nom = valeur_saisie($_POST["nom"]);
$mail = valeur_saisie($_POST["mail"]);
// initialiser la variable du message
$message = "";
// contrler les valeurs saisies
if ($nom == "")
{ $message .= "Le nom est obligatoire.\n"; }
if ($mail == "")
{ $message .= "Le mail est obligatoire.\n"; }
if (! eregi("^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]
([-.]?[0-9a-z])*\.[a-z]{2,3}$",$mail))
{ $message .= "Le mail n'est pas valide.\n"; }
// tester s'il y a des erreurs
if ($message == "") {
// pas d'erreur
// enregistrer les informations quelque part
// et rediriger l'utilisateur vers une page d'accueil
header("location: accueil.php");
// interrompre l'excution du script
exit;
} else {
// erreur
// prparer le message pour l'affichage
$message = vers_page($message);
}
// dans le code HTML qui suit, inclusion d'un petit bout
// de code PHP pour afficher le message
?>
<HTML>
<HEAD><TITLE>Erreur</TITLE></HEAD>
<BODY>
<FONT COLOR="red"><?php echo $message; ?></FONT>
<!-- Petit formulaire contenant un bouton permettant
---- de revenir en arrire (avec du JavaScript) pour corriger
-->
<FORM>
<<INPUT TYPE="button" VALUE="Corriger"
onClick="self.history.back()">
</FORM>
</BODY>
</HTML>

D'autres logiques d'enchanement peuvent exister, la fonction header permettant d'envisager diffrents cas de
figure(voirladocumentationPHP).

Le rsultat du traitement peut aussi tre affich dans une autre fentre grce l'option TARGET de la balise
<FORM>.

Exemple

- 4- ENI Editions - All rigths reserved


<FORM ACTION="traitement.php" METHOD="POST"
TARGET="traitement">

Silafentren'existepas,elleseracreparlenavigateur.

ENI Editions - All rigths reserved - 5-


Introduction

Vued'ensemble

L'utilisationd'unebasededonnesSQLestsouventindispensablepourmettreenplaceunsiteWebdynamique.
C'esteneffetunmoyenstandardisdestockerdesdonnesutilespourlesite :

- liste des utilisateurs avec leurs prfrences ;

- catalogue de produits ;

- trace des transactions effectues...

PHP propose un support natif pour un grand nombre de bases de donnes, parmi lesquelles MySQL, Oracle,
Microsoft SQL Server, Informix, Sybase. Par ailleurs, PHP supporte ODBC (Open DataBase Connectivity) et peut
doncaccdertoutebasededonnessupportantODBC.

En complment, en version 5, PHP est livr avec SQLite, librairie qui implmente un moteur de base de donnes
SQL. SQLite peut tre utilis pour stocker des donnes dans une base SQL, sans avoir mettre en place la
partieserveurdelabasededonnes(commec'estlecasavecMySQL,Oracle,etc.).

Danscechapitre,noustudieronsMySQL,Oracle,MicrosoftSQLServeretSQLite.

Typiquement,lorsdel'utilisationd'unebasededonnes,lescriptPHPabesoind'effectueruneouplusieursdes
tchessuivantes :

- se connecter et se dconnecter ;

- lire des donnes (une ou plusieurs lignes) ;

- mettre jour des donnes (ajout, modification ou suppression) ;

Cesdiffrentestchestypessonttudiesdanscechapitre.

Une connaissance minimale du langage SQL est ncessaire pour aborder ce chapitre.

Pour les diffrents exemples prsents ici, nous supposons l'existence d'une base contenant une table ARTICLE
prsentantlastructuresuivante :

Colonne Contenu
identifiant Identifiant de l'article (aliment automatiquement par le serveur)
libelle Libell de l'article
prix Prix de l'article

LecontenudecettetableARTICLEestlesuivant:

identifiant libelle prix


1 Abricots 35.5
2 Cerises 48.9
3 Fraises 29.95
4 Pches 37.2

Lanotiondefetch

Quellequesoitlabase,l'instructiond'excutiond'unerequte SELECT(envuedeliredesdonnes)secontente

ENI Editions - All rigths reserved - 1-


d'excuterlarequteaucunedonnen'estretourne.Aprsexcutiondelarequte,ilfautextraireleslignes
dursultat :c'estlanotionde"fetch".

Pourrsumerlefonctionnement,l'instructiond'excutiond'unerequte SELECTidentifieunrsultatetpositionne
unpointeurinternesurlapremirelignedecersultat :

L'instructionFETCHpermetdelirelalignecourantedursultat,deramenerlesvaleursdansdesvariablesPHPet
defaireavancerlepointeursurlalignesuivante :

- 2- ENI Editions - All rigths reserved


UtilisationdeMySQL

Prambule

Enversion5,PHPproposedeuxextensionspouraccderunebasededonnesMySQL :

- "MySQL" (prfixe mysql_) ;

- "MySQLi" (prfixe mysqli_).

L'extension MySQL est l'ancienne extension, prsente dans les versions antrieures de PHP cette extension
peut tre utilise pour accder n'importe quelle version de MySQL, mais elle ne supporte pas les nouvelles
fonctionnalitsdelaversion4.1deMySQL.

Pour utiliser les nouvelles fonctionnalits de la version 4.1 de MySQL, il faut utiliser l'extension MySQLi, apparue
en version 5 de PHP cette extension peut aussi tre employe pour accder une version plus ancienne de
MySQL,sousrservedenepasutiliserlesfonctionnalitsapparuesdanslaversion4.1deMySQL.

Mis part les nouvelles fonctionnalits de la version 4.1 de MySQL, les deux extensions sont trs proches en
termes de fonctionnalits. Trs souvent, elles proposent les mmes fonctions, avec des syntaxes identiques ou
compatibles. Sauf exception, pour passer de MySQL MySQLi, il suffit de remplacer le prfixe mysql_ dans le
nomdelafonctionparleprfixemysqli_.

l'heure o cet ouvrage est rdig, la version 4.1 de MySQL est encore en dveloppement (version 4.1.1
Alpha), et l'extension PHP la plus utilise est l'extension MySQL (pour accder des bases MySQL trs souvent
enversion3.2xou4.0).

En consquence, nous commencerons par prsenter de manire dtaille l'utilisation de l'extension MySQL.
Ensuite, nous tablirons une correspondance entre l'extension MySQLi et l'extension MySQL, en nous focalisant
surlesdiffrencesetlesprincipalesnouveauts.

Connexionetdconnexion

Lafonctionmysql_connectpermetd'tabliruneconnexionavecunebaseMySQL.

Syntaxe

ressource mysql_connect([chane serveur[:port]][, chane utilisateur][, chane mot_de_passe][,


boolen nouvelle][, entier indicateurs])

serveur[:port]

Nomduserveurventuellementsuivid'unnumrodeport.
Valeurpardfaut :localhost:3306.

utilisateur

Nomdel'utilisateuremployerpourtablirlaconnexion.
Valeurpardfaut :lepropritaireduprocessusduserveurWeb.

mot_de_passe

Motdepasseutiliserpourtablirlaconnexion.
Valeurpardfaut :chanevide(pasdemotdepasse).

nouvelle

Permetdeforcerl'tablissementd'unenouvelleconnexion(TRUE).
Valeurpardfaut :FALSE.

ENI Editions - All rigths reserved - 1-


indicateurs

Combinaisondesconstantessuivantes :
MYSQL_CLIENT_COMPRESS:utiliserunprotocoledecompression
MYSQL_CLIENT_IGNORE_SPACE :autoriserdesespacesaprslenomdesfonctions
MYSQL_CLIENT_INTERACTIVE : modifie la dure d'inactivit avant fermeture de la connexion pour un client de
typeinteractif.

La fonction mysql_connect retourne un identifiant de connexion ou, en cas d'erreur, la valeur FALSE
accompagned'unmessaged'alerteenvoyl'affichage(cf.chapitreGrerleserreursdansunscriptPHPpour
grercettesituationcorrectement).

Danslemmescript,appelerdeuxfois mysql_connectaveclesmmesparamtresn'ouvrepasdeuxconnexions
diffrentes : lors du deuxime appel, l'identifiant de la connexion dj ouverte est retourn. Pour modifier ce
comportement et forcer l'ouverture d'une nouvelle connexion, il faut donner la valeur TRUE au paramtre
nouvelle.

Exemple

<?php
// utilisation des valeurs par dfaut
$id1 = mysql_connect();
echo "\$id1 = $id1<BR>\n";
// spcification des paramtres
$id2 = mysql_connect("diane","oheu","rz245");
echo "\$id2 = $id2<BR>\n";
// exemple d'chec (" hermes " n'existe pas)
$id3 = mysql_connect("hermes","oheu","rz245");
echo "\$id3 = $id3<BR>\n";
// nouvel appel sans paramtre
$id4 = mysql_connect();
echo "\$id4 = $id4 (<B>= \$id1</B>)<BR>\n";
// gal $id1
?>

Rsultat

$id1 = Resource id #1
$id2 = Resource id #2
Warning: mysql_connect() [function.mysql-connect]: Unknown MySQL Server Host 'hermes' (11001) in
d:\scripts php\index.php on line 9
$id3 =
$id4 = Resource id #1 (= $id1)

Une valeur FALSE est convertie en chane vide dans un echo (d'ou la valeur de $id3).

Les connexions ouvertes dans un script sont automatiquement fermes la fin du script, sauf dconnexion
expliciteavantavecmysql_close(voirciaprs).

Lafonctionmysql_pconnectpermetd'obtenirunfonctionnementdiffrentetd'tabliruneconnexion"permanente"
qui ne sera pas ferme la fin du script et pourra tre rutilise dans ce script ou dans un autre script
ultrieurement.

Lasyntaxeestidentiquelasyntaxedelafonctionmysql_connect,sansleparamtrenouvelle.

Lorsdel'appellafonction mysql_pconnectdansunscript,PHPvrifiesiuneconnexionpermanenteadjt
ouverte avec les mmes paramtres (serveur, utilisateur et mot de passe) : si oui, l'identifiant de cette
connexion est retourn dans le cas contraire, une nouvelle connexion est tablie (et cette connexion ne sera
pasfermelafinduscript,autorisantainsisarutilisationultrieure).

La directive de configuration mysql.allow_persistent doit tre on pour pouvoir ouvrir des connexions
permanentes. Par ailleurs, les directives mysql.max_persistent et mysql.max_links permettent
respectivement de limiter le nombre de connexions permanentes et le nombre total de connexions. Grce
d'autres directives, vous pouvez dfinir des valeurs par dfaut (serveur, port, etc.) et modifier le timeout de
connexion.

- 2- ENI Editions - All rigths reserved


Lafonctionmysql_closepermetdefermeruneconnexionencoursdescript.

Syntaxe

boolen mysql_close([ressource connexion])

connexion

Identifiantdeconnexionretournparlafonctionmysql_connect.
Sinonprcis,fermeturedeladernireconnexionouverte.

Lafonctionmysql_closeretourneTRUEencasdesuccsetFALSEencasd'erreur(accompagnd'unealerte).

Lafonctionmysql_closeestsanseffetsuruneconnexionpermanente.

Toutes les connexions non permanentes sont automatiquement fermes la fin du script.

Exemple

<?php
// connexion
$id1 = mysql_connect();
echo "\$id1 = $id1<BR>\n";
// dconnexion
$ok = mysql_close($id1);
echo "\$ok = ".(($ok)?"TRUE":"FALSE")."<BR>\n";
// tentative de dconnexion d'une connexion dj close
$ok = mysql_close($id1);
echo "\$ok = ".(($ok)?"TRUE":"FALSE")."<BR>\n";
?>

Rsultat

$id1 = Resource id #1
$ok = TRUE
Warning: mysql_close(): 1 is not a valid MySQL-Link resource in
d:\scripts php\index.php on line 9
$ok = FALSE

Liredesdonnes

Liredesdonnesdansunebasencessitetroisoprations :

- slectionner la base de donnes laquelle envoyer la requte (un serveur MySQL pouvant abriter plusieurs bases
distinctes) ;

- envoyer, pour excution, une requte (en l'occurrence SELECT) au serveur ;

- rcuprer la ou les lignes correspondant au rsultat de la requte.

Slectionnerunebasededonnes

La fonctionmysql_select_dbpermetdeslectionnerlabasededonnesutiliserpourlaconnexionpasseen
paramtre.

Syntaxe

boolen mysql_select_db (chane base, [ressource connexion])

Avec

base

ENI Editions - All rigths reserved - 3-


Nomdelabase.

connexion

Identifiantdeconnexionretournparlafonctionmysql_connect.
Si non prcis, utilise la dernire connexion ouverte s'il n'y en a pas, tente d'ouvrir une connexion avec un
appellafonctionmysql_connectsansparamtre.

La fonction mysql_select_db retourne TRUE en cas de succs et FALSE en cas d'erreur. mysql_select_db ne
gnrepasd'alerteencasd'erreur.

Exemple

<?php
// connexion
$connexion = mysql_connect();
// slection d'une base qui existe
$rsultat1 = mysql_select_db("diane",$connexion);
echo "\$rsultat1 = ",($rsultat1)?'TRUE':'FALSE',"<BR>\n";
// slection d'une base qui n'existe pas
$rsultat2 = mysql_select_db("hermes",$connexion);
echo "\$rsultat2 = ",($rsultat2)?'TRUE':'FALSE',"<BR>\n";
?>

Rsultat

$rsultat1 = TRUE
$rsultat2 = FALSE

Excuterunerequte

Lafonctionmysql_querypermetd'envoyerunerequtepourexcutionlabasededonnesactiveduserveur.

Syntaxe

ressource mysql_query(chane requte, [ressource connexion])

requte

Textedelarequteexcuter.

connexion

Identifiantdeconnexionretournparlafonctionmysql_connect.
Si non prcis, utilisation de la dernire connexion ouverte s'il n'y en a pas, tentative d'ouverture d'une
connexionavecunappellafonctionmysql_connectsansparamtre.

Dans le cas d'un ordre SELECT (ou SHOW, EXPLAIN, DESCRIBE), la fonction mysql_query retourne un identifiant
dersultatderequte,encasdesuccs,et FALSEencasd'checpourlesautresordresSQL,cettefonction
retourneTRUEencasdesuccs.mysql_querynegnrepasd'alerteencasd'erreur.

Exemple

<?php
// connexion et slection de la base (erreurs tester ...)
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion) ;
// dfinition de la requte
$requte = "SELECT * FROM articles";
// excution de la requte
$rsultat1 = mysql_query($requte,$connexion);
echo "\$rsultat1 = ",
($rsultat1)? $rsultat1:'FALSE',"<BR>\n";
// dfinition d'une mauvaise requte
$requte = "SELECT * FROM article";
// excution de la requte
$rsultat2 = mysql_query($requte,$connexion);

- 4- ENI Editions - All rigths reserved


echo "\$rsultat2 = ",
($rsultat2)? $rsultat1:'FALSE',"<BR>\n";
?>

Rsultat

$rsultat1 = Resource id #3
$rsultat2 = FALSE

Larequtequiachouretourne FALSEsansgnrerd'alerte (cf.Grerleserreurs,pourlarcuprationd'un


codeoud'unmessaged'erreur).
Pourrappel,lafonctionmysql_queryexcutelarequte,indiquesilarequtes'estexcutecorrectementmais
nerenvoieaucunedonne.Ilvafalloirextraireleslignesdursultat.

Il existe une autre fonction, mysql_db_query, qui agit de manire similaire, en permettant de slectionner la
basechaqueexcution.Cettefonctionestdprcieetnedoitplustreutilise elleestconservepourdes
raisonsdecompatibilitascendante.

Dans le cas d'un ordre SELECT, le rsultat de la requte excute par mysql_query est mis en buffer. Il existe
une autre fonction, mysql_unbuffered_query, qui possde la mme syntaxe que mysql_query, et permet
aussi d'excuter une requte, mais sans placer le rsultat dans un buffer. Pour les requtes volumineuses,
mysql_unbuffered_query consomme beaucoup moins de mmoire que mysql_query et permet d'extraire la
premirelignebienplusrapidement :iln'yapasbesoind'attendrequelatotalitdursultatsoitmiseenbuffer.
Par contre, aprs excution de la requte avec mysql_unbuffered_query, il n'est pas possible de connatre le
nombredelignesdursultat(voir ciaprs),nid'excuteruneautrerequteavantd'avoirextraitlatotalitdes
lignes.

Connatrelenombredelignesdanslersultat

Lafonctionmysql_num_rowspermetdeconnatrelenombredelignesdanslersultat.

Syntaxe

entier mysql_num_rows(ressource rsultat)

rsultat

Identifiantdersultatderequteretournparlafonctionmysql_query.

Cette fonction est utilisable uniquement pour les requtes SELECT. Si la requte a t excute avec
mysql_unbuffered_query,cettefonctionretournelenombredelignesluescestade(0justeaprsl'excution
delarequte).

Exemple

<?php
// connexion et slection de la base (erreurs tester ...)
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion) ;
// dfinition de la requte
$requte = "SELECT * FROM articles";
// excution de la requte
$rsultat = mysql_query($requte);
// rcupration du nombre de lignes
$nombre = mysql_num_rows($rsultat);
echo "Nombre d'articles : $nombre<BR>\n";
// dfinition de la requte
$requte = "SELECT * FROM articles WHERE prix > 40";
// excution de la requte
$rsultat = mysql_query($requte);
// rcupration du nombre de lignes
$nombre = mysql_num_rows($rsultat);
echo "Nombre d'articles dont le prix est suprieur 40 : $nombre<BR>\n";
?>

Rsultat

ENI Editions - All rigths reserved - 5-


Nombre d'articles : 4
Nombre d'articles dont le prix est suprieur 40 : 1

Lirelersultatdelarequte

Le rsultat de l'excution (avec succs) d'une requte SELECT peut tre lu par les fonctions
mysql_fetch_array,mysql_fetch_assoc, mysql_fetch_objectou mysql_ fetch_row.

Ces fonctions effectuent le mme traitement : lecture de la ligne courante du rsultat et avancement du
pointeursurlalignesuivante(voirl'introduction).

Cesfonctionsdiffrentsurletypededonnesutilispourretournerlersultat.

Syntaxe

tableau mysql_fetch_array(ressource rsultat, entier type)


tableau mysql_fetch_assoc(ressource rsultat)
objet mysql_fetch_object(ressource rsultat)
tableau mysql_fetch_row(ressource rsultat)

rsultat

Identifiantdersultatderequteretournparlafonctionmysql_query.

type

Typedersultatgalunedesconstantessuivantes :MYSQL_ASSOC,MYSQL_NUM,MYSQL_BOTH.

Les fonctions mysql_fetch_array, mysql_fetch_assoc et mysql_fetch_row retournent la ligne courante du


rsultat sous la forme d'un tableau, chaque ligne du tableau correspondant une colonne du rsultat. La
fonctionmysql_fetch_objectretournelalignecourantesouslaformed'unobjet.
S'iln'yaplusdeligneliredanslersultat,cesfonctionsretournentFALSE.

Pourlafonctionmysql_fetch_assoc,ils'agitd'untableauassociatifdontlaclestlenomdelacolonne.Pourla
fonctionmysql_fetch_row,ils'agitd'untableauindicesentiers,l'indice0correspondantlapremirecolonne,
l'indice1ladeuxime,etc.Enfin,pourlafonctionmysql_fetch_array,letypedutableaudpenddudeuxime
paramtre :

MYSQL_NUM

Tableauindicesentiers(commelafonctionmysql_fetch_row).

MYSQL_ASSOC

Tableauassociatif(commelafonctionmysql_fetch_assoc).

MYSQL_BOTH
(valeur par dfaut)

Lesdeuxlafois.
Chaquecolonneestprsentedeuxfois.

Exemple:

Requte SELECT *
FROM articles
Colonnes identifiant libelle prix
1re ligne du 1 Abricots 35.5
rsultat

Rsultat d'un fetch (lecture avec diffrentes fonctions):

- 6- ENI Editions - All rigths reserved


mysql_fetch_row mysql_fetch_assoc
ou ou
mysql_fetch_array mysql_fetch_array mysql_fetch_array
(...,MYSQL_NUM) (...,MYSQL_ASSOC) (...,MYSQL_BOTH)
Indice/Cl Valeur Indice/Cl Valeur Indice/Cl Valeur
0 1 identifiant 1 identifiant 1
1 Abricots libelle Abricots 0 1
2 35.5 prix 35.5 libelle Abricots
1 Abricots
prix 35.5
2 35.5

La fonction mysql_fetch_object retourne un objet, avec un attribut par colonne, le nom de l'attribut
correspondantaunomdelacolonne.

Exemple:

Attribut Valeur
identifiant 1
libelle Abricots
prix 35.5

En cas d'utilisation d'un alias de colonne dans la requte SELECT (exemple SELECT AVG(prix) prix_moyen
FROM articles),c'estl'aliasdecolonnequiestutiliscommeclounomd'attribut.

Exemple

<?php
// inclusion du fichier qui contient la dfinition de
// afficher_tableau
include("fonctions.inc");
// connexion et slection de la base (erreurs tester...)
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion) ;
// excution de la requte
$rsultat = mysql_query("SELECT * FROM articles");
// Premier fetch avec mysql_fetch_row
$ligne = mysql_fetch_row($rsultat);
afficher_tableau($ligne,"mysql_fetch_row");
// Deuxime fetch avec mysql_fetch_assoc
$ligne = mysql_fetch_assoc($rsultat);
afficher_tableau($ligne,"mysql_fetch_assoc");
// Troisime fetch avec mysql_fetch_array
// - sans deuxime paramtre = MYSQL_BOTH
$ligne = mysql_fetch_array($rsultat);
afficher_tableau($ligne,"mysql_fetch_array");
// Quatrime fetch avec mysql_fetch_object
$ligne = mysql_fetch_object($rsultat);
echo "<P><B>mysql_fetch_object</B><BR>";
echo "\$ligne->identifiant = $ligne->identifiant<BR>";
echo "\$ligne->libelle = $ligne->libelle<BR>";
echo "\$ligne->prix = $ligne->prix<BR>";
// Cinquime fetch de nouveau avec mysql_fetch_row
// - normalement, plus de ligne
$ligne = mysql_fetch_row($rsultat);
if (! $ligne) {
echo "<B>Cinquime fetch : plus rien</B>";
}
?>

Rsultat

mysql_fetch_row
0 = 1

ENI Editions - All rigths reserved - 7-


1 = Abricots
2 = 35.5
mysql_fetch_assoc
identifiant = 2
libelle = Cerises
prix = 48.9
mysql_fetch_array
0 = 3
identifiant = 3
1 = Fraises
libelle = Fraises
2 = 29.95
prix = 29.95

mysql_fetch_object
$ligne->identifiant = 4
$ligne->libelle = Pches
$ligne->prix = 37.2

Cinquime fetch : plus rien

Cetexemplepermetd'observer:

- les diffrents modes de rcupration d'une ligne de rsultat ;

- le fait qu' chaque fetch, le pointeur interne avance, et que le fetch suivant retourne donc la ligne suivante, jusqu'
avoir parcouru toutes les lignes.

En cas d'utilisation d'un identifiant de rsultat non valide, les fonctions mysql_fetch_* retournent FALSE et
affichentenplusunealertedutype :

Warning: mysql_fetch_row(): supplied argument is not a valid MySQL result resource in


d:\scripts php\index.php on line 5

Quellemthodeutiliser ?

Touteslesmthodessevalent,notammentdupointdevuedesperformances.Personnellement,nousavonsune
petite prfrence pour l'utilisation des fonctions mysql_fetch_assoc et mysql_fetch_object qui permettent
d'employerlenomdescolonnesdelarequteetderendrelecodepluslisible.

Exempledecodepourlalectured'uneligne

Un premier type de lecture consiste souvent lire une seule ligne d'information dans une table ou plusieurs
tablesavecjointure(s) :obtentiond'informationssurl'utilisateurquivientdeseconnecter,fichededescription
d'unarticle...

Exemple

<?php
// inclure un fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// initialiser les variables
$identifiant = "";
$libell = "";
$prix = "";
$message = "";
// Tester la faon dont le script est appel
if (! empty($_POST)) {
// traitement du formulaire ...
// rappel : lorsqu'un formulaire n'a qu'une zone de texte
// et que l'utilisateur tape return ou enter, le bouton de
// validation n'est pas considr comme cliqu. Pour savoir
// si le formulaire a t soumis, il faut tester si
// $_POST (ou $_GET) est vide ou non.
// rcuprer les valeurs saisies
$identifiant = valeur_saisie($_POST["identifiant"]);
// contrler les valeurs saisies
if ($identifiant == "") {

- 8- ENI Editions - All rigths reserved


$message .= "L'identifiant est obligatoire.\n";
}
if (! ereg("^[0-9]+$",$identifiant)) {
$message .=
"L'identifiant doit tre un nombre.\n";
}
// tester s'il y a des erreurs ce stade
;if ($message == "") {
// pas d'erreur
// connexion et slection de la base
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion) ;
// excuter la requte de slection
$requte = "SELECT * FROM articles WHERE
identifiant = $identifiant";
$rsultat = mysql_query($requte);
// fetch si la requte a bien t excute
if ($rsultat) {
$article = mysql_fetch_assoc($rsultat);
}
// tester le rsultat
if (! $rsultat) { // requte pas OK
$message .= "Erreur.\n";
} elseif (! $article) { // rsultat vide
$message .=
"Pas d'article pour cet identifiant.\n";
} else { // OK
// rcuprer les informations afficher
$libell = $article["libelle"];
$prix = $article["prix"];
// mise en forme
$libell = vers_page($libell);
$prix = number_format($prix,2,"," ," ");
$prix = vers_page($prix);
}
}
// tester s'il y a des erreurs ce stade
if ($message != "") {
// erreur
// prparer le message pour l'affichage
$message = vers_page($message);
// bien s'assurer que les informations
// afficher sont vides
$libell = "";
$prix = "";
}
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Consultation d'un article</TITLE></HEAD>
<BODY>
<FORM METHOD="POST">
Identifiant de l'article :
<INPUT TYPE="text" NAME="identifiant"
VALUE="<?php echo vers_formulaire($identifiant); ?>">
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<TABLE BORDER="0">
<TR><TD><U>Libell :</U> </TD>
<TD><?php echo $libell; ?></TD></TR>
<TR><TD><U>Prix :</U> </TD>
<TD><?php echo $prix; ?></TD></TR>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Rsultat (aprs saisie et clic sur le bouton OK

ENI Editions - All rigths reserved - 9-


Ilestrelativementsimpled'crireunefonctiongnriquepermettantdelireuneligne.

Exemple

<?php
function db_lire_ligne($requte) {
// la variable $ok est utilise pour savoir
// si tout se passe bien
// se connecter (par dfaut) et slectionner la base
$ok = ( ($connexion = mysql_connect()) != FALSE );
if ($ok) {
$ok = mysql_select_db("diane",$connexion);
}
// excuter la requte et tester le rsultat pour affecter
// la variable $ok
if ($ok) {
$ok = ( ($rsultat = mysql_query($requte)) != FALSE );
}
if ($ok) { // excution OK
// lire la ligne
$ligne = mysql_fetch_assoc($rsultat);
}
// retourner $ligne ou FALSE en cas d'erreur
return ($ok)?$ligne:FALSE;
}
?>

Ilestpossible(souhaitable)d'amliorerlagestiondeserreurs(cf.Grerleserreurs).

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// dfinir la requte
$requte = "SELECT * FROM articles WHERE identifiant= 1";
// lire le rsultat
$ligne = db_lire_ligne($requte);
if ($ligne) {
echo "$ligne[libelle] - $ligne[prix]";
}
?>

Rsultat (sauf erreur)

Abricots - 35.5

Exempledecodepourlalecturedetoutesleslignes

Un deuxime type de lecture consiste souvent afficher une liste d'lments extraits de la base (liste
d'utilisateurs,listed'articles...).

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// se connecter et slectionner la base (erreurs traiter)
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion);
// excuter la requte de slection
$requte = "SELECT * FROM articles";
$rsultat = mysql_query($requte);
// fetch si la requte a bien t excute
if ($rsultat) {
// boucle jusqu' avoir un fetch FALSE
while ($article = mysql_fetch_assoc($rsultat)) {
// remplir un tableau avec chaque ligne extraite
// remarque : le tableau est multidimensionnel

- 10 - ENI Editions - All rigths reserved


// puisque $article est lui-mme un tableau
$articles[] = $article;
}
}
// tester le rsultat
if (! $rsultat) { // requte pas OK
$message .= "Erreur.\n";
} elseif (empty($articles)) { // rsultat vide
$message .=
"Aucun article dans la base.\n";
} else { // OK
// mettre en forme les donnes (idem prcdemment)
// remarque : aurait pu tre fait dans la boucle
// de fetch pour optimiser les performances
for ($i=0;$i<count($articles);$i++) {
$articles[$i]["libelle"] =
vers_page($articles[$i]["libelle"]);
$articles[$i]["prix"] =
vers_page(number_format($articles[$i]["prix"],2,"," ," "))
}
}
// tester s'il y a des erreurs ce stade
if ($message != "") {
// erreur
// prparer le message pour l'affichage
$message = vers_page($message);
// bien s'assurer que les informations
// afficher sont vides
unset($articles);
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML -->
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if (isset($articles)) { // s'il y a un rsultat afficher
foreach($articles as $article) { // boucle sur les articles
// gnration de la ligne de la table HTML
// remarque : printf() rend le code lisible
printf("<TR><TD>%d</TD><TD>%s</TD><TD>%s</TD></TR>",
$article["identifiant"],
$article["libelle"],
$article["prix"]);
}
}
?>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Il est possible d'crire le mme exemple de manire plus compacte. Ce dernier sera alors plus conome en
mmoireetplusperformant :lefetchesteffectuaucoursdelaconstructiondelatableHTML.

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// se connecter et slectionner la base (erreurs traiter)
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion);
// excuter la requte de slection
// - le rsultat n'est pas mis en buffer
$requte = "SELECT * FROM articles";
$rsultat = mysql_unbuffered_query($requte);
// tester le rsultat
if (! $rsultat) { // requte pas OK

ENI Editions - All rigths reserved - 11 -


// message d'erreur
$message .= "Erreur.\n";
// prparer le message pour l'affichage
$message = vers_page($message);
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML -->
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if ($rsultat) { // s'il y a un rsultat afficher
// boucle de fetch
while ($article = mysql_fetch_assoc($rsultat)) {
// mise en forme des donnes
$article["libelle"] = vers_page($article ["libelle"]);
$article["prix"] = vers_page(
number_format($article["prix"],2,"," ," "));
// gnration de la ligne de la table HTML
printf("<TR><TD>%d</TD><TD>%s</TD><TD>%s</TD></TR>",
$article["identifiant"],
$article["libelle"],
$article["prix"]);
} // while
// si le rsultat est vide, prparer un message
if (mysql_num_rows($rsultat) == 0) {
$message = vers_page("Aucun article dans la base.");
}
} // if ($rsultat)
?>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Pourpermettrel'utilisateurd'agirsurlaliste,ilestpossibled'imbriquerunformulaireoudesliensaveclatable
HTML.

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// se connecter et slectionner la base (erreurs traiter)
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion);

// excuter la requte de slection


$requte = "SELECT * FROM articles";
$rsultat = mysql_query($requte);
// tester le rsultat
if (! $rsultat) { // requte pas OK
// message d'erreur
$message .= "Erreur.\n";
// prparer le message pour l'affichage
$message = vers_page($message);
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML l'intrieur d'un
---- formulaire -->
<FORM METHOD="POST">
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">

- 12 - ENI Editions - All rigths reserved


<TH>Libell</TH><TH>Prix</TH><TH>Case</TH><TH>Lien</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if ($rsultat) { // s'il y a un rsultat afficher
// boucle de fetch
while ($article = mysql_fetch_assoc($rsultat)) {
// mise en forme des donnes
$article["libelle"] = vers_page($article ["libelle"]);
$article["prix"] = vers_page(
number_format($article["prix"],2,"," ," "));
// gnration de la ligne de la table HTML
// - une case cocher dans une colonne
// - un lien dans une autre colonne
printf(
"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>",
$article["libelle"],
$article["prix"],
"<INPUT TYPE=\"checkbox\" NAME=\"choix[]\"
VALUE=\"$article[identifiant]\">",
"<A HREF=\"javascript:alert($article[identifiant])\">
action<A>");
} // while
// si le rsultat est vide, prparer un message
if (mysql_num_rows($rsultat) == 0) {
$message = vers_page("Aucun article dans la base.");
}
} // if ($rsultat)
?>
</TABLE>
<BR><INPUT TYPE="submit" NAME="action" VALUE="Action">
</FORM>
<FONT COLOR="green">
<?php
// traitement du formulaire
// simple affichage des identifiants cochs
if (isset($_POST["action"])) {
if (isset($_POST["choix"])) {
echo "Identifiant(s) coch(s) : ".
implode("+",$_POST["choix"]);
}
}
?>
</FONT>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Rsultat

- Affichage initial de la page :

- Aprs clic sur un lien :

ENI Editions - All rigths reserved - 13 -


- Aprs clic sur le bouton Action :

Sur le lien, la place du code JavaScript, il est possible de mettre une vraie URL et d'enchaner sur une autre
page (cf. chapitre Grer les sessions pour comprendre comment placer un paramtre dans l'URL et pouvoir ainsi
passeruneinformation,icil'identifiantchoisi,uneautrepage).

Encequiconcerneletraitementduformulaire,toutestenvisageable.
Lencore,pourlalecturedeplusieurslignes,unefonctiongnriquepeuttreutilise.

Exemple

<?php
function db_lire_lignes_dans_tableau($requte) {
// la variable $ok est utilise pour savoir
// si tout se passe bien
// se connecter (par dfaut) et slectionner la base
$ok = ( ($connexion = mysql_connect()) != FALSE );
if ($ok) {
$ok = mysql_select_db("diane",$connexion);
}
// excuter la requte et tester le rsultat pour affecter
// la variable $ok
if ($ok) {
$ok = ( ($rsultat = mysql_query($requte)) != FALSE );
}
$tableau = array();
if ($ok) { // excution OK
// lire les lignes dans un tableau
while ($ligne = mysql_fetch_assoc($rsultat)) {
$tableau[] = $ligne;
}
}
// retourner $tableau ou FALSE en cas d'erreur
return ($ok)?$tableau:FALSE;
}
?>

- 14 - ENI Editions - All rigths reserved


Utilisation

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// dfinir la requte
$requte = "SELECT * FROM articles";
// lire le rsultat dans un tableau
$articles = db_lire_lignes_dans_tableau($requte);
// afficher le premier article lu
if ($articles) {
echo count($articles)." articles<BR>";
echo "Premier article : ";
echo $articles[0]["libelle"]," - ",
$articles[0]["prix"];
}
?>

Rsultat (sauf erreur)

4 articles
Premier article : Abricots 35.5

Cettefonctiongnriquepeut,parexemple,treutilisepourconstruireuneliste<SELECT>>dansunformulaire.

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// chargement de la liste des fruits
$requte = "SELECT identifiant,libelle FROM articles
ORDER BY libelle";
$fruits_du_march = db_lire_lignes_dans_tableau($requte);
?>
<!-- construction du formulaire -->
<FORM METHOD="POST">
Fruits prfrs :<BR>
<SELECT NAME="fruits[]" MULTIPLE SIZE="8">
<?php
// code PHP gnrant la partie dynamique du formulaire
// parcourir la liste afficher
foreach($fruits_du_march as $fruit) {
// gnrer la balise OPTION avec l'identifiant
// pour l'option VALUE et le libell pour le texte affich
// dans la liste
echo "<OPTION VALUE=\"$fruit[identifiant]\">
$fruit[libelle]\n";
}
?>
</SELECT>
<INPUT TYPE="submit" NAME="OK" VALUE="OK"><BR>
</FORM>

Rsultat

Mettrejourdesdonnes

MettrejourdesdonnesconsisteexcuterdesrequtesINSERT(cration),UPDATE(modification)ouDELETE
(suppression).

ENI Editions - All rigths reserved - 15 -


L'excutiondecetypederequtes'effectueaveclafonctionmysql_query,commepourunerequteSELECT.

Encomplment,deuxfonctionssontintressantes :mysql_affected_rowsetmysql_insert_id.

La fonction mysql_affected_rows permet de connatre le nombre de lignes concernes (insres, modifies ou


supprimes)parladernirerequteINSERT, UPDATE ou DELETEexcutedansunesession.

Syntaxe

entier mysql_affected_rows([ressource connexion])

connexion

Identifiantdeconnexionretournparlafonctionmysql_connect.
Sinonprcis,utiliseladernireconnexionouverte.

Siladernirerequteachou,lafonctionmysql_affected_rowsretourne1.

La fonction mysql_affected_rows est cense ne pas fonctionner avec des requtes SELECT ; ce n'est pas vrai !

Dans le cas d'un ordre UPDATE, mysql_affected_rows ne compte pas les lignes non modifies lorsque les valeurs avant
et aprs sont les mmes.

La fonction mysql_insert_id retourne la valeur du dernier identifiant gnr pour une colonne ayant le type
AUTO_INCREMENTparunerequteINSERTdansunesession.

Syntaxe

entier mysql_insert_id([ressource connexion])

connexion

Identifiantdeconnexionretournparlafonctionmysql_connect.
Sinonprcis,utiliseladernireconnexionouverte.

Siaucunidentifiantn'atgnrautomatiquement,lafonctionmysql_insert_idretournezro.

La requte INSERT n'a pas besoin d'tre la dernire requte excute dans la session.

Exemples

<?php
// inclusion du fichier qui contient la dfinition des
// fonctions gnrales
include("fonctions.inc");
// dfinition d'une petite fonction d'affichage de la liste
// des articles
function AfficherArticles() {
$requte = "SELECT * FROM articles";
$articles = db_lire_lignes_dans_tableau($requte);
if ($articles) {
echo "<B>Liste des articles :</B><BR>";
foreach($articles as $a) {
echo "$a[identifiant] - $a[libelle] - $a[prix]<BR>";
}
} else {
echo "<B>Plus d'articles.</B><BR>";
}
}
// affichage de contrle
AfficherArticles();
// la connexion a t tablie par la fonction
// db_lire_lignes_dans_tableau appele dans AfficherArticles
// requte INSERT
$requte = "INSERT INTO articles(libelle,prix)
VALUES('Poires',29.9)";
$rsultat = mysql_query("diane",$requte);

- 16 - ENI Editions - All rigths reserved


$identifiant = mysql_insert_id(); // rcuprer l'identifiant
echo "Identifiant du nouvel article = $identifiant.<BR>";
// requte UPDATE
$requte = "UPDATE articles SET prix = prix * 1.1
WHERE prix < 40";
$rsultat = mysql_query($requte);
$nombre = mysql_affected_rows();
echo "$nombre article(s) augment(s).<BR>";
// requte DELETE
$requte = "DELETE FROM articles WHERE prix > 40";
$rsultat = mysql_query($requte);
$nombre = mysql_affected_rows();
echo "$nombre article(s) supprims(s).<BR>";
// affichage de contrle
AfficherArticles();
?>

Rsultat

Liste des articles :


1 - Abricots - 35.5
2 - Cerises - 48.9
3 - Fraises - 29.95
4 - Pches - 37.2
Identifiant du nouvel article = 5.
4 article(s) augment(s).
2 article(s) supprims(s).

Liste des articles :


1 - Abricots - 39.05
3 - Fraises - 32.945
5 - Poires - 32.89

Crerdesformulairesquipermettentdemettrejourlesdonnesesttrssimple.

titred'exemple,nousallonsconstruireunformulairequipermetderaliserunesaisieenliste.

Prsentation du formulaire

Le formulaire propose le contenu actuel de la table qui peut tre modifi (saisie directe dans les zones) ou
supprim(parlescasescocher),pluscinqlignesvidesquipermettentdesaisirdenouvellesvaleurs.Danstous
lescas,l'identifiantnepeuttresaisi,c'estleserveurMySQLquival'attribuer.

Chaque ligne du tableau contient quatre zones de formulaire qui sont nommes (option NAME de la balise
<INPUT>)delamaniresuivante :

Colonne Nom
Identifiant saisie[i][modifier]
Libell saisie[i][libelle]

ENI Editions - All rigths reserved - 17 -


Prix saisie[i][prix]
Supprimer saisie[i][supprimer]

L'indice i est l'identifiant de l'article pour les lignes qui existent, et un numro compris entre 1 et 5 pour les
lignes vides. La zone de la colonne Identifiant est une zone masque (TYPE="hidden") qui va tre employe
pouridentifierleslignesdanslesquellesl'utilisateuraeffectuunemodification.

Avec ce processus de nommage, toute la saisie est rcupre dans le script PHP sous la forme d'un tableau
multidimensionnel nomm $lignes. Chaque ligne du tableau correspond une ligne du formulaire avec la cl
gale l'identifiant (ou 1 5 pour les nouvelles lignes) et la valeur gale un tableau associatif donnant les
lmentssaisis.

Pour identifier les lignes modifies par l'utilisateur, les zones de saisie du libell et du prix des lignes existantes
contiennentlecodeJavaScriptsuivant :

onChange="document.formulaire[$n].value=1"

CecodeJavaScriptapoureffet,chaquefoisquelazoneenquestionestmodifie,deplacerun1danslazone
masque associe la ligne. Le formulaire s'appelant formulaire (<FORM NAME = "formulaire"...),
l'expression document.formulaire[n] dsigne la nime zone du formulaire formulaire du document courant,
la premire zone du formulaire ayant le numro 0. Dans le source, la variable $n est calcule pour chaque ligne
$i du formulaire, par la formule $n = 4 * ($i - 1) : la zone cache de la ligne 1 a le numro 0 (c'est la
premireduformulaire),celledelaligne2lenumro4etainsidesuite.

Cetexemplepeut(doit)treamlior :

- pour contrler la saisie de l'utilisateur ;

- pour grer les erreurs.

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// se connecter et slectionner la base
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion);
// traitement du formulaire
if (isset($_POST["OK"])) {
// rcuprer le tableau contenant la saisie
$lignes = $_POST["saisie"];
foreach($lignes as $identifiant => $ligne) {
// nettoyage de la saisie
$libell = valeur_saisie($ligne["libelle"]);
$prix = valeur_saisie($ligne["prix"]);
$prix = str_replace(",",".",$prix); // , => .
$prix = str_replace(" ","",$prix); // supprimer espaces
// ce niveau, il faudrait vrifier la saisie ...
$requte = "";
if ($identifiant < 0 and $libell.$prix != "") {
// identifiant ngatif et quelque chose de saisi
// = cration = INSERT
$requte = "INSERT INTO articles(libelle,prix)
VALUES('$libell',$prix)";
} elseif (isset($ligne["supprimer"])) {
// case " supprimer " coche = suppression = DELETE
$requte = "DELETE FROM articles
WHERE identifiant = $identifiant";
} elseif (isset($ligne["modifier"])) {
// zone " modifier " TRUE (1) = modification = UPDATE
$requte = "UPDATE articles
SET libelle = '$libell', prix = $prix
WHERE identifiant = $identifiant";
}

- 18 - ENI Editions - All rigths reserved


// si une requte a t dtermine, l'excuter
if ($requte != "") {
mysql_query($requte);
// ce niveau, il faudrait tester les erreurs ...
}
}
}
// recharger les articles
$requte = "SELECT * FROM articles";
$rsultat = mysql_query($requte);
// ce niveau, il faudrait tester les erreurs ...
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Gestion des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML l'intrieur d'un
---- formulaire -->
<FORM NAME="formulaire" METHOD="POST">
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
<TH>Supprimer</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if ($rsultat) { // s'il y a un rsultat afficher
// initialisation d'un compteur de ligne
$i = 0;
// boucle de fetch
while ($article = mysql_fetch_assoc($rsultat)) {
// incrmentation du compteur de ligne
$i++;
// calcul du numro d'ordre dans le formulaire de la
// zone cache correspondant l'identifiant
$n = 4 * ($i - 1);
// mise en forme des donnes
$article["libelle"] = vers_page($article["libelle"]);
$article["prix"] = vers_page(
number_format($article["prix"],2,"," ," "));
// gnration de la ligne de la table HTML
// insertion des balises INPUT du formulaire
printf(
"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>",
"$article[identifiant]
<INPUT TYPE=\"hidden\"
NAME=\"saisie[$article[identifiant]][modifier]\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[$article[identifiant]][libelle]\"
VALUE=\"$article[libelle]\"
OnChange=\"document.formulaire[$n].value=1\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[$article[identifiant]][prix]\"
VALUE=\"$article[prix]\"
onChange=\"document.formulaire[$n].value=1\">",
"<INPUT TYPE=\"checkbox\"
NAME=\"saisie[$article[identifiant]][supprimer]\"
VALUE=\"$article[identifiant]\">");
} // while
// ajout de 5 lignes vides pour la cration
// (sans identifiant, sans case de suppression)
for($i=1;$i<=5;$i++) {
printf(
"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>",
"",
"<INPUT TYPE=\"text\"
NAME=\"saisie[-$i][libelle]\"
VALUE=\"\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[-$i][prix]\"
VALUE=\"\">",
"");
} // for
}
?>
</TABLE>
<BR><INPUT TYPE="submit" NAME="OK" VALUE="Enregistrer">
</FORM>
</BODY>

ENI Editions - All rigths reserved - 19 -


</HTML>

Grerleserreurs

Les fonctions mysql_errno etmysql_error permettent de rcuprer des informations sur l'erreur ventuelle de
ladernireoprationeffectuedansunesession.

Syntaxe

entier mysql_errno([ressource connexion])


chane mysql_error([ressource connexion])

connexion

Identifiantdeconnexionretournparlafonctionmysql_connect.
Sinonprcis,utiliseladernireconnexionouverte.

Lafonctionmysql_errnoretourneunnumrod'erreuretlafonctionmysql_error,lemessageassoci.

Exemple

<?php
// se connecter un mauvais serveur
$connexion = mysql_connect('hermes');
echo "1 : ".mysql_errno()." - ".mysql_error()."<BR>";
// se connecter correctement (par dfaut)
$connexion = mysql_connect();
echo "2 : ".mysql_errno()." - ".mysql_error()."<BR>";
// slectionner une mauvaise base
$ok = mysql_select_db("hermes",$connexion);
echo "3 : ".mysql_errno()." - ".mysql_error()."<BR>";
// slectionner la bonne base
$ok = mysql_select_db("diane",$connexion);
echo "4 : ".mysql_errno()." - ".mysql_error()."<BR>";
// une bonne requte pour commencer
$requte = "SELECT * FROM articles";
$rsultat = mysql_query($requte);
echo "5 : ".mysql_errno()." - ".mysql_error()."<BR>";
// requte sur une table qui n'existe pas
$requte = "SELECT * FROM article";
$rsultat = mysql_query($requte);
echo "6 : ".mysql_errno()." - ".mysql_error()."<BR>";
// requte INSERT qui viole une cl primaire
$requte = "INSERT INTO articles(identifiant,libelle,prix)
VALUES(1,'Poires',29.9)";
$rsultat = mysql_query($requte);
echo "7 : ".mysql_errno()." - ".mysql_error()."<BR>";
// tentative de fetch sur un mauvais rsultat
$requte = "SELECT * FROM article";
$rsultat = mysql_query($requte);
echo "8 : ".mysql_errno()." - ".mysql_error()."<BR>";
$ligne = mysql_fetch_assoc($rsultat);
echo "9 : ".mysql_errno()." - ".mysql_error()."<BR>";
?>

Rsultat

Warning: mysql_connect() [function.mysql-connect]: Unknown


MySQL Server Host 'hermes' (11001) in d:\scripts php\index.php on line 3
1 : 2005 - Unknown MySQL Server Host 'hermes' (11001)
2 : 0 -
3 : 1049 - Unknown database 'hermes'
4 : 0 -
5 : 0 -
6 : 1146 - Table 'diane.article' doesn't exist
7 : 1062 - Duplicate entry '1' for key 1
8 : 1146 - Table 'diane.article' doesn't exist
Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource in
d:\scripts php\index.php on line 31
9 : 1146 - Table 'diane.article' doesn't exist

Lepoint1illustrelefaitqu'encasd'erreurlorsdelaconnexion,unealerteestafficheencomplment.

- 20 - ENI Editions - All rigths reserved


Lespoints8et9illustrentlefaitqueleserreursliesl'utilisationd'uneressource(deconnexionoudersultat)
non valide gnre une alerte qui est directement affiche. Dans ce cas, l'erreur n'est pas une erreur MySQL et
les fonctions mysql_errno ou mysql_error ne sont pas rinitialises et ne retournent donc pas d'erreur
spcifique :lemessagedupoint9estenfaitceluidupoint8.

Enpratique,lesfonctionsmysql_errnoetmysql_errornesontd'aucuneutilitsurlesfetch.

Par ailleurs, nous verrons au chapitre Grer les erreurs dans un script PHP comment supprimer l'affichage des
alertes.

Cesfonctionspeuventtremisesenuvretitred'exemplesurunedenosfonctionsgnriques.

Exemple

<?php
function db_lire_ligne($requte, &$erreur) {
// dans cette nouvelle version, db_lire_ligne prend un
// deuxime paramtre par rfrence dans lequel un numro et un message
// seront stocks en cas d'erreur (sous la forme d'un tableau)
// initialiser $erreur
$erreur = array(0,""); // numro = 0 message vide
// tablir la connexion
$ok = ($connexion = mysql_connect());
if ($ok) { // c'est bon
// slectionner la base de donnes
$ok = mysql_select_db("diane",$connexion);
}
if ($ok) { // c'est tojours bon
// excuter la requte et tester le rsultat pour
// affecter la variable $ok
$ok = ( ($rsultat = mysql_query($requte)) != FALSE );
}
if ($ok) { // tout est OK
// lire la ligne
$ligne = mysql_fetch_assoc($rsultat);
} else { // problme quelque part
// rcuprer les informations sur l'erreur
$erreur = array(mysql_errno(),mysql_error());
}
// retourner $ligne ou FALSE en cas d'erreur
return ($ok)?$ligne:FALSE;
}
?>

Utilisation

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// premier appel avec une erreur
$requte = "SELECT * FROM article WHERE identifiant = 1";
if (! ($ligne = db_lire_ligne($requte,$erreur))) {
echo "$erreur[0] - $erreur[1]<BR>";
} else {
echo "$ligne[libelle] - $ligne[prix]<BR>";
}
// deuxime appel correct
$requte = "SELECT * FROM articles WHERE identifiant = 1";
if (! ($ligne = db_lire_ligne($requte,$erreur))) {
echo "$erreur[0] - $erreur[1]<BR>";
} else {
echo "$ligne[libelle] - $ligne[prix]<BR>";
}
?>

Rsultat

1146 - Table 'diane.article' doesn't exist


Abricots - 35.5

ENI Editions - All rigths reserved - 21 -


MySQLi

Introduction

L'extensionMySQLipeuttreutilisesoitsousuneformeprocdurale(commel'extensionMySQL),soitsousune
formeobjet.

En cas d'utilisation sous une forme procdurale, l'extension MySQLi est trs proche de l'extension MySQL (mis
part les nouvelles fonctionnalits de la version 4.1 de MySQL, supportes par l'extension MySQLi mais pas par
l'extension MySQL). Trs souvent, les deux extensions proposent les mmes fonctions, avec des syntaxes
identiques ou compatibles. Sauf exception, pour passer de l'extension MySQL l'extension MySQLi, il suffit de
remplacerleprfixemysql_danslenomdelafonctionparleprfixemysqli_.

Parcontre,l'utilisationdel'extensionMySQLisousuneformeobjetestsensiblementdiffrentedel'utilisationde
l'extensionMySQL.Danssaformeorienteobjet,l'extensionMySQLipropose3classes :

mysqli

connexionentrePHPetMySQL.

mysqli_stmt

requteprpare.

mysqli_result

rsultatdel'excutiond'unerequte.

Cesdiffrentesclassesoffrentdesmthodesquipermettentd'effectuerlesdiffrentesactions(excutiond'une
requte,rcuprationdursultat,etc.).

Correspondanceavecl'extensionMySQL

Toutes les fonctions prsentes prcdemment dans l'extension MySQL, l'exception de la fonction
mysql_pconnect, ont un quivalent direct dans l'extension MySQLi il suffit de remplacer le prfixe mysql_ par
mysqli_ :

MySQL MySQLi Syntaxe


mysql_connect mysqli_connect Voir remarque 1
mysql_close mysqli_close Voir remarque 2
mysql_select_db mysqli_select_db Voir remarque 3
mysql_query mysqli_query Voir remarque 3
mysql_num_rows mysqli_num_rows Identique
mysql_fecth_array mysqli_fecth_array Identique
mysql_fecth_array mysqli_fecth_array Identique
mysql_fecth_object mysqli_fecth_object Identique
mysql_fecth_row mysqli_fecth_row Identique
mysql_affected_rows mysqli_affected_rows Voir remarque 2
mysql_insert_id mysqli_insert_id Voir remarque 2
mysql_errno mysqli_errno Voir remarque 2
mysql_error mysqli_error Voir remarque 2

Remarques

Les premiers paramtres de mysql_connect et mysqli_connect sont identiques (serveur, utilisateur, mot de

- 22 - ENI Editions - All rigths reserved


passe) lesparamtressuivantssontdiffrents.Parailleurs,lafonctionmysqli_connectpermetdeslectionner
labaseutiliserdslaconnexion(quatrimeparamtre) l'appelmysqli_select_dbestalorsinutile.

MySQLi ne permet pas d'utiliser de connexion par dfaut dans les appels de fonctions. En consquence, un
identifiant de connexion valide doit tre pass en paramtre mysql_close, mysql_affected_rows,
mysql_insert_id,mysql_errnoetmysql_error.

Pourlesfonctions mysqli_select_db etmysqli_query,lasyntaxeestinverse :l'identifiantdeconnexiondoit


trepassenpremierparamtre,etildevientobligatoire.

Les fonctions mysqli_connect et mysqli_query> ne retournent plus des ressources mais des objets. Dans la
pratique, cela n'a aucune incidence car le rsultat de ces fonctions est simplement pass en paramtre
d'autresfonctions.

Endehorsdesfonctionsmysqli_errno et mysqli_error,MySQLioffrelesfonctionsmysqli_connect_error et
mysqli_connect_errnoquipermettentdercuprerdesinformationssuruneventuelleerreurdeconnexion.

MySQLineproposepasdefonctionsmysqli_unbuffered_query.Parcontre,lafonction mysqli_querypossde
un troisime paramtre qui permet d'indiquer si le rsultat doit tre mis en buffer (constante
MYSQLI_STORE_RESULT, valeur par dfaut) ou non (constante MYSQLI_USE_RESULT). Pour les requtes
volumineuses,l'utilisationdeMY-SQLI_USE_RESULTconsommebeaucoupmoinsdemmoireetpermetd'extrairela
premirelignebienplusrapidement :iln'yapasbesoind'attendrequelatotalitdursultatsoitmisenbuffer.
Par contre, aprs excution de la requte avec MY-SQLI_USE_RESULT, il n'est pas possible de connatre le
nombredelignesdursultat,nid'excuteruneautrerequteavantd'avoirextraitlatotalitdeslignesoulibr
lersultat(fonctionmysqli_free_result).

Exemple

<?php
// dfinir quelques variables
$serveur = "diane";
$utilisateur = "root";
$mot_de_passe = "";
$base="diane";
// connexion = mysqli_connect
// - pas de slection de la base dans cet appel
$connexion = mysqli_connect($serveur,$utilisateur,$mot_de_passe);
// vrifier le succs de la connexion
// - mysqli_connect_errno = numro de l'erreur de connexion
// - mysqli_connect_error = message de l'erreur de connexion
if (mysqli_connect_errno() != 0) {
echo sprintf(
"Erreur mysqli_connect : %d - %s<BR>",
mysqli_connect_errno(),
mysqli_connect_error());
exit;
}
// slectionner la base = mysqli_select_db
// - diffrences par rapport mysql_select_db
// > syntaxe inverse
// > identifiant de connexion obligatoire
// - inutile si base slectionne dans mysqli_connect
$ok = mysqli_select_db($connexion,$base);
if (! $ok) {
// rcuprer une erreur MySQLi = mysqli_errno & mysqli_error
// - diffrences par rapport mysql_errno & mysql_error
// > identifiant de connexion obligatoire
echo sprintf(
"Erreur mysqli_select_db : %d - %s<BR>\n",
mysqli_errno($connexion),
mysqli_error($connexion));
exit;
}
// excuter une requte = mysqli_query
// - diffrences par rapport mysql_query
// > syntaxe inverse

ENI Editions - All rigths reserved - 23 -


// > identifiant de connexion obligatoire
// > troisime paramtre (optionnel) : mode du rsultat
// . MYSQLI_USE_RESULT : rsultat non mis en buffer
// . MYSQLI_STORE_RESULT : rsultat mis en buffer (dfaut)
$requte = "SELECT * FROM articles";
$mode = MYSQLI_STORE_RESULT;
$rsultat = mysqli_query($connexion,$requte,$mode);
if (! $rsultat) {
echo sprintf(
"Erreur mysqli_query : %d - %s<BR>\n",
mysqli_errno($connexion),
mysqli_error($connexion));
exit;
}
// dterminer le nombre de lignes du rsultat = mysqli_num_rows
// - identique mysql_num_rows
// - inutilisable si emploi de MYSQLI_USE_RESULT
// dans mysqli_query
if ($mode == MYSQLI_USE_RESULT) {
echo "Nombre d'articles impossible dterminer<BR>\n";
} else {
echo sprintf("Nombre d'articles : %s<BR>\n",
mysqli_num_rows($rsultat));
}
// rcuprer le rsultat = mysqli_fetch_*
// - diffrences par rapport mysql_fetch_*
// > constantes MYSQLI_NUM, MYSQLI_ASSOC, MYSQLI_BOTH
$ligne = mysqli_fetch_array($rsultat, MYSQLI_ASSOC);
echo sprintf("Premier article : %s - %s<BR>\n",
$ligne['libelle'],$ligne['prix']);
// librer le rsultat = mysqli_free_result
// - pas obligatoire : les ressources sont libres la
// fin du script
// - permet d'anticiper (important si rsultat volumineux)
// - ncessaire si utilisation de MYSQLI_USE_RESULT
// dans mysqli_query
mysqli_free_result($rsultat);
// excuter une requte = mysqli_query
// - exemple avec INSERT
$requte = "INSERT INTO articles(libelle,prix) VALUES('Poires',29.9)";
$rsultat = mysqli_query($connexion,$requte);
// rcuprer l'identifiant gnr = mysqli_insert_id
// - diffrences par rapport mysql_insert_id
// > identifiant de connexion obligatoire
echo sprintf(
"Identifiant du nouvel article = %s<BR>\n",
mysqli_insert_id($connexion));
// excuter une requte = mysqli_query
// - exemple avec UPDATE
$requte = "UPDATE articles SET prix = prix * 1.05";
$rsultat = mysqli_query($connexion,$requte);
// rcuprer le nombre de lignes mises jour =
// mysqli_affected_rows
// - diffrences par rapport mysql_affected_rows
// > identifiant de connexion obligatoire
echo sprintf(
"Nombre d'articles modifis = %s<BR>\n",
mysqli_affected_rows($connexion));
// dconnexion = mysqli_close
// - diffrences par rapport mysql_close
// > identifiant de connexion obligatoire
mysqli_close($connexion);
?>

Rsultat

Nombre d'articles : 4
Premier article : Abricots - 35.5
Identifiant du nouvel article = 5
Nombre d'articles modifis = 5

Requtesprpares

LaprincipalenouveautdeMySQL4.1,utilisableavecl'extensionMySQLi,estlanotionderequteprpare.

Une requte paramtre est une requte qui contient des paramtres matrialiss par un point d'interrogation

- 24 - ENI Editions - All rigths reserved


(?).

Exemples

SELECT * FROM articles WHERE identifiant = ?


INSERT INTO articles(libelle,prix) VALUES(?,?)

Un paramtre ne peut pas remplacer un nom de table, un nom de colonne ou toute une partie de la requte.

Exemples interdits

SELECT * FROM ?
SELECT * FROM articles WHERE ?

Lestapesd'utilisationd'unerequteparamtresontlessuivantes :

- envoyer la requte pour analyse au serveur = mysqli_stmt_prepare ;

- associer des variables PHP aux paramtres de la requte (notion de "bind") = mysqli_stmt_bind_param ;

- excuter la requte = mysqli_stmt_execute.

Danslecasd'unerequteSELECT,ilyadeuxtapessupplmentaires :

- associer des variables PHP aux colonnes du rsultat = mysqli_stmt_bind_result;

- extraire les lignes du rsultat = mysqli_stmt_fetch.

chaque excution de la requte prpare, la valeur courante des variables PHP associes aux paramtres est
utilise. L'intrt est de pouvoir employer plusieurs fois la mme requte avec des valeurs diffrentes des
paramtressansanalyserdenouveaularequte,cequipermetd'amliorerlesperformances.

Plusieursautresfonctionspeuventtreutilisesaveclesrequtesprpares :

mysqli_stmt_init

Creunerequteprpare.

mysqli_stmt_close

Fermeunerequteprpare.

mysqli_stmt_affected_rows

Retournelenombredelignesmisesjourparunerequteprpare.

mysqli_stmt_store_result

Metenbufferlersultatd'unerequteprpare.

mysqli_stmt_num_rows

Retournelenombredelignesslectionnesparunerequteprpare.

mysqli_stmt_free_result

Librelersultatd'unerequteprpare.

mysqli_stmt_errno

ENI Editions - All rigths reserved - 25 -


Retournelecoded'erreurd'unerequteprpare.

mysqli_stmt_error

Retournelemessaged'erreurd'unerequteprpare.

Exemple de mise jour

<?php
// dfinir quelques variables
$serveur="diane";
$utilisateur="root";
$mot_de_passe="";
$base="diane";
// connexion (avec slection de la base)
$connexion = mysqli_connect($serveur,$utilisateur,
$mot_de_passe,$base);
// dfinir la requte excuter
// - requte d'insertion avec deux paramtres
$requte = "INSERT INTO articles(libelle,prix) VALUES(?,?)";
// crer une requte prpare = mysqli_stmt_init
// - retourne un objet requte utiliser dans la suite
$stmt = mysqli_stmt_init($connexion);
// prparer la requte = mysqli_stmt_prepare
// - retourne simplement TRUE (succs) ou FALSE (erreur)
$ok = mysqli_stmt_prepare($stmt,$requte);
// associer des variables aux paramtres = mysqli_stmt_bind_param
// - le deuxime argument contient un ou plusieurs caractres
// indiquant le type des paramtres :
// i = entier, d = dcimal, s = chane
// - les arguments suivants sont les variables associer
// aux paramtres
// - l'association est positionnelle
// - retourne simplement TRUE (succs) ou FALSE (erreur)
// - sur notre exemple :
// > premier paramtre = chane = $libell
// > deuxime paramtre = dcimal = $prix
$ok = mysqli_stmt_bind_param($stmt,"sd",$libell,$prix);
// donner des valeurs aux variables
$libell = 'Bananes';
$prix = 15.35;
// excuter la requte prpare = mysqli_stmt_execute
// - retourne simplement TRUE (succs) ou FALSE (erreur)
$ok = mysqli_stmt_execute($stmt);
// rcuprer des informations sur l'excution d'une
// requte prpare
// - mysqli_stmt_affected_rows = nombre de lignes mises jour
// - mysqli_stmt_errno = numro d'erreur
// - mysqli_stmt_error = message d'erreur
// par contre, pas de mysqli_stmt_insert_id
// => utiliser mysqli_insert_id
echo sprintf(
"%s article insr - Identifiant = %s - Erreur = %s<BR>\n",
mysqli_stmt_affected_rows($stmt),
mysqli_insert_id($connexion),
mysqli_stmt_errno($stmt));
// il est alors possible de donner d'autre valeurs aux variables
// et d'xecuter de nouveau la requte
$libell = 'Pommes';
$prix = 24.5;
$ok = mysqli_stmt_execute($stmt);
echo sprintf(
"%s article insr - Identifiant = %s - Erreur = %s<BR>\n",
mysqli_stmt_affected_rows($stmt),
mysqli_insert_id($connexion),
mysqli_stmt_errno($stmt));
// il est aussi possible d'associer d'autres variables aux
// paramtres et d'xecuter de nouveau la requte
$ok = mysqli_stmt_bind_param($stmt,"sd",$libell_bis,$prix_bis);
$libell_bis = 'Oranges';
$prix_bis = 30;
$ok = mysqli_stmt_execute($stmt);
echo sprintf(
"%s article insr - Identifiant = %s - Erreur = %s<BR>\n",
mysqli_stmt_affected_rows($stmt),
mysqli_insert_id($connexion),
mysqli_stmt_errno($stmt));

- 26 - ENI Editions - All rigths reserved


// fermer une requte prpare = mysqli_stmt_close
// - retourne simplement TRUE (succs) ou FALSE (erreur)
$ok = mysqli_stmt_close($stmt);
// dconnexion = mysqli_close
mysqli_close($connexion);
?>

Rsultat

1 article insr - Identifiant = 6 - Erreur = 0


1 article insr - Identifiant = 7 - Erreur = 0
1 article insr - Identifiant = 8 - Erreur = 0

Exemple de lecture

<?php
// dfinir quelques variables
$serveur="diane";
$utilisateur="root";
$mot_de_passe="";
$base="diane";
// connexion (avec slection de la base)
$connexion = mysqli_connect($serveur,$utilisateur,
$mot_de_passe,$base);
// dfinir la requte excuter
// - requte de slection avec un paramtre
$requte = "SELECT identifiant,libelle
FROM articles WHERE libelle LIKE ?";
// crer une requte prpare = mysqli_stmt_init
$stmt = mysqli_stmt_init($connexion);
// prparer la requte = mysqli_stmt_prepare
$ok = mysqli_stmt_prepare($stmt,$requte);
// associer des variables PHP aux paramtres =
// mysqli_stmt_bind_param
$ok = mysqli_stmt_bind_param($stmt,"s",$recherche);
// donner des valeurs aux variables
$recherche = 'P%';
// excuter la requte prpare = mysqli_stmt_execute
$ok = mysqli_stmt_execute($stmt);
// associer des variables aux colonnes du rsultat =
// mysqli_stmt_bind_result
// - une variable par colonne
mysqli_stmt_bind_result($stmt,$identifiant,$libell);
// extraire les lignes du rsultat = mysqli_stmt_fetch
// - retourne TRUE (succs), FALSE (erreur) ou NULL (plus de ligne)
// - les donnes de la ligne extraite sont charges dans les
// variables associes aux colonnes du rsultat
echo "<B> Premier appel = LIKE '$recherche'</B><BR>\n";
while (mysqli_stmt_fetch($stmt)) {
echo "$identifiant - $libell<BR>\n";
}
// librer le rsultat = mysqli_stmt_free_result
mysqli_stmt_free_result($stmt);
// excuter de nouveau la requte prpare avec une nouvelle valeur
$recherche = '%an%';
$ok = mysqli_stmt_execute($stmt);
// mettre le resultat en buffer = mysqli_stmt_store_result
$ok = mysqli_stmt_store_result($stmt);
// afficher le nombre de lignes slectionnes =
// mysqli_stmt_num_rows
// - impossible dans le premier cas car le rsultat n'avait pas
// t mis en buffer
echo "<B> Deuxime appel = LIKE '$recherche'</B><BR>\n";
echo sprintf("Nombre d'articles : %s<BR>\n",
mysqli_stmt_num_rows($stmt));
// extraire les lignes du rsultat = mysqli_stmt_fetch
// - utilise les variables lies prcdemment
while (mysqli_stmt_fetch($stmt)) {
echo "$identifiant - $libell<BR>\n";
}
// librer le rsultat = mysqli_stmt_free_result
mysqli_stmt_free_result($stmt);
// fermer une requte prpare = mysqli_stmt_close
$ok = mysqli_stmt_close($stmt);
// dconnexion = mysqli_close
mysqli_close($connexion);
?>

ENI Editions - All rigths reserved - 27 -


Rsultat

Premier appel = LIKE 'P%'


4 - Pches
5 - Poires
7 - Pommes
Deuxime appel = LIKE '%an%'
Nombre d'articles : 2
6 - Bananes
8 - Oranges

- 28 - ENI Editions - All rigths reserved


Utilisationd'Oracle

Prambule

PHP dispose de deux bibliothques pour accder Oracle : la bibliothque "Oracle" (prfixe des fonctions =
ora_)et"Oracle8"(prfixedesfonctions=oci).

La bibliothque "Oracle 8" est plus complte et plus puissante que la bibliothque "Oracle" elle permet
notammentd'utiliserlestypesLOBetROWIDetd'tablirdesliaisonsentredesvariablesPHPetdesvariablesdans
larequteSQL(processusde"bind variable").

Hormiscesdiffrences,l'utilisationdesdeuxbibliothquesestsimilaireetparatrafamilireauxpersonnesquiont
dj utilis les OCI Oracle, les prcompilateurs du type Pro*C ou des API (Application Programming Interface)
commeOLEDB(ObjectLinkingandEmbeddingDataBase)ouJDBC(JavaDataBaseConnectivity).

Danscetouvrage,nousavonschoisideprsenterlabibliothque"Oracle8".Contrairementcequelenomdela
bibliothque laisse penser, cette bibliothque peut tre utilise pour accder n'importe quelle version d'Oracle
(7,8,9).

En version 5, beaucoup de fonctions de cette bibliothque ont t renommes ; au prfixe prs, les fonctions portent
maintenant des noms identiques aux fonctions similaires des autres bases de donnes. Les anciens noms peuvent toujours
tre utiliss pour des raisons de compatibilit ascendante, mais sont dprcis. Cet ouvrage prsente les fonctions avec leur
nom de la version 5 mais rappelle l'ancien nom.

EnvironnementNLS

L'environnement NLS (National Language Support), utilis lors de l'excution des requtes, est dfini par les
variablesd'environnementhabituellespositionnessurleserveurquiexcutePHP :

- NLS_LANG

- NLS_DATE_FORMAT...

Sicesvariablesd'environnementnesontpaspositionnes,lesparamtrespardfautduserveurOraclesontpris
encompte.

Cette situation peut conduire des diffrences de fonctionnement d'un mme programme entre deux
environnements.Parexemple,sivousrcuprezdansunerequteunecolonnedetypeDATE,uneconversionen
chane est automatiquement effectue (car PHP ne supporte pas le type DATE en tant que tel) selon le
paramtreNLS_DATE_FORMATactif selonlaconfigurationetl'environnement,lachanercuprepeutavoirdes
formatsdiffrents(DD/MM/YYYY,DDMONYY...).

Desproblmesanaloguesseproduisentaveclesdonnesnumriquesquisont,ellesaussi,convertiesenchane
avecunsparateurdcimaletunsparateurdegroupequipeutvarierselonl'environnement.

Sil'environnementn'estpasmatris,ilestpossibled'agirauniveauducodePHPpourobteniruncodeportable
d'unenvironnementl'autre :

- soit en effectuant systmatiquement des conversions explicites dans les ordres SQL (TO_CHAR
(SYSDATE,'DD/MM/YYYY'), TO_DATE('31/08/2001','DD/MM/YYYY'), TO_CHAR(prix,'9999.99'),
TO_NUMBER('123.45','999.99') par exemple) ;

- soit en excutant, aprs chaque ouverture de session, des requtes ALTER SESSION (ALTER SESSION SET
NLS_DATE_FORMAT = 'DD/MM/YYYY' et/ou ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ', ' par
exemple).

Connexionetdconnexion

Lafonctionoci_connect(anciennementociLogon)permetd'ouvriruneconnexionavecunebaseOracle.

ENI Editions - All rigths reserved - 1-


Syntaxe

ressource oci_connect(chane utilisateur, chane mot_de_passe,


[, chane nom_de_service])

Avec

utilisateur

Nomdel'utilisateuremployerpourtablirlaconnexion.

mot_de_passe

Motdepasseutiliserpourtablirlaconnexion.

nom_de_service

Nom d'un service rseau valide, dfini dans le fichier tnsnames.ora, sur lequel tablir la connexion. Si non
spcifi, la fonction oci_connect utilise la variable d'environnement ORACLE_SID pour la connexion une
instancelocale,oulavariableTWO_TASK(linux)ouLOCAL(Windows),pourlaconnexionuneinstancedistante.

La fonction oci_connect retourne un identifiant de connexion en cas de succs ou, en cas d'erreur, la valeur
FALSE accompagne d'un message d'alerte envoy l'affichage (cf. chapitre Grer les erreurs dans un script
PHP).

Appeler deux fois la fonction oci_connect avec les mmes paramtres, dans le mme script, retourne deux
identifiants de connexion diffrents mais c'est en fait la mme connexion qui est partage. Ce point est
importantcarlesordresmissurlapremireconnexionetceuxmissurladeuximesontenfaitexcutsdans
lammetransaction :unCOMMITouROLLBACKsurl'unedesdeuxconnexionsagirasurlesdeux.

En cas de besoin, la fonction oci_new_connect anciennement ocinlogon peut tre utilise pour ouvrir deux
connexions indpendantes dans le mme script avec les mmes paramtres. La syntaxe de la fonction
oci_new_connectestlammequecelledelafonctionoci_connect.

Exemple

<?php
// connexion un nom de service rseau
$id1 = oci_connect("demeter","demeter","diane");
echo "\$id1 = $id1<BR>\n";
// connexion la variable d'environnement ORACLE_SID
$id2 = oci_connect("demeter","demeter");
echo "\$id2 = $id2<BR>\n";
// exemple d'chec (mauvais mot de passe)
$id3 = oci_connect("demeter","zeus","diane");
echo "\$id3 = $id3<BR>\n";
// nouvelle connexion avec les mmes paramtres que 1
$id4 = oci_connect("demeter","demeter","diane");
echo "\$id4 = $id4 (<B><> \$id1 mais c'est
trompeur</B>)<BR>\n";
// nouvelle connexion avec les mmes paramtres que 1
$id5 = oci_new_connect ("demeter","demeter","diane");
echo "\$id5 = $id5 (<B><> \$id1 et c'est rel</B>)<BR>\n";
?>

Rsultat

$id1 = Resource id #3
$id2 = Resource id #5
Warning: oci_connect() [function.oci-connect]:
OCISessionBegin: ORA-01017: nom d'utilisateur/mot de passe non valide;
connexion refuse in d:\scripts php\index.php on line 9
$id3 =
$id4 = Resource id #6 (<> $id1 mais c'est trompeur)
$id5 = Resource id #8 (<> $id1 et c'est rel)

Les connexions ouvertes dans un script sont automatiquement fermes la fin du script, sauf dconnexion

- 2- ENI Editions - All rigths reserved


expliciteavantaveclafonctionoci_close(voirciaprs).

La fonction oci_pconnect (anciennement ocipLogon) permet d'obtenir une action diffrente et d'tablir une
connexiondite"permanente"quineserapasfermelafinduscriptetpourratrerutilisedanscescriptou
dansunautreultrieurement.

Lasyntaxeestidentiquelasyntaxedelafonctionoci_connect.

Lors de l'appel la fonction oci_pconnect dans un script, PHP regarde si une connexion permanente a dj t
ouverte avec les mmes paramtres (utilisateur, mot de passe et nom de service) : si oui, l'identifiant de cette
connexionestretourn sinon,unenouvelleconnexionesttablie(etcetteconnexionneserapasfermela
finduscript,autorisantainsisarutilisationultrieure).
Lafonctionoci_close(anciennementocilogoff)permetdefermeruneconnexionencoursdescript.

Syntaxe

boolen oci_close(ressource connexion)

Avec

connexion

Identifiantdeconnexionretournparlesfonctionsoci_connectouoci_new_connect.

En thorie (voir l'exemple ciaprs), la fonction oci_close retourne TRUE en cas de succs et FALSE en cas
d'erreur(accompagnd'unealerte).
Lafonctionoci_closeestsanseffetsuruneconnexionpermanente.

Toutes les connexions non permanentes sont automatiquement fermes la fin du script.

Exemple

<?php
// connexion
$id1 = oci_connect("demeter","demeter","diane");
echo "\$id1 = $id1<BR>\n";
// dconnexion
$ok = oci_close($id1);
echo "\$ok = ",var_dump($ok),"<B>(!)</B><BR>\n";
// tentative de dconnexion d'une connexion dj close
$ok = oci_close($id1);
echo "\$ok = ",var_dump($ok),"<B>(!)</B><BR>\n";
?>

Rsultat

$id1 = Resource id #3
$ok = NULL (!)
$ok = NULL (!)

Depuis la version 4 de PHP, la fonction oci_close qui est cense faire quelque chose ne fait rien et retourne
systmatiquement NULL ! Le source de la bibliothque semble indiquer que ce comportement est volontaire.

Liredesdonnes

Liredesdonnesdansunebasencessitetroisoprations :

- envoyer une requte (en l'occurrence un ordre SELECT) au serveur pour analyse (tape de "parse") ;

- excuter la requte ;

- rcuprer la ou les lignes correspondant au rsultat de la requte.

ENI Editions - All rigths reserved - 3-


Analyserunerequte

Lafonctionoci_parse(anciennementociparse)permetd'envoyerunerequtepouranalyseauserveur.

Syntaxe

ressource oci_parse(ressource connexion, chane requte)

Avec

connexion

Identifiantdeconnexionretournparlafonctionoci_connect(ouoci_new_connectouoci_pconnect).

requte

Textedelarequteanalyser.

La fonction oci_parse retourne un identifiant de curseur dans tous les cas (succs ou chec) le fait qu'un
curseur soit invalide, pour cause de requte incorrecte, n'est dtect qu'au moment de l'excution (voir ci
aprs).

Exemple

<?php
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// dfinition de la requte
$requte = "SELECT * FROM articles";
// analyse de la requte
$curseur1 = oci_parse($connexion,$requte);
echo "\$curseur1 = $curseur1<BR>\n";
// dfinition d'une mauvaise requte (table inexistante)
$requte = "SELECT * FROM article";
// analyse de la requte
$curseur2 = oci_parse($connexion,$requte);
echo "\$curseur2 = $curseur2<BR>\n";
?>

Rsultat

$curseur1 = Resource id #4
$curseur2 = Resource id #5

Excuterunerequte

La fonction oci_execute (anciennement ociexecute) permet d'excuter une requte prcdemment envoye
pouranalyseauserveur.

Syntaxe

boolen oci_execute(ressource curseur[, entier mode])

curseur

Identifiantducurseurexcuter.

mode

Indique si un COMMIT automatique doit tre excut ou pas (sans objet pour une requte SELECT (cf. Mettre
jourdesdonnes)).

Lafonctionoci_executeretourneTRUEencasdesuccsetFALSEencasd'chec(accompagnd'unealerte).

- 4- ENI Editions - All rigths reserved


Exemple

<?php
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// dfinition de la requte
$requte = "SELECT * FROM articles";
// analyse de la requte
$curseur1 = oci_parse($connexion,$requte);
echo "\$curseur1 = $curseur1<BR>\n";
// excution de la requte
$ok1 = oci_execute($curseur1);
echo "\$ok1 = ".(($ok1)?"TRUE":"FALSE")."<BR>\n";
// dfinition d'une mauvaise requte
$requte = "SELECT * FROM article";
// analyse de la requte
$curseur2 = oci_parse($connexion,$requte);
echo "\$curseur2 = $curseur2<BR>\n";
// excution de la requte
$ok2 = oci_execute($curseur2);
echo "\$ok2 = ".(($ok2)?"TRUE":"FALSE")."<BR>\n";
?>

Rsultat

$curseur1 = Resource id #4
$ok1 = TRUE
$curseur2 = Resource id #5
Warning: oci_execute() [function.oci-execute]:
OCIStmtExecute: ORA-00942: Table ou vue inexistante in
d:\scripts php\index.php on line 18
$ok2 = FALSE

Nousallonsvoirdanslepointsuivantcommentrcuprer,danslescript,uncodeouunmessaged'erreur.

Commeindiquenintroduction,lafonctionoci_executeexcutelarequte,indiquesilarequtes'estexcute
correctementmaisnerenvoieaucunedonne.Ilvafalloirextraireleslignesdursultat.

La bibliothque "Oracle" (fonctions ora_*) possde une instruction, ora_do, qui regroupe l'analyse, l'excution et la lecture
de la premire ligne ; la bibliothque "Oracle 8" ne possde pas de fonction similaire.

Connatrelenombredelignesdanslersultat

ladiffrencedeMySQL,iln'yaaucunmoyen,avantlecture,deconnatrelenombredelignesdanslersultat.

Parcontre,encoursdelecture(voirsectionsuivante),lafonction oci_num_rows(anciennement ociRowCount)


permetdeconnatrelenombretotaldelignesluescestade.

Syntaxe

entier oci_num_rows(ressource curseur)

curseur

Identifiantducurseurdanslequellarequteatexcute.

Sil'excutiondelarequteachou,lafonctionoci_num_rowsretournezro.

Lirelersultatdelarequte

Le rsultat de l'excution (russie) d'une requte SELECT peut tre lu par les fonctions oci_fetch_array,
oci_fetch_assoc,oci_fetch_object,oci_fetch_rowetoci_fetch_all.

Les fonctions oci_fetch_array, oci_fetch_assoc, oci_fetch_object et oci_fetch_row lisent une ligne de


rsultat et font avancer le pointeur sur la ligne suivante ces fonctions diffrent sur le type de donnes utilis
pour retourner le rsultat. Elles sont apparues en version 5 et ont une syntaxe trs proche des fonctions
quivalentesdeMySQL.Danslesversionsprcdentes,lafonction ocifetchintopeuttreutiliselaplace

ENI Editions - All rigths reserved - 5-


cettedernireexistetoujourspourdesraisonsdecomptabilitascendantemaisestdprcie.

Syntaxe

tableau oci_fetch_array(ressource curseur [, entier type])


tableau oci_fetch_assoc(ressource curseur)
objet oci_fetch_object(ressource curseur)
tableau oci_fetch_row(ressource curseur)

Avec

curseur

Identifiantducurseurprcdemmentexcut.

type

Typedersultatdfiniparunecombinaisondesconstantessuivantes :
OCI_BOTH(valeurpardfaut)
OCI_ASSOC
OCI_NUM
OCI_RETURN_NULLS

Les fonctions oci_fetch_array, oci_fetch_assoc et oci_fetch_row retournent la ligne courante du rsultat


sous la forme d'un tableau, chaque ligne du tableau correspondant une colonne du rsultat. La fonction
oci_fetch_objectretournelalignecourantesouslaformed'unobjet.

S'iln'yaplusdeligneliredanslersultat,cesfonctionsretournentFALSE.

Pour la fonction oci_fetch_assoc, il s'agit d'un tableau associatif dont la cl est le nom de la colonne (en
majuscules).Pourlafonction oci_fetch_row,ils'agitd'untableauindicesentiers,l'indice0correspondantla
premire colonne, l'indice 1 la deuxime, etc. Enfin pour la fonction oci_fetch_array, le type du tableau
dpenddudeuximeparamtre :

OCI_NUM

Tableauindicesentiers(commelafonctionoci_fetch_row).

OCI_ASSOC

Tableauassociatif(commelafonctionoci_fetch_assoc).

OCI_BOTH
(valeur par dfaut)

Lesdeuxlafois.
Chaquecolonneestprsentedeuxfois.
quivalentOCI_NUM+OCI_ASSOC.

Les fonctions oci_fetch_object, oci_fetch_assoc et oci_fetch_row ne font pas figurer les colonnes ayant
une valeur NULL (mais les indices sont prservs dans le cas de la fonction oci_fetch_row). Par dfaut, le
comportementestidentiquepourlafonctionoci_fetch_array.

Supposonsparexemplequelescolonnes libelle et prixdelatable articlesacceptentdesvaleurs NULL et


quelecontenudelatablesoitlesuivant :

identifiant libelle prix


1 Abricots 35.5
2 Cerises
3 29.95

- 6- ENI Editions - All rigths reserved


Troisappelslafonctionoci_fetch_array(sansdeuximeparamtre),aprsexcutiondelarequteSELECT *
FROM articles,donnerontlesrsultatssuivants :

1er fetch 2e fetch 3e fetch


Indice/Cl Valeur Indice/Cl Valeur Indice/Cl Valeur
0 1 0 2 0 3
IDENTIFIANT 1 IDENTIFIANT 2 IDENTIFIANT 3
1 Abricots 1 Cerise 2 29.95
LIBELLE Abricots LIBELLE Cerise PRIX 29.95
2 35.5
PRIX 35.5

Desrsultatssimilairessontobtenusavecoci_fetch_assoc,oci_fetch_rowetoci_fetch_object.

Lors de l'utilisation de la fonction oci_fetch_array, il est possible d'employer la constante OCI_RETURN_NULLS


endeuximeparamtrepourconserverdansletableaulescolonnesayantunevaleurNULL.

Il n'y a aucun moyen de conserver les colonnes ayant une valeur NULL lors de l'utilisation des autres fonctions
oci_fetch_*.

Les constantes peuvent tre additionnes pour prciser plusieurs comportements. Par exemple,
OCI_ASSOC+OCI_RETURN_NULLSpermetd'obteniruntableauassociatifavecconservationdesvaleursNULL.

Exemple:

Requte SELECT * FROM


articles
Colonnes identifiant libelle prix
1re ligne du 1 Abricots
rsultat

Rsultat d'un appel oci_fetch_array avec:

OCI_NUM + OCI_ASSOC OCI_BOTH


+ +
OCI_RETURN_NULLS OCI_RETURN_NULLS OCI_RETURN_NULLS
Indice/Cl Valeur Indice/Cl Valeur Indice/Cl Valeur
0 1 IDENTIFIANT 1 0 1
1 Abricots LIBELLE Abricots IDENTIFIANT 1
2 PRIX 1 Abricots
LIBELLE Abricots
2
PRIX

Utiliser OCI_RETURN_NULLS seul revient employer OCI_NUM+OCI_RETURN_ NULLS.

En cas d'utilisation d'un alias de colonne dans la requte SELECT (exemple SELECT AVG(prix) prix_moyen
FROM articles), c'est l'alias de colonne (en majuscules, sauf s'il est spcifi entre guillemets, auquel cas la
casseestrespecte)quiestutiliscommeclounomd'attribut.

Exemple

<?php
// inclusion du fichier qui contient la dfinition de

ENI Editions - All rigths reserved - 7-


// afficher_tableau
include("fonctions.inc");
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// dfinition de la requte
$requte = "SELECT * FROM articles";
// analyse de la requte
$curseur = oci_parse($connexion,$requte);
// excution de la requte
$ok = oci_execute($curseur);
// premier fetch avec oci_fetch_row
$ligne = oci_fetch_row($curseur);
afficher_tableau($ligne,"oci_fetch_row");
// dtermination du nombre de lignes lues ce stade
$nombre = oci_num_rows($curseur);
echo "<BR>$nombre ligne lue ce stade";
// deuxime fetch avec oci_fetch_assoc
$ligne = oci_fetch_assoc($curseur);
afficher_tableau($ligne,"oci_fetch_assoc");
// dtermination du nombre de lignes lues ce stade
$nombre = oci_num_rows($curseur);
echo "<BR>$nombre lignes lue ce stade";
// troisime fetch avec oci_fetch_array
// - sans deuxime paramtre = OCI_BOTH
$ligne = oci_fetch_array($curseur);
afficher_tableau($ligne,"oci_fetch_array");
// dtermination du nombre de lignes lues ce stade
$nombre = oci_num_rows($curseur);
echo "<BR>$nombre lignes lue ce stade";
// quatrime fetch avec oci_fetch_object
$ligne = oci_fetch_object($curseur);
echo "<P><B>oci_fetch_object</B><BR>";
echo "\$ligne->IDENTIFIANT = $ligne->IDENTIFIANT<BR>";
echo "\$ligne->LIBELLE = $ligne->LIBELLE<BR>";
echo "\$ligne->PRIX = $ligne->PRIX<BR>";
// dtermination du nombre de lignes lues ce stade
$nombre = oci_num_rows($curseur);
echo "<BR>$nombre lignes lue ce stade";
// cinquime fetch de nouveau sans paramtre
// - normalement, plus de ligne
$ligne = oci_fetch_array($curseur);
if (! $ligne) {
echo "<P><B>Cinquime fetch : plus rien</B><BR>";
}
// dtermination du nombre de lignes lues ce stade
$nombre = oci_num_rows($curseur);
echo "<BR>$nombre lignes lue ce stade";
?>

Rsultat (en supposant que la colonne prix est toujours renseigne)

oci_fetch_row
0 = 1
1 = Abricots
2 = 35,5
1 ligne lue ce stade
oci_fetch_assoc
IDENTIFIANT = 2
LIBELLE = Cerises
PRIX = 48,9
2 lignes lue ce stade
oci_fetch_array
0 = 3
IDENTIFIANT = 3
1 = Fraises
LIBELLE = Fraises
2 = 29,95
PRIX = 29,95
3 lignes lue ce stade
oci_fetch_object
$ligne->IDENTIFIANT = 4
$ligne->LIBELLE = Pches
$ligne->PRIX = 37,2
4 lignes lue ce stade
Cinquime fetch : plus rien
4 lignes lue ce stade

Cetexemplepermetdevoir:

- 8- ENI Editions - All rigths reserved


- Les diffrents modes de rcupration d'une ligne de rsultat ;

- Le fait qu' chaque fetch, le pointeur interne avance, et que le fetch suivant retourne donc la ligne suivante,
jusqu' avoir parcouru toutes les lignes.

LesfonctionsretournentFALSEetaffichentunealertedanslescassuivants :

- curseur non analys (pas d'appel la fonction oci_parse) ;

Warning: oci_fetch_row(): supplied argument is not a valid OCI8-Statement resource in


d:\scripts php\index.php on line 13

- curseur non excut (pas d'appel la fonction oci_execute) ;

Warning: oci_fetch_row() [function.oci-fetch-row]: OCIFetchInto: ORA-24338: descripteur


d'instruction non excut in d:\scripts php\index.php on line 13

- curseur excut avec erreur

Warning: oci_fetch_row() [function.oci-fetch-row]: OCIFetchInto: ORA-24374: dfinition non


excute aprs extraction ou excution et extraction in d:\scripts php\index.php on line 13

La fonction oci_fetch_all (anciennement ocifetchstatement) lit toutes les lignes du rsultat dans un
tableau.

Syntaxe

entier oci_fetch_all(ressource curseur, tableau rsultat, [entier ignorer[, entier nombre[,


entier type]]])

Avec

curseur

Identifiantducurseurprcdemmentexcut.

rsultat

Variablequicontiendralersultatenretour.
Lecontenuinitialdelavariableestcras.

ignorer

Nombredelignesdudbutdursultatnepasramener.0pardfaut :lersultatdbutelapremireligne.

nombre

Nombre de lignes retourner, partir de la premire ligne retourne. 1 par dfaut : toutes les lignes sont
retournes.

type

Typedersultatdfiniparunecombinaisondesconstantessuivantes :
OCI_FETCHSTATEMENT_BY_ROW
OCI_FETCHSTATEMENT_BY_COLUMN(valeurpardfaut)
OCI_ASSOC(valeurpardfaut)
OCI_NUM

La fonctionoci_fetch_allretournelenombredelignesdursultatouFALSEsilersultatneprsenteaucune
ligne(ouencasd'erreur).

ENI Editions - All rigths reserved - 9-


Attention ! Les lignes ignores, mme si elles ne sont pas prsentes dans le rsultat, sont quand mme extraites (fetch).
Or, la fonction oci_num_rows retourne le nombre total de lignes extraites. En consquence, lorsque des lignes sont ignores
dans oci_fetch_all, le rsultat retourn par oci_fetch_all et oci_num_rows est diffrent (la diffrence tant gale au
nombre de lignes ignores).

Letableauretourndansrsultatparlafonctionoci_fetch_allestuntableaumultidimensionnel.Pardfaut,
letableauprincipalestuntableauassociatifcontenantunelignepourchaquecolonnedelarequte :laclest
galeaunomdelacolonne, enmajuscules,etlavaleurestuntableauindicesentiersquicontientlesvaleurs
delacolonnepourl'ensembledeslignesdursultat(indice0pourla1re ligne,1pourla2e ,etc.).

La structure du tableau peut tre modifie en spcifiant une ou plusieurs des constantes suivantes pour le
paramtretype :

OCI_FETCHSTATEMENT_BY_ROW

Le tableau principal contient une ligne pour chaque ligne de la requte ce tableau est forcment indices
entiers.Letableausecondairecontientunelignepourchaquecolonnedelarequte.

OCI_FETCHSTATEMENT_BY_COLUMN
(valeur par dfaut)

Le tableau principal contient une ligne pour chaque colonne de la requte. Le tableau secondaire contient une
lignepourchaquelignedelarequte cetableauestforcmentindicesentiers.

OCI_ASSOC
(valeur par dfaut)

Letableaudescolonnesestuntableauassociatif.

OCI_NUM

Letableaudescolonnesestuntableauindicesentiers.

Il n'est pas possible de combiner entre elles les constantes OCI_FETCHSTATEMENT_BY_ROW et


OCI_FETCHSTATEMENT_BY_COLUMN,niOCI_ASSOCetOCI_NUM.

ladiffrencedesautresfonctionsoci_fetch_*,lafonctionoci_fetch_allretournelesvaleursNULL.

En cas d'utilisation, d'un alias de colonne dans la requte SELECT (exemple SELECT AVG(prix) prix_moyen
FROM articles),c'estl'aliasdecolonne(enmajuscules,saufs'ilestspcifientreguillemets,auquelcaslacasse
estrespecte)quiestutiliscommecl.

Exemple

<?php
// inclusion du fichier qui contient la dfinition de
// afficher_tableau
include("fonctions.inc");
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// dfinition de la requte
$requte = "SELECT * FROM articles";
// analyse de la requte
$curseur = oci_parse($connexion,$requte);
// excution de la requte
$ok = oci_execute($curseur);
// fetch de toutes les lignes
// - paramtres par dfaut
$nombre = oci_fetch_all($curseur,$rsultat);
afficher_tableau($rsultat,
'oci_fetch_all($curseur,$rsultat)');
echo ($nombre)?"$nombre lignes dans le rsultat":"FALSE";
// autre dtermination du nombre de lignes lues
$nombre = oci_num_rows($curseur);
echo "<BR>$nombre lignes dans le rsultat";
// excution de la requte
$ok = oci_execute($curseur);

- 10 - ENI Editions - All rigths reserved


// fetch de toutes les lignes
// - rsultat partiel : ignorer la 1re ligne
// 2 lignes en tout
$nombre = oci_fetch_all($curseur,$rsultat,1,2);
afficher_tableau($rsultat,
'oci_fetch_all($curseur,$rsultat,1,2)');
echo ($nombre)?"$nombre lignes dans le rsultat":"FALSE";
// autre dtermination du nombre de lignes lues
$nombre = oci_num_rows($curseur);
echo "<BR>$nombre lignes dans le rsultat";
// excution de la requte
$ok = oci_execute($curseur);
// fetch de toutes les lignes
// - rsultat partiel : 2 lignes en tout
// - prsentation par ligne
$nombre = oci_fetch_all($curseur,$rsultat,
0,2,OCI_FETCHSTATEMENT_BY_ROW);
afficher_tableau($rsultat,
'oci_fetch_all($curseur,$rsultat,'.
'0,2,OCI_FETCHSTATEMENT_BY_ROW)');
echo ($nombre)?"$nombre lignes dans le rsultat":"FALSE";
// autre dtermination du nombre de lignes lues
$nombre = oci_num_rows($curseur);
echo "<BR>$nombre lignes dans le rsultat";
// excution de la requte
$ok = oci_execute($curseur);
// fetch de toutes les lignes
// - rsultat partiel : 2 lignes en tout
// - prsentation par ligne
// - tableau numrique pour les colonnes
$nombre = oci_fetch_all($curseur,$rsultat,
0,2,OCI_FETCHSTATEMENT_BY_ROW+OCI_NUM);
afficher_tableau($rsultat,
'oci_fetch_all($curseur,$rsultat,'.
'0,2,OCI_FETCHSTATEMENT_BY_ROW+OCI_NUM)');
echo ($nombre)?"$nombre lignes dans le rsultat":"FALSE";
// autre dtermination du nombre de lignes lues
$nombre = oci_num_rows($curseur);
echo "<BR>$nombre lignes dans le rsultat";
// dfinition d'une requte qui ne retourne aucune ligne
$requte = "SELECT * FROM articles WHERE 0=1";
// analyse de la requte
$curseur = oci_parse($connexion,$requte);
// excution de la requte
$ok = oci_execute($curseur);
// Fetch de toutes les lignes
// - paramtres par dfaut
$nombre = oci_fetch_all($curseur,$rsultat);
afficher_tableau($rsultat,"Pas de rsultat : par colonne");
echo ($nombre)?"$nombre lignes dans le rsultat":"FALSE";
// autre dtermination du nombre de lignes lues
$nombre = ociRowCount($curseur);
echo "<BR>$nombre ligne dans le rsultat";
// excution de la requte
$ok = oci_execute($curseur);
// Fetch de toutes les lignes
// - prsentation par ligne
$nombre = oci_fetch_all($curseur,$rsultat,0,-1,OCI_FETCHSTATEMENT_BY_ROW);
afficher_tableau($rsultat,"Pas de rsultat : par ligne");
echo ($nombre)?"$nombre lignes dans le rsultat":"FALSE";
// autre dtermination du nombre de lignes lues
$nombre = ociRowCount($curseur);
echo "<BR>$nombre ligne dans le rsultat";
?>

Rsultat (en supposant que les prix ont t remis dans la table)

oci_fetch_all($curseur,$rsultat)
IDENTIFIANT =
0 = 1
1 = 2
2 = 3
3 = 4
LIBELLE =
0 = Abricots
1 = Cerises
2 = Fraises
3 = Pches

ENI Editions - All rigths reserved - 11 -


PRIX =
0 = 35,5
1 = 48,9
2 = 29,95
3 = 37,2
4 lignes dans le rsultat
4 lignes dans le rsultat
oci_fetch_all($curseur,$rsultat,1,2)
IDENTIFIANT =
0 = 2
1 = 3
LIBELLE =
0 = Cerises
1 = Fraises
PRIX =
0 = 48,9
1 = 29,95
2 lignes dans le rsultat
3 lignes dans le rsultat
oci_fetch_all($curseur,$rsultat,0,2,OCI_FETCHSTATEMENT_BY_ROW)
0 =
IDENTIFIANT = 1
LIBELLE = Abricots
PRIX = 35,5
1 =
IDENTIFIANT = 2
LIBELLE = Cerises
PRIX = 48,9
2 lignes dans le rsultat
2 lignes dans le rsultat
oci_fetch_all($curseur,$rsultat,0,2,OCI_FETCHSTATEMENT_BY_ROW+OCI_NUM)
0 =
0 = 1
1 = Abricots
2 = 35,5
1 =
0 = 2
1 = Cerises
2 = 48,9
2 lignes dans le rsultat
2 lignes dans le rsultat
Pas de rsultat : par colonne
IDENTIFIANT =
LIBELLE =
PRIX =
FALSE
0 ligne dans le rsultat
Pas de rsultat : par ligne
FALSE
0 ligne dans le rsultat

Ledeuximeexemplemontreladiffrencedersultatentre oci_fetch_allet oci_num_rowslorsquedeslignes


sontignoresdansoci_fetch_all.

Les deux derniers exemples montrent ce qui se passe lorsque la requte ne retourne aucune ligne. Lors d'une
prsentation par colonnes (par dfaut), le tableau est initialis avec la liste des colonnes. Lors d'une
prsentationparlignes,letableauestvide.

Lafonctionoci_fetch_allretourneFALSEetafficheunealertedanslescassuivants :

- curseur non analys (pas d'appel la fonction oci_parse) ;

Warning: oci_fetch_all(): supplied argument is not a valid OCI8-Statement resource in


d:\scripts php\index.php on line 13

- curseur non excut (pas d'appel la fonction ociExecute) ;

Warning: oci_fetch_all() [function.oci-fetch-all]: OCIFetchStatement:


ORA-24338: descripteur d'instruction non excut in d:\scripts php\index.php on line 13

- curseur excut avec erreur ;

- 12 - ENI Editions - All rigths reserved


Warning: oci_fetch_all() [function.oci-fetch-all]: OCIFetchStatement:
ORA-24374: dfinition non excute aprs extraction ou excution et
extraction in d:\scripts php\index.php on line 13

- curseur dj compltement parcouru :

Warning: oci_fetch_all() [function.oci-fetch-all]: OCIFetchStatement:


ORA-01002: Extraction en rupture de squence in d:\scripts\index.php
on line 13

Quellemthodeutiliser ?

Pour lire une seule ligne, les fonctions oci_fetch_array, oci_fetch_assoc, oci_fetch_object et
oci_fetch_row peuvent tre utilises indiffremment. C'est avant tout une affaire de got personnel il n'y a
aucune diffrence de performance entre les diffrentes fonctions. Personnellement, nous avons une petite
prfrencepourl'utilisationdutableauassociatifavecconservationdesvaleursNULL.

Pour lire toutes les lignes, vous pouvez utiliser la fonction oci_fetch_all si vous souhaitez passer par un
tableauetquelastructuredutableauvousconvienne.Sivousnesouhaitezpaspasserparuntableauouquela
structuredutableaunevousconviennepas,vouspouvezutiliserunedesautresfonctions oci_fetch_*etune
boucle.

Utiliserdesrequtesparamtres

Avec Oracle, il est possible d'employer des requtes paramtres, de les envoyer pour analyse au serveur puis
d'associer un paramtre de la requte une variable PHP (notion de "bind"). chaque excution, la valeur
courantedelavariablePHPestutilise.

L'intrt est de pouvoir rutiliser plusieurs fois la mme requte, avec des valeurs diffrentes de paramtres,
sansanalyserdenouveaularequte.Parailleurs,l'utilisationdevariables"bind"amliorelepartagedesrequtes
danslammoireOracle(dansla"sharedpool").

Auniveaudelarequte,unparamtreestunidentifiantprcdducaractredeuxpoints (:).

Exemple

$requte = "SELECT * FROM articles WHERE identifiant = :p1";

Un paramtre ne peut pas remplacer un nom de table, un nom de colonne ou toute une partie de la requte.

Exemples interdits

$requte = "SELECT * FROM :p1";


$requte = "SELECT * FROM articles WHERE :p1";

La fonction oci_bind_by_name (anciennement OciBindByName) permet, ensuite, d'tablir la liaison entre un


paramtredelarequteetunevariablePHP.

Syntaxe

boolen oci_bind_by_name(ressource curseur, chane paramtre, mixte variable[, entier longueur[,


entier type]])

curseur

Identifiantducurseurprcdemmentanalys.

paramtre

Nomduparamtredanslarequte(aveclecaractre:)
Exemple ::p1

variable

ENI Editions - All rigths reserved - 13 -


VariablePHPassocie.

longueur

Longueurmaximumdel'espaceutilispourlaliaison.
Valeurpardfaut :1(voirlesconsquencesciaprs).

type

Indiquesilaliaisonestd'untypeparticulierl'aided'unedesconstantessuivantes :
OCI_B_ROWID,OCI_B_CLOB,OCI_B_BLOB,OCI_B_BFILE
OCI_B_CFILE, OCI_B_NTY, OCI_B_CURSOR

La fonction oci_bind_by_name retourne TRUE si l'association a pu s'effectuer et FALSE dans le cas contraire
(accompagnd'unealerte).

L'unit du paramtre longueur n'est pas clairement dfinie dans la documentation l'usage, il semble que ce
soit un nombre de caractres (y compris pour les nombres). Si ce paramtre est gal 1 (soit explicitement,
soitpardfautlorsqu'iln'estpasrenseign),lalongueurestdfinieparlecontenudelavariableau moment de
l'appellafonction silavariablen'estpasdfinie,lalongueurestgale1.

Leparamtrelongueurdoittrepositionnavecsoincaruneerreurrisquedesurveniraumomentdel'appella
fonctionoci_execute,silalongueurdelavariablecetinstantestsuprieurelalongueurpriseencompteau
momentdel'appeloci_bind_by_name.

Exemple de message

Warning: OCI_Execute() [function.oci-execute]:


OCIStmtExecute: ORA-01460: demande d'une conversion non implmente
ou irraliste in d:\scripts php\index.php on line 15.

Une des solutions, pour viter les problmes, consiste appeler systmatiquement la fonction
oci_bind_by_name sans paramtre juste avant chaque appel la fonction oci_execute. De cette manire,
voustescertaindeprendrelalongueuractuelledelavariable.Uneautreapprocheconsisteplacerunevaleur
avecunegrandemargedescurit.

Le paramtre type permet de grer des types de donnes particuliers, en l'occurrence les diffrents types LOB
(BLOB, CLOB et BFILE) et le type ROWID, les types de donnes dfinis par l'utilisateur et les curseurs. Si ce
paramtreestspcifi,ilfautmettreleparamtrelongueur1.

Exemple

<?php
// inclusion du fichier qui contient la dfinition de
// afficher_tableau
include("fonctions.inc");
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// dfinition d'une premire requte paramtre
$requte = "SELECT * FROM articles WHERE identifiant = :p1";
// analyse de la requte
$curseur = oci_parse($connexion,$requte);
// association entre le paramtre et la variable PHP
oci_bind_by_name($curseur,":p1",$identifiant,10);
// excution de la requte avec une premire valeur de la variable
$identifiant = 1;
$ok = oci_execute($curseur);
// lire le rsultat
$ligne = oci_fetch_assoc($curseur);
echo "$ligne[IDENTIFIANT] - $ligne[LIBELLE]<BR>";
// excution de la requte avec une deuxime valeur
// de la variable (utilisation du mme curseur)
$identifiant = 2;
$ok = oci_execute($curseur);
// lire le rsultat
$ligne = oci_fetch_assoc($curseur);
echo "$ligne[IDENTIFIANT] - $ligne[LIBELLE]<BR>";

- 14 - ENI Editions - All rigths reserved


// dfinition d'une requte qui slectionne les ROWID
$requte = "SELECT ROWID FROM articles";
// analyse de la requte
$curseur = oci_parse($connexion,$requte);
// excution de la requte
$ok = oci_execute($curseur);
// rcupration du premier ROWID
$ligne = oci_fetch_assoc($curseur);
$rowid = $ligne['ROWID'];
// dfinition d'une requte paramtre utilisant le ROWID
$requte = "SELECT * FROM articles WHERE ROWID = :p1";
// analyse de la requte
$curseur = oci_parse($connexion,$requte);
// association entre le paramtre et la variable PHP
oci_bind_by_name($curseur,":p1",$rowid,-1,OCI_B_ROWID);
// excution de la requte avec le premier ROWID
//(actuellement dans $rowid)
$ok = oci_execute($curseur);
// lire le rsultat
$ligne = oci_fetch_assoc($curseur);
echo "$ligne[IDENTIFIANT] - $ligne[LIBELLE]<BR>";
?>

Rsultat

1 - Abricots
2 - Cerises
1 - Abricots

Les types de donnes BLOB, CLOB, BFILE et ROWID se manipulent, en PHP, sous forme d'objets la fonction
oci_new_descriptor (anciennement OciNewDescriptor) permet de crer ces objets en cas de besoin. titre
d'illustration,unexemplepluscompletdel'utilisationduROWIDestdonndanslepointMettrejourdesdonnes
de ce chapitre. En cas de besoin, le ROWID peut tre converti dans la requte en chane (fonction SQL
ROWIDTOCHAR)etrciproquement(fonctionSQLCHARTOROWID) ilestalorsplusfacilemanipuler(parexemple,
pourleplacerdansunezonedeformulairecache).

Exempledecodepourlalectured'uneligne

Un premier type de lecture consiste souvent lire une seule ligne d'information dans une table ou plusieurs
tablesavecjointure(s) :obtentiond'informationssurl'utilisateurquivientdeseconnecter,fichededescription
d'unarticle...

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// initialiser les variables
$identifiant = "";
$libell = "";
$prix = "";
$message = "";
// Tester comment le script est appel
if (! empty($_POST)) {
// traitement du formulaire ...
// rappel : lorsqu'un formulaire n'a qu'une zone de texte
// et que l'utilisateur tape return ou enter, le bouton de
// validation n'est pas considr comme cliqu. Pour savoir
// si le formulaire a t soumis, il faut tester si
// $_POST (ou $_GET) est vide ou non.
// rcuprer les valeurs saisies
$identifiant = valeur_saisie($_POST["identifiant"]);
// contrler les valeurs saisies
if ($identifiant == "") {
$message .= "L'identifiant est obligatoire.\n";
}
if (! ereg("^[0-9]+$",$identifiant)) {
$message .=
"L'identifiant doit tre un nombre.\n";
}
// tester s'il y a des erreurs ce stade
if ($message == "") {
// pas d'erreur

ENI Editions - All rigths reserved - 15 -


// excuter la requte de slection
// connexion
$ok =($connexion =
oci_connect("demeter","demeter","diane"));
if ($ok) {
// dfinition de la requte (paramtre)
$requte = "SELECT * FROM articles WHERE
identifiant = :p1";
// analyse de la requte
$ok = ($curseur = oci_parse($connexion,$requte));
}
if ($ok) {
// association entre le paramtre et la variable
$ok = oci_bind_by_name($curseur,":p1",$identifiant,32);
}
if ($ok) {
// excution de la requte
$ok = oci_execute($curseur);
}
if ($ok) {
// fetch
$article =
oci_fetch_array($curseur,OCI_ASSOC+OCI_RETURN_NULLS);
}
// tester le rsultat
if (! $ok) { // requte pas OK
$message .= "Erreur.\n";
} elseif (! $article) { // rsultat vide
$message .=
"Pas d'article pour cet identifiant.\n";
} else { // OK
// rcuprer les informations afficher
// - bien noter les cls en majuscules
$libell = $article["LIBELLE"];
$prix = $article["PRIX"];
// mise en forme
$libell = vers_page($libell);
$prix = number_format($prix,2,"," ," ");
$prix = vers_page($prix);
}
}
// tester s'il y a des erreurs ce stade
if ($message != "") {
// erreur
// prparer le message pour l'affichage
$message = vers_page($message);
// bien s'assurer que les informations afficher sont vides
$libell = "";
$prix = "";
}
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Consultation d'un article</TITLE></HEAD>
<BODY>
<FORM METHOD="POST">
Identifiant de l'article :
<INPUT TYPE="text" NAME="identifiant"
VALUE="<?php echo vers_formulaire($identifiant); ?>">
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<TABLE BORDER="0">
<TR><TD><U>Libell :</U> </TD>
<TD><?php echo $libell; ?></TD></TR>
<TR><TD><U>Prix :</U> </TD>
<TD><?php echo $prix; ?></TD></TR>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?><</FONT>
</BODY>
</HTML>

Rsultat (aprs saisie et clic sur le bouton OK)

- 16 - ENI Editions - All rigths reserved


Ilestrelativementsimpled'crireunefonctiongnriquepermettantdelireuneligne.

Exemple

<?php
function db_lire_ligne($requte) {
// se connecter
$ok =($connexion =
oci_connect("demeter","demeter","diane"));
if ($ok) { // connexion OK
// analyser la requte
$ok = ($curseur = oci_parse($connexion,$requte));
}
if ($ok) { // analyse OK
// excuter la requte
$ok = oci_execute($curseur);
}
if ($ok) { // excution OK
// lire le rsultat
$ligne =
oci_fetch_array($curseur,OCI_ASSOC+OCI_RETURN_NULLS);
}
// retourner $ligne ou FALSE en cas d'erreur
return ($ok)?$ligne:FALSE;
}
?>

Ilestpossible(souhaitable)d'amliorerlagestiondeserreurs(cf.Grerleserreurs).

Exemple d'utilisation

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// dfinir la requte
$requte = "SELECT * FROM articles WHERE identifiant= 1";
// lire le rsultat
$ligne = db_lire_ligne($requte);
if ($ligne) {
// bien noter les cls en majuscules
echo "$ligne[LIBELLE] - $ligne[PRIX]";
}
?>

Rsultat (sauf erreur)

Abricots - 35.5

Exempledecodepourlalecturedetoutesleslignes

Un deuxime type de lecture consiste souvent afficher une liste d'lments extraits de la base (liste
d'utilisateurs,listed'articles...).

Exemple (en utilisant la fonction oci_fetch_all pour tout charger dans un tableau)

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// excuter la requte de slection

ENI Editions - All rigths reserved - 17 -


// connexion
$ok =($connexion =
oci_connect("demeter","demeter","diane"));
if ($ok) {
// dfinition de la requte
$requte = "SELECT * FROM articles";
// analyse de la requte
$ok = ($curseur = oci_parse($connexion,$requte));
}
if ($ok) {
// excution de la requte
$ok = oci_execute($curseur);
}
if ($ok) {
// fetch
$nombre = oci_fetch_all($curseur,$articles);
}
// tester le rsultat
if (! $ok) { // requte pas OK
$message .= "Erreur.\n";
} elseif ($nombre == FALSE) { // rsultat vide
$message .=
"Aucun article dans la base.\n";
} else { // OK
// mettre en forme les donnes (idem prcdemment)
// noter l'inversion de la logique de parcours du tableau
// par rapport MySQL
for ($i=0;$i<$nombre;$i++) {
$articles["LIBELLE"][$i] =
vers_page($articles["LIBELLE"][$i]);
$articles["PRIX"][$i] =
vers_page(
number_format($articles["PRIX"][$i],2,"," ," "));
}
}
// tester s'il y a des erreurs ce stade
if ($message != "") {
// erreur
// prparer le message pour l'affichage
$message = vers_page($message);
// bien s'assurer que les informations
// afficher sont vides
unset($articles);
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML -->
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if ($nombre != FALSE) { // s'il y a un rsultat afficher
for ($i=0;$i<$nombre;$i++) { // boucle sur les articles
// gnration de la ligne de la table HTML
// remarque : printf() rend le code lisible
printf("<TR><TD>%d</TD><TD>%s</TD><TD>%s</TD></TR>",
$articles["IDENTIFIANT"][$i],
$articles["LIBELLE"][$i],
$articles["PRIX"][$i]);
}
}
?>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Il est possible d'crire le mme exemple de manire plus compacte. Ce dernier sera alors plus conome en
mmoireetplusperformant :lefetchesteffectuaucoursdelaconstructiondelatableHTML.

Exemple

- 18 - ENI Editions - All rigths reserved


<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// excuter la requte de slection
// connexion
$ok =($connexion =
oci_connect("demeter","demeter","diane"));
if ($ok) {
// dfinition de la requte
$requte = "SELECT * FROM articles";
// analyse de la requte
$ok = ($curseur = oci_parse($connexion,$requte));
}
if ($ok) {
// excution de la requte
$ok = oci_execute($curseur);
}
// tester le rsultat
if (! $ok) { // requte pas OK
// message d'erreur
$message .= "Erreur.\n";
// prparer le message pour l'affichage
$message = vers_page($message);
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML -->
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if ($ok) { // s'il y a un rsultat afficher
// boucle de fetch
while ($article = oci_fetch_array($curseur,
OCI_ASSOC+OCI_RETURN_NULLS)) {
// mise en forme des donnes
$article["LIBELLE"] = vers_page($article ["LIBELLE"]);
$article["PRIX"] = vers_page(
, number_format($article["PRIX"],2,"," ," "));
// gnration de la ligne de la table HTML
printf ("<TR><TD>%d</TD><TD>%s</TD><TD>%s</TD></TR>",
$article["IDENTIFIANT"],
$article["LIBELLE"],
$article["PRIX"]);
} // while
// si le rsultat est vide, prparer un message
// oci_num_rows donne le nombre de lignes lues ...
if (oci_num_rows($curseur) == 0) {
$message = vers_page("Aucun article dans la base.");
}
} // if ($ok)
?>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Pourpermettrel'utilisateurd'agirsurlaliste,ilestpossibled'imbriquerunformulaireoudesliensaveclatable
HTML.

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// excuter la requte de slection
// connexion
$ok =($connexion =

ENI Editions - All rigths reserved - 19 -


oci_connect("demeter","demeter","diane"));
if ($ok) {
// dfinition de la requte
$requte = "SELECT * FROM articles";
// analyse de la requte
$ok = ($curseur = oci_parse($connexion,$requte));
}
if ($ok) {
// excution de la requte
$ok = oci_execute($curseur);
}
// tester le rsultat
if (! $ok) { // requte pas OK
// message d'erreur
$message .= "Erreur.\n";
// prparer le message pour l'affichage
$message = vers_page($message);
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML l'intrieur d'un
---- formulaire -->
<FORM METHOD="POST">
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Libell</TH><TH>Prix</TH><TH>Case</TH><TH>Lien</TH>
</TR>

<!-- code PHP pour les lignes du tableau -->


<?php
if ($ok) { // s'il y a un rsultat afficher
// boucle de fetch
while ($article = oci_fetch_array($curseur,
OCI_ASSOC+OCI_RETURN_NULLS)) {
// mise en forme des donnes
$article["LIBELLE"] = vers_page($article ["LIBELLE"]);
$article["PRIX"] = vers_page(
number_format($article["PRIX"],2,"," ," "));
// gnration de la ligne de la table HTML
// - une case cocher dans une colonne
// - un lien dans une autre colonne
printf("<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD>
<TD>%s</TD></TR>",
$article["LIBELLE"],
$article["PRIX"],
"<INPUT TYPE=\"checkbox\" NAME=\"choix[]\"
VALUE=\"$article[IDENTIFIANT]\">",
"<A HREF=\"javascript:alert($article[IDENTIFIANT])\">
action<A>");
} // while
// si le rsultat est vide, prparer un message
// oci_num_rows donne le nombre de lignes lues ...
if (oci_num_rows($curseur) == 0) {
$message = vers_page("Aucun article dans la base.");
}
} // if ($ok)
?>
</TABLE>
<BR><INPUT TYPE="submit" NAME="action" VALUE="Action">
</FORM>
<FONT COLOR="green">
<?php
// traitement du formulaire
// simple affichage des identifiants cochs
if (isset($_POST["action"])) {
if (isset($_POST["choix"])) {
echo "Identifiant(s) coch(s) : ".
implode("+",$_POST["choix"]);
}
?>
</FONT>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

- 20 - ENI Editions - All rigths reserved


Rsultat

- Affichage initial de la page :

- Aprs clic sur un lien :

- Aprs clic sur le bouton Action :

Sur le lien, la place du code JavaScript, il est possible de mettre une vraie URL et d'enchaner sur une autre
page(cf.chapitreGrerlessessionspourcomprendrecommentmettreunparamtredansl'URLetpouvoirainsi
passeruneinformation,icil'identifiantchoisi,uneautrepage).

Encequiconcerneletraitementduformulaire,toutestenvisageable.

Lencore,pourlalecturedeplusieurslignes,unefonctiongnriquepeuttreutilise.

ENI Editions - All rigths reserved - 21 -


Exemple

<?php
function db_lire_lignes_dans_tableau($requte) {
// se connecter
$ok =($connexion =
oci_connect("demeter","demeter","diane"));
if ($ok) { // connexion OK
// analyser requte
$ok = ($curseur = oci_parse($connexion,$requte));
}
if ($ok) { // analyse OK
// excuter la requte
$ok = oci_execute($curseur);
}
if ($ok) { // excution OK
// lire le rsultat
$nombre = oci_fetch_all($curseur,$tableau);
}
// retourner $tableau ou FALSE en cas d'erreur
return ($ok)?$tableau:FALSE;
}
?>

Utilisation

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// dfinir la requte
$requte = "SELECT * FROM articles";
// lire le rsultat dans un tableau
$articles = db_lire_lignes_dans_tableau($requte);
// afficher le premier article lu
if ($articles) {
echo count($articles['IDENTIFIANT'])." articles<BR>";
echo "Premier article : ";
echo "{$articles['LIBELLE'][0]} - {$articles['PRIX'][0]}";
}
?>

Rsultat (sauf erreur)

4 articles
Premier article : Abricots - 35.5

ladiffrencedeMySQL,letableaun'estpasvidesilersultatestvide.Cependant,ilestfaciledemodifierce
comportement,encasdebesoin,parappellafonctionarray().

Cettefonctiongnriquepeut,parexemple,treutilisepourconstruireuneliste<SELECT>dansunformulaire.

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// chargement de la liste des fruits
$requte = "SELECT identifiant,libelle FROM articles
ORDER BY libelle";
$fruits_du_march = db_lire_lignes_dans_tableau($requte);
?>
<!-- construction du formulaire -->
<FORM METHOD="POST">
Fruits prfrs :<BR>
<SELECT NAME="fruits[]" MULTIPLE SIZE="8">
<?php
// code PHP gnrant la partie dynamique du formulaire
// parcourir la liste afficher
$nombre = count($fruits_du_march['IDENTIFIANT']);
for($i=0;$i<$nombre;$i++) {
// gnrer la balise OPTION avec l'identifiant
// pour l'option VALUE et le libell pour le texte affich dans la liste
echo "<OPTION VALUE=
\"{$fruits_du_march['IDENTIFIANT'][$i]}\">

- 22 - ENI Editions - All rigths reserved


{$fruits_du_march['LIBELLE'][$i]}\n";
}
?>
</SELECT>
<INPUT TYPE="submit" NAME="OK" VALUE="OK"><BR>
</FORM>

Rsultat

Mettrejourdesdonnes

MettrejourdesdonnesconsisteexcuterdesrequtesINSERT(cration),UPDATE(modification)ouDELETE
(suppression).

L'excution de ce type de requte s'effectue avec les fonctions oci_parse et oci_execute, comme pour une
requteSELECT,aveclammepossibilitd'utiliserdesrequtesparamtres.

UnedesdiffrencesfondamentalesavecMySQLconcernelagestiondestransactions.

Par dfaut, la fonction oci_execute agit en "auto COMMIT" : si l'ordre de mise jour a russi, il est
immdiatementCOMMIT.PourgrerunetransactioncomposedeplusieursordresSQL,ilconvientd'excuterles
ordresindividuelssanslemode"autoCOMMIT"etd'excuter,lafin,unordreCOMMITouROLLBACK.

La fonction oci_execute accepte un deuxime paramtre qui permet d'indiquer le fonctionnement souhait vis
visduCOMMIT.

Cedeuximeparamtrepeutprendredeuxvaleurs :

OCI_COMMIT_ON_SUCCESS
(valeurpardfaut)

COMMITautomatiquesil'ordredemisejours'estcorrectementexcut.

OCI_DEFAULT

PasdeCOMMITautomatique.

PourexcuterunordreCOMMITouROLLBACK,deuxmthodessontdisponibles :

- La premire consiste excuter ces ordres, comme les autres ordres SQL, l'aide des fonctions oci_parse et
oci_execute.

- La deuxime consiste utiliser les fonctions oci_commit et oci_rollback (anciennement ociCommit et


ociRollback).

Syntaxe

boolen oci_commit(ressource connexion)


boolen oci_rollback(ressource connexion)

connexion

Identifiantdelaconnexionsurlaquelleexcuterl'ordreSQLCOMMITouROLLBACK.

ENI Editions - All rigths reserved - 23 -


Exemple

<?php
// premire mthode
$ok = oci_execute(oci_parse($connexion,"COMMIT"));
$ok = oci_execute(oci_parse($connexion,"ROLLBACK"));
// deuxime mthode
$ok = oci_commit($connexion);
$ok = oci_rollback($connexion);
?>

La bibliothque "Oracle 8" ne propose par d'quivalent la fonction mysql_insert_id mais il est possible
d'utiliserlaclauseRETURNINGdesordresSQLINSERT, UPDATEouDELETE(voirciaprs).

En complment, la fonction oci_num_rows, tudie prcdemment, permet de connatre le nombre de lignes


concernesparladernirerequteINSERT, UPDATEouDELETEexcutedansuncurseur.

Dans les requtes INSERT, UPDATE et DELETE, Oracle autorise (depuis la version 8i), de placer la fin des
requtesINSERT, UPDATEet DELETE,uneclauseRETURNINGquipermetdercuprerlavaleurd'uneouplusieurs
colonnes aprs l'insertion et la modification, ou avant la suppression. Pour rcuprer ces valeurs dans le code
PHP,ilsuffitd'utiliserdesparamtresetdelesassocierdesvariablesaveclafonctionoci_bind_by_name.

Syntaxe

RETURNING colonne[, ...] INTO :paramtre[, ...]

Exemples

<?php
// inclusion du fichier qui contient la dfinition des fonctions gnrales
include("fonctions.inc");
// dfinition d'une petite fonction d'affichage de la liste des articles
function AfficherArticles() {
$requte = "SELECT * FROM articles";
$articles = db_lire_lignes_dans_tableau($requte);
if ($articles) {
echo "<B>Liste des articles :</B><BR>";
$nombre = count($articles['IDENTIFIANT']);
for($i=0;$i<$nombre;$i++) {
echo "{$articles['IDENTIFIANT'][$i]} _
{$articles['LIBELLE'][$i]} _
{$articles['PRIX'][$i]}<BR>";
}
} else {
echo "<B>Plus d'articles.</B><BR>";
}
}
// affichage de contrle
AfficherArticles();
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// requte INSERT (paramtre)
$requte = "INSERT INTO articles(libelle,prix)
VALUES(:p1,:p2)
RETURNING identifiant, ROWID, ROWIDTOCHAR(ROWID)
INTO :r1,:r2,:r3";
// analyse
$curseur = oci_parse($connexion,$requte);
// cration d'une variable pour le rowid
$rowid = oci_new_descriptor($connexion,OCI_D_ROWID);
// association entre les variables et les paramtres
oci_bind_by_name($curseur,":p1",$libell,50);
oci_bind_by_name($curseur,":p2",$prix,32);
oci_bind_by_name($curseur,":r1",$identifiant,32);
oci_bind_by_name($curseur,":r2",$rowid,-1,OCI_B_ROWID);
oci_bind_by_name($curseur,":r3",$rowid_chane,32);
// excution de la requte
$libell = "Poire"; // valeur du libell (sans s)
$prix = 0; // valeur du prix (0 pour l'instant)
$ok = oci_execute($curseur); // COMMIT automatique
echo "Identifiant du nouvel article = $identifiant.<BR>";
echo "ROWID du nouvel article = $rowid (objet !).<BR>";
echo "ROWID du nouvel article = $rowid_chane (chane).<BR>";

- 24 - ENI Editions - All rigths reserved


// requte UPDATE paramtre utilisant le ROWID objet
$requte = "UPDATE articles SET prix = :p1
WHERE ROWID = :p2";
// analyse
$curseur = oci_parse($connexion,$requte);
// association entre les variables et les paramtres
oci_bind_by_name($curseur,":p1",$prix,32);
oci_bind_by_name($curseur,":p2",$rowid,-1,OCI_B_ROWID);
// excution de la requte
$prix = 29.9; // valeur du prix ($rowid dj initialis)
$ok = oci_execute($curseur); // COMMIT automatique
// requte UPDATE paramtre utilisant le ROWID chane
$requte = "UPDATE articles SET libelle = :p1
WHERE ROWID = CHARTOROWID(:p2)";
// analyse
$curseur = oci_parse($connexion,$requte);
// association entre les variables et les paramtres
oci_bind_by_name($curseur,":p1",$libell,50);
oci_bind_by_name($curseur,":p2",$rowid_chane,32);
// excution de la requte
$libell = "Poires"; // valeur du libell (avec un s)
// $rowid_chane dj initialis
$ok = oci_execute($curseur); // COMMIT automatique
// requte UPDATE (non paramtre)
$requte = "UPDATE articles SET prix = prix * 1.1
WHERE prix < 40";
// analyse
$curseur = oci_parse($connexion,$requte);
// excution de la requte
$ok = oci_execute($curseur); // COMMIT automatique
$nombre = oci_num_rows($curseur);
echo "$nombre article(s) augment(s).<BR>";
// requte DELETE (non paramtre)
$requte = "DELETE FROM articles WHERE prix > 40";
// analyse
$curseur = oci_parse($connexion,$requte);
// excution de la requte
$ok = oci_execute($curseur); // COMMIT automatique
$nombre = oci_num_rows($curseur);
echo "$nombre article(s) supprims(s).<BR>";
// affichage de contrle
AfficherArticles();
?>

Rsultat

Liste des articles :


1 - Abricots - 35.5
2 - Cerises - 48.9
3 - Fraises - 29.95
4 - Pches - 37.2
Identifiant du nouvel article = 5.
ROWID du nouvel article = Object (objet !).
ROWID du nouvel article = AAAESgAACAAAEQCA (chane).
4 article(s) augment(s).
2 article(s) supprims(s).
Liste des articles :
1 - Abricots - 39.05
3 - Fraises - 32.945
5 - Poires - 32.89

Cetexempleillustrelesdeuxtechniquesd'utilisationduROWID :

- emploi d'un objet ROWID initialement cr avec la fonction oci_new_descriptor,

- emploi sous forme d'une chane de caractres.

Crerdesformulairesquipermettentdemettrejourlesdonnesesttrssimple.

titred'exemple,nousallonsconstruireunformulairequipermetderaliserunesaisieenliste.

Prsentation du formulaire

ENI Editions - All rigths reserved - 25 -


Le formulaire propose le contenu actuel de la table qui peut tre modifi (saisie directe dans les zones) ou
supprim(parlescasescocher),pluscinqlignesvidesquipermettentdesaisirdenouvellesvaleurs.Danstous
lescas,l'identifiantn'estpassaisissable(c'estleserveurOraclequival'attribuer).

Chaque ligne du tableau contient quatre zones de formulaire qui sont nommes (option NAME de la balise
<INPUT>)delamaniresuivante :

Colonne Nom
Identifiant saisie[i][modifier]
Libell saisie[i][libelle]
Prix saisie[i][prix]
Supprimer saisie[i][supprimer]

L'indice i est l'identifiant de l'article pour les lignes qui existent, et un numro compris entre 1 et 5 pour les
lignesvides.Lazonedelacolonne Identifiantestunezonemasque(TYPE="hidden")quivatreutilisepour
identifierleslignesdanslesquellesl'utilisateuraeffectuunemodification.

Avec ce processus de nommage, toute la saisie est rcupre dans le script PHP sous la forme d'un tableau
multidimensionnel nomm $lignes. Chaque ligne du tableau correspond une ligne du formulaire avec la cl
gale l'identifiant (ou 1 5 pour les nouvelles lignes) et la valeur gale un tableau associatif donnant les
lmentssaisis.

Pour identifier les lignes modifies par l'utilisateur, les zones de saisie du libell et du prix des lignes existantes
contiennentlecodeJavaScriptsuivant :

onChange="document.formulaire[$n].value=1"

CecodeJavaScriptapoureffet,chaquefoisquelazoneenquestionestmodifie,deplacerun1danslazone
masque associe la ligne. Le formulaire s'appelant formulaire (<FORM NAME = "formulaire"...>),
l'expression document.formulaire[n] dsigne la nime zone du formulaire formulaire du document courant,
la premire zone du formulaire ayant le numro 0. Dans le source, la variable $n est calcule pour chaque ligne
$i du formulaire, par la formule $n = 4 * ($i - 1) : la zone cache de la ligne 1 a le numro 0 (c'est la
premireduformulaire),celledelaligne2lenumro4etainsidesuite.

Cetexemplepeut(doit)treamlior :

- pour contrler la saisie de l'utilisateur,

- pour grer les erreurs.

Exemple

- 26 - ENI Editions - All rigths reserved


<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// connexion
$ok =($connexion =
oci_connect("demeter","demeter","diane"));
// traitement du formulaire
if (isset($_POST["OK"])) {
// dfinition des curseurs paramtrs pour la mise jour
// pour optimiser, il serait possible d'attendre la
// premire utilisation d'une des requtes pour la dfinir
$requte = "INSERT INTO articles(libelle,prix)
VALUES(:p1,:p2)";
$cursINS = oci_parse($connexion,$requte);
oci_bind_by_name($cursINS,":p1",$libell,40);
oci_bind_by_name($cursINS,":p2",$prix,32);
$requte = "UPDATE articles
SET libelle = :p1, prix = :p2
WHERE identifiant = :p3";
$cursUPD = oci_parse($connexion,$requte);
oci_bind_by_name($cursUPD,":p1",$libell,40);
oci_bind_by_name($cursUPD,":p2",$prix,32);
oci_bind_by_name($cursUPD,":p3",$identifiant,32);
$requte = "DELETE FROM articles
WHERE identifiant = :p1";
$cursDEL = oci_parse($connexion,$requte);
oci_bind_by_name($cursDEL,":p1",$identifiant,32);
// rcuprer le tableau contenant la saisie
$lignes = $_POST["saisie"];
foreach($lignes as $identifiant => $ligne) {
// nettoyage de la saisie
$libell = valeur_saisie($ligne["libelle"]);
$prix = valeur_saisie($ligne["prix"]);
$prix = str_replace(",",".",$prix); // , => .
$prix = str_replace(" ","",$prix); // supprimer espaces
// ce niveau, il faudrait vrifier la saisie ...
$curseur = NULL;
if ($identifiant < 0 and $libell.$prix != "") {
// identifiant ngatif et quelque chose de saisi
// = cration = INSERT
$curseur = $cursINS;
} elseif (isset($ligne["supprimer"])) {
// case " supprimer " coche = suppression = DELETE
$curseur = $cursDEL;
} elseif (isset($ligne["modifier"])) {
// zone " modifier " TRUE (1) = modification = UPDATE
$curseur = $cursUPD;
}
// si une requte a t dtermine, l'excuter
if ($curseur != NULL) {
// pas de COMMIT automatique
$ok = oci_execute($curseur,OCI_DEFAULT);
// en cas d'erreur, interrompre le traitement
if (! $ok) {break; }
}
} // foreach
// Tester $ok pour savoir s'il faut faire un COMMIT ou un ROLLBACK
if ($ok) { // OK = COMMIT
$ok = oci_commit($connexion);
} else { // pas OK = ROLLBACK
$ok = oci_rollback($connexion);
// prparer un message d'erreur (plutt succinct !)
$message = vers_page("Erreur lors de la mise jour.");
}
}
// recharger les articles
$requte = "SELECT * FROM articles";
$curseur = oci_parse($connexion,$requte);
$ok = oci_execute($curseur);
// ce niveau, il faudrait tester les erreurs ...
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Gestion des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML l'intrieur d'un
---- formulaire -->
<FORM NAME="formulaire" METHOD="POST">

ENI Editions - All rigths reserved - 27 -


<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
<TH>Supprimer</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if ($ok) { // s'il y a un rsultat afficher
// initialisation d'un compteur de ligne
$i = 0;
// boucle de fetch
while ($article = oci_fetch_array($curseur,OCI_ASSOC+OCI_RETURN_NULLS)) {
// incrmentation du compteur de ligne
$i++;
// calcul du numro d'ordre dans le formulaire de la
// zone cache correspondant l'identifiant
$n = 4 * ($i - 1);
// mise en forme des donnes
$article["LIBELLE"] = vers_page($article["LIBELLE"]);
$article["PRIX"] = vers_page(
number_format($article["PRIX"],2,"," ," "));
// gnration de la ligne de la table HTML
// insertion des balises INPUT du formulaire
printf(
"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>",
"$article[IDENTIFIANT]
<INPUT TYPE=\"hidden\"
NAME=\"saisie[$article[IDENTIFIANT]][modifier]\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[$article[IDENTIFIANT]][libelle]\"
VALUE=\"$article[LIBELLE]\"
onChange=\"document.formulaire[$n].value=1\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[$article[IDENTIFIANT]][prix]\"
VALUE=\"$article[PRIX]\"
onChange=\"document.formulaire[$n].value=1\">",
"<INPUT TYPE=\"checkbox\"
NAME=\"saisie[$article[IDENTIFIANT]][supprimer]\"
VALUE=\"$article[IDENTIFIANT]\">");
} // while
// ajout de 5 lignes vides pour la cration
// (sans identifiant, sans case de suppression)
for($i=1;$i<=5;$i++) {
printf(
"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>",
"",
"<INPUT TYPE=\"text\"
NAME=\"saisie[-$i][libelle]\"
VALUE=\"\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[-$i][prix]\"
VALUE=\"\">",
"");
} // for
}
?>
</TABLE>
<BR><INPUT TYPE="submit" NAME="OK" VALUE="Enregistrer">
</FORM>
<!-- affichage du message -->
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Appeleruneprocdurestocke

La bibliothque "Oracle 8" permet trs facilement d'excuter des blocs PL/SQL anonymes ou d'appeler des
procdures ou des fonctions stockes et des packages. Les procdures, fonctions et packages peuvent avoir
desparamtresenentre(IN)etensortie(OUT).

Le principe gnral consiste soumettre un bloc PL/SQL pour analyse et excution par l'intermdiaire des
fonctions oci_parse et oci_execute. L'appel la fonction oci_bind_by_name permet, en plus, d'associer des
variablesPHPauxventuelsparamtresdublocPL/SQL.

Si l'un des paramtres est un curseur (au sens REF CURSOR Oracle), il faut utiliser une variable PHP d'un type

- 28 - ENI Editions - All rigths reserved


adapt lafonctionoci_new_cursor(anciennementOciNewCursor)permetdecrerunetellevariable.

Syntaxe

ressource oci_new_cursor(ressource connexion)

connexion

Identifiantdelaconnexionsurlaquellelecurseurdoittrecr.

Lafonctionoci_new_cursorretourneunidentifiantdecurseurouFALSEencasd'erreur.

Pour associer un paramtre de type curseur et une variable de type curseur, il faut utiliser la constante
OCI_B_CURSORendernierparamtredelafonctionoci_bind_by_name(avecunelongueurgale1).

Aprs excution du bloc, la variable de type curseur contient un identifiant de curseur qu'il faut excuter
(fonctionoci_execute)avantdepouvoirlireleslignes(fonctionoci_fetch_*).

Nousallonsillustrercesdiffrentesfonctionnalitsl'aidedupackageOraclesuivant :

CREATE OR REPLACE PACKAGE pkg_articles IS


TYPE curseur IS REF CURSOR;
PROCEDURE creer(
p_libelle IN VARCHAR2,
p_prix IN NUMBER,
p_identifiant OUT NUMBER);
FUNCTION compter RETURN NUMBER;
PROCEDURE lire(
p_identifiant IN NUMBER,
p_curseur OUT curseur);
END pkg_articles;
/
CREATE OR REPLACE PACKAGE BODY pkg_articles IS
-- procdure d'insertion dans la table articles
-- retourne l'identifiant du nouvel article
-- dans p_identifiant
PROCEDURE creer(
p_libelle IN VARCHAR2,
p_prix IN NUMBER,
p_identifiant OUT NUMBER)
IS
BEGIN
INSERT INTO articles(identifiant,libelle,prix)
VALUES(s_articles.NEXTVAL,p_libelle,p_prix)
RETURNING identifiant INTO p_identifiant;
COMMIT;
END;
-- fonction de comptage des articles
FUNCTION compter RETURN NUMBER
IS
v_nombre NUMBER(9) := 0;

BEGIN
SELECT COUNT(identifiant) INTO v_nombre
FROM articles;
RETURN v_nombre;
END;
-- procdure de lecture d'un article (si p_identifiant > 0)
-- ou de tous les articles (si p_identifiant = 0)
-- le rsultat est retourn sous la forme d'un curseur
PROCEDURE lire(
p_identifiant IN NUMBER,
p_curseur OUT curseur)
IS
BEGIN
IF p_identifiant = 0 THEN
OPEN p_curseur FOR
SELECT * FROM articles;
ELSE
OPEN p_curseur FOR
SELECT * FROM articles
WHERE identifiant = p_identifiant;
END IF;

ENI Editions - All rigths reserved - 29 -


END;
END pkg_articles;
/

Source PHP

<?php
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// insertion l'aide du package
// - la procdure est appele dans un bloc PL/SQL
$requte = "BEGIN pkg_articles.creer(:p1,:p2,:r1); END;";
// analyse
$curseur = oci_parse($connexion,$requte);
// association paramtres/variables
oci_bind_by_name($curseur,":p1",$libell,50);
oci_bind_by_name($curseur,":p2",$prix,32);
oci_bind_by_name($curseur,":r1",$identifiant,32);
// excution avec certaines valeurs
$libell = "Pommes";$prix = 10;
// Pas de COMMIT automatique de oci_execute (le package
// s'en charge)
$ok = oci_execute($curseur,OCI_DEFAULT);
// affichage de l'identifiant du nouvel article
echo "Identifiant du nouvel article = $identifiant.<BR>";
// comptage l'aide du package
// - la procdure est appele dans un bloc PL/SQL
$requte = "BEGIN :r1 := pkg_articles.compter; END;";
// analyse
$curseur = oci_parse($connexion,$requte);
// association paramtres/variables
oci_bind_by_name($curseur,":r1",$nombre,32);
// excution
$ok = oci_execute($curseur,OCI_DEFAULT);
echo "$nombre article(s) dans la base.<BR>";
// lecture d'un article l'aide du package
// - la procdure est appele dans un bloc PL/SQL
$requte = "BEGIN pkg_articles.lire(:p1,:r1); END;";
// analyse
$curseur = oci_parse($connexion,$requte);
// cration d'un curseur pour le rsultat
$curseur_rsultat = oci_new_cursor($connexion);
// association paramtres/variables
oci_bind_by_name($curseur,":p1",$identifiant,32);
oci_bind_by_name($curseur,":r1",$curseur_rsultat,
-1,OCI_B_CURSOR);
// excution avec la valeur actuelle de $identifiant
// => lecture de l'article insr prcdemment
$ok = oci_execute($curseur,OCI_DEFAULT);
// excution du curseur rsultat
$ok = oci_execute($curseur_rsultat,OCI_DEFAULT);
// fetch
$article = oci_fetch_array($curseur_rsultat,
OCI_ASSOC+OCI_RETURN_NULLS);
echo "Nouveau : $article[LIBELLE] - $article[PRIX]<BR>";
// lecture de tous les articles l'aide du package
// - le curseur $curseur peut tre rutilis
// - par contre, $curseur_rsultat est "inutilisable" : il faut
// le recrer et le r-associer
oci_free_cursor($curseur_rsultat); // libration du premier
$curseur_rsultat = oci_new_cursor($connexion);
oci_bind_by_name($curseur,":r1",$curseur_rsultat,
-1,OCI_B_CURSOR);
// excution avec $identifiant = 0
$identifiant = 0;
$ok = oci_execute($curseur,OCI_DEFAULT);
// excution du curseur rsultat
$ok = oci_execute($curseur_rsultat,OCI_DEFAULT);
// fetch de toutes les lignes
echo "Liste : <BR>";
while ($article = oci_fetch_array($curseur_rsultat,
OCI_ASSOC+OCI_RETURN_NULLS)) {
echo "&nbsp&nbsp$article[LIBELLE] - $article[PRIX]<BR>";
}
?>

Rsultat

- 30 - ENI Editions - All rigths reserved


Identifiant du nouvel article = 5.
5 article(s) dans la base.
Nouveau : Pommes - 10
Liste :
Abricots - 35,5
Cerises - 48,9
Fraises - 29,95
Pches - 37,2
Pommes - 10

Les ressources utilises par les curseurs sont automatiquement libres la fin du script. En cas de besoin, les
fonctionsoci_free_cursoretoci_free_statementpeuventtreappelespourunelibrationanticipe.

Illustrationdesproblmeslisl'environnementNLS

Danscettepartie,nousallonsillustrerlanaturedesproblmesquipeuventseproduireavecl'environnementNLS
ettudierlesdiffrentessolutionspourrsoudrecesproblmes.

Exemple

<?php
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// rcupration de la date du serveur
$requte = "SELECT SYSDATE FROM dual";
$curseur = oci_parse($connexion,$requte);
$ok = oci_execute($curseur);
$ligne = oci_fetch_assoc($curseur);
echo "SYSDATE = $ligne[SYSDATE]<BR>";
// augmentation des prix l'aide d'une requte paramtre
$requte = "UPDATE articles SET prix = prix * :p1";
$curseur = oci_parse($connexion,$requte);
oci_bind_by_name($curseur,":p1",$coefficient,32);
$coefficient = 1.05; // 5% d'augmentation
$ok = oci_execute($curseur);
echo oci_num_rows($curseur)." lignes modifies.";
?>

Rsultat dans un certain environnement NLS

SYSDATE = 20-MAY-04
4 lignes modifies.

Rsultat dans un autre environnement NLS

SYSDATE = 20/05/04
Warning: oci_execute() [function.oci-execute]:
OCIStmtExecute: ORA-01722: Nombre non valide in d:\scripts php\index.php
on line 16
0 lignes modifies.

Ques'estilpassentrelesdeux ?

Leparamtre NLS_TERRITORYasimplementtchangde americafrance.Or,ceparamtregouverne,entre


autres,lecomportementvisvisdesformatsdedateetdesformatsdenombre.

Deuxproblmespeuventseproduire :

- Une donne attendue selon un certain format, et manipule dans le code selon ce format, peut changer de format en
fonction de l'environnement et donc poser des problmes dans le code.

- Une requte peut tre excute avec succs dans un environnement et pas dans l'autre.

L'erreursurladeuximerequteestlieaufaitque,dansunenvironnementfranais,lesparateurdcimalest
lavirgule(nonlepoint)etquelecoefficientd'augmentationpassenparamtreaunsparateurdcimalgalau
point.Labibliothquesemblepasserlesdonnesnumriquessousformedechane,cequiprovoqueunproblme

ENI Editions - All rigths reserved - 31 -


potentieldeconversion.

Dans le cas o l'environnement n'est pas matris et o vous souhaitez crire un code portable, ces problmes
peuventtretraitsdedeuxfaons :

- au cas par cas, chaque requte,

- globalement, en positionnant la session dans un environnement adapt.

Exemple avec la premire solution

<?php
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// rcupration de la date du serveur
// - la mise en forme attendue est obtenue par une
// conversion explicite
$requte = "SELECT TO_CHAR(SYSDATE, 'DD/MM/YYYY') d
FROM dual";
$curseur = oci_parse($connexion,$requte);
$ok = oci_execute($curseur);
$ligne = oci_fetch_assoc($curseur);
echo "SYSDATE = $ligne[D]<BR>"; // utilisation de l'alias
// augmentation des prix l'aide d'une requte paramtre
// - la chane implicitement passe en paramtre est
// explicitement convertie l'aide du bon format
$requte = "UPDATE articles
SET prix = prix * TO_NUMBER(:p1,'9.99')";
$curseur = oci_parse($connexion,$requte);
oci_bind_by_name($curseur,":p1",$coefficient,32);
$coefficient = 1.05; // 5% d'augmentation
$ok = oci_execute($curseur);
echo oci_num_rows($curseur)." lignes modifies.";
?>

Rsultat, quel que soit l'environnement

SYSDATE = 20/05/2004
4 lignes modifies.

Exemple avec la deuxime solution

<?php
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// dfinition de l'environnement souhait par
// deux requtes ALTER SESSION
$requte = "ALTER SESSION SET NLS_DATE_FORMAT='DD/MM/YYYY'";
$ok = oci_execute(oci_parse($connexion,$requte));
$requte = "ALTER SESSION SET NLS_NUMERIC_CHARACTERS='.,'";
$ok = oci_execute(oci_parse($connexion,$requte));
// rcupration de la date du serveur
$requte = "SELECT SYSDATE FROM dual";
$curseur = oci_parse($connexion,$requte);
$ok = oci_execute($curseur);
$ligne = oci_fetch_assoc($curseur);
echo "SYSDATE = $ligne[SYSDATE]<BR>";
// augmentation des prix l'aide d'une requte paramtre
$requte = "UPDATE articles SET prix = prix * :p1";
$curseur = oci_parse($connexion,$requte);
oci_bind_by_name($curseur,":p1",$coefficient,32);
$coefficient = 1.05; // 5% d'augmentation
$ok = oci_execute($curseur);
echo oci_num_rows($curseur)." lignes modifies.";
?>

Rsultat, quel que soit l'environnement

SYSDATE = 20/05/2004
4 lignes modifies.

- 32 - ENI Editions - All rigths reserved


Grerleserreurs

Lafonctionoci_error (anciennementociError)permetdercuprerdesinformationssurl'erreurventuellede
ladernireoprationeffectuedansuncurseur.

Syntaxe

tableau oci_error([ressource curseur])

curseur

Identifiantducurseuroudelaconnexion.

Lafonction oci_errorretourneuntableauassociatifsiladernireoprationeffectuedanslecurseuragnr
une erreur : la ligne de cl code donne le numro de l'erreur Oracle et la ligne de cl message, le message
associ. Si la dernire opration effectue dans le curseur n'a pas gnr d'erreur, la fonction oci_error
retourneFALSE.

Si la fonction oci_error est appele sans paramtre, elle doit retourner l'erreur ventuelle, rencontre sur la
dernire opration ralise (tout curseur confondu). Dans la pratique, cette syntaxe ne fonctionne qu'aprs un
appeloci_connectetpermetdercuprerlemessaged'erreurventuel,relatiflaconnexion.

Exemple

<?php
// mauvaise connexion
$connexion = oci_connect("demeter","MotDePasseErron","diane");
$e = oci_error(); // noter l'appel sans paramtre
echo "1 : ".($e?"$e[code] - $e[message]":"OK")."<BR>";
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// une bonne requte pour commencer
$requte = "SELECT * FROM articles";
$curseur = oci_parse($connexion,$requte);
$ok = oci_execute($curseur);
$e = oci_error($curseur);
echo "<P>2 : ".($e?"$e[code] - $e[message]":"OK")."<BR>";
// requte sur une table qui n'existe pas
$requte = "SELECT * FROM article";
$curseur = oci_parse($connexion,$requte);
$e = oci_error($curseur);
echo "<P>3.a : ".($e?"$e[code] - $e[message]":"OK")."<BR>";
$ok = oci_execute($curseur);
$e = oci_error(); // appel sans paramtre pour voir
echo "3.b : ".($e?"$e[code] - $e[message]":"OK")."<BR>";
$e = oci_error($curseur);
echo "3.c : ".($e?"$e[code] - $e[message]":"OK")."<BR>";
// requte INSERT qui viole une cl primaire
$requte = "INSERT INTO articles(identifiant,libelle,prix)
VALUES(1,'Poires',29.9)";
$curseur = oci_parse($connexion,$requte);
$ok = oci_execute($curseur);
$e = oci_error($curseur);
echo "<P>4 : ".($e?"$e[code] - $e[message]":"OK")."<BR>";
// tentative de fetch sur un mauvais rsultat
$requte = "SELECT * FROM article";
$curseur = oci_parse($connexion,$requte);
$ok = oci_execute($curseur);
$e = oci_error($curseur);
echo "<P>5.a : ".($e?"$e[code] - $e[message]":"OK")."<BR>";
$ligne = oci_fetch_assoc($curseur);
$e = oci_error($curseur);
echo "5.b : ".($e?"$e[code] - $e[message]":"OK")."<BR>";
?>

Rsultat

Warning: oci_connect() [function.oci-connect]:


OCISessionBegin: ORA-01017: invalid username/password; logon denied in
d:\scripts php\index.php on line 3
1 : 1017 - ORA-01017: invalid username/password; logon denied

ENI Editions - All rigths reserved - 33 -


2 : OK
3.a : OK
Warning: oci_execute() [function.oci-execute]:
OCIStmtExecute: ORA-00942: table or view does not exist in
d:\scripts php\index.php on line 22
3.b : OK
3.c : 942 - ORA-00942: table or view does not exist
Warning: oci_execute() [function.oci-execute]:
OCIStmtExecute: ORA-00001: unique constraint (DEMETER.ARTICLES$PK) violated in d:\scripts
php\index.php on line 32
4 : 1 - ORA-00001: unique constraint (DEMETER.ARTICLES$PK) violated
Warning: oci_execute() [function.oci-execute]:
OCIStmtExecute: ORA-00942: table or view does not exist in
d:\scripts php\index.php on line 39
5.a : 942 - ORA-00942: table or view does not exist
Warning: oci_fetch_assoc() [function.oci-fetch-assoc]:
OCIFetchInto: ORA-24374: define not done before fetch or
execute and fetch in d:\scripts php\index.php on line 42
5.b : 24374 - ORA-24374: define not done before fetch or execute and fetch

Quellequesoitl'erreur,unealerteestaffiche(cf.chapitreGrerleserreursdansunscriptPHPpoursupprimer
l'affichagedecesalertes).

Lersultat3fournitdeuxinformations :

- La fonction oci_error, sans paramtre, n'est d'aucune utilit, en dehors d'un appel aprs la fonction oci_connect.

- La fonction oci_parse, sur une mauvaise requte, ne gnre jamais d'erreur: la fonction oci_parse ne retourne
pas FALSE et la fonction oci_error retourne FALSE (donc pas d'erreur). L'erreur sera dtecte uniquement lors de
l'excution.

ContrairementMySQL,uneerreurestretournesiunetentativede fetchesteffectuesuruncurseurquin'a
pastexcut.

Dans la pratique, il convient d'appeler la fonction oci_error() aprs la fonction oci_connect, et oci_error
($curseur)aprslafonctionoci_execute.

Cesfonctionspeuventtremisesenuvre,titred'exemple,surunedenosfonctionsgnriques.

Exemple

<?php
function db_lire_ligne($requte, &$erreur) {
// dans cette nouvelle version, db_lire_ligne prend un
// deuxime paramtre par rfrence dans lequel un numro et un message
// seront stocks en cas d'erreur (sous la forme d'un tableau)
// initialiser $erreur
// code = 0, message vide
// le tableau est conforme la structure du tableau
// retourn par oci_error
$erreur = array("code" => 0, "message" => "");
// se connecter
$ok =($connexion =
oci_connect("demeter","demeter","diane"));
if ($ok) { // connexion OK
// analyser requte
$ok = ($curseur = oci_parse($connexion,$requte));
}
if ($ok) { // analyse OK
// excuter la requte
$ok = oci_execute($curseur);
}
if ($ok) { // excution OK
// lire le rsultat
$ligne = oci_fetch_array($curseur,
OCI_ASSOC+OCI_RETURN_NULLS);
}
if (! $ok) { // erreur quelque part
// si connexion OK, rcuprer l'erreur du curseur
// sinon, rcuprer l'erreur de la connexion
$erreur = $connexion?oci_error($curseur):oci_error();
}

- 34 - ENI Editions - All rigths reserved


// retourner $ligne ou FALSE en cas d'erreur
return ($ok)?$ligne:FALSE;
?>

Utilisation

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// premier appel avec une erreur
$requte = "SELECT * FROM article WHERE identifiant = 1";
if (! ($ligne = db_lire_ligne($requte,$erreur))) {
echo "$erreur[code] - $erreur[message]<BR>";
} else {
echo "$ligne[LIBELLE] - $ligne[PRIX]<BR>";
}
// deuxime appel correct
$requte = "SELECT * FROM articles WHERE identifiant = 1";
if (! ($ligne = db_lire_ligne($requte,$erreur))) {
echo "$erreur[code] - $erreur[message]<BR>";
} else {
echo "$ligne[LIBELLE] - $ligne[PRIX]<BR>";
?>

Rsultat

Warning: oci_execute() [function.oci-execute]:


OCIStmtExecute: ORA-00942: table or view does not exist in
d:\scripts php\index.php on line 42
942 - ORA-00942: Table ou vue inexistante
Abricots - 35.5

Le tableau retourn par la fonction oci_error offre deux lignes supplmentaires avec les cls offset et sqltext. La ligne
de cl offset donne la position de l'erreur dans le texte de la requte et la ligne de cl sqltext donne le texte de la requte.

ENI Editions - All rigths reserved - 35 -


UtilisationdeMicrosoftSQLServer

Prambule

LejeudefonctionspropospourMicrosoftSQLServeresttrsprochedeceluideMySQL.

En rgle gnrale, il suffit de remplacer le prfixe mysql_ des fonctions de MySQL par mssql_ pour obtenir la
fonctionquivalentedeMicrosoftSQLServer.Leprfixe mssql_nedoitpastreconfonduavec msql_quiestle
prfixedesfonctionsdelabasemSQL.

Connexionetdconnexion

Lafonctionmssql_connectpermetd'tabliruneconnexionavecunebaseSQLServer.

Syntaxe

ressource mssql_connect(chane serveur, chane utilisateur,


chane mot_de_passe)

serveur

Nomduserveur.

utilisateur

Nomdel'utilisateuremployerpourtablirlaconnexion.

mot_de_passe

Motdepasseutiliserpourtablirlaconnexion.

La fonction mssql_connect retourne un identifiant de connexion ou, en cas d'erreur, la valeur FALSE
accompagned'unmessaged'alerteenvoyl'affichage(cf.chapitre GrerleserreursdansunscriptPHPpour
grercettesituationcorrectement).

Danslemmescript,appelerdeuxfois mssql_connectaveclesmmesparamtresn'ouvrepasdeuxconnexions
diffrentes :lorsdudeuximeappel,l'identifiantdelaconnexiondjouverteestretourn.

Exemple

<?php
// exemple de connexion correcte
$id1 = mssql_connect("diane","demeter","demeter");
echo "\$id1 = $id1<BR>\n";
// exemple d'chec (mauvais mot de passe)
$id2 = mssql_connect("diane","demeter","zeus");
echo "\$id2 = $id2<BR>\n";
// nouvelle connexion avec les mmes paramtres que 1
$id3 = mssql_connect("diane","demeter","demeter");
echo "\$id3 = $id3 (= $id1)<BR>\n";
// gal $id1
?>

Rsultat

$id1 = Resource id #1
Warning: mssql_connect() [function.mssql-connect]: message:
chec de la connexion de l'utilisateur 'demeter'. (severity 14)
in d:\scripts php\index.php on line 8
Warning: mssql_connect() [function.mssql-connect]: Unable to
connect to server: diane in d:\scripts php\index.php on line 8
$id2 =
$id3 = Resource id #1 (= Resource id #1)

ENI Editions - All rigths reserved - 1-


Les connexions ouvertes dans un script sont automatiquement fermes la fin du script, sauf dconnexion
expliciteavantavecmssql_close(voirciaprs).

La fonction mssql_pconnect permet d'obtenir un fonctionnement diffrent et d'tablir une connexion dite
"permanente"quineserapasfermelafinduscriptetpourratrerutilisedanscescriptouunautrescript
ultrieurement.

Lasyntaxeestidentiquelasyntaxedelafonctionmssql_connect.

Lors de l'appel la fonction mssql_pconnect dans un script, PHP regarde si une connexion permanente a dj
t ouverte avec les mmes paramtres (serveur, utilisateur et mot de passe) : si oui, l'identifiant de cette
connexionestretourn sinon,unenouvelleconnexionesttablie(etcetteconnexionneserapasfermela
finduscript,autorisantainsisarutilisationultrieure).

La directive de configurationmssql.allow_persistent doit tre onpourouvrirdesconnexionspermanentes.


Par ailleurs, les directives mssql.max_persistent et mssql.max_linkspermettentrespectivementdelimiterle
nombredeconnexionspermanentesetlenombretotaldeconnexions.

Implicitement, la connexion est tablie sur la base par dfaut associe l'utilisateur toutes les requtes qui
sontexcutessurcetteconnexion,s'effectuentimplicitementsurcettebasepardfaut.

Lafonctionmssql_select_dbpermetdechangerlabaseactivedelaconnexion.

Syntaxe

boolen mssql_select_db(chane base[,ressource connexion])

base

Nomdelabaseactiver.

connexion

Identifiantdeconnexionretournparlafonctionmssql_connect.
Sinonprcis,s'appliqueladernireconnexionouverte.

La fonction mssql_select_db retourne TRUE si la base a pu tre change et FALSE autrement (accompagn
d'unealerte).

Exemple

<?php
// connexion
$connexion = mssql_connect("diane","demeter","demeter");
// changement de base
$ok = mssql_select_db("pubs",$connexion);
echo "\$ok = ".(($ok)?"TRUE":"FALSE")."<BR>\n";
// tentative de changement pour une base qui n'existe pas
$ok = mssql_select_db("pub",$connexion);
echo "\$ok = ".(($ok)?"TRUE":"FALSE")."<BR>\n";
?>

Rsultat

$ok = TRUE
Warning: mssql_select_db() [function.mssql-select-db]:
message: Impossible de trouver l'entre dans sysdatabases pour la base de donnes 'pub'. Aucune
entre ne porte ce nom. Assurez-vous que le nom est correctement saisi. (severity 16)
in d:\scripts php\index.php on line 8
Warning: mssql_select_db() [function.mssql-select-db]:
Unable to select database: pub in d:\scripts php\index.php on line 8
$ok = FALSE

Lafonctionmssql_closepermetdefermeruneconnexionencoursdescript.

- 2- ENI Editions - All rigths reserved


Syntaxe

boolen mssql_close([ressource connexion])

connexion

Identifiantdeconnexionretournparlafonctionmssql_connect.
Sinonprcis,fermeturedeladernireconnexionouverte.

Lafonctionmssql_closeretourneTRUEencasdesuccsetFALSEencasd'erreur(accompagnd'unealerte).

Lafonctionmssql_closeestsanseffetsuruneconnexionpermanente.

Toutes les connexions non permanentes sont automatiquement fermes la fin du script.

Exemple

<?php
// connexion
$id1 = mssql_connect("diane","demeter","demeter");
echo "\$id1 = $id1<BR>\n";
// dconnexion
$ok = mssql_close($id1);
echo "\$ok = ".(($ok)?"TRUE":"FALSE")."<BR>\n";
// tentative de dconnexion d'une connexion dj close
$ok = mssql_close($id1);
echo "\$ok = ".(($ok)?"TRUE":"FALSE")."<BR>\n";
?>

Rsultat

$id1 = Resource id #1
$ok = TRUE
$ok = TRUE

Cetexemplemontrequefermeruneconnexiondjclosenegnrepasd'erreur.

Liredesdonnes

Liredesdonnesdansunebasencessitedeuxoprations :

- envoyer, pour excution, une requte (en l'occurrence un ordre SELECT) au serveur ;

- rcuprer la ou les lignes correspondant au rsultat de la requte.

Excuterunerequte

Lafonctionmssql_querypermetd'envoyerunerequtepourexcutionauserveur.

Syntaxe

ressource mssql_query(chane requte[, ressource connexion])

requte

Textedelarequteexcuter.

connexion

Identifiantdeconnexionretournparlafonctionmssql_connect.
Sinonprcis,utilisationdeladernireconnexionouverte.

La fonction mssql_query retourne un identifiant de rsultat de requte, en cas de succs, et FALSE en cas

ENI Editions - All rigths reserved - 3-


d'chec(accompagnd'unealerte).

Rappel : la requte s'excute sur la base active de la connexion (base par dfaut de l'utilisateur ou base prcdemment
slectionne par la fonction mssql_select_db).

Exemple

<?php
// connexion
$connexion = mssql_connect("diane","demeter","demeter");
// dfinition de la requte
$requte = "SELECT * FROM articles";
// excution de la requte sur la base actuelle
$rsultat1 = mssql_query($requte,$connexion);
echo "\$rsultat1 = $rsultat1<BR>\n";
// dfinition d'une mauvaise requte
$requte = "SELECT * FROM article";
$rsultat2 = mssql_query($requte,$connexion);
echo "\$rsultat2 = $rsultat2<BR>\n";
// excution de la bonne requte sur une mauvaise base
$ok = mssql_select_db("msdb",$connexion);
$requte = "SELECT * FROM articles";
$rsultat3 = mssql_query($requte,$connexion);
echo "\$rsultat3 = $rsultat3<BR>\n";
?>

Rsultat

rsultat1 = Resource id #2
Warning: mssql_query() [function.mssql-query]: message:
'article' : nom d'objet incorrect. (severity 16) in
d:\scripts php\index.php on line 10
Warning: mssql_query() [function.mssql-query]: Query failed
in d:\scripts php\index.php on line 10
$rsultat2 =
Warning: mssql_query() [function.mssql-query]: message:
'articles' : nom d'objet incorrect. (severity 16)
in d:\scripts php\index.php on line 15
Warning: mssql_query() [function.mssql-query]: Query failed in
d:\scripts php\index.php on line 15
$rsultat3 =

Commeindiquenintroduction,lafonctionmssql_queryexcutelarequte,indiquesilarequtes'estexcute
correctementmaisnerenvoieaucunedonne.Ilvafalloirextraireleslignesdursultat.

Connatrelenombredelignesdanslersultat

Lafonctionmssql_num_rowspermetdeconnatrelenombredelignesdanslersultat.

Syntaxe

entier mssql_num_rows(ressource rsultat)

rsultat

Identifiantdersultatderequteretournparlafonctionmssql_query.

CettefonctionestutilisableuniquementpourlesrequtesSELECT.

Exemple

<?php
// connexion
$connexion = mssql_connect("diane","demeter","demeter");
// dfinition de la requte
$requte = "SELECT * FROM articles";
// excution de la requte (avec la connexion courante)
$rsultat = mssql_query($requte);
// rcupration du nombre de lignes

- 4- ENI Editions - All rigths reserved


$nombre = mssql_num_rows($rsultat);
echo "Nombre d'articles : $nombre<BR>\n";
// dfinition de la requte
$requte = "SELECT * FROM articles WHERE prix > 40";
// excution de la requte (avec la connexion courante)
$rsultat = mssql_query($requte);
// rcupration du nombre de lignes
$nombre = mssql_num_rows($rsultat);
echo "Nombre d'articles dont le prix est suprieur 40 : $nombre<BR>\n";
?>

Rsultat

Nombre d'articles : 4
Nombre d'articles dont le prix est suprieur 40 : 1

Lirelersultatdelarequte

Lersultatdel'excution(russie)d'unerequte SELECTpeuttrelugrceauxfonctions mssql_fetch_array,


mssql_fetch_assoc,mssql_fetch_objectoumssql_fetch_row.

Ces fonctions effectuent le mme traitement : lecture de la ligne courante du rsultat et avancement du
pointeursurlalignesuivante(voirl'introduction).

Cesfonctionsdiffrentsurletypededonnesutilispourretournerlersultat.

Syntaxe

tableau mssql_fetch_array(ressource rsultat [, entier type])


tableau mssql_fetch_assoc(ressource rsultat)
objet mssql_fetch_object(ressource rsultat)
tableau mssql_fetch_row(ressource rsultat)

rsultat

Identifiantdersultatderequteretournparlafonctionmssql_query.

type

Typedersultatgalunedesconstantessuivantes :
MSSQL_ASSOC, MSSQL_NUM, MSSQL_BOTH

Les fonctions mssql_fetch_array, mssql_fetch_assoc et mssql_fetch_row retournent la ligne courante du


rsultat sous la forme d'un tableau, chaque ligne du tableau correspondant une colonne du rsultat. La
fonctionmssql_fetch_objectretournelalignecourantesouslaformed'unobjet.

S'iln'yaplusdeligneliredanslersultat,cesfonctionsretournentFALSE.

Pourlafonctionmssql_fetch_assoc,ils'agitd'untableauassociatifdontlaclestlenomdelacolonne.Pourla
fonctionmssql_fetch_row,ils'agitd'untableauindicesentiers,l'indice0correspondantlapremirecolonne,
l'indice1ladeuxime,etc.Enfin,pourlafonctionmysql_fetch_array,letypedutableaudpenddudeuxime
paramtre :

MSSQL_NUM

Tableauindicesentiers(commelafonctionmssql_ fetch_row).

MSSQL_ASSOC

Tableauassociatif(commelafonctionmssql_fetch_assoc).

MSSQL_BOTH
(valeur par dfaut)

Lesdeuxlafois.

ENI Editions - All rigths reserved - 5-


Chaquecolonneestprsentedeuxfois.

Exemple:

Requte SELECT *
FROM articles
Colonnes identifiant libelle prix
1re ligne du 1 Abricots 35.5
rsultat

Rsultat d'un fetch (lecture avec diffrentes fonctions)

mssql_fetch_row mssql_fetch_assoc
ou ou
mssql_fetch_array mssql_fetch_array mssql_fetch_array
(...,MSSQL_NUM) (...,MSSQL_ASSOC) (...,MSSQL_BOTH)
Indice/Cl Valeur Indice/Cl Valeur Indice/Cl Valeur
0 1 identifiant 1 identifiant 1
1 Abricots libelle Abricots 0 1
2 35.5 prix 35.5 libelle Abricots
1 Abricots
prix 35.5
2 35.5

La fonction mssql_fetch_object retourne un objet, avec un attribut par colonne, le nom de l'attribut
correspondantaunomdelacolonne.
En cas d'utilisation d'un alias de colonne dans la requte SELECT (exemple SELECT AVG(prix) prix_moyen
FROM articles),c'estl'aliasdecolonnequiestutiliscommeclounomd'attribut.

Exemple

<?php
// inclusion du fichier qui contient la dfinition de
// afficher_tableau
include("fonctions.inc");
// connexion
$connexion = mssql_connect("diane","demeter","demeter");
// excution de la requte sur la connexion courante
$rsultat = mssql_query("SELECT * FROM articles");
// Premier fetch avec mssql_fetch_row
$ligne = mssql_fetch_row($rsultat);
afficher_tableau($ligne,"mssql_fetch_row");
// Deuxime fetch avec mssql_fetch_assoc
$ligne = mssql_fetch_assoc($rsultat);
afficher_tableau($ligne,"mssql_fetch_assoc");
// Troisime fetch avec mssql_fetch_array
// - sans deuxime paramtre = MSSQL_BOTH
$ligne = mssql_fetch_array($rsultat);
afficher_tableau($ligne,"mssql_fetch_array");
// Quatrime fetch avec mssql_fetch_object
$ligne = mssql_fetch_object($rsultat);
echo "<P><B>mssql_fetch_object</B><BR>";
echo "\$ligne->identifiant = $ligne->identifiant<BR>";
echo "\$ligne->libelle = $ligne->libelle<BR>";
echo "\$ligne->prix = $ligne->prix<BR>";
// Cinquime fetch de nouveau avec mssql_fetch_row
// - normalement, plus de ligne
$ligne = mssql_fetch_row($rsultat);
if (! $ligne) {
echo "<P><B>Cinquime fetch : plus rien</B>";
}
?>

Rsultat

- 6- ENI Editions - All rigths reserved


mssql_fetch_row
0 = 1
1 = Abricots
2 = 35.50
mssql_fetch_assoc
identifiant = 2
libelle = Cerises
prix = 48.90
mssql_fetch_array
0 = 3
identifiant = 3
1 = Fraises
libelle = Fraises
2 = 29.95
prix = 29.95
mssql_fetch_object
$ligne->identifiant = 4
$ligne->libelle = P_ches
$ligne->prix = 37.20
Cinquime fetch : plus rien

Vousobservezgrcecetexemple :

- les diffrents modes de rcupration d'une ligne de rsultat,

- le fait qu' chaque fetch, le pointeur interne avance, et que le fetch suivant retourne donc la ligne suivante, jusqu'
avoir parcouru toutes les lignes.

En cas d'utilisation d'un identifiant de rsultat non valide, les fonctions mysql_fech_* retournent FALSE et
affichent,enplus,unealertedutype :

Warning: mssql_fetch_row(): supplied argument is not a valid MS SQL-result resource in


d:\scripts php\index.php on line 9

Quellemthodeutiliser ?

Touteslesmthodessevalent,notammentdupointdevuedesperformances.Personnellement,nousavonsune
petite prfrence pour l'utilisation des fonctions mssql_fetch_assoc, mssql_fetch_array et
mssql_fetch_object qui permettent d'employer le nom des colonnes de la requte et de rendre le code plus
lisible.

Exempledecodepourlalectured'uneligne

Unpremiertypedelectureconsistesouventenvisageruneseuleligned'informationdansunetableouplusieurs
tablesavecjointure(s) :obtentiond'informationssurl'utilisateurquivientdeseconnecter,fichededescription
d'unarticle...

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
//initialiser les variables
$identifiant="";
$libell="";
$prix="";
$message="";
// Tester comment le script est appel
if (! empty($_POST)) {
// traitement du formulaire ...
// rappel : lorsqu'un formulaire n'a qu'une zone de texte
// et que l'utilisateur tape return ou enter, le bouton de validation
// n'est pas considr comme cliqu. Pour savoir
// si le formulaire a t soumis, il faut tester si
// $_POST (ou $_GET) est vide ou non.
// rcuprer les valeurs saisies
$identifiant = valeur_saisie($_POST["identifiant"]);
// contrler les valeurs saisies
if ($identifiant == "") {
$message .= "L'identifiant est obligatoire.\n";

ENI Editions - All rigths reserved - 7-


}
if (! ereg("^[0-9]+$",$identifiant)) {
$message .=
"L'identifiant doit tre un nombre.\n";
}
// tester s'il y a des erreurs ce stade
if ($message == "") {
// pas d'erreur
// connexion
$connexion = mssql_connect("diane","demeter","demeter");
// excuter la requte de slection
$requte = "SELECT * FROM articles WHERE
identifiant = $identifiant";
$rsultat = mssql_query($requte);
// fetch si la requte a bien t excute
if ($rsultat) {
$article = mssql_fetch_array($rsultat);
}
// tester le rsultat
if (! $rsultat) { // requte pas OK
$message .= "Erreur.\n";
} elseif (! $article) { // rsultat vide
$message .=
"Pas d'article pour cet identifiant.\n";
} else { // OK
// rcuprer les informations afficher
$libell = $article["libelle"];
$prix = $article["prix"];
// mise en forme
$libell = vers_page($libell);
$prix = number_format($prix,2,"," ," ");
$prix = vers_page($prix);
}
}
// tester s'il y a des erreurs ce stade
if ($message != "") {
// erreur
// prparer le message pour l'affichage
$message = vers_page($message);
// bien s'assurer que les informations afficher sont vides
$libell = "";
$prix = "";
}
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Consultation d'un article</TITLE></HEAD>
<BODY>
<FORM METHOD="POST">
Identifiant de l'article :
<INPUT TYPE="text" NAME="identifiant"
VALUE="<?php echo vers_formulaire($identifiant); ?>">
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<TABLE BORDER="0">
<TR><TD><U>Libell :</U> </TD>
<TD><?php echo $libell; ?></TD></TR>
<TR><TD><U>Prix :</U> </TD>
<TD><?php echo $prix; ?></TD></TR>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Rsultat (aprs saisie et clic sur le bouton OK)

Ilestrelativementsimpled'crireunefonctiongnriquepermettantdelireuneligne.

- 8- ENI Editions - All rigths reserved


Exemple

<?php
function db_lire_ligne($requte) {
// se connecter
$connexion = mssql_connect("diane","demeter","demeter");
// excuter la requte et tester le rsultat pour affecter
// la variable $ok
$ok = (($rsultat = mssql_query($requte)) != FALSE);
if ($ok) { // excution OK
// lire la ligne
$ligne = mssql_fetch_array($rsultat);
}
// retourner $ligne ou FALSE en cas d'erreur
return ($ok)?$ligne:FALSE;
}
?>

Ilestpossible(souhaitable)d'amliorerlagestiondeserreurs(cf.Grerleserreurs).

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// dfinir la requte
$requte = "SELECT * FROM articles WHERE identifiant= 1";
// lire le rsultat
$ligne = db_lire_ligne($requte);
if ($ligne) {
echo "$ligne[libelle] - $ligne[prix]";
}
?>

Rsultat (sauf erreur)

Abricots - 35.5

Exempledecodepourlalecturedetoutesleslignes

Un deuxime type de lecture consiste souvent afficher une liste d'lments extraits de la base (liste
d'utilisateurs,listed'articles...).

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// se connecter
$connexion = mssql_connect("diane","demeter","demeter");
// excuter la requte de slection
$requte = "SELECT * FROM articles";
$rsultat = mssql_query($requte);
// fetch si la requte a bien t excute
if ($rsultat) {
// boucle jusqu' avoir un fetch FALSE
while ($article = mssql_fetch_array($rsultat)) {
// remplir un tableau avec chaque ligne extraite
// remarque : le tableau est multidimensionnel
// puisque $article est lui-mme un tableau
$articles[] = $article;
}
}
// tester le rsultat
if (! $rsultat) { // requte pas OK
$message .= "Erreur.\n";
} elseif (empty($articles)) { // rsultat vide
$message .=
"Aucun article dans la base.\n";

ENI Editions - All rigths reserved - 9-


} else { // OK
// mettre en forme les donnes (idem prcdemment)
// remarque : aurait pu tre fait dans la boucle
// de fetch pour optimiser les performances
for ($i=0;$i<count($articles);$i++) {
$articles[$i]["libelle"] =
vers_page($articles[$i]["libelle"]);
$articles[$i]["prix"] =
vers_page(number_format($articles[$i]["prix"],2,"," ," "));
}
}
// tester s'il y a des erreurs ce stade
if ($message != "") {
// erreur
// prparer le message pour l'affichage
$message = vers_page($message);
// bien s'assurer que les informations
// afficher sont vides
unset($articles);
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML -->
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if (isset($articles)) { // s'il y a un rsultat afficher
foreach($articles as $article) { // boucle sur les articles
// gnration de la ligne de la table HTML
// remarque : printf() rend le code lisible
printf("<TR><TD>%d</TD><TD>%s</TD><TD>%s</TD></TR>",
$article["identifiant"],
$article["libelle"],
$article["prix"]);
}
}
?>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

On peut crire le mme exemple de manire plus compacte, un peu plus conome en mmoire et peuttre un
peuplusperformante :lefetchesteffectuaucoursdelaconstructiondelatableHTML.

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// se connecter
$connexion = mssql_connect("diane","demeter","demeter");
// excuter la requte de slection
$requte = "SELECT * FROM articles";
$rsultat = mssql_query($requte);
// tester le rsultat
if (! $rsultat) { // requte pas OK
// message d'erreur
$message .= "Erreur.\n";
// prparer le message pour l'affichage
$message = vers_page($message);
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML -->
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">

- 10 - ENI Editions - All rigths reserved


<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if ($rsultat) { // s'il y a un rsultat afficher
// boucle de fetch
while ($article = mssql_fetch_array($rsultat)) {
// mise en forme des donnes
$article["libelle"] = vers_page($article ["libelle"]);
$article["prix"] = vers_page(
number_format($article["prix"],2,"," ," "));
// gnration de la ligne de la table HTML
printf("<TR><TD>%d</TD><TD>%s</TD><TD>%s</TD></TR>",
$article["identifiant"],
$article["libelle"],
$article["prix"]);
} // while
// si le rsultat est vide, prparer un message
if (mssql_num_rows($rsultat) == 0) {
$message = vers_page("Aucun article dans la base.");
}
} // if ($rsultat)
?>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Pourpermettrel'utilisateurd'agirsurlaliste,ilestpossibled'imbriquerunformulaireoudesliensaveclatable
HTML.

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// se connecter
$connexion = mssql_connect("diane","demeter","demeter");
// excuter la requte de slection
$requte = "SELECT * FROM articles";
$rsultat = mssql_query($requte);
// tester le rsultat
if (! $rsultat) { // requte pas OK
// message d'erreur
$message .= "Erreur.\n";
// prparer le message pour l'affichage
$message = vers_page($message);
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML l'intrieur d'un
---- formulaire -->
<FORM METHOD="POST">
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Libell</TH><TH>Prix</TH><TH>Case</TH><TH>Lien</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if ($rsultat) { // s'il y a un rsultat afficher
// boucle de fetch
while ($article = mssql_fetch_array($rsultat)) {
// mise en forme des donnes
$article["libelle"] = vers_page($article ["libelle"]);
$article["prix"] = vers_page(
number_format($article["prix"],2,"," ," "));
// gnration de la ligne de la table HTML
// - une case cocher dans une colonne
// - un lien dans une autre colonne
printf(

ENI Editions - All rigths reserved - 11 -


"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>",
$article["libelle"],
$article["prix"],
"<INPUT TYPE=\"checkbox\" NAME=\"choix[]\"
VALUE=\"$article[identifiant]\">",
"<A HREF=\"javascript:alert($article[identifiant])\">
action<A>");
}
// si le rsultat est vide, prparer un message
if (mssql_num_rows($rsultat) == 0) {
$message = vers_page("Aucun article dans la base.");
}
} // if ($rsultat)
?>
</TABLE>
<BR><INPUT TYPE="submit" NAME="action" VALUE="Action">
</FORM>
<FONT COLOR="green">
<?php
// traitement du formulaire
// simple affichage des identifiants cochs
if (isset($_POST["action"])) {
if (isset($_POST["choix"])) {
echo "Identifiant(s) coch(s) : ".
implode("+",$_POST["choix"]);
}
}
?>
</FONT>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Rsultat

- Affichage initial de la page :

- Aprs clic sur un lien :

- Aprs clic sur le bouton Action :

- 12 - ENI Editions - All rigths reserved


Sur le lien, la place du code JavaScript, il est possible de placer une vraie URL et d'enchaner sur une autre
page(cf.chapitreGrerlessessionspourcomprendrecommentmettreunparamtredansl'URLetpouvoirainsi
passeruneinformation,icil'identifiantchoisi,uneautrepage).

Encequiconcerneletraitementduformulaire,toutestenvisageable.

Lencore,pourlalecturedeplusieurslignes,unefonctiongnriqueestutilisable.

Exemple

<?php
function db_lire_lignes_dans_tableau($requte) {
// se connecter
$connexion = mssql_connect("diane","demeter","demeter");
// excuter la requte et tester le rsultat pour affecter
// la variable $ok
$ok = (($rsultat = mssql_query($requte)) != FALSE);
if ($ok) { // excution OK
// lire les lignes dans un tableau
while ($ligne = mssql_fetch_array($rsultat)) {
$tableau[] = $ligne;
}
}
// retourner $tableau ou FALSE en cas d'erreur
return ($ok)?$tableau:FALSE;
}
?>

Utilisation

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// dfinir la requte
$requte = "SELECT * FROM articles";
// lire le rsultat dans un tableau
$articles = db_lire_lignes_dans_tableau($requte);
// afficher le premier article lu
if ($articles) {
echo count($articles)." articles<BR>";
echo "Premier article : ";
echo "{$articles[0]['libelle']} - {$articles[0]['prix']}";
}
?>

Rsultat (sauf erreur)

4 articles
Premier article : Abricots - 35.50

Cettefonctiongnriquepeut,parexemple,treutilisepourconstruireuneliste<SELECT>dansunformulaire.

ENI Editions - All rigths reserved - 13 -


Exemple:

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// chargement de la liste des fruits
$requte = "SELECT identifiant,libelle FROM articles
ORDER BY libelle";
$fruits_du_march = db_lire_lignes_dans_tableau($requte);
?>
<!-- construction du formulaire -->
<FORM METHOD="POST">
Fruits prfrs :<BR>
<SELECT NAME="fruits[]" MULTIPLE SIZE="8">
<?php
// code PHP gnrant la partie dynamique du formulaire
// parcourir la liste afficher
foreach($fruits_du_march as $fruit) {
// gnrer la balise OPTION avec l'identifiant pour l'option
// VALUE et le libell pour le texte affich dans la liste
echo "<OPTION VALUE=\"$fruit[identifiant]\">
$fruit[libelle]\n";
}
?>
</SELECT>
<INPUT TYPE="submit" NAME="OK" VALUE="OK"><BR>
</FORM>

Rsultat

Mettrejourdesdonnes

MettrejourdesdonnesconsisteexcuterdesrequtesINSERT(cration),UPDATE(modification)ouDELETE
(suppression).

L'excutiondecetypederequtes'effectueaveclafonctionmssql_query,commepourunerequteSELECT.

Il n'y a pas d'quivalent, avec Microsoft SQL Server, la fonction MySQL mysql_effected_rows et la fonction
mssql_num_rows ne fonctionne pas pour une requte INSERT, UPDATE ou DELETE. Par contre, il est possible
d'excuterunerequteSELECT @@ROWCOUNTpourobteniruneinformationsurlenombredelignesaffectesparle
dernierordredemisejour(voirlesexemplesdelapagesuivante).

Il n'y a pas d'quivalent non plus la fonction MySQL mysql_insert_id mais il est possible d'excuter une
requte SELECT SCOPE_IDENTITY() ou SELECT @@IDENTITY pour rcuprer la dernire valeur de type auto
incrmentgnre(voirlesexemplesdelapagesuivante).
Pardfaut,lesordressontautomatiquement COMMITs.Pourregrouperplusieursordresdemisejourdansune
transaction, il faut excuter, avec la fonction mssql_query, la requte BEGIN TRANSACTION avant le premier
ordre,etlarequteCOMMIT TRANSACTION(ouROLLBACK TRANSACTION)aprsledernierordre.

Exemples

<?php
// inclusion du fichier qui contient la dfinition des fonctions gnrales
include("fonctions.inc");
// dfinition d'une petite fonction d'affichage de la liste des articles
function AfficherArticles() {
$requte = "SELECT * FROM articles";
$articles = db_lire_lignes_dans_tableau($requte);
if ($articles) {
echo "<B>Liste des articles :</B><BR>";

- 14 - ENI Editions - All rigths reserved


foreach($articles as $a) {
echo "$a[identifiant] - $a[libelle] - $a[prix]<BR>";
}
} else {
echo "<B>Plus d'articles.</B><BR>";
}
}
// connexion
$connexion = mssql_connect("diane","demeter","demeter");
// affichage de contrle
AfficherArticles();
// requte INSERT
$requte = "INSERT INTO articles(libelle,prix)
VALUES('Poires',29.9)";
$rsultat = mssql_query($requte);
// rcuprer l'identifiant gnr
$rsultat = mssql_query("SELECT SCOPE_IDENTITY()");
$ligne = mssql_fetch_row($rsultat);
echo "Identifiant du nouvel article = $ligne[0].<BR>";
// requte UPDATE
$requte = "UPDATE articles SET prix = prix * 1.1
WHERE prix < 40";
$rsultat = mssql_query($requte);
// rcuprer le nombre de lignes modifies
$rsultat = mssql_query("SELECT @@ROWCOUNT");
$ligne = mssql_fetch_row($rsultat);
echo "$ligne[0] article(s) augment(s).<BR>";
// requte DELETE
$requte = "DELETE FROM articles WHERE prix > 40";
$rsultat = mssql_query($requte);
// rcuprer le nombre de lignes supprimes
$rsultat = mssql_query("SELECT @@ROWCOUNT");
$ligne = mssql_fetch_row($rsultat);
echo "$ligne[0] article(s) supprims(s).<BR>";
// affichage de contrle
AfficherArticles();
?>

Rsultat

Liste des articles :


1 - Abricots - 35.50
2 - Cerises - 48.90
3 - Fraises - 29.95
4 - Pches - 37.20
Identifiant du nouvel article = 5.
4 article(s) augment(s).
2 article(s) supprims(s).

Liste des articles :


1 - Abricots - 39.05
3 - Fraises - 32.95
5 - Poires - 32.89

Crerdesformulairesquipermettentdemettrejourlesdonnesesttrssimple.

titred'exemple,nousallonsconstruireunformulairepourraliserunesaisieenliste.

Prsentation du formulaire

ENI Editions - All rigths reserved - 15 -


Le formulaire propose le contenu actuel de la table qui peut tre modifi (saisie directe dans les zones) ou
supprim (par les cases cocher), ainsi que cinq lignes vides permettant de saisir de nouvelles valeurs. Dans
touslescas,l'identifiantn'estpassaisissable(c'estleserveurMicrosoftSQLServerquival'attribuer).

Chaque ligne du tableau contient quatre zones de formulaire qui sont nommes (option NAME de la balise
<INPUT>)delamaniresuivante :

Colonne Nom
Identifiant saisie[i][modifier]
Libell saisie[i][libelle]
Prix saisie[i][prix]
Supprimer saisie[i][supprimer]

L'indice i est l'identifiant de l'article pour les lignes qui existent, et un numro compris entre 1 et 5 pour les
lignesvides.Lazonedelacolonne Identifiantestmasque(TYPE="hidden")ellevatreutilisepouridentifier
leslignesdanslesquellesl'utilisateuraeffectuunemodification.

Avec ce processus de nommage, toute la saisie est rcupre dans le script PHP sous la forme d'un tableau
multidimensionnel nomm $lignes. Chaque ligne du tableau correspond une ligne du formulaire avec la cl
gale l'identifiant (ou 1 5 pour les nouvelles lignes) et la valeur gale un tableau associatif donnant les
lmentssaisis.

Pour identifier les lignes modifies par l'utilisateur, les zones de saisie du libell et du prix des lignes existantes
contiennentlecodeJavaScriptsuivant :

onChange="document.formulaire[$n].value=1"

Ce code JavaScript a pour effet, chaque fois que la zone en question est modifie, de mettre un 1 dans la
zone masque associe la ligne. Le formulaire s'appelant formulaire (<FORM NAME = "formulaire"...),
l'expression document.formulaire[n] dsigne la nime zone du formulaire formulaire du document courant,
la premire zone du formulaire ayant le numro 0. Dans le source, la variable $n est calcule pour chaque ligne
$i du formulaire, grce la formule $n = 4 * ($i - 1) : la zone cache de la ligne 1 a le numro 0 (c'est la
premireduformulaire),celledelaligne2lenumro4etainsidesuite.

Cetexemplepeut(doit)treamliorpour :

- contrler la saisie de l'utilisateur ;

- grer les erreurs.

Exemple

- 16 - ENI Editions - All rigths reserved


<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// connexion
$connexion = mssql_connect("diane","demeter","demeter");
// traitement du formulaire
if (isset($_POST["OK"])) {
// marquer le dbut de la transaction
$rsultat = mssql_query("BEGIN TRANSACTION");
// rcuprer le tableau contenant la saisie
$lignes = $_POST["saisie"];
foreach($lignes as $identifiant => $ligne) {
// nettoyage de la saisie
$libell = valeur_saisie($ligne["libelle"]);
$prix = valeur_saisie($ligne["prix"]);
$prix = str_replace(",",".",$prix); // , => .
$prix = str_replace(" ","",$prix); // supprimer espaces
// ce niveau, il faudrait vrifier la saisie ...
$requte = "";
if ($identifiant < 0 and $libell.$prix != "") {
// identifiant ngatif et quelque chose de saisi
// = cration = INSERT
$requte = "INSERT INTO articles(libelle,prix)
VALUES('$libell',$prix)";
} elseif (isset($ligne["supprimer"])) {
// case " supprimer " coche = suppression = DELETE
$requte = "DELETE FROM articles
WHERE identifiant = $identifiant";
} elseif (isset($ligne["modifier"])) {
// zone " modifier " TRUE (1) = modification = UPDATE
$requte = "UPDATE articles
SET libelle = '$libell', prix = $prix
WHERE identifiant = $identifiant";
}
// si une requte a t dtermine, l'excuter
if ($requte != "") {
$rsultat = mssql_query($requte);
// en cas d'erreur, interrompre le traitement
if (! $rsultat) {break; }
}
} // foreach
// Tester $rsultat pour savoir s'il faut faire
// un COMMIT TRANSACTION ou un ROLLBACK TRANSACTION
if ($rsultat) { // $rsultat != FALSE = COMMIT
$rsultat = mssql_query("COMMIT TRANSACTION");
} else { // pas OK = ROLLBACK
$rsultat = mssql_query("ROLLBACK TRANSACTION");
// prparer un message d'erreur (plutt succinct !)
$message = vers_page("Erreur lors de la mise jour.");
}
}
// recharger les articles
$requte = "SELECT * FROM articles";
$rsultat = mssql_query($requte);
// ce niveau, il faudrait tester les erreurs ...
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Gestion des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML l'intrieur d'un
---- formulaire -->
<FORM NAME="formulaire" METHOD="POST">
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
<TH>Supprimer</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if ($rsultat) { // s'il y a un rsultat afficher
// initialisation d'un compteur de ligne
$i = 0;
// boucle de fetch
while ($article = mssql_fetch_array($rsultat)) {
// incrmentation du compteur de ligne
$i++;

ENI Editions - All rigths reserved - 17 -


// calcul du numro d'ordre dans le formulaire de la
// zone cache correspondant l'identifiant
$n = 4 * ($i - 1);
// mise en forme des donnes
$article["libelle"] = vers_page($article["libelle"]);
$article["prix"] = vers_page(
number_format($article["prix"],2,"," ," "));
// gnration de la ligne de la table HTML
// insertion des balises INPUT du formulaire
printf(
"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>",
"$article[identifiant]
<INPUT TYPE=\"hidden\"
NAME=\"saisie[$article[identifiant]][modifier]\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[$article[identifiant]][libelle]\"
VALUE=\"$article[libelle]\"
onChange=\"document.formulaire[$n].value=1\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[$article[identifiant]][prix]\"
VALUE=\"$article[prix]\"
onChange=\"document.formulaire[$n].value=1\">",
"<INPUT TYPE=\"checkbox\"
NAME=\"saisie[$article[identifiant]][supprimer]\"
VALUE=\"$article[identifiant]\">");
}
// ajout de 5 lignes vides pour la cration
// (sans identifiant, sans case de suppression)
for($i=1;$i<=5;$i++) {
printf(
"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>",
"",
"<INPUT TYPE=\"text\"
NAME=\"saisie[-$i][libelle]\"
VALUE=\"\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[-$i][prix]\"
VALUE=\"\">",
"");
} // for
}
?>
</TABLE>
<BR><INPUT TYPE="submit" NAME="OK" VALUE="Enregistrer">
</FORM>
<!-- affichage du message -->
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Appeleruneprocdurestocke

La bibliothque Microsoft SQL Server permet trs facilement d'excuter des blocs TransactSQL, d'appeler des
procduresstockesquiretournentventuellementdesvaleurs.

LeprincipegnralconsistesoumettreleblocTransactSQL,oul'ordre EXECUTE procdure,pourexcution,par


l'intermdiairedelafonction mssql_query.Danslecasdel'excutiond'uneprocdure,sicettedernireretourne
unrsultat,ilestpossibled'utiliserlesfonctionsdefetchpourlirecersultat.

Nousallonsillustrercesdiffrentesfonctionnalitsl'aidedesprocduressuivantes :

-- procdure d'insertion dans la table articles


-- retourne l'identifiant du nouvel article
CREATE PROCEDURE CreerArticle
@libelle VARCHAR(40),
@prix NUMERIC(6,2)
AS
BEGIN
INSERT INTO articles(libelle,prix) VALUES(@libelle,@prix)
SELECT SCOPE_IDENTITY()
END
GO
-- procdure de comptage des articles
CREATE PROCEDURE CompterArticles
AS
BEGIN

- 18 - ENI Editions - All rigths reserved


SELECT COUNT(identifiant) FROM articles
END
GO
-- procdure de lecture d'un article (si @identifiant > 0)
-- ou de tous les articles (si @identifiant = 0 ; par dfaut)
CREATE PROCEDURE LireArticles
@identifiant INT = 0
AS
BEGIN
IF @identifiant = 0
SELECT * FROM articles
ELSE
SELECT * FROM articles
WHERE identifiant = @identifiant
END
GO

Source PHP

<?php
// connexion
$connexion = mssql_connect("diane","demeter","demeter");
// insertion l'aide de la procdure
$requte = "EXECUTE CreerArticle 'Pommes', 10";
// excution
$rsultat = mssql_query($requte);
// rcupration de l'identifiant du nouvel article
$ligne = mssql_fetch_row($rsultat);
$identifiant = $ligne[0];
echo "Identifiant du nouvel article = $identifiant.<BR>";
// comptage l'aide de la procdure
$requte = "EXECUTE CompterArticles";
// excution
$rsultat = mssql_query($requte);
// rcupration du rsultat
$ligne = mssql_fetch_row($rsultat);
$nombre = $ligne[0];
echo "$nombre article(s) dans la base.<BR>";
// lecture d'un article l'aide de la procdure
// => celui insr prcdemment ($identifiant)
$requte = "EXECUTE LireArticles $identifiant";
// excution
$rsultat = mssql_query($requte);
// rcupration du rsultat
$article = mssql_fetch_array($rsultat);
echo "Nouveau : $article[libelle] - $article[prix]<BR>";
// lecture de tous les articles l'aide de la procdure
// => appel sans paramtre
$requte = "EXECUTE LireArticles";
// excution
$rsultat = mssql_query($requte);
// rcupration du rsultat
echo "Liste : <BR>";
// fetch de toute les lignes
while ($article = mssql_fetch_array($rsultat)) {
echo "&nbsp&nbsp$article[libelle] - $article[prix]<BR>";
}
?>

Rsultat:

Identifiant du nouvel article = 5.


5 article(s) dans la base.
Nouveau : Pommes 10.00
Liste :
Abricots - 35.50
Cerises - 48.90
Fraises - 29.95
Pches - 37.20
Pommes - 10.00

Grerleserreurs

Lagestiondeserreursproposeparlabibliothquen'estpastrspratique.

ENI Editions - All rigths reserved - 19 -


La fonction mssql_get_last_message retourne le dernier message (pas forcment d'erreur) gnr par le
serveur :cemessageestpluttsuccinctetnedonnepaslenumrodel'erreur.

En complment, la fonction mssql_min_message_severity permet, dans une certaine mesure, de contrler le


niveau de svrit (au sens Microsoft SQL Serveur) des messages directement affichs. Par contre, cette
fonctionnepermetpasdelesfairedisparatrecompltement(cf.chapitreGrerleserreursdansunscriptPHP).

Syntaxe

chane mssql_get_last_message()
mssql_min_message_severity()&

Exemples

<?php
// mauvaise connexion
$connexion = mssql_connect("diane",
"demeter","MotDePasseErron");
$message = mssql_get_last_message();
echo "1 : $message<BR>";
// connexion
$connexion = mssql_connect("diane","demeter","demeter");
$message = mssql_get_last_message();
echo "<P>2 : $message<BR>";
// une bonne requte pour commencer
$requte = "SELECT * FROM articles";
$rsultat = mssql_query($requte);
$message = mssql_get_last_message();
echo "<P>3 : $message<BR>";
// requte sur une table qui n'existe pas
$requte = "SELECT * FROM article";
$rsultat = mssql_query($requte);
$message = mssql_get_last_message();
echo "<P>4 : $message<BR>";
// requte UPDATE qui viole une contrainte NOT NULL
$requte = "UPDATE articles SET prix = NULL";
$rsultat = mssql_query($requte);
$message = mssql_get_last_message();
echo "<P>5 : $message<BR>";
// tentative de fetch sur un mauvais rsultat
$requte = "SELECT * FROM article";
$rsultat = mssql_query($requte);
$message = mssql_get_last_message();
echo "<P>6.a : $message<BR>";
$ligne = mssql_fetch_row($rsultat);
$message = mssql_get_last_message();
echo "<P>6.b : $message<BR>";
?>

Rsultat

Warning: mssql_connect() [function.mssql-connect]: message:


chec de la connexion de l'utilisateur 'demeter'.
(severity 14) in d:\scripts php\index.php on line 5
Warning: mssql_connect() [function.mssql-connect]:
Unable to connect to server: diane in d:\scripts php\index.php on line 5
1 : chec de la connexion de l'utilisateur 'demeter'.
2 : Le contexte de la base de donnes a t chang en 'pubs'.
3 : Le contexte de la base de donnes a t chang en 'pubs'.
Warning: mssql_query() [function.mssql-query]: message: 'article' :
nom d'objet incorrect. (severity 16) in d:\scripts php\index.php on line 22
Warning: mssql_query() [function.mssql-query]: Query failed
in d:\scripts php\index.php on line 22
4 : 'article' : nom d'objet incorrect.
Warning: mssql_query() [function.mssql-query]: message:
Impossible d'insrer la valeur NULL dans la colonne 'prix',
table 'pubs.dbo.articles'. Cette colonne n'accepte pas les valeurs NULL. UPDATE a chou.
(severity 16) in d:\scripts php\index.php on line 28
Warning: mssql_query() [function.mssql-query]: Query failed
in d:\scripts php\index.php on line 28
5 : L'instruction a t arrte.
Warning: mssql_query() [function.mssql-query]: message:
'article' : nom d'objet incorrect. (severity 16) in d:\scripts php\index.php on line 34

- 20 - ENI Editions - All rigths reserved


Warning: mssql_query() [function.mssql-query]: Query failed
in d:\scripts php\index.php on line 34
6.a : 'article' : nom d'objet incorrect.
Warning: mssql_fetch_row(): supplied argument is not a valid MS SQL-result resource in
d:\scripts php\index.php on line 37
6.b : 'article' : nom d'objet incorrect.

Plusieursremarques :

- La fonction mssql_get_last_message ne retourne pas uniquement des messages d'erreur, comme en tmoigne le
message rcupr suite une connexion russie (rsultat2) qui indique la base courante.

- Le rsultat 3 montre que la fonction mssql_get_last_message retourne le dernier message mis par le serveur,
mme si ce message est ancien et que des ordres SQL ont t excuts depuis.

- Les rsultats 4 et surtout 5 montrent que les messages rcuprs lors d'une erreur sont plutt succincts et ne donnent
pas d'information trs prcise sur la nature de l'erreur.

Quellequesoitl'erreur,uneouplusieursalertessontaffiches.Parailleurs,nousallonsvoirauchapitreGrerles
erreurs dans un script PHP comment supprimer l'affichage des alertes la fonction
mssql_min_message_severitypermetd'enliminerunepartie.

Exemple avec un appel pralable de mssql_min_message_severity (100)

Warning: mssql_connect() [function.mssql-connect]: Unable to connect to server: diane in


d:\scripts php\index.php on line 4
1 : chec de la connexion de l'utilisateur 'demeter'.
2 : Le contexte de la base de donnes a t chang en 'pubs'.
3 : Le contexte de la base de donnes a t chang en 'pubs'.
Warning: mssql_query() [function.mssql-query]: Query failed
in d:\scripts php\index.php on line 18
4 : 'article' : nom d'objet incorrect.
Warning: mssql_query() [function.mssql-query]: Query failed
in d:\scripts php\index.php on line 23
5 : L'instruction a t arrte.
Warning: mssql_query() [function.mssql-query]: Query failed
in d:\scripts php\index.php on line 28
6.a : 'article' : nom d'objet incorrect.
Warning: mssql_fetch_row(): Supplied argument is not a valid MS SQL-result resource in
d:\scripts php\index.php on line 31
6.b : 'article' : nom d'objet incorrect.

Surcetexemple,unmoinsgrandnombred'alertessontaffiches.Apriori,iln'estpaspossibledefairemieux,car
lesniveauxdegravitdeMicrosoftSQLServervontjusqu'25 :100estdoncdjlargementaudessus.

UneautresolutionconsisteexcuterlarequteSELECT @@ERRORpourrcuprer,surleserveur,lenumrode
l'erreurdudernierordreSQLexcut(0sipasd'erreur).Cettesolutionncessiteuneconnexionrussie.

Exemples

<?php
// limiter la quantit de message
mssql_min_message_severity(100);
// connexion
$connexion = mssql_connect("diane","demeter","demeter");
$erreur = mssql_fetch_row(mssql_query("SELECT @@ERROR"));
$numro = $erreur[0];
echo "1 : numro de l'erreur = $numro<BR>";
// requte sur une table qui n'existe pas
$requte = "SELECT * FROM article";
$rsultat = mssql_query($requte);
$erreur = mssql_fetch_row(mssql_query("SELECT @@ERROR"));
$numro = $erreur[0];
echo "<P>2 : numro de l'erreur = $numro<BR>";
// requte UPDATE qui viole une contrainte NOT NULL
$requte = "UPDATE articles SET prix = NULL";
$rsultat = mssql_query($requte);
$erreur = mssql_fetch_row(mssql_query("SELECT @@ERROR"));
$numro = $erreur[0];
echo "<P>3 : numro de l'erreur = $numro<BR>";

ENI Editions - All rigths reserved - 21 -


?>

Rsultat

1 : numro de l'erreur = 0
Warning: mssql_query() [function.mssql-query]: Query failed
in d:\scripts php\index.php on line 10
2 : numro de l'erreur = 208
Warning: mssql_query() [function.mssql-query]: Query failed
in d:\scripts php\index.php on line 16
3 : numro de l'erreur = 515>

Lesnumrosretournscorrespondentbienaunumrod'erreurMicrosoftSQLServersousjacent(515=violation
d'unecontrainteNOT NULLnotamment).

Cesfonctionspeuventtremisesenuvretitred'exemplesurunedenosfonctionsgnriques.

Source PHP

<?php
function db_lire_ligne($requte, &$erreur) {
// dans cette nouvelle version, db_lire_ligne prend un deuxime paramtre
// par rfrence dans lequel un numro et un message seront stocks
// en cas d'erreur (sous la forme d'un tableau) initialiser $erreur
$erreur = array(0,""); // numro = 0, message vide
// se connecter
if (! ($ok = mssql_connect("diane","demeter","demeter"))) {
// -1 = numro d'erreur interne l'application
$erreur = array(-1,mssql_get_last_message());
};
// excuter la requte et tester le rsultat pour affecter la variable $ok
if ($ok) { // connexion OK
$ok = (($rsultat = mssql_query($requte)) != FALSE);
if (! $ok) {
$erreur[1] = mssql_get_last_message(); // message
// rcuprer le numro de l'erreur dans @@ERROR
$temp = mssql_fetch_row(
mssql_query("SELECT @@ERROR"));
$erreur[0] = $temp[0]; // numro
}
}
if ($ok) { // excution OK
// lire la ligne
$ligne = mssql_fetch_array($rsultat);
}
// retourner $ligne ou FALSE en cas d'erreur
return ($ok)?$ligne:FALSE;
}
?>

Utilisation

<?php
// inclure le fichier qui contient les diffrentes fonctions gnrales
require("fonctions.inc");
// premier appel avec une erreur
$requte = "SELECT * FROM article WHERE identifiant = 1";
if (! ($ligne = db_lire_ligne($requte,$erreur))) {
echo "$erreur[0] - $erreur[1]<BR>";
} else {
echo "$ligne[libelle] - $ligne[prix]<BR>";
}
// deuxime appel correct
$requte = "SELECT * FROM articles WHERE identifiant = 1";
if (! ($ligne = db_lire_ligne($requte,$erreur))) {
echo "$erreur[0] - $erreur[1]<BR>";
} else {
echo "$ligne[libelle] - $ligne[prix]<BR>";
}
?>

Rsultat

- 22 - ENI Editions - All rigths reserved


Warning: mssql_query() [function.mssql-query]: message:
'article' : nom d'objet incorrect. (severity 16) in
d:\scripts php\index.php on line 36
Warning: mssql_query() [function.mssql-query]: Query failed in
d:\scripts php\index.php on line 36
208 - 'article' : nom d'objet incorrect.
Abricots - 35.50

ENI Editions - All rigths reserved - 23 -


UtilisationdeSQLite

Prambule

SQLiteestunelibrairiequiimplmenteunmoteurdebasededonnesSQL.

SQLite peut tre utilise pour stocker des donnes dans une base SQL, sans avoir mettre en place la partie
serveurdelabasededonnes(commec'estlecasavecMySQL,Oracle,etc.).

SQLitelitetcritdirectementdanslesfichiersdelabasededonnes.

Pourplusd'informationsurSQLite,vouspouvezvisiterlesiteWebsuivant :http://sqlite.org/.

Ouvriretfermerunebase

Lafonctionsqlite_openpermetd'ouvrirunebaseSQLite.

Syntaxe

ressource sqllite_open([chane fichier [, entier mode][, chane erreur])

Avec

fichier

Cheminverslefichierdelabasededonnes.

mode

Non utilis actuellement. Prvu pour le mode d'ouverture de la base. Valeur par dfaut : 666 (seule valeur
autoriseactuellement).

erreur

Variablepasseparrfrencepermettantdercuprerunventuelmessaged'erreur.

Lafonctionsqlite_openretourneunidentifiantdebasededonnesouFALSEencasd'erreur,accompagnd'un
message d'alerte envoy l'affichage nous verrons, dans le chapitre Grer les erreurs dans un script PHP,
commentgrercettesituationcorrectement.

Silabase(i.e.lefichier)n'existepasdj,SQLitetenteradelacrer.

Exemple

<?php
// ouverture d'une base qui existe dj
$id1 = sqlite_open('diane.dbf', 666, $erreur);
echo "\$id1 = $id1<BR>\n";
echo "\$erreur = $erreur<BR>\n";
// tentative d'ouverture d'une base avec un mauvais chemin
$id2 = sqlite_open('d:/base/diane.dbf', 666, $erreur);
echo "\$id2 = $id2<BR>\n";
echo "\$erreur = $erreur<BR>\n";
?>

Rsultat

$id1 = Resource id #2
$erreur =
Warning: sqlite_open() [function.sqlite-open]: unable to open database: d:\base\diane.dbf in
d:\scripts php\index.php on line 7
$id2 =
$erreur = unable to open database: d:\base\diane.dbf

ENI Editions - All rigths reserved - 1-


Une valeur FALSE est convertie en chane vide dans un echo (d'o la valeur de $id2).

Les bases ouvertes dans un script sont automatiquement fermes la fin du script, sauf fermeture explicite
avantavecsqlite_close(voirciaprs).

La fonction sqlite_popen permet d'obtenir un fonctionnement diffrent et d'ouvrir une base de faon
"permanente"quineserapasfermelafinduscriptetpourratrerutilisedanscescriptoudansunautre
scriptplustard.

Lasyntaxeestidentiquelasyntaxedelafonctionsqlite_open.

Lors de l'appel la fonction sqlite_popen dans un script, PHP regarde si la base a dj t ouverte : si oui,
l'identifiantdecettebasededonnesestretourn autrement,labaseestouverte(etcettebaseneserapas
fermelafinduscript,cequiautoriseainsisarutilisationultrieure).

Lafonctionsqlite_closepermetdefermerunebasededonnes.

Syntaxe

sqlite_close([ressource base])

Avec

base

Identifiantdebasededonnesretournparlafonctionsqlite_open.

Lafonctionmysql_closeretourneTRUEencasdesuccsetFALSEencasd'erreur(accompagnd'unealerte).
Tenterdefermerunebasedjfermeprovoquel'affichaged'unealerte.

Toutes les bases ouvertes de faon non permanente sont automatiquement fermes la fin du script.

Exemple

<?php
// ouverture
$id1 = sqlite_open('diane.dbf');
echo "\$id1 = $id1<BR>\n";
// fermeture
sqlite_close($id1);
// tentative de fermeture d'une base dj ferme
sqlite_close($id1);
?>

Rsultat

id1 = Resource id #2
Warning: sqlite_close(): 2 is not a valid sqlite database resource
in d:\scripts php\index.php on line 8

Liredesdonnes

Liredesdonnesdansunebasencessitedeuxoprations :

- excuter une requte (en l'occurrence SELECT) sur la base ;

- rcuprer la ou les lignes correspondant au rsultat de la requte.

Excuterunerequte

Lafonctionsqlite_querypermetd'excuterunerequtesurunebase.

- 2- ENI Editions - All rigths reserved


Syntaxe

ressource sqlite_query(chane requte, ressource base)


ressource sqlite_query(ressource base ,chane requte)

Avec

base

Identifiantdebasededonnesretournparlafonctionsqlite_open.

requte

Textedelarequteexcuter.

Danslecasd'unordreSELECT,lafonctionsqlite_queryetourneunidentifiantdersultatderequteencasde
succs et FALSE en cas d'chec (avec affichage d'un message d'alerte) pour les autres ordres SQL, cette
fonctionretourneTRUEencasdesuccs.

Exemple

<?php
// ouverture
$base = sqlite_open('diane.dbf');
// dfinition de la requte
$requte = "SELECT * FROM articles";
// excution de la requte
$rsultat1 = sqlite_query($requte,$base);
echo "\$rsultat1 = ",
($rsultat1)? $rsultat1:'FALSE',"<BR>\n";
// dfinition d'une mauvaise requte
$requte = "SELECT * FROM article";
// excution de la requte
$rsultat2 = sqlite_query($requte,$base);
echo "\$rsultat2 = ",
($rsultat2)? $rsultat2:'FALSE',"<BR>\n";
?>

Rsultat

$rsultat1 = Resource id #3
Warning: sqlite_query() [function.sqlite-query]: no such table:
article in d:\scripts php\index.php on line 12
$rsultat2 = FALSE

Comme indiqu en introduction, la fonction sqlite_query excute la requte, indique si la requte s'est
excutecorrectementmaisnerenvoieaucunedonne.Ilvafalloirextraireleslignesdursultat.

Il existe une variante de sqlite_query, nomme sqlite_array_query, qui excute une requte et retourne
directementlersultatdansuntableau(prsenteciaprs).

Danslecasd'unordreSELECT,lersultatdelarequteexcuteparsqlite_queryestmisenbuffer.Ilexiste
une autre fonction, sqlite_unbuffered_query, qui possde la mme syntaxe que sqlite_query et permet
aussi d'excuter une requte, mais sans mettre le rsultat dans un buffer. Pour les requtes volumineuses,
sqlite_unbuffered_query consomme beaucoup moins de mmoire que sqlite_query et permet d'extraire la
premirelignebienplusrapidement :iln'yapasbesoind'attendrequelatotalitdursultatsoitmisenbuffer.
Parcontre,aprsexcutiondelarequteavec sqlite_unbuffered_query,iln'estpaspossibledeconnatrele
nombredelignesdursultat(voirciaprs).

Connatrelenombredelignesdanslersultat

Lafonctionsqllite_num_rowspermetdeconnatrelenombredelignesdanslersultat.

Syntaxe

ENI Editions - All rigths reserved - 3-


entier sqlite_num_rows(ressource rsultat)

Avec

rsultat

Identifiantdersultatderequteretournparlafonctionsqlite_query.

CettefonctionestutilisableuniquementpourlesrequtesSELECT.

Exemple

<?php
// ouverture
$base = sqlite_open('diane.dbf');
// dfinition de la requte
$requte = "SELECT * FROM articles";
// excution de la requte
$rsultat = sqlite_query($requte,$base);
// rcupration du nombre de lignes
$nombre = sqlite_num_rows($rsultat);
echo "Nombre d'articles : $nombre<BR>\n";
// dfinition de la requte
$requte = "SELECT * FROM articles WHERE prix > 40";
// excution de la requte
$rsultat = sqlite_query($requte,$base);
// rcupration du nombre de lignes
$nombre = sqlite_num_rows($rsultat);
echo "Nombre d'articles dont le prix est suprieur 40 : $nombre<BR>\n";
?>

Rsultat

Nombre d'articles : 4
Nombre d'articles dont le prix est suprieur 40 : 1

Lirelersultatdelarequte

Lersultatdel'excution(russie)d'unerequteSELECTpeuttreluparlafonctionsqlite_fetch_array.

Syntaxe

tableau sqlite_fetch_array(ressource rsultat, entier type)

Avec

rsultat

Identifiantdersultatderequteretournparlafonctionsqlite_query.

type

Typedersultatgalunedesconstantessuivantes :
SQLITE_ASSOC,SQLITE_NUM,SQLITE_BOTH

Lafonction sqlite_fetch_arrayretournelalignecourantedursultatsouslaformed'untableau,chaqueligne
dutableaucorrespondantunecolonnedursultat.

S'iln'yaplusdeligneliredanslersultat,lafonctionretourneFALSE.

Letypedutableau(numriqueouassociatif)dpenddudeuximeparamtre :

SQLITE_NUM

Tableauindicesentiers.

- 4- ENI Editions - All rigths reserved


SQLITE_ASSOC

Tableauassociatif.

SQLITE_BOTH
(valeur par dfaut)

Lesdeuxlafois.
Chaquecolonneestprsentedeuxfois.

Exemple:

Requte SELECT * FROM


articles
Colonnes identifiant libelle prix
1re ligne du 1 Abricots 35.5
rsultat

Rsultatd'unfetchavec :

sqlite_fetch_array sqlite_fetch_array sqlite_fetch_array


(...,SQLITE_NUM) (...,SQLITE_ASSOC) (...,SQLITE_BOTH)
Indice/Cl Valeur Indice/Cl Valeur Indice/Cl Valeur
0 1 identifiant 1 identifiant 1
1 Abricots libelle Abricots 0 1
2 35.5 prix 35.5 libelle Abricots
1 Abricots
prix 35.5
2 35.5

En cas d'utilisation, d'un alias de colonne dans la requte SELECT (exemple SELECT AVG(prix) prix_moyen
FROM articles),c'estl'aliasdecolonnequiestutiliscommecl.

Exemple

<?php
// inclusion du fichier qui contient la dfinition de
// afficher_tableau
include("fonctions.inc");
// ouverture
$base = sqlite_open('diane.dbf');
// excution de la requte
$rsultat = sqlite_query("SELECT * FROM articles",$base);
// Premier fetch sans deuxime paramtre
$ligne = sqlite_fetch_array($rsultat);
afficher_tableau($ligne,"sans deuxime paramtre");
// Deuxime fetch avec SQLITE_BOTH
$ligne = sqlite_fetch_array($rsultat,SQLITE_BOTH);
afficher_tableau($ligne,"SQLITE_BOTH");
// Troisime fetch avec SQLITE_ASSOC
$ligne = sqlite_fetch_array($rsultat,SQLITE_ASSOC);
afficher_tableau($ligne,"SQLITE_ASSOC");
// Quatrime fetch avec SQLITE_NUM
$ligne = sqlite_fetch_array($rsultat,SQLITE_NUM);
afficher_tableau($ligne,"SQLITE_NUM");
// Cinquime fetch de nouveau sans deuxime paramtre
// - normalement, plus de ligne
$ligne = sqlite_fetch_array($rsultat);
if (! $ligne) {
echo "<P><B>Cinquime fetch : plus rien</B>";
}
?>

ENI Editions - All rigths reserved - 5-


Rsultat

sans deuxime paramtre


0 = 1
identifiant = 1
1 = Abricots
libelle = Abricots
2 = 35.5
prix = 35.5
SQLITE_BOTH
0 = 2
identifiant = 2
1 = Cerises
libelle = Cerises
2 = 48.9
prix = 48.9
SQLITE_ASSOC
identifiant = 3
libelle = Fraises
prix = 29.95
SQLITE_NUM
0 = 4
1 = Pches
2 = 37.2
Cinquime fetch : plus rien

Cetexemplepermetdevoir:

- les diffrents modes de rcupration d'une ligne de rsultat ;

- chaque fetch, le pointeur interne avance, et que le fetch suivant retourne donc la ligne suivante, jusqu' avoir
parcouru toutes les lignes.

En cas d'utilisation d'un identifiant de rsultat non valide, la fonction sqlite_fech_array retourne FALSE et
affiche,enplus,unealertedutype :

Warning: sqlite_fetch_array() expects parameter 1 to be resource, boolean given in d:\scripts


php\index.php on line 5

Encasdebesoin,lafonctionsqlite_has_morepeuttreutilisepourdterminers'ilrestedeslignesextraire
dansunrsultat.

Syntaxe

boolen sqlite_has_more(ressource rsultat)

Avec

rsultat

Identifiantdersultatderequteretournparlafonctionsqlite_query.

Lafonction sqlite_has_moreretourne TRUEs'ilrestedeslignesextrairedanslersultatetFALSEdanslecas


contraire.

SQLite propose aussi une fonction, sqlite_array_query, qui permet d'excuter une requte et de retourner le
rsultat dans un tableau. Cette fonction est l'quivalent de l'appel la fonction sqlite_query suivi d'une srie
d'appelslafonctionsqlite_fetch_array(pourchaquelignedursultat),enbeaucoupplusperformant.

Syntaxe

tableau sqlite_array_query(ressource base, chane requte, entier type)


tableau sqlite_array_query(chane requte, ressource base, entier type)

Avec

- 6- ENI Editions - All rigths reserved


base

Identifiantdebasededonnesretournparlafonctionsqlite_open.

requte

Textedelarequteexcuter.

type

Typedersultatgalunedesconstantessuivantes :
SQLITE_ASSOC,SQLITE_NUM,SQLITE_BOTH

La fonction sqlite_array_query retourne un tableau multidimensionnel en cas de succs, ou FALSE en cas


d'erreur. Le tableau principal est un tableau indices entiers contenant une ligne pour chaque ligne du rsultat
(indice0pourla1re ligne,1pourla2e ,etc.).Letableausecondaireestuntableaunumriqueouassociatif(ou
lesdeux)selonlavaleurduparamtretype(voirlafonctionsqlite_fetch_array.

Exemple

<?php
// inclusion du fichier qui contient la dfinition de
// afficher_tableau
include("fonctions.inc");
// ouverture
$base = sqlite_open('diane.dbf');
// dfinition de la requte
// - deux articles seulement
$requte = "SELECT * FROM articles LIMIT 2";
// excution de la requte et rcupration du
// rsultat dans un tableau
// - pas de troisime paramtre => SQLITE_BOTH
$rsultat = sqlite_array_query($requte,$base);
afficher_tableau($rsultat);
?>

Rsultat

0 =
0 = 1
identifiant = 1
1 = Abricots
libelle = Abricots
2 = 35.5
prix = 35.5
1 =
0 = 2
identifiant = 2
1 = Cerises
libelle = Cerises
2 = 48.9
prix = 48.9

Exempledecodepourlalectured'uneligne

Un premier type de lecture consiste souvent lire une seule ligne d'information dans une table (ou plusieurs
tablesavecjointure) :informationssurl'utilisateurquivientdeseconnecter,fiched'informationd'unarticle...

Exemple

<?php
// inclure un fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// initialiser les variables
$identifiant = "";
$libell = "";
$prix = "";
$message = "";
// Tester la faon dont le script est appel

ENI Editions - All rigths reserved - 7-


if (! empty($_POST)) {
// traitement du formulaire _
// rappel : lorsqu'un formulaire n'a qu'une zone de texte
//et que l'utilisateur tape return ou enter, le bouton de
// validation n'est pas considr comme cliqu. Pour savoir
// si le formulaire a t soumis, il faut tester si
// $_POST (ou $_GET) est vide.
// rcuprer les valeurs saisies
$identifiant = valeur_saisie($_POST["identifiant"]);
// contrler les valeurs saisies
if ($identifiant == "") {
$message .= "L'identifiant est obligatoire.\n";
}
if (! ereg("^[0-9]+$",$identifiant)) {
$message .=
"L'identifiant doit tre un nombre.\n";
}
// tester s'il y a des erreurs ce stade
if ($message == "") {
// pas d'erreur
// ouverture de la base
$base = sqlite_open('diane.dbf');
// excuter la requte de slection
$requte = "SELECT * FROM articles WHERE
identifiant = $identifiant";
$rsultat = sqlite_query($requte,$base);
// fetch si la requte a bien t excute
if ($rsultat) {
$article = sqlite_fetch_array($rsultat);
}
// tester le rsultat
if (! $rsultat) { // requte pas OK
$message .= "Erreur.\n";
} elseif (! $article) { // rsultat vide
$message .=
"Pas d'article pour cet identifiant.\n";
} else { // OK

// rcuprer les informations afficher


$libell = $article["libelle"];
$prix = $article["prix"];
// mise en forme
$libell = vers_page($libell);
$prix = number_format($prix,2,"," ," ");
$prix = vers_page($prix);
}
}
// tester s'il y a des erreurs ce stade
if ($message != "") {
// erreur
// prparer le message pour l'affichage
$message = vers_page($message);
// bien s'assurer que les informations
// afficher sont vides
$libell = "";
$prix = "";
}
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Consultation d'un article</TITLE></HEAD>
<BODY>
<FORM METHOD="POST">
Identifiant de l'article :
<INPUT TYPE="text" NAME="identifiant"
VALUE="<?php echo vers_formulaire($identifiant); ?>">
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<TABLE BORDER="0">
<TR><TD><U>Libell :</U> </TD>
<TD><?php echo $libell; ?></TD></TR>
<TR><TD><U>Prix :</U> </TD>
<TD><?php echo $prix; ?></TD></TR>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

- 8- ENI Editions - All rigths reserved


Rsultat (aprs saisie et clic sur le bouton OK)

Ilestrelativementsimpled'crireunefonctiongnriquepermettantdelireuneligne.

Exemple

<?php
function db_lire_ligne($requte) {
// la variable $ok est utilise pour savoir
// si tout se passe bien
// ouvrir la base
$ok = ( ($base = sqlite_open('diane.dbf')) != FALSE );
// excuter la requte et tester le rsultat pour affecter
// la variable $ok
if ($ok) {
$ok = ( ($rsultat = sqlite_query($requte,$base))
!= FALSE );
}
if ($ok) { // excution OK
// lire la ligne
$ligne = sqlite_fetch_array($rsultat);
}
// retourner $ligne ou FALSE en cas d'erreur
return ($ok)?$ligne:FALSE;
}
?>

Ilestpossible(souhaitable)d'amliorerlagestiondeserreurs(cf.Grerleserreurs).

Exemple d'utilisation

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// dfinir la requte
$requte = "SELECT * FROM articles WHERE identifiant= 1";
// lire le rsultat
$ligne = db_lire_ligne($requte);
if ($ligne) {
echo "$ligne[libelle] - $ligne[prix]";
}
?>

Rsultat (sauf erreur)

Abricots - 35.5

Exempledecodepourlalecturedetoutesleslignes

Un deuxime type de lecture consiste souvent afficher une liste d'lments extraits de la base (liste
d'utilisateurs,listed'articles...).

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// ouvrir la base
$ok = ( ($base = sqlite_open('diane.dbf')) != FALSE );
// excuter la requte de slection et charger directement
// les donnes dans un tableau

ENI Editions - All rigths reserved - 9-


$requte = "SELECT * FROM articles";
$articles = sqlite_array_query($requte,$base);
// tester le rsultat
if ($articles === FALSE) { // requte pas OK
$message .= "Erreur.\n";
} elseif (empty($articles)) { // rsultat vide
$message .=
"Aucun article dans la base.\n";
} else { // OK
// mettre en forme les donnes (idem prcdemment)
for ($i=0;$i<count($articles);$i++) {
$articles[$i]["libelle"] =
vers_page($articles[$i]["libelle"]);
$articles[$i]["prix"] =
vers_page(number_format($articles[$i]["prix"],2,"," ," "));
}
}
// tester s'il y a des erreurs ce stade
if ($message != "") {
// erreur
// prparer le message pour l'affichage
$message = vers_page($message);
// bien s'assurer que les informations
// afficher sont vides
unset($articles);
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML -->
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if (isset($articles)) { // s'il y a un rsultat afficher
foreach($articles as $article) { // boucle sur les articles
// gnration de la ligne de la table HTML
// remarque : printf() rend le code lisible
printf("<TR><TD>%d</TD><TD>%s</TD><TD>%s</TD></TR>",
$article["identifiant"],
$article["libelle"],
$article["prix"]);
}
}
?>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Le mme exemple peut tre crit de manire plus compacte, plus conome en mmoire et plus performante : le
fetchesteffectuaucoursdelaconstructiondelatableHTMLsurunerequtedontlersultatn'apastmis
enbuffer.

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// ouvrir la base
$ok = ( ($base = sqlite_open('diane.dbf')) != FALSE );
// excuter la requte de slection
// - le rsultat n'est pas mis en buffer
$requte = "SELECT * FROM articles";
$rsultat = sqlite_unbuffered_query($requte,$base);
// tester le rsultat
if (! $rsultat) { // requte pas OK
// message d'erreur
$message .= "Erreur.\n";
// prparer le message pour l'affichage
$message = vers_page($message);
}

- 10 - ENI Editions - All rigths reserved


// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML -->
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if ($rsultat) { // s'il y a un rsultat afficher
// boucle de fetch
$nombre_lignes = 0;
while ($article = sqlite_fetch_array($rsultat)) {
$nombre_lignes++;
// mise en forme des donnes
$article["libelle"] = vers_page($article ["libelle"]);
$article["prix"] = vers_page(
number_format($article["prix"],2,"," ," "));
// gnration de la ligne de la table HTML
printf("<TR><TD>%d</TD><TD>%s<</TD><TD>%s</TD></TR>",
$article["identifiant"],
$article["libelle"],
$article["prix"]);
} // while
// si le rsultat est vide, prparer un message
if ($nombre_lignes == 0) {
$message = vers_page("Aucun article dans la base.");
}
} // if ($rsultat)
?>
</TABLE>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Pourpermettrel'utilisateurd'agirsurlaliste,ilestpossibled'imbriquerunformulaireoudesliensaveclatable
HTML.

Exemple

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// ouvrir la base
$ok = ( ($base = sqlite_open('diane.dbf')) != FALSE );
// excuter la requte de slection
// - le rsultat n'est pas mis en buffer
$requte = "SELECT * FROM articles";
$rsultat = sqlite_unbuffered_query($requte,$base);
// tester le rsultat
if (! $rsultat) { // requte pas OK
// message d'erreur
$message .= "Erreur.\n";
// prparer le message pour l'affichage
$message = vers_page($message);
}
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Liste des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML l'intrieur d'un
---- formulaire -->
<FORM METHOD="POST">
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Libell</TH><TH>Prix</TH><TH>Case</TH><TH>Lien</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php

ENI Editions - All rigths reserved - 11 -


if ($rsultat) { // s'il y a un rsultat afficher
// boucle de fetch
$nombre_lignes = 0;
while ($article = sqlite_fetch_array($rsultat)) {
$nombre_lignes++;
// mise en forme des donnes
$article["libelle"] = vers_page($article ["libelle"]);
$article["prix"] = vers_page(
number_format($article["prix"],2,"," ," "));
// gnration de la ligne de la table HTML
// - une case cocher dans une colonne
// - un lien dans une autre colonne
printf(
"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>",
$article["libelle"],
$article["prix"],
"<INPUT TYPE=\"checkbox\" NAME=\"choix[]\"
VALUE=\"$article[identifiant]\">",
"<A HREF=\"javascript:alert($article[identifiant])\">
action<A>");
} // while
// si le rsultat est vide, prparer un message
if ($nombre_lignes == 0) {
$message = vers_page("Aucun article dans la base.");
}
} // if ($rsultat)
?>
</TABLE>
<BR><INPUT TYPE="submit" NAME="action" VALUE="Action">
</FORM>
<FONT COLOR="green">
<?php
// traitement du formulaire
// simple affichage des identifiants cochs
if (isset($_POST["action"])) {
if (isset($_POST["choix"])) {
echo "Identifiant(s) coch(s) : ".
implode("+",$_POST["choix"]);
}
}
?>
</FONT>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Rsultat

- Affichage initial de la page :

- Aprs clic sur un lien :

- 12 - ENI Editions - All rigths reserved


- Aprs clic sur le bouton Action :

Sur le lien, la place du code JavaScript, il est possible de mettre une vraie URL et d'enchaner sur une autre
page (voir le chapitre Grer les sessions pour comprendre comment placer un paramtre dans l'URL et pouvoir
ainsipasseruneinformation,icil'identifiantchoisi,uneautrepage).

Encequiconcerneletraitementduformulaire,toutestenvisageable.

Lencore,pourlalecturedeplusieurslignes,unefonctiongnriqueestpossible.

Exemple

<?php
function db_lire_lignes_dans_tableau($requte) {
// la variable $ok est utilise pour savoir
// si tout se passe bien
// ouvrir la base
$ok = ( ($base = sqlite_open('diane.dbf')) != FALSE );
// excuter la requte et rcuprer le rsultat directement
// dans un tableau
if ($ok) {
$tableau = sqlite_array_query($requte,$base);
// tester le rsultat pour affecter la variable $ok
$ok = ( $tableau != FALSE );
}
// retourner $tableau ou FALSE en cas d'erreur
return ($ok)?$tableau:FALSE;
}
?>

Utilisation

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales

ENI Editions - All rigths reserved - 13 -


require("fonctions.inc");
// dfinir la requte
$requte = "SELECT * FROM articles";
// lire le rsultat dans un tableau
$articles = db_lire_lignes_dans_tableau($requte);

// afficher le premier article lu


if ($articles) {
echo count($articles)." articles<BR>";
echo "Premier article : ";
echo "{$articles[0]['libelle']} {$articles[0][ 'prix']}";
}
?>

Rsultat (sauf erreur)

4 articles
Premier article : Abricots - 35.5

Mettrejourdesdonnes

MettrejourdesdonnesconsisteexcuterdesrequtesINSERT(cration),UPDATE(modification)ouDELETE
(suppression).

L'excutiondecetypederequtes'effectueaveclafonctionsqlite_query,commepourunerequteSELECT.

Encomplment,deuxfonctionssontintressantes :sqlite_changesetsqlite_last_insert_rowid.

La fonction sqlite_changes permet de connatre le nombre de lignes concernes (insres, modifies ou


supprimes)parladernirerequteINSERT,UPDATEouDELETEexcutesurunebase.

Syntaxe

entier sqlite_changes(ressource base)

Avec

base

Identifiantdebasededonnesretournparlafonctionsqlite_open.

Siladernirerequteachou,lafonctionsqlite_changesretourne0.

Lafonction sqlite_last_insert_rowidretournelavaleurdudernieridentifiantgnrparunerequteINSERT
surunebase,pourunecolonnedclareenINTEGER PRIMARY KEY.

Syntaxe

entier sqlite_last_insert_rowid(ressource base)

Avec

base

Identifiantdebasededonnesretournparlafonctionsqlite_open.

Siaucunidentifiantn'atgnrautomatiquement,lafonctionsqlite_last_insert_rowidretourne0.

La requte INSERT n'a pas besoin d'tre la dernire requte excute sur la base.

Exemples

<?php

- 14 - ENI Editions - All rigths reserved


// inclusion du fichier qui contient la dfinition des
// fonctions gnrales
include("fonctions.inc");
// dfinition d'une petite fonction d'affichage de la liste
// des articles
function AfficherArticles() {
$requte = "SELECT * FROM articles";
$articles = db_lire_lignes_dans_tableau($requte);
if ($articles) {
echo "<B>Liste des articles :</B><BR>";
foreach($articles as $a) {
echo "$a[identifiant] - $a[libelle] - $a[prix]<BR>";
}
} else {
echo "<B>Plus d'articles.</B><BR>";
}
}
// ouverture
$base = sqlite_open('diane.dbf');
// affichage de contrle
AfficherArticles();
// requte INSERT
$requte = "INSERT INTO articles(libelle,prix)
VALUES('Poires',29.9)";
$rsultat = sqlite_query($requte,$base);
// rcuprer l'identifiant
$identifiant = sqlite_last_insert_rowid($base);
echo "Identifiant du nouvel article = $identifiant.<BR>";
// requte UPDATE
$requte = "UPDATE articles SET prix = prix * 1.1
WHERE prix < 40";
$rsultat = sqlite_query($requte,$base);
$nombre = sqlite_changes($base);
echo "$nombre article(s) augment(s).<BR>";
// requte DELETE
$requte = "DELETE FROM articles WHERE prix > 40";
$rsultat = sqlite_query($requte,$base);
$nombre = sqlite_changes($base);
echo "$nombre article(s) supprims(s).<BR>";
// affichage de contrle
AfficherArticles();
?>

Rsultat

Liste des articles :


1 - Abricots - 35.5
2 - Cerises - 48.9
3 - Fraises - 29.95
4 - Pches - 37.2
Identifiant du nouvel article = 5.
4 article(s) augment(s).
2 article(s) supprims(s).
Liste des articles :
1 - Abricots - 39.05
3 - Fraises - 32.945
5 - Poires - 32.89

Crerdesformulairesquipermettentdemettrejourlesdonnesesttrssimple.

titred'exemple,nousallonsconstruireunformulairequipermetderaliserunesaisieenliste.

Prsentation du formulaire

ENI Editions - All rigths reserved - 15 -


Le formulaire propose le contenu actuel de la table qui peut tre modifi (saisie directe dans les zones) ou
supprim (par les cases cocher), plus cinq lignes vides qui permettent de saisir de nouvelles valeurs dans
touslescas,l'identifiantn'estpassaisissable(c'estSQLitequival'attribuer).

Chaquelignedutableaucontient4zonesdeformulairequisontnommes(optionNAMEdelabalise<INPUT>)de
lamaniresuivante :

Colonne Nom
Identifiant saisie[i][modifier]
Libell saisie[i][libelle]
Prix saisie[i][prix]
Supprimer saisie[i][supprimer]

L'indice i est l'identifiant de l'article pour les lignes qui existent et un numro compris entre 1 et 5 pour les
lignesvides.Lazonedelacolonne Identifiantestunezonemasque(TYPE="hidden")quivatreutilisepour
identifierleslignesdanslesquellesl'utilisateuraeffectuunemodification.

Avec ce processus de nommage, toute la saisie sera rcupre dans le script PHP sous la forme d'un tableau
multidimensionnel nomm $lignes. Chaque ligne du tableau correspond une ligne du formulaire avec la cl
gale l'identifiant (ou 1 5 pour les nouvelles lignes) et la valeur gale un tableau associatif donnant les
lmentssaisis.

Pour identifier les lignes modifies par l'utilisateur, les zones de saisie du libell et du prix des lignes existantes
contiennentlecodeJavaScriptsuivant :

onChange="document.formulaire[$n].value=1"

Ce code JavaScript a pour effet, chaque fois que la zone en question est modifie, de mettre un 1 dans la
zone masque associe la ligne. Le formulaire s'appelant formulaire (<FORM NAME = "formulaire"...),
l'expression document.formulaire[n] dsigne la nime zone du formulaire formulaire du document courant,
la premire zone du formulaire ayant le numro 0. Dans le source, la variable $n est calcule pour chaque ligne
$i du formulaire par la formule $n = 4 * ($i - 1) : la zone cache de la ligne 1 a le numro 0 (c'est la
premireduformulaire),celledelaligne2lenumro4etainsidesuite.

Cetexemplepeut(doit)treamliorpour :

- contrler la saisie de l'utilisateur ;

- grer les erreurs.

Source

- 16 - ENI Editions - All rigths reserved


<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// initialiser la variable de message
$message = "";
// ouvrir la base
$base = sqlite_open('diane.dbf');
// traitement du formulaire
if (isset($_POST["OK"])) {
// rcuprer le tableau contenant la saisie
$lignes = $_POST["saisie"];
foreach($lignes as $identifiant => $ligne) {
// nettoyage de la saisie
$libell = valeur_saisie($ligne["libelle"]);
$prix = valeur_saisie($ligne["prix"]);
$prix = str_replace(",",".",$prix); // , => .
$prix = str_replace(" ","",$prix); // supprimer espaces
// ce niveau, il faudrait vrifier la saisie ...
$requte = "";
if ($identifiant < 0 and $libell.$prix != "") {
// identifiant ngatif et quelque chose de saisi
// = cration = INSERT
$requte = "INSERT INTO articles(libelle,prix)
VALUES('$libell',$prix)";
} elseif (isset($ligne["supprimer"])) {
// case " supprimer " coche = suppression = DELETE
$requte = "DELETE FROM articles
WHERE identifiant = $identifiant";
} elseif (isset($ligne["modifier"])) {
// zone " modifier " TRUE (1) = modification = UPDATE
$requte = "UPDATE articles
SET libelle = '$libell', prix = $prix
WHERE identifiant = $identifiant";
}
// si une requte a t dtermine, l'excuter
if ($requte != "") {
sqlite_query($requte,$base);
// ce niveau, il faudrait tester les erreurs ...
}
}
}
// recharger les articles
$requte = "SELECT * FROM articles";
$rsultat = sqlite_unbuffered_query($requte,$base);
// ce niveau, il faudrait tester les erreurs ...
// Affichage de la page ...
?>
<HTML>
<HEAD><TITLE>Gestion des articles</TITLE></HEAD>
<BODY>
<!-- construction d'une table HTML l'intrieur d'un
---- formulaire -->
<FORM NAME="formulaire" METHOD="POST">
<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">
<!-- ligne de titre -->
<TR ALIGN=\"center\">
<TH>Identifiant</TH><TH>Libell</TH><TH>Prix</TH>
<TH>Supprimer</TH>
</TR>
<!-- code PHP pour les lignes du tableau -->
<?php
if ($rsultat) { // s'il y a un rsultat afficher
// initialisation d'un compteur de ligne
$i = 0;
// boucle de fetch
while ($article = sqlite_fetch_array($rsultat)) {
// incrmentation du compteur de ligne
$i++;
// calcul du numro d'ordre dans le formulaire de la
// zone cache correspondant l'identifiant
$n = 4 * ($i - 1);
// mise en forme des donnes
$article["libelle"] = vers_page($article["libelle"]);
$article["prix"] = vers_page(
number_format($article["prix"],2,"," ," "));
// gnration de la ligne de la table HTML
// insertion des balises INPUT du formulaire
printf(
"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>",

ENI Editions - All rigths reserved - 17 -


"$article[identifiant]
<INPUT TYPE=\"hidden\"
NAME=\"saisie[$article[identifiant]][modifier]\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[$article[identifiant]][libelle]\"
VALUE=\"$article[libelle]\"
onChange=\"document.formulaire[$n].value=1\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[$article[identifiant]][prix]\"
VALUE=\"$article[prix]\"
onChange=\"document.formulaire[$n].value=1\">",
"<INPUT TYPE=\"checkbox\"
NAME=\"saisie[$article[identifiant]][supprimer]\"
VALUE=\"$article[identifiant]\">");
} // while
// ajout de 5 lignes vides pour la cration
// (sans identifiant, sans case de suppression)
for($i=1;$i<=5;$i++) {
printf(
"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>",
"",
"<INPUT TYPE=\"text\"
NAME=\"saisie[-$i][libelle]\"
VALUE=\"\">",
"<INPUT TYPE=\"text\"
NAME=\"saisie[-$i][prix]\"
VALUE=\"\">",
"");
} // for
}
?>
</TABLE>
<BR><INPUT TYPE="submit" NAME="OK" VALUE="Enregistrer">
</FORM>
</BODY>
</HTML>

Grerleserreurs

Les fonctions sqlite_last_error et sqlite_error_string permettent de rcuprer des informations sur


l'erreurventuelledeladernireoprationeffectuesurunebase.

Syntaxe

entier sqlite_last_error(ressource base)


chane sqlite_error_string(entier numro)

Avec

base

Identifiantdebasededonnesretournparlafonctionsqlite_open.

numro

Numrod'erreurSQLite.

La fonctionsqlite_last_errorretournelenumrod'erreurdeladernireoprationeffectuesurunebase.La
fonctionsqlite_error_stringretournelemessaged'erreurassociunnumrod'erreur.

Exemple

<?php
// ouverture
$base = sqlite_open('diane.dbf');
// une bonne requte pour commencer
$requte = "SELECT * FROM articles";
$rsultat = sqlite_query($requte,$base);
$code = sqlite_last_error($base);
$message = sqlite_error_string($code);
echo "1 : $code - $message<BR>";

- 18 - ENI Editions - All rigths reserved


// requte sur une table qui n'existe pas
$requte = "SELECT * FROM article";
$rsultat = sqlite_query($requte,$base);
$code = sqlite_last_error($base);
$message = sqlite_error_string($code);
echo "2 : $code - $message<BR>";
// requte INSERT qui viole une cl primaire
$requte = "INSERT INTO articles(identifiant,libelle,prix)
VALUES(1,'Poires',29.9)";
$rsultat = sqlite_query($requte,$base);
$code = sqlite_last_error($base);
$message = sqlite_error_string($code);
echo "3 : $code - $message<BR>";
// tentative de fetch sur un mauvais rsultat
$requte = "SELECT * FROM article";
$rsultat = sqlite_query($requte,$base);
$code = sqlite_last_error($base);
$message = sqlite_error_string($code);
echo "4 : $code - $message<BR>";
$ligne = mysql_fetch_assoc($rsultat);
$code = sqlite_last_error($base);
$message = sqlite_error_string($code);
echo "5 : $code - $message<BR>";
?>

Rsultat

1 : 0 - not an error
Warning: sqlite_query() [function.sqlite-query]: no such table:
article in d:\scripts php\index.php on line 12
2 : 1 - SQL logic error or missing database
Warning: sqlite_query() [function.sqlite-query]: PRIMARY KEY
must be unique in d:\scripts php\index.php on line 19
3 : 19 - constraint failed
Warning: sqlite_query() [function.sqlite-query]: no such table:
article in d:\scripts php\index.php on line 25
4 : 1 - SQL logic error or missing database
Warning: mysql_fetch_assoc(): supplied argument is not a valid
MySQL result resource in d:\scripts php\index.php on line 29
5 : 1 - SQL logic error or missing database

Le point 5 illustre le fait que les erreurs lies l'utilisation d'une ressource de rsultat non valide n'est pas une
erreur SQLite. Dans ce cas, la fonction sqlite_last_error n'est pas rinitialise et ne retourne donc pas
d'erreurspcifique :lecodeetlemessagedupoint 5sontenfaitceuxdupoint4.

En pratique, les fonctions sqlite_last_error et sqlite_error_string sont employes aprs l'excution des
requtes mais ne sont d'aucune utilit sur l'ouverture de la base et sur les "fetch". Pour l'ouverture de la base,
nousavonsvuquelafonctionsqlite_openpermettaitdercupreruneerreurventuelledansunevariable.

Par ailleurs, nous verrons au chapitre Grer les erreurs dans un script PHP comment supprimer l'affichage des
alertes.

Cesfonctionspeuventtremisesenuvretitred'exemplesurunedenosfonctionsgnriques.

Source

<?php
function db_lire_ligne($requte, &$erreur) {
// dans cette nouvelle version, db_lire_ligne prend un
// deuxime paramtre par rfrence dans lequel un numro
// et un message seront stocks en cas d'erreur (sous la
// forme d'un tableau)
// initialiser $erreur
$erreur = array(0,""); // numro = 0, message vide
// ouvrir la base et tester le rsultat pour affecter
// la variable $ok
$base = sqlite_open('diane.dbf',666,$erreur_ouverture);
$ok = empty($erreur_ouverture);
// en cas d'erreur, affecter $erreur
if (! $ok ) {
// un code d'erreur fictif est utilis
$erreur = array(-1,$erreur_ouverture);
}

ENI Editions - All rigths reserved - 19 -


// excuter la requte et tester le rsultat pour affecter
// la variable $ok
if ($ok) {
$ok = ( ($rsultat = sqlite_query($requte,$base))
!= FALSE );
// en cas d'erreur, rcuprer les informations
// sur l'erreur
if (! $ok) {
$erreur = array(sqlite_last_error($base),
sqlite_error_string(sqlite_last_error($base)));
}
}
if ($ok) { // excution OK
// lire la ligne
$ligne = sqlite_fetch_array($rsultat);
}
// retourner $ligne ou FALSE en cas d'erreur
return ($ok)?$ligne:FALSE;
}
?>

Utilisation

<?php
// inclure le fichier qui contient les diffrentes fonctions
// gnrales
require("fonctions.inc");
// premier appel avec une erreur
$requte = "SELECT * FROM article WHERE identifiant = 1";
if (! ($ligne = db_lire_ligne($requte,$erreur))) {
echo "$erreur[0] - $erreur[1]<BR>";
} else {
echo "$ligne[libelle] - $ligne[prix]<BR>";
}
// deuxime appel correct
$requte = "SELECT * FROM articles WHERE identifiant = 1";
if (! ($ligne = db_lire_ligne($requte,$erreur))) {
echo "$erreur[0] - $erreur[1]<BR>";
} else {
echo "$ligne[libelle] - $ligne[prix]<BR>";
}
?>

Rsultat

Warning: sqlite_query() [function.sqlite-query]: no such


table: article in d:\scripts php\index.php on line 21
1 - SQL logic error or missing database
Abricots - 35.5

- 20 - ENI Editions - All rigths reserved


"Magicquotes" :leretour

Prambule

Nous avons vu dans le chapitre Gestion des formulaires que PHP proposait une fonctionnalit, appele "magic
quotes", dont l'objectif principal est de rsoudre un problme li l'enregistrement des donnes, dans une base
dedonnes,eneffectuantunencodagesurlesdonnessaisiesdansunformulaire.

Exemple (insertion en base d'une donne qui contient une apostrophe):

<?php
// donne qui pose problme (peut tre saisie dans un formulaire)
$libell = "Pomme d'api";
$prix = 10;
// requte
$requte = "INSERT INTO articles(libelle,prix)
VALUES('$libell',$prix)";
echo "$requte<BR>";
// Excution avec MySQL
echo "<P><B>MySQL</B><BR>";
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion);
$rsultat = mysql_query($requte);
echo mysql_error()."<BR>"; // MySQL ne gnre pas d'alerte
// Excution avec Oracle
echo "<P><B>Oracle</B><BR>";
$connexion = oci_connect("demeter","demeter","diane");
$rsultat = oci_execute(oci_parse($connexion,$requte));
// Excution avec SQL Serveur
echo "<P><B>SQL Serveur</B><BR>";
$connexion = mssql_connect("diane","demeter","demeter");
$rsultat = mssql_query($requte);
// Excution avec SQLite
echo "<P><B>SQLite</B><BR>";
$base = sqlite_open('diane.dbf');
$rsultat = sqlite_query($requte,$base);
?>

Rsultat

INSERT INTO articles(libelle,prix) VALUES('Pomme d'api',10)


MySQL
You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server
version for the right syntax to use near 'api',10)' at line 2
Oracle

Warning: oci_parse() [function.oci-parse]: OCIParse: ORA-01756:


une chane entre apostrophes ne se termine pas correctement
in d:\scripts php\index.php on line 16
Warning: oci_execute(): Supplied argument is not a valid OCI8-Statement resource in d:\scripts
php\index.php on line 16
SQL Serveur
Warning: mssql_query() [function.mssql-query]: message: Ligne 2 :
syntaxe incorrecte vers 'api'. (severity 15) in d:\scripts php\index.php
on line 20
Warning: mssql_query() [function.mssql-query]: message: Ouvrez
les guillemets avant la chane de caractres ',10)'.
(severity 15) in d:\scripts php\index.php on line 20
Warning: mssql_query() [function.mssql-query]: Query failed
in d:\scripts php\index.php on line 20
SQLite
Warning: sqlite_query() [function.sqlite-query]: near "api": syntax error
in d:\scripts php\index.php on line 27

EnSQL,ledlimiteurdechanedecaractresestl'apostrophe :siunerequteenvoielachane'Pomme d'api'


labase,cettedernirevainterprter'Pomme d'commeunechaneetnesaurapasquoifairedureste(api'.

Pour rgler ce problme, il faut indiquer la base que les apostrophes l'intrieur de la chane ne sont pas les
dlimiteurs de la chane, gnralement en faisant prcder l'apostrophe d'un caractre
"magique" ("d'chappement") : c'est le caractre antislash (\) pour MySQL ou apostrophe (') pour MySQL et
d'autresbasescommeOracle,SybaseouMicrosoftSQLServer.

ENI Editions - All rigths reserved - 1-


Exemple

<?php
// donne corrige (valable pour toutes les bases)
$libell = "Pomme d''api";
$prix = 10;
// requte
$requte = "INSERT INTO articles(libelle,prix)
VALUES('$libell',$prix)";
echo "$requte<BR>";
// Excution avec MySQL
echo "<P><B>MySQL</B><BR>";
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion);
$rsultat = mysql_query($requte);
echo mysql_error()."<BR>"; // MySQL ne gnre pas d'alerte
// Excution avec Oracle
echo "<P><B>Oracle</B><BR>";
$connexion = oci_connect("demeter","demeter","diane");
$rsultat = oci_execute(oci_parse($connexion,$requte));
// Excution avec SQL Serveur
echo "<P><B>SQL Serveur</B><BR>";
$connexion = mssql_connect("diane","demeter","demeter");
$rsultat = mssql_query($requte);
// Excution avec SQLite
echo "<P><B>SQLite</B><BR>";
$base = sqlite_open('diane.dbf');
$rsultat = sqlite_query($requte,$base);
?>

Rsultat

INSERT INTO articles(libelle,prix) VALUES('Pomme d''api',10)


MySQL
Oracle
SQL Serveur
SQLite

EncequiconcerneMySQL,unencodageaveclecaractreantislash(\)auraitaussifonctionne(maispasavec
lesautresbases).

$libell = "Pomme d\'api";

La fonctionnalit "magic quotes" d'encodage automatique rpond cette problmatique : si elle est active
(directive de configuration magic_quotes_gpc = on), toutes les donnes issues d'un formulaire (mthodes GET
ouPOST),d'uneURL(mthodeGET)oud'uncookiesontautomatiquementencodesaveclecaractreantislash
(\),ouapostrophe(')siladirectivedeconfigurationmagic_quotes_sybaseeston.

Malheureusement,nousavonsvuquecettefonctionnalit"magicquotes"posaitd'autresproblmesvisvis :

- de l'affichage des donnes dans la page HTML ;

- de la dpendance potentielle du code des directives de configuration.

Pour mmoire, la solution propose consiste s'assurer que les donnes sont charges dans des variables sans
encodageetfairecequ'ilfautaumomentdel'enregistrementdanslabase c'estcequenousallonsvoirdans
cechapitre.

Chargementdesdonnesenprovenanced'unebase

Unencodage"magicquotes"automatiqueestpossiblesurlesdonnesluesdansunebase,maisuniquementpour
MySQLetSQLServer.

Si la directive de configuration magic_quotes_runtime est on, toutes les donnes lues dans une base (ou
dans un fichier) ont automatiquement un encodage avec un anti slash (\) sur les caractres apostrophe ('),
guillemet(")etbiensrantislash(\).
Siladirectiveestoff,aucunencodageneseproduit.

- 2- ENI Editions - All rigths reserved


Du point de vue du caractre d'chappement utiliser, PHP propose la directive magic_quotes_sybase si
cettedirectiveeston,PHPutiliselecaractred'chappementapostrophe(')laplaceducaractreantislash
(\).Deplus,danscecas,seullecaractreapostrophe(')estchapp(lesautrescaractresneposentpasde
problme).

Exemple (avec l'article d'identifiant 5 contenant la donne "Pomme d'api")

<?php
// requte
$requte = "SELECT libelle FROM articles
WHERE identifiant = 5";
// Excution avec MySQL
echo "<B>MySQL</B><BR>";
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion);
$rsultat = mysql_query($requte);
$article = mysql_fetch_row($rsultat);
echo "$article[0]<BR>";
// Excution avec Oracle
echo "<B>Oracle</B><BR>";
$connexion = oci_connect("demeter","demeter","diane");
oci_execute($rsultat = oci_parse($connexion,$requte));
$article = oci_fetch_row($rsultat);
echo "$article[0]<BR>";
// Excution avec SQL Serveur
echo "<B>SQL Serveur</B><BR>";
$connexion = mssql_connect("diane","demeter","demeter");
$rsultat = mssql_query($requte);
$article = mssql_fetch_row($rsultat);
echo "$article[0]<BR>";
// Excution avec SQLite
echo "<B>SQLite</B><BR>";
$base = sqlite_open('diane.dbf');
$rsultat = sqlite_query($requte,$base);
$article = sqlite_fetch_array($rsultat);
echo "$article[0]<BR>";
?>

Rsultat (magic_quotes_runtime = off)

MySQL
Pomme d'api
Oracle
Pomme d'api
SQL Serveur
Pomme d'api
SQLite
Pomme d'api

Rsultat (magic_quotes_runtime = on et magic_quotes_sybase = off)

MySQL
Pomme d\'api
Oracle
Pomme d'api
SQL Serveur
Pomme d\'api
SQLite
Pomme d'api

Rsultat (magic_quotes_runtime = on et magic_quotes_sybase = on)

MySQL
Pomme d''api
Oracle
Pomme d'api
SQL Serveur
Pomme d''api
SQLite
Pomme d'api

En complment, la fonction get_magic_quotes_runtime permet de connatre la valeur de la directive

ENI Editions - All rigths reserved - 3-


magic_quotes_runtimeetlafonctionset_magic_quotes_runtime,delamodifierencoursdescript.

Syntaxe

entier get_magic_quotes_runtime()
boolen set_magic_quotes_runtime(entier valeur)

valeur

Nouvellevaleurdeladirectivemagic_quotes_runtime
0 =dsactiv(off),1=activ(on

Lafonctionset_magic_quotes_runtimeretourneTRUEsilechangements'esteffectuetFALSEautrement.
Lafonctionget_magic_quotes_runtimeretourne0sil'optionestdsactiveet1sielleestactive.

Exemple

<?php
// requte
$requte = "SELECT libelle FROM articles
WHERE identifiant = 5";
// Excution avec MySQL : magic_quotes_runtime = 1
echo "<B>set_magic_quotes_runtime(1)</B><BR>";
set_magic_quotes_runtime(1);
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion);
$rsultat = mysql_query($requte);
$article = mysql_fetch_row($rsultat);
echo "$article[0]<BR>";
// Excution avec MySQL : magic_quotes_runtime = 0
echo "<B>set_magic_quotes_runtime(0)</B><BR>";
set_magic_quotes_runtime(0);
$connexion = mysql_connect();
$ok = mysql_select_db("diane",$connexion);
$rsultat = mysql_query($requte);
$article = mysql_fetch_row($rsultat);
echo "$article[0]<BR>";
?>

Rsultat (si magic_quotes_sybase = off)

set_magic_quotes_runtime(1)
Pomme d\'api
set_magic_quotes_runtime(0)
Pomme d'api

La fonction set_magic_quotes_runtime sera particulirement intressante avec MySQL et SQL Server pour
crireuncodeindpendantdelaconfiguration :avantchaqueexcutiond'unerequteSELECT,ilsuffitd'appeler
cettefonctionaveclavaleur0ou1correspondantlastratgiequevousavezadopte.
La fonction db_lire_ligne (ciaprs)peutainsitreadapte,suivantlastratgiedenepasavoirdedonnes
encodesdanslesvariables.

Exemple

<?php
function db_lire_ligne($requte, &$erreur) {
// initialiser $erreur
$erreur = array(0,""); // numro = 0 message vide
// pas d'encodage sur les donnes lues dans la base
$ok = set_magic_quotes_runtime(0);
// tablir la connexion
$ok = ($connexion = mysql_connect());
if ($ok) { // c'est bon
// slectionner la base de donnes
$ok = mysql_select_db("diane",$connexion);
}
if ($ok) { // c'est toujours bon
// excuter la requte et tester le rsultat pour
// affecter la variable $ok
$ok = ( ($rsultat = mysql_query($requte)) != FALSE );

- 4- ENI Editions - All rigths reserved


}
if ($ok) { // tout est OK
// lire la ligne
$ligne = mysql_fetch_assoc($rsultat);
} else { // problme quelque part
// rcuprer les informations sur l'erreur
$erreur = array(mysql_errno(),mysql_error());
}
// retourner $ligne ou FALSE en cas d'erreur
return ($ok)?$ligne:FALSE;
}
?>

Dans le mme ordre d'ide, un appel du type set_magic_quotes_runtime(get_magic_quotes_gpc()) permet


d'obtenir,pourlesdonnesissuesdelabase,lemmecomportementquepourlesdonnesGPC.

Misejourdesdonnesdanslabase

Pour la mise jour des donnes dans la base, il faut s'assurer que toutes les donnes de type "texte" ont le
caractred'chappementadapt(\ou'pourMySQL,'pourlesautresbases)devantchaqueapostrophe.

Sivousavezadoptunestratgiedanslaquelletouteslesvariablescontiennentdesdonnesencodes,iln'ya
rienfaire.

l'inverse,sivousavezadoptunestratgie(plusnaturelle ?)danslaquelletouteslesvariablesnecontiennent
pasdedonnesencodes,ilconvientd'assurerl'chappementdesapostrophesdanslesdonnesenvoyesla
base.

Lesfonctionsaddslashesetmysql_escape_stringpeuventtreutilises.

Syntaxe

chane addslashes(chane valeur)


chane mysql_escape_string(chane valeur)

valeur

Chanedecaractreschapper.

La fonction mysql_escape_stringajouteunantislash (\) devant tous les caractres apostrophe ('), guillemet
(") et antislash (\) trouvs dans la chane valeur, quelle que soit la valeur de la directive de configuration
magic_quotes_sybase.

Lafonction addslashesajouteunantislash(\)devanttouslescaractresapostrophe('),guillemet(")etanti
slash (\) trouvs dans la chane valeur, si la directive de configuration magic_quotes_sybase est off. Par
contre, si la directive de configuration magic_quotes_sybase est on, la fonction addslashes se contente
d'ajouteruneapostrophe(')devantlescaractresapostrophe(')trouvsdanslachanevaleur.

Le paramtre valeur ne doit pas dj tre chapp.

Exemple

<?php
$valeur = " ' \ \" "; // c'est pour tester ...
echo addslashes($valeur)."<BR>";
echo mysql_escape_string($valeur)."<BR>";
?>

Rsultat (si magic_quotes_sybase = off)

\' \\ \"
\' \\ \"

Aucunediffrenceentrelesdeuxfonctions.

ENI Editions - All rigths reserved - 5-


Rsultat (si magic_quotes_sybase = on)

'' \ "
\' \\ \"

Il n'y a pas de changement pour la fonction mysql_escape_string mais un comportement diffrent pour la
fonctionaddslashes.Conclusions :

- La fonction mysql_escape_string est intressante, car indpendante de la configuration, mais elle est valable
uniquement pour MySQL.

- La fonction addslashes est intressante car elle est valable pour toutes les bases, mais elle est dpendante de la
configuration.

La solution, si vous souhaitez avoir un code qui fonctionne avec toutes les bases et qui soit indpendant de la
configuration,estd'criresaproprefonction.

Exemple

<?php
function vers_base($valeur) {
// le seul caractre qui pose vraiment problme est l'apostrophe (') ;
// c'est donc le seul qui est chapp par cette fonction
// une solution valable pour toutes les bases consiste
// l'chapper par lui-mme => remplacement de ' par ''
return str_replace("'","''",$valeur);
}
$valeur = " ' \ \" "; // c'est pour tester ...
echo vers_base($valeur)."<BR>";
?>

Rsultat

'' \ "

Unetellefonctionpeutfacilementtreappelelorsdelaconstructiond'unerequte.

Exemple

<?php
function vers_base($valeur) {
// le seul caractre qui pose vraiment problme est l'apostrophe (') ;
// c'est donc le seul qui est chapp par cette fonction une solution
// valable pour toutes les bases consiste
// l'chapper par lui-mme => remplacement de ' par ''
return str_replace("'","''",$valeur);
}
$libell = "Pomme d'api";
$prix = 10;
// l'utilisation du sprintf rend plus lisible la construction de la requte
$requte = sprintf(
"INSERT INTO articles(libelle,prix) VALUES('%s',%s)",
vers_base($libell),
$prix);
echo "$requte<BR>";
?>

Rsultat

INSERT INTO articles(libelle,prix) VALUES('Pomme d''api',10)

Ilestpossibleaussid'crireunefonctiongnrique,danslemmeespritquelafonction sprintf, en marquant


l'emplacementdesparamtresparunesquence%n, n valant1pourlepremierparamtre,2pourledeuxime...
Cette fonction accepte un nombre variable de paramtres, le premier tant la structure de la requte et les
suivants les valeurs des paramtres dans l'ordre de numrotation (cf. chapitre Constantes, variables, types et
tableauxManipulationdeschanesdecaractres).

- 6- ENI Editions - All rigths reserved


Exemple

<?php
function construire_requte($requte) {
// rcuprer le nombre de paramtres
$nombre_param = func_num_args();
// boucler sur tous les paramtres partir du deuxime
// (le premier contient la requte de base)
for($i=1;$i<$nombre_param;$i++) {
// rcuprer la valeur du paramtre
$valeur = func_get_arg($i);
// si c'est une chane, remplacer ' par ''
if (is_string($valeur)) {
$valeur = str_replace("'","''",$valeur);
}
// mettre la valeur son emplacement %n (n = $i)
$requte = str_replace("%$i",$valeur,$requte);
}
// retourner la requte
return $requte;
}
// des variables contiennent des valeurs venant de quelque part ...
$libell = "Pomme d'api";
$prix = 10;
// construction de la requte
$requte = construire_requte(
"INSERT INTO articles(libelle,prix) VALUES('%1',%2)",
$libell,
$prix);
echo "$requte<BR>";
?>

Rsultat

INSERT INTO articles(libelle,prix) VALUES('Pomme d''api',10)

Il n'y a pas de problme de ce type lors de l'utilisation de requtes paramtres avec Oracle.

Exemple

<?php
// connexion
$connexion = oci_connect("demeter","demeter","diane");
// requte INSERT (paramtre)
$requte = "INSERT INTO articles(libelle,prix)
VALUES(:p1,:p2)";
// analyse
$curseur = oci_parse($connexion,$requte);
// association entre les variables et les paramtres
oci_bind_by_name($curseur,":p1",$libell,50);
oci_bind_by_name($curseur,":p2",$prix,32);
// excution de la requte
$libell = "Pomme d'api"; // pas de problme avec d'api /$prix = 10;
$ok = oci_execute($curseur); // COMMIT automatique
$nombre = oci_num_rows($curseur);
echo "$nombre article insr.<BR>";
?>

Rsultat

1 article insr.

ENI Editions - All rigths reserved - 7-


Descriptionduproblme

Le protocole HTTP (HyperText Transfer Protocol) est un protocole "sans tat" : rien ne permet d'identifier que
c'estlemmeutilisateurquitaitprcdemmentsurlapageAetqui,maintenant,accdelapage B.
En ce qui concerne PHP, nous savons maintenant qu'une variable a une porte gale au script dans lequel elle
estdfinie,etqu'elleexisteuniquementletempsdel'excutionduscript.

Exemple

- Page HTML de connexion :

<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="accueil.php" METHOD="POST">
Nom : <INPUT TYPE="text" NAME="nom" VALUE=""><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
</BODY>
</HTML>

- Script PHP pour le traitement de la page :

<?php
// traitement du formulaire
if (! empty($_POST)) {
// rcupration de la valeur saisie
$nom = $_POST["nom"];
}
// Affichage de la page d'accueil
?>
<HTML>
<HEAD><TITLE>Accueil</TITLE></HEAD>
<BODY>
Bonjour <?php echo $nom; ?> !<BR>
<!-- lien vers une autre page -->
<A HREF="action.php">Action</A>
</BODY>
</HTML>

- Script PHP appel par le lien :

<HTML>
<HEAD><TITLE>Action</TITLE></HEAD>
<BODY>
<!-- affichage du nom de l'utilisateur -->
Bonjour <?php echo $nom; ?> !<BR>
Action...
</BODY>
</HTML>

Rsultat

- Affichage initial et saisie :

- Rsultat du clic sur le bouton OK :

- Rsultat du clic sur le lien (si les erreurs de niveau E_NOTICE ne sont pas affiches) :

ENI Editions - All rigths reserved - 1-


L'informationsaisiesurlapremirepageestdfiniedansladeuximepagequiestjustementappelepourtraiter
lasaisieduformulaire.Lavariable $nom,dfiniedanscescript,n'existepasdanslescript action.php(problme
deporte).

Leproblmeestlemmesilescriptaccueil.phpestappeldenouveauparlelien.

Exemple

<?php
// traitement du formulaire
if (! empty($_POST)) {
// rcupration de la valeur saisie
$nom = $_POST["nom"];
}
// Affichage de la page d'accueil
?>
<HTML>
<HEAD><TITLE>Accueil</TITLE></HEAD>
<BODY>
Bonjour <?php echo $nom; ?> !<BR>
<!-- lien vers une autre page -->
<A HREF="accueil.php">Accueil</A>
</BODY>
</HTML>

Rsultat

- Affichage dans la page d'accueil aprs l'identification :

- Rsultat du clic sur le lien (si les erreurs de niveau E_NOTICE ne sont pas affiches) :

Lersultatestlemme :lavaleurdelavariablelafindelapremireexcutionduscriptn'estpasconserve
lafinduscript(problmededuredevie).

Or,unsiteinteractifquinesecontentepasd'afficherdespageslesunesderrirelesautres,asouventbesoin,
du point de vue de la logique applicative, d'identifier un utilisateur d'une page l'autre et de conserver des
informations relatives cet utilisateur d'une page l'autre (typiquement, un panier lectronique constitu par
l'utilisateursurunepagedoittoujourstredfinisurlapagepermettantlepaiement).

Le terme "session" dsigne la priode de temps correspondant la navigation continue d'un utilisateur sur un
site. "Grer les sessions" signifie donc tre en mesure d'identifier l'instant o un nouvel utilisateur accde une
pagedusiteetdeconserverdesinformationsrelativescetutilisateurjusqu'cequ'ilquittelesite.L'utilisateur
n'est pas forcment un utilisateur authentifi par un nom et un mot de passe mais peut trs bien tre un
"anonyme",nonrfrencparlesite,quieffectueunachat.Deplusenplus,lessitesinteractifsproposentdes
fonctionnalitsd'identification(membre,abonn...)carcelapermetdeconserverdesinformationssurl'utilisateur
d'unevisitel'autre(prfrencesparexemple).Cettepossibilitestgalementtudiedanscechapitremaisdu
pointdevuedelanotiondesession,lavisitedel'utilisateurlevendredicorrespondraunesessiondiffrentede
savisitedulundi,mmesicertainesinformationssaisieslelundisontsusceptiblesd'trerestitueslevendredi.

Cechapitreapourobjectifdeprsenterlesdiffrentestechniquesquivontpermettre,d'unepartd'identifierun
utilisateuret,d'autrepart,de"suivre"cetutilisateuretlesdonnesquiluisontassocies,d'unepagel'autre.

Nous allons aussi tudier une variante qui consiste identifier un utilisateur et conserver des informations
d'unevisiteuneautre.

- 2- ENI Editions - All rigths reserved


Enprambule,nousallonsvoircommentauthentifierunutilisateuretcrerunidentifiantunique.

Nous allons ensuite aborder pour la gestion des sessions, les mthodes "artisanales" puis les nouvelles
fonctionnalitsoffertesparPHPdepuislaversion4.

Enfin, nous allons terminer ce chapitre en voquant les techniques permettant de conserver des informations
d'unevisitel'autre.

ENI Editions - All rigths reserved - 3-


Authentification

Vued'ensemble

Certains sites ont besoin d'authentifier les utilisateurs qui accdent au site afin de vrifier que ces derniers sont
bieninscrits.

Cetteauthentificationcomprendgnralementdeuxtapes :

- saisie par l'utilisateur d'informations d'identification, typiquement un nom et un mot de passe ;

- vrification que l'identification saisie correspond bien un utilisateur inscrit.

Saisiedel'identification

L'identificationpeuttresaisiededeuxmanires :

- par l'intermdiaire d'un formulaire prvu cet effet ;

- par les fonctions d'authentification HTTP.

Formulaire

Ilesttrssimpledecrerunpetitformulairepermettantl'utilisateurdesaisirunnometunmotdepasse.

Exemple de script PHP (login.php) qui affiche ce formulaire (fonction de vrification utilisateur existe, pour l'instant non
dfinie)

<?php
// inclusion du fichier contenant les fonctions gnrales
include("fonctions.inc");
function utilisateur_existe($identifiant,$mot_de_passe) {
// fonction qui vrifie que l'identification saisie est correcte
// alatoire, en attendant mieux...
return (bool) rand(0,1);
}
// initialisation des variables
$identifiant = "";
$mot_de_passe = "";
$message = "";
// traitement du formulaire
if (isset($_POST["connexion"])) {
// rcuprer les informations saisies
$identifiant =
valeur_saisie($_POST["identifiant"]);
$mot_de_passe =
valeur_saisie($_POST["mot_de_passe"]);
// vrifier que l'utilisateur existe
if (utilisateur_existe($identifiant,$mot_de_passe)) {
// l'utilisateur existe ...
// typiquement, partir sur une autre page et interrompre le script
header("location: accueil.php");
exit;
} else {
// l'utilisateur n'existe pas ...
// typiquement, afficher un message et proposer de
// nouveau l'identification
$message = "Identification incorrecte. ";
$message .= "Essayez de nouveau.";
// laisser le formulaire s'afficher de nouveau ...
}
}
?>
<HTML>
<HEAD><TITLE>MonSite.com</TITLE></HEAD>
<BODY>
<FORM ACTION="login.php" METHOD="POST">
<TABLE BORDER=0>
<TR>

ENI Editions - All rigths reserved - 1-


<TD ALIGN="right">Identifiant :</TD>
<TD><INPUT TYPE="text" NAME="identifiant" VALUE=
"<?php echo vers_formulaire($identifiant); ?>"></TD>
</TR>
<TR>
<TD ALIGN="right">Mot de passe :</TD>
<TD><INPUT TYPE="password" NAME="mot_de_passe" VALUE=
"<?php echo vers_formulaire($mot_de_passe); ?>"></TD>
</TR>
<TR>
<TD></TD>
<TD ALIGN="right"><INPUT TYPE="submit" NAME="connexion"
VALUE= "Connexion"></TD>
</TR>
</TABLE>
</FORM>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Rsultat

- Affichage initial :

- Saisie :

- Rsultat si l'identification est errone :

L'utilisationd'unezonedetypepasswordpermetdemasquerlasaisiedumotdepasse.

Si la saisie est incorrecte, la page est propose de nouveau. Dans le cas contraire, une page d'accueil est
affiche.

AuthentificationHTTP

l'aide de la fonction header, il est possible de demander au navigateur d'afficher une fentre de dialogue
invitantl'utilisateursaisirunnometunmotdepasse.Lemessaged'entteenvoyerest :

WWW-Authenticate: Basic realm="xxxxx"

xxxxx = nom affich (nom d'organisation par exemple)

Sil'utilisateurcliquesurleboutonOK,lescriptestappeldenouveauaveclesvaleurssaisiesdisponiblesdansles

- 2- ENI Editions - All rigths reserved


variablesPHP :$PHP_AUTH_USERet$PHP_AUTH_PW.

Par scurit, il est prfrable de rcuprer ces informations via le tableau associatif $_SERVER, avec les cls
PHP_AUTH_USER et PHP_AUTH_PW. Dans la pratique, ce n'est pas une obligation, car nous vrifierons ensuite que
l'utilisateurexistebien.Sicetutilisateur nousaenvoyl'informationsanspasserparledialogue,nouslesaurons.

Exemple (script login.php avec cette technique):

<?php
// inclusion du fichier contenant les fonctions gnrales
include("fonctions.inc");
function utilisateur_existe($identifiant,$mot_de_passe) {
// fonction qui vrifie que l'identification saisie est correcte
// alatoire, en attendant mieux...
return (bool) rand(0,1);
}
function Authentification($message) {
header("WWW-Authenticate: Basic realm=\"$message\"");
// si l'utilisateur clique sur le bouton annuler,
// les lignes suivantes s'excutent (sinon, le script est
// de nouveau appel mais avec $PHP_AUTH_USER renseign
// et le script ne passera plus par ici)
// typiquement, afficher un message et proposer
// l'utilisateur d'essayer de nouveau
echo "<FONT COLOR=\"red\">Vous devez saisir un nom et
un mot de passe pour accder au site.</FONT><BR>";
echo "<A HREF=login.php>Essayer de nouveau</A>";
exit;
}
if (! isset($_SERVER["PHP_AUTH_USER"])) {
// pas de variable $PHP_AUTH_USER = premier appel du script
// demande d'identifiation
Authentification("MonSite.com");
} else {
// variable $PHP_AUTH_USER existe = appel aprs saisie
// rcuprer les information saisies
$identifiant =
valeur_saisie($_SERVER["PHP_AUTH_USER"]);
$mot_de_passe =
valeur_saisie($_SERVER["PHP_AUTH_PW"]);
// vrifier que l'utilisateur existe
if (utilisateur_existe($identifiant,$mot_de_passe)) {
// l'utilisateur existe ...
// typiquement, partir sur une autre page et interrompre le script
header("location: accueil.php");
exit;
} else {
// l'utilisateur n'existe pas ...
// Essayer de nouveau
Authentification
("MonSite.com : identification incorrecte");
}
}
?>

Rsultat

- Affichage initial (Internet Explorer version 6) :

ENI Editions - All rigths reserved - 3-


- Clic sur le bouton Annuler :

- Nouvel affichage (par le lien) et saisie :

- Nouvel affichage si l'identification est incorrecte :

- 4- ENI Editions - All rigths reserved


Sil'identificationestcorrecte,unepaged'accueilestaffiche.

Pour l'instant, sur les deux exemples, l'accs la page d'accueil n'est pas protg : un utilisateur qui demande cette page y
accde sans problme.

Vrifierl'identificationsaisie

Quelle que soit la mthode d'identification utilise au point prcdent, il convient ensuite de vrifier que les
informationssaisiescorrespondentbienunutilisateur"connu".
Typiquement,cecontrleestralisl'aided'unebasededonnesquicontientlalistedesutilisateurs,ainsique,
sansdouted'autresinformations.
Nousallonsprendrecommehypothsedetravail,pourlasuite,l'utilisationd'unebasemySQL,etdanscettebase,
l'existenced'unetableutilisateursprsentantdeuxcolonnes,identifiantetmot_de_passe.

Exemple

<?php
// inclusion du fichier contenant les fonctions gnrales
include("fonctions.inc");
function utilisateur_existe($identifiant,$mot_de_passe) {
// fonction qui vrifieque l'identification saisie est correcte
// dfinition et excution de la requte
$requte = sprintf(
"SELECT * FROM utilisateurs WHERE identifiant = '%s'",
vers_base($identifiant));
$erreur = "";
$utilisateur = db_lire_ligne($requte,$erreur);
// l'identification est bonne s'il existe un utilisateur ayant
// l'identifiant saisi (! empty...) et que le mot de passe corresponde
// ($utilisateur...== ...)
$existe = ((! empty($utilisateur)) and
($utilisateur["mot_de_passe"] == $mot_de_passe));
// rsultat
return $existe;
}
?>

D'autres mthodes d'authentification, qui ne s'appuient pas sur une base de donnes sont envisageables (simple
fichierparexemple).

ENI Editions - All rigths reserved - 5-


Crerunidentifiantunique

Dans de nombreuses situations, dont celles relatives la gestion des sessions, il est ncessaire de gnrer des
identifiantsuniques.

Eneffet,danslecontextedelagestiondessessions,cetidentifiantestsouventutilecarilpermet,commeson
noml'indique,d'identifierlessessionsetdonc,depouvoirlesdiffrencier.

PHPproposelafonctionuniqidpourgnrerdesidentifiantsuniques.

Syntaxe

entier uniqid([chane prfixe])

prfixe

Prfixeajouterl'identifiant.
Mettreunechanevideounerienmettresivousnesouhaitezpasdeprfixe.

La fonction uniqid retourne une chane de treize caractres (sans compter le prfixe) calcule partir de
l'heurecouranteenmicrosecondes.

Exemple

<?php
echo uniqid()."<BR>";
echo uniqid()."<BR>";
echo uniqid("abc")."<BR>";
?>

Rsultat

3b9651f96756f
3b9651f9675b7
abc3b9651f9675e5

Cet exemple montre que l'identifiant gnr est unique, mme si la diffrence entre deux appels successifs est
faible.Parcontre,l'identifiantgnrpeuttrejuginsuffisammentalatoireetunpeutropfaciledterminer.

Une technique classique consiste alors crypter l'identifiant gnr. La fonction md5 permet de le faire trs
facilement,enutilisantunemthodeMD5.

Syntaxe

chane md5(chane valeur)

Valeur

Chanecrypter.

Lafonctionmd5retournelachanecrypte.

Exemple

<?php
echo md5("olivier");
?>

Rsultat

d3ca5dde60f88db606021eeba2499c02

ENI Editions - All rigths reserved - 1-


Lacombinaisondesfonctionsuniqidetmd5donnelecodesuivant :

<?php
echo md5(uniqid())."<BR>";
echo md5(uniqid())."<BR>";
echo md5(uniqid())."<BR>";
?>

Rsultat

7de6a154b916f6f96e3031dd002d0a3e
d45dd6c61405f3462219c2b0b8ec6865
790bcbaf32a4fcb76f6ee8fdf8b1ecfd

Lenouvelidentifiantcomprend32caractresilest,maintenant,plusalatoireetmoinsfaciledterminer.

Pour les paranoaques de la scurit, il est possible d'aller encore plus loin en utilisant, en plus, un prfixe
alatoire.

Exemple

<?php
// gnration d'identifiants prfixe alatoire crypts
echo md5(uniqid(rand()))."<BR>";
echo md5(uniqid(rand()))."<BR>";
echo md5(uniqid(rand()))."<BR>";
?>

Rsultat

7b8d690bd713a6486d1bea0b0444da66
85d53b9cf512f40484d9c5eecd2f9978
cb7b9243a45ff2beb5a57fde09a9d7a5

Unefonctiongnriquepeuttrecritepourdfinirunidentifiantunique.

Exemple

<?php
function identifiant_unique() {
// gnration de l'identifiant
return md5(uniqid(rand()));
}
?>

- 2- ENI Editions - All rigths reserved


Passerdesinformationsparl'URL

Principe

L'URL(UniformResourceLocator)peuttreutilisepourpasserdesinformationsd'unepageuneautre.

Syntaxe

url_classique?nom=valeur[&...]

Le point d'interrogation (?) introduit la liste des paramtres de l'URL spars par le caractre perluette (&)
chaqueparamtreestconstituparuncouplenom/valeursouslaformenom=valeur.

Exemples

www.monsite.com/info/accueil.php?prenom=Olivier
chercher.php?prenom=Olivier&nom=HEURTEL

En PHP, les paramtres passs l'URL correspondant un script, sont disponibles dans ce script sous la forme
devariablessansavoirbesoind'effectuerlamoindreanalysedel'URL.

Lesprincipesdercuprationdelavariablessontlesmmesquepourlesvaleurssaisiesdansunformulaire(cf.
chapitreGestiondesFormulaires).

Tous les paramtres de l'URL sont automatiquement enregistrs dans le tableau associatif $_GET : la cl du
tableauestgaleaunomduparamtre.

Exemple

- Script page1.php :

<?php
// initialisation d'une variable
$nom="Olivier";
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<!-- lien vers la page 2 en passant la valeur de $nom
dans l'URL -->
<A HREF="page2.php?nom=<?php echo $nom; ?>">Page 2</A>
</BODY>
</HTML>

- Source de la page dans le navigateur:

<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<!-- lien vers la page 2 en passant la valeur de $nom
dans l'URL -->
<A HREF="page2.php?nom=Olivier">Page 2</A>
</BODY>
</HTML>

- Script page2.php

<?php
// rcupration des informations passes dans l'URL
$nom=$_GET["nom"];
echo $nom;
?>

Rsultat

ENI Editions - All rigths reserved - 1-


- Affichage de la page 1 :

- Rsultat du clic sur le lien :

Ainsi, des variables dfinies dans un script peuvent tre transmises un autre script. C'est la valeur qui est
transmise, pas la variable ellemme rien n'interdit dans le script cible de rcuprer la valeur pour la mettre
dansunevariableportantunautrenom.

Silavaleurtransmettrenecontientpasdecaractresspciaux(espace,perluette(&),pointd'interrogation
(?), etc.), elle peut tre place directement dans l'URL comme indiqu prcdemment. Dans le cas contraire, il
estncessairedel'encoderpourviterquecescaractresparticulierssoientmalinterprts.

Sur l'exemple prcdent, si la variable contient "Olivier & Xavier", seul "Olivier" sera rcupr dans la variable
$noml'arrivecarle&estinterprtcommelesparateurdeparamtre.

Cetencodagepeuttreralistrsfacilementgrceauxfonctionsurlencodeouraw-urlencode.

Syntaxe

chane urlencode(chane valeur)


chane rawurlencode(chane valeur)

valeur

Chaneencoder.

Ces deux fonctions retournent la chane aprs encodage. L'encodage consiste remplacer tous les caractres
nonalphanumriquesparunesquence%xy, xytantunnombrehexadcimalgalaucodeASCIIducaractre.
Ladiffrenceentrelesdeuxfonctionsestsubtileetconcernejustelecaractreespace :lafonctionurlencode
remplace les espaces par le caractre "plus" (+), le vrai caractre "plus" tant luimme encod, alors que la
fonction rawurlencoderemplacelesespacesparlasquence%20(codeASCII32enhexadcimal).Lafonction
urlencode est conforme au type MIME application/xwwwformurlencoded (type utilis pour transmettre les
valeurs des formulaires) alors que la fonction rawurlencode est conforme la RFC1738 a priori, il faut plutt
employerlafonctionrawurlencode.

Exemple

<?php
// initialisation d'une variable
$nom="Olivier & Xavier";
echo urlencode($nom)."<BR>";

- 2- ENI Editions - All rigths reserved


echo rawurlencode($nom)."<BR>";
?>

Rsultat

Olivier+%26+Xavier
Olivier%20%26%20Xavier

Lescriptpage1.phppeuttremodifidelamaniresuivante :

<?php
// initialisation d'une variable
$nom="Olivier & Xavier";
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<!-- lien vers la page 2 en passant la valeur de $nom
dans l'URL -->
<A HREF="page2.php?nom=<?php echo rawurlencode($nom); ?>">
Page 2</A>
</BODY>
</HTML>

Source de la page dans le navigateur

<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<!-- lien vers la page 2 en passant la valeur de $nom
dans l'URL -->
<A HREF="page2.php?nom=Olivier%20%26%20Xavier">
Page 2</A>
</BODY>
</HTML>

Rsultat affich l'arrive

Olivier & Xavier

Lachanedelarequtepeutaussitreconstruitel'aidedelafonctionhttp_build_queryapparueenversion
5.

Syntaxe

chane http_build_query(tableau donnes [, chane prfixe])

Avec

donnes

Tableau contenant les donnes utiliser pour construire la chane de la requte. L'indice ou la cl du tableau
sontutilisscommenomduparamtrepourlavaleurassocie.

prfixe

Prfixe utiliser pour le nom des paramtres, lorsqu'il s'agit d'un indice numrique. Permet d'avoir l'arrive un
nomexploitablecommenomdevariable(unnomdevariablePHPnepeutpascommencerparunchiffre).

Cette fonction construit, puis encode, une chane de requte sous la forme cl1=valeur1&cl2=valeur2&...
enutilisantlescls(ouindices)etvaleurstrouvesdansletableaudonnes.S'ilestsaisi,leparamtreprfixe
estajoutdevantlesindicesnumriques.

Exemple

<?php

ENI Editions - All rigths reserved - 3-


// initialisation du tableau contenant les donnes
$donnes=array("nom" => "Olivier & Xavier","David + Thomas");
// construction de la chane de la requte
// - sans prfixe
echo http_build_query($donnes)."<BR>";
// - avec prfixe
echo http_build_query($donnes,"v_")."<BR>";
?>

Rsultat

nom=Olivier+%26+Xavier&0=David+%2B+Thomas
nom=Olivier+%26+Xavier&v_0=David+%2B+Thomas

Il existe deux fonctions, urldecode et rawurldecode, qui permettent de dcoder une chane pralablement encode,
respectivement par urlencode ou rawurlencode. Ces fonctions de dcodage n'ont pas besoin d'tre appeles lorsque des
donnes encodes sont transmises par l'URL. En effet, ces donnes sont automatiquement dcodes l'arrive.

"magicquotes" :leretour

Comme nous l'avons expliqu dans le chapitre 7, la valeur rcupre dans le script d'arrive peut par contre,
subir l'encodage "magic quotes" si la directive de configuration magic_quotes_gpc (souvenezvous que gpc
signifieGet/Post/Cookie)eston.

Exemple

<?php
// initialisation d'une variable avec apostrophe
$nom="c'est l't";
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<!-- lien vers la page 2 en passant la valeur de $nom
dans l'URL -->
<A HREF="page2.php?nom=<?php echo rawurlencode($nom); ?>">
Page 2</A>
</BODY>
</HTML>

Source de la page (' est encod en %27)

<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<!-- lien vers la page 2 en passant la valeur de $nom
dans l'URL -->
<A HREF="page2.php?nom=c%27est%20l%27%E9t%E9">
Page 2</A>
</BODY>
</HTML>

Rsultat (magic_quotes_gpc = on et magic_quotes_sybase = off)

c\'est l\'t

En consquence, lors de la rcupration d'une information transmise par URL, il convient ventuellement
d'appeler la fonction stripslashes ou notre fonction gnrique valeur_saisie pour supprimer l'encodage
"magicquotes".

Applicationlagestiondessessions

Cette technique de transmission de donnes par l'URL peut tre utilise pour la gestion des sessions, en
transmettantlesinformationsdesessiondansl'URL.

Lesprincipessontlessuivants :

- 4- ENI Editions - All rigths reserved


- Chaque session est matrialise par un identifiant unique.

- Cet identifiant de session est systmatiquement intgr dans les URL qui permettent de naviguer entre les diffrentes
pages du site.

- Dans chaque script (page) concern par la gestion des sessions, commencez par tester si le script a t appel avec
une URL contenant un identifiant de session; si ce n'est pas le cas, l'utilisateur n'a pas encore de session (c'est la
premire page qu'il visite) et il faut ouvrir la session. Cette ouverture de session peut se matrialiser par la simple
attribution d'un identifiant unique ou par la redirection vers une page d'identification, si le site n'accepte pas les
utilisateurs anonymes.

Exemple (avec deux pages)

- Script page1.php:

<?php
// inclusion du fichier qui contient les fonctions gnrales
include("fonctions.inc");
// tester si la session est ouverte, c'est dire si une
// variable " session " a t transmise par l'URL
if (! isset($_GET["session"]) ) {
// variable " session " vide = pas de session
// => ouvrir la session
// pour cet exemple :
// - identifiant de session
$session = identifiant_unique();
// - date/heure d'ouverture de la session
$date = date("\l\e d/m/Y H:i:s");
// - message
$message = "Nouvelle session : $session - $date";
} else {
// variable " session " non vide = session ouverte
// => rcuprer les informations de l'URL
$session = $_GET["session"];
$date = $_GET["date"]; // message
$message = "Session dj ouverte: $session - $date";
}
// construction des paramtres de l'url : $session + $date
// $session n'a pas besoin d'tre encod
$url = "?session=$session&date=".rawurlencode($date);
// dtermination de la date et de l'heure actuelle (pas celle
// de l'ouverture de la session
$actuel = "Nous sommes le ".date("d/m/Y").
" ; il est ".date("H:i:s");
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1 - <?php echo $actuel; ?></B><BR>
<?php echo $message; ?><BR>
<!-- lien vers les autres pages -->
<A HREF="page2.php<?php echo $url; ?>">Page 2</A>
</BODY>
</HTML>

- Script page2.php (identique l'exception de la partie HTML):

<?php
...
?>
<HTML>
<HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<B>Page 2 - <?php echo $actuel; ?></B><BR>
<?php echo $message; ?><BR>
<!-- lien vers les autres pages -->
<A HREF="page1.php<?php echo $url; ?>">Page 1</A>
</BODY>
</HTML>

Rsultat

ENI Editions - All rigths reserved - 5-


- Premier appel de l'URL http://.../page1.php :

- Rsultat du clic sur le lien Page 2 :

>

- Rsultat du clic sur le lien Page 1 :

- Rsultat du clic sur le bouton Prcdente du navigateur :

La page n'a pas t mise jour car elle est dans le cache du navigateur. Une solution ce problme est
proposeaupoint4Remarquesetconclusion.

L'utilisation de cette technique peut tre illustre sur une gestion de sessions avec authentification des
utilisateurs.

Exemple

- Script login.php pour l'authentification :

<?php
// inclusion du fichier contenant les fonctions gnrales
include("fonctions.inc");
function utilisateur_existe($identifiant,$mot_de_passe) {
// fonction qui vrifie que l'identification saisie est correcte
$requte = sprintf(
"SELECT * FROM utilisateurs WHERE identifiant = '%s'",
vers_base($identifiant));
$erreur = "";
$utilisateur = db_lire_ligne($requte,$erreur);
// l'identification est bonne s'il existe un utilisateur
// ayant l'identifiant saisi (! empty ...) et que le mot
// de passe correspond ($utilisateur ... == ...)
$existe = ((! empty($utilisateur)) and
($utilisateur["mot_de_passe"] == $mot_de_passe));
return $existe;
}
// initialisation des variables
$identifiant = "";
$mot_de_passe = "";
$message = "";
// traitement du formulaire
if (isset($_POST["connexion"])) {
// rcuprer les informations saisies

- 6- ENI Editions - All rigths reserved


$identifiant =
valeur_saisie($_POST["identifiant"]);
$mot_de_passe =
valeur_saisie($_POST["mot_de_passe"]);
// vrifier que l'utilisateur existe
if (utilisateur_existe($identifiant,$mot_de_passe)) {
// l'utilisateur existe ...
// => ouvrir la session
$session = identifiant_unique();
$date = date("\l\e d/m/Y H:i:s");
// puis le rediriger vers la page1 en fournissant les informations
// dans l'URL
$url = "?session=$session&date=".rawurlencode($date).
"&identifiant=".rawurlencode($identifiant);
header("location: page1.php$url");
exit;
} else {
// l'utilisateur n'existe pas ...
// typiquement, afficher un message et proposer de
// nouveau l'identification
$message = "Identification incorrecte.
Essayez de nouveau.";
// laisser le formulaire s'afficher de nouveau ...
}
}
?>
<HTML>
<HEAD><TITLE>Login</TITLE></HEAD>
<BODY>
<FORM ACTION="login.php" METHOD="POST">
<TABLE BORDER=0>
<TR>
<TD ALIGN="right">Identifiant :</TD>
<TD><INPUT TYPE="text" NAME="identifiant" VALUE=
"<?php echo vers_formulaire($identifiant); ?>"></TD>
</TR>
<TR>
<TD ALIGN="right">Mot de passe :</TD>
<TD><INPUT TYPE="password" NAME="mot_de_passe" VALUE=
"<?php echo vers_formulaire($mot_de_passe); ?>"></TD>
</TR>
<TR>
<TD></TD>
<TD ALIGN="right"><INPUT TYPE="submit" NAME="connexion"
VALUE= "Connexion"></TD>
</TR>
</TABLE>
</FORM>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

- Script page1.php pour une page du site :

<?php
// inclusion du fichier qui contient les fonctions gnrales
include("fonctions.inc");
// tester si la session est ouverte, c'est--dire si une
// variable " session " a t transmise par l'URL
if (! isset($_GET["session"]) ) {
// variable " session " vide = pas de session
// => rediriger l'utilisateur vers la page de login
header("location: login.php");
exit;
} else {
// variable " session " non vide = session ouverte
// => rcuprer les autres informations de l'URL pour cet exemple :
// - identifiant de session
$session = $_GET["session"];
// - date/heure d'ouverture de la session
$date = $_GET_["date"];
// - identifiant de l'utilisateur
$identifiant =
valeur_saisie($_GET_["identifiant"]);
// message
$message = "Session : $session - $identifiant - $date";
}
// construction des paramtres de l'url : $session + $date

ENI Editions - All rigths reserved - 7-


// $session n'a pas besoin d'tre encod
$url = "?session=$session&date=".rawurlencode($date).
"&identifiant=".rawurlencode($identifiant);
// dtermination de la date et de l'heure actuelle (pas celle
// de l'ouverture de la session
$actuel = "Nous sommes le ".date("d/m/Y").
" ; il est ".date("H:i:s");
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1 - <?php echo $actuel; ?></B><BR>
<?php echo $message; ?><BR>
<!-- lien vers les autres pages -->
<A HREF="page2.php<?php echo $url; ?>">Page 2</A>
</BODY>
</HTML>

Le premier appel de l'URL http://.../page1.php provoque la redirection de l'utilisateur vers la page


d'identification. Aprs une identification russie, l'utilisateur revient sur la page 1 qui affiche les informations
suivantes :

Page 1 - Nous sommes le 04/05/2004 ; il est 11:26:20


Session : 5fb1ed8a147b56fc1349dd3d08799f0f - heurtel - le 04/05/2004 11:26:20
Page 2

L'accsauxpagesdusiteestmaintenantprotg,ouplutt,sembleprotg(dtaildanslasectionsuivante).

Le script login.php montre la possibilit de placer des paramtres derrire l'URL passe la fonction header.

Remarquesetconclusion

Lesutilisateursmalinset/oumalintentionns

Pour les deux exemples donns, un utilisateur (malin et/ou mal intentionn) qui appelle une URL
http://.../page1.php?session=abcaccdesansproblmelapagedemandeenoutrepassantlemcanisme
d'ouverturedesessionet,notamment,lepassageparlapaged'identificationdansledeuximeexemple :

Page 1 - Nous sommes le 04/05/2004 ; il est 11:36:18


Session : abc - -
Page 2

En effet, actuellement, le script se contente de tester l'existence d'une valeur pour le paramtre session dans
l'URL, sans vrifier que la valeur en question correspond une vraie session. Pour cela, il faut conserver, ct
serveur, dans un fichier ou dans une base, la trace des sessions rellement ouvertes, c'estdire la trace des
identifiants de session rellement attribus par l'application. En complment, il faut prvoir un mcanisme de
dure de vie (30 minutes , 1 heure, 6 heures...) qui fasse en sorte qu'un utilisateur n'emploie pas un identifiant
desessionattribuprcdemment.

Nepastouttransmettredansl'URL

Lemcanismeemploypourconserver,ctserveur,latracedessessionsouvertes,peutaussitreutilispour
conserver des informations complmentaires sur la session et ne pas tre oblig ainsi de passer toutes les
valeurs par l'URL : seul l'identifiant de session peut l'tre. Il suffit alors, au dbut de chaque script, d'utiliser
l'identifiant de session pour rcuprer les informations complmentaires de la session, et, en fin de script, de
renregistrer,ctserveur,lesinformationsdesessionquionttmodifies.

Casdutraitementd'unformulaire

Lorsdutraitementd'unformulaire,lescriptn'estpasappelparunlien <A HREF...>telquenousvenonsdele


voirmaisparl'optionACTIONdelabalise<FORM>.

La technique de transmission des informations de session par l'URL peut tre utilise dans l'URL de l'option
ACTION.

Exemple

- 8- ENI Editions - All rigths reserved


<?php
...
$url = "?session=$session";
...
?>
...
<FORM ACTION="page1.php<?php echo $url; ?>" METHOD="POST">
...

Le script appel (page1.php sur notre exemple) peut rcuprer l'identifiant de la session dans le tableau $_GET
etlesvaleursduformulairedansletableau$_POST.

Nous allons voir dans la partie E (Passer des informations par une zone de formulaire cache), que l'information
desessionpeutaussi,danscecas,tretransmisedansleformulaire.

Forcerlerafrachissementd'unepage

Pourrsoudreleproblmedespagesnonmisesjourcartoujoursprsentesdanslecachedunavigateur,ilfaut
envoyerdesenttescomplmentairesdanslapageHTMLl'aidedelafonctionheader.

Exemple

// HTTP 1.0
header("Pragma: no-cache");
// HTTP 1.1
header("Cache-Control: no-store, no-cache, must-revalidate");

Conclusion

Utiliser l'URL pour transmettre des informations de session est envisageable mais ncessite beaucoup de code
pourconstruirequelquechosedesolide.

Nous n'indiquons volontairement pas d'exemple plus complet pour la gestion des sessions avec cette technique
car,depuisPHP4,lesfonctionnalitsdegestiondessessionsonttintroduitespoursimplifierledveloppement
et apporter des solutions simples aux diffrentes problmatiques voques prcdemment : autant les utiliser
(cf.GrerlessessionsUtiliserlagestiondessessionsdePHP).

La technique prsente dans cette partie doit tre vue comme une mthode permettant de transmettre des
informationssimplesd'unepageuneautre,sanschercherunescuritimportante.

ENI Editions - All rigths reserved - 9-


Passerdesinformationsparunezone
deformulairecache

Principe

Nous avons vu dans le chapitre 7 que les informations saisies dans un formulaire taient transmises au script
chargdutraitementetpouvaient,ensuite,treaffichesdansunenouvellepage.

Cettemthodepeuttreutilisepourtransmettre,aupassage,d'autresinformationsnonsaisiesparl'utilisateur,
typiquementenlesplaantdansunezonedeformulairecache.

Exemple

- Script page1.php :

<?php
// initialisation d'une variable
$nom="Olivier";
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<!-- lien vers la page 2 avec un bouton de formulaire -->
<FORM ACTION="page2.php" METHOD="POST">
<!-- l'information transmettre est cache -->
<INPUT TYPE="hidden" NAME="nom" VALUE="<?php echo $nom; ?>">
<INPUT TYPE="submit" NAME="page2" VALUE="Page 2">
</FORM>
</BODY>
</HTML>

- Source de la page dans le navigateur :

<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<!-- lien vers la page 2 avec un bouton de formulaire -->
<FORM ACTION="page2.php" METHOD="POST">
<!-- l'information transmettre est cache -->
<INPUT TYPE="hidden" NAME="nom" VALUE="Olivier">
<INPUT TYPE="submit" NAME="page2" VALUE="Page 2">
</FORM>
</BODY>
</HTML>

Scriptpage2.php:

<?php
// rcupration des informations passes dans l'URL
$nom=$_POST["nom"];
echo $nom;
?>

Rsultat

- Affichage de la page 1 :

ENI Editions - All rigths reserved - 1-


- Rsultat du clic sur le bouton :

Avecleformulaire,iln'yapasdeproblmed'encodage(effectuautomatiquement).

Pas contre, dans le chapitre 7, nous avons vu (et rsolu) les diffrents problmes qui pouvaient se produire,
avec la fonctionnalit "magic quotes" ou l'intgration dans le formulaire de caractres spciaux. Il ne faut donc
pasoublierd'utiliserlesfonctions stripslashes et htmlspecialcharsoulesfonctionsgnriquescresdans
lesexemplesprcdentsvers_formulaireetvaleur_saisie.

Applicationlagestiondessessions

Cettetechniquedetransmissiondedonnesparunformulairepeuttreutilisepourlagestiondessessions,en
transmettantlesinformationsdesessiondansleszonescachesd'unformulaire.

Lesprincipesmisenuvresontlesmmesqu'avecl'URL.

Exemple (avec deux pages)

- Script page1.php :

<?php
// inclusion du fichier qui contient les fonctions gnrales
include("fonctions.inc");
// tester si la session est ouverte, c'est--dire si une
// variable " session " a t transmise par le formulaire
if (! isset($_POST["session"]) ) {
// variable " session " vide = pas de session
// => ouvrir la session
// pour cet exemple :
// - identifiant de session
$session = identifiant_unique();
// - date/heure d'ouverture de la session
$date = date("\l\e d/m/Y H:i:s");
// - message
$message = "Nouvelle session : $session - $date";
} else {
// variable " session " non vide = session ouverte
// => rcuprer les informations caches du formulaire
$session = $_POST["session"];
$date = $_POST["date"];
// message
$message = "Session dj ouverte: $session - $date";
}

// dtermination de la date et de l'heure actuelle (pas celle


// de l'ouverture de la session
$actuel = "Nous sommes le ".date("d/m/Y").
" ; il est ".date("H:i:s");
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1 - <?php echo $actuel; ?></B><BR>
<?php echo $message; ?><BR>
<!-- lien vers les autres pages avec un formulaire -->
<FORM ACTION="page2.php" METHOD="POST">
<INPUT TYPE="hidden" NAME="session"
VALUE="<?php echo $session; ?>">

- 2- ENI Editions - All rigths reserved


<INPUT TYPE="hidden" NAME="date"
VALUE="<?php echo $date; ?>">
<INPUT TYPE="submit" NAME="page2" VALUE="Page 2">
</FORM>
</BODY>
</HTML>

- Script page2.php (identique l'exception de la partie HTML) :

<?php
...
?>
<HTML>
<HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<B>Page 2 - <?php echo $actuel; ?></B><BR>
<?php echo $message; ?><BR>
<!-- lien vers les autres pages avec un formulaire -->
<FORM ACTION="page1.php" METHOD="POST">
<INPUT TYPE="hidden" NAME="session"
VALUE="<?php echo $session; ?>">
<INPUT TYPE="hidden" NAME="date"
VALUE="<?php echo $date; ?>">
<INPUT TYPE="submit" NAME="page1" VALUE="Page 1">
</FORM>
</BODY>
</HTML>

Rsultat

- Premier appel de l'URL http://.../page1.php :

- Rsultat du clic sur le bouton Page 2 :

- Rsultat du clic sur le bouton Page 1 :

- Rsultat du clic sur le bouton Prcdente du navigateur :

ENI Editions - All rigths reserved - 3-


La page n'a pas t mise jour car elle est dans le cache du navigateur. Une solution ce problme a t
proposeaupointD4.Remarquesetconclusion.

L'ouverture de session, par passage dans une page d'identification, peut s'effectuer sur le mme principe qu'au
point D Passer des informations par l'URL. La seule difficult rsoudre concerne la redirection de la page
d'identification vers une autre page du site, aprs une connexion russie : l'utilisation de la fonction header ne
permet pas de transmettre des informations par la mthode du formulaire. Le plus simple consiste, alors,
inverserlgrementlalogiqueetfairetraiterleformulaired'identificationparlescriptdelapage1 cedernier
sechargeantderenvoyerl'utilisateursurlapaged'identificationencasd'checdeconnexion.Danslapratique,
cetteapprochen'estpastrslgantedupointdevuedel'organisationducode.

Remarquesetconclusion

Lesutilisateursmalinset/oumalintentionns

Unutilisateur(malinet/oumalintentionn)peutconstruireunepageavecsonpropreformulaire,comprenantune
zone nomme "session", contenant une valeur quelconque et qui appelle le script page1.php il accde alors
sansproblmelapage1,enoutrepassantlemcanismed'ouverturedesessionet,notamment,lepassagepar
lapaged'identificationdansledeuximeexemple.

CommedanslepointDPasserdesinformationsparl'URL,lasolutionconsistegardertrace,ctserveur,des
sessionsrellementouvertes.

Nepastouttransmettredansleformulaire

CommedanslepointD Passerdesinformationsparl'URL,lemcanismeutilispourconserver,ctserveur,la
trace des sessions ouvertes, peut aussi tre utilis pour conserver des informations complmentaires sur la
sessionet,ainsi,nepastreobligdepassertouteslesvaleursdansleformulaire.

Casdelanavigationparbalise<AHREF...>

Latechniqueproposedanscettesectionn'estpasfacilecombineraveclanavigationparbalise<A HREF...>.

Plusieurssolutionssontenvisageables :

- Mettre en place une navigation uniquement base de boutons; ce n'est pas trs lgant et, surtout, pas dans l'esprit
de la navigation sur le Web.

- Utiliser les deux techniques; cela risque d'alourdir la programmation, sauf si l'on utilise systmatiquement la mthode
GET pour le traitement des formulaires: que les donnes soient transmises par URL ou par formulaire, elle sont
rcuprables dans $_GET.

Conclusion

Utiliser les formulaires pour transmettre des informations de session est envisageable mais ceci ncessite
beaucoup de code pour construire quelque chose de solide et peut conduire une interface de navigation qui
n'estpasdansl'espritduWeb.

Comme pour la gestion des sessions par l'URL, nous n'allons pas plus loin dans les exemples : autant utiliser les
fonctionnalitsdegestiondessessionsdePHP(cf.GrerlessessionsUtiliserlagestiondessessionsdePHP).

La technique prsente dans cette partie doit tre vue comme une technique permettant de transmettre
ponctuellement des informations complmentaires dans un formulaire dj prsent. Par contre, crer un

- 4- ENI Editions - All rigths reserved


formulaire comprenant un bouton et quelques zones caches, spcialement pour transmettre des informations,
n'estpastrslgantdupointdevuedel'organisationducode.

ENI Editions - All rigths reserved - 5-


Utiliserdescookies

Principe

Un cookie est un petit fichier dpos, par un site, sur le poste de l'internaute et qui peut contenir des
informations.
LescookiessontautomatiquementrenvoysauserveurWeb,parlenavigateur,lorsquel'internautenaviguedans
lespagesdusiteenquestion.
PHPpermetdercuprertrsfacilement,dansdesvariables,lesdonnesstockesdanslecookie.

Lafonctionsetcookiepermetdedposeruncookiesurlepostedel'internaute.

Syntaxe simplifie

boolen setcookie(chane nom [, chane valeur [, entier expiration [, chane chemin [, chane domaine
[, entier securis]]]]])

Avec

nom

Nomducookie.

valeur

Valeurstockedanslecookie.

expiration

Dated'expirationducookie(timestampUnix).

chemin

Chemin sur le serveur dans lequel le cookie est disponible. Mettre / pour rendre le cookie disponible sur le
domaineentierou /rep/pourrendrelecookiedisponibledanslerpertoire /rep/dudomaineettoussessous
rpertoires.Pardfaut,galaurpertoirepartirduquellecookieatdpos.

domaine

Domaineauquellecookieestrenvoy. .monSite.com(avecunpointaudbut)permetparexemplederendrele
cookiedisponiblepourtouslessousdomainesdemonSite.com.

scuris

Mettre1pourindiquerquelecookienedoittretransmisquesuruneconnexionscurise(0pardfaut).

Si la fonction n'est appele qu'avec le paramtre nom, le cookie portant ce nom est supprim du poste de
l'internaute. Si les paramtres domaine et chemin avaient t spcifis lors du dpot du cookie, il faut les
spcifierl'identiquepoursupprimerlecookie(mettreunedated'expirationdanslepass).
Sileparamtrevaleurestspcifi,uncookieportantlenom nometcontenantlavaleurvaleurestenvoysur
le poste de l'utilisateur s'il existe dj un cookie portant ce nom, ce dernier est mis jour avec la nouvelle
valeur.

Leparamtreexpirationpermetdedterminerladated'expirationducookie(etdoncladatedesasuppression
du poste de l'utilisateur) si ce paramtre est non spcifi (ou gal 0) le cookie expire la fin de la session,
c'estdirelorsquel'utilisateurquittelesite.

Lescookiessontenvoysdansl'enttedelapage.l'instardelafonctionheader,lafonction setcookiedoit
donc tre appele avant toute instruction (PHP ou HTML), cette dernire ayant pour effet de commencer
construirelapageHTML.Encasdeproblme,unmessagedutypesuivantestaffich :

ENI Editions - All rigths reserved - 1-


Warning: Cannot add header information - headers already sent by (output started at d:\scripts
php\test.php:1) in d:\scripts php\test.php on line 7

La fonction setcookie retourne TRUE si l'instruction a pu tre excute (pas de donnes dj transmises), et
FALSEdanslecascontraire. Parcontre,lecodederetourdelafonctionnedonneaucuneinformationsurlefait
que le cookie a rellement pu tre dpos sur le poste de l'utilisateur : si ce dernier refuse les cookies, la
fonctionsetcookieretournequandmmeTRUEbienquelecookien'aitpastdpos.

Les cookies sont grs par site ; deux cookies de sites diffrents peuvent porter le mme nom. Le cookie est dpos sur le
poste de l'internaute par la fonction setcookie puis renvoy ultrieurement lors de la visite de n'importe quelle page du site.

Exemple

<?php
// dpt d'un cookie nomm " nom " contenant
// la valeur " Olivier " et expirant la fin de la session
$ok = setcookie("nom","Olivier");
// idem mais expirant date du jour (time() en secondes)
// plus 30 fois 24 fois 3600 secondes (soit 30 jours)
$ok = setcookie("nom","Olivier",time()+(30*24*3600));
// suppression du cookie nomm " nom "
$ok = setcookie("nom");
?>

Lorsque le cookie est renvoy au serveur Web, par le navigateur, lors de la demande d'une page PHP, la valeur
du cookie est accessible dans une variable PHP selon un mcanisme identique celui mis en uvre pour les
formulairesetlesURL.

La valeur de chaque cookie envoy, par le navigateur, est automatiquement enregistre dans le tableau
associatif$_COOKIE :lacldutableauestgaleaunomducookie.

Les variables de cookie sont aussi disponibles dans le tableau associatif $_REQUEST ou peuvent tre importes dans le
script par appel la fonction import_request_variables (cf. Gestion des formulaires - Contrler les donnes saisies -
Rcuprer les donnes saisies dans le formulaire).

Exemple

- Script page1.php qui dpose deux cookies :

<?php
// premier cookie expirant la fin de la session
$ok1 = setcookie("prnom","Olivier");
// deuxime cookie expirant dans 30 jours
$ok2 = setcookie("nom","HEURTEL",time()+(30*24*3600));
// rsultat
if ($ok1 and $ok2) {
$message = "Cookies dposs (du moins, a priori)";
} else {
$message = "L'un des cookies n'a pas pu tre dpos";
}
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1</B><BR>
<?php echo $message; ?><BR>
<A HREF="page2.php">Page 2</A>
</BODY>
</HTML>

- Script page2.php qui affiche la valeur des deux cookies :

<HTML>
<HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<?php
if ( isset($_COOKIE["prnom"]) ) {
echo "\$_COOKIE[\"prnom\"] = {$_COOKIE['prnom']}<BR>";
} else {

- 2- ENI Editions - All rigths reserved


echo "\$_COOKIE[\"prnom\"] = <BR>";
}
if ( isset($_COOKIE["nom"]) ) {
echo "\$_COOKIE[\"nom\"] = {$_COOKIE['nom']}<BR>";
} else {
echo "\$_COOKIE[\"nom\"] = <BR>";
}
?>
</BODY>
</HTML>

Rsultat

- Affichage de la page 1 :

Page 1
Cookies dposs (du moins, a priori)
Page 2

- Rsultat du clic sur le lien :

$_COOKIE["prnom"] = Olivier
$_COOKIE["nom"] = HEURTEL

- Rsultat d'un retour, avant trente jours, sur la page 2 du mme site:

$_COOKIE["prnom"] =
$_COOKIE["nom"] = HEURTEL

Le cookie de dure de vie gale la session n'existe plus la sortie de la session et l'information est perdue
l'informationstockedansl'autrecookierestedisponible(danslalimitedesaduredevie).

Il est possible de stocker n'importe quelle chane dans le cookie sans avoir se soucier d'un ventuel
encodage/dcodage :l'encodageetledcodagesonteffectusautomatiquement.

Lecookieestdpossurlepostedel'internauteparlafonction setcookie,puisestrenvoy ultrieurementlors


de la visite de n'importe quelle page du site (en fonction de la valeur des paramtres chemin et domaine) le
cookien'estpasdisponibleimmdiatementdanslapagequiledpose.

Exemple

<?php
// valeur du cookie avant
$avant = (isset($_COOKIE ["heure"]))?$_COOKIE ["heure"]:"";
// dpt du cookie expirant la fin de la session
$ok = setcookie("heure",date("H:i:s"));
// valeur du cookie aprs
$aprs = (isset($_COOKIE ["heure"]))?$_COOKIE ["heure"]:"";
// heure actuelle
$actuel = date("H:i:s");
// affichage
echo "Actuel : $actuel<BR>";
echo "Avant : $avant<BR>";
echo "Aprs : $aprs<BR>";

?>

Rsultat du premier appel

Actuel : 14:53:18
Avant :
Aprs :

Lors du premier appel, le cookie n'existe pas avant (c'est normal) et n'existe toujours pas aprs, car il a
simplementtenvoymaisn'estpasencore"revenu"(manireimagedeprsenterleschoses).

Rsultat du deuxime appel (dans la mme session)

ENI Editions - All rigths reserved - 3-


Actuel : 14:53:30
Avant : 14:53:18
Aprs : 14:53:18

Lors du deuxime appel, la valeur du cookie est disponible ds le dbut du script (le cookie est revenu avec la
requtepourlapage),etabienunevaleurquicorrespondl'instantoilatdpos parcontre,savaleur
aprsnerefltepasimmdiatementlaralit(mmeprincipequepourledptinitial :lecookien'estpasencore
"revenu").

Rsultat du troisime appel (dans la mme session)

Actuel : 14:53:41
Avant : 14:53:30
Aprs : 14:53:30

Lorsdutroisimeappel,lecookieabienunevaleurquicorrespondsamisejourlorsdudeuximeappel.

Une des consquences de ce mode de fonctionnement est qu'il n'est pas possible, tout de suite aprs avoir
dposlecookie,detestersilecookieatacceptounonparleposte.

Pour savoir si un poste accepte les cookies, il faut dposer un cookie et recharger une page dans laquelle la
prsenceounonducookiepermettradedterminersileposteacceptelescookies.

Exemple de script tester_cookie.php qui permet de faire ce test

<?php
// tester si c'est le deuxime appel de la page
if (! isset($_GET["retour"])) {
// non ...
// dposer le cookie
setcookie("test","test");
// et recharger la page avec une information dans
// l'URL indiquant que c'est le deuxime passage
header("Location: tester_cookie.php?retour=1");
} else {
// oui ...
// tester si le cookie est revenu
if (isset($_COOKIE["test"])) { // oui ...
echo "Cookie accept";
} else { // non ...
echo "Cookie refus";
}
}
?>

Il est possible de rcuprer un tableau comme valeur de cookie sous rserve d'utiliser une notation de type
tableaulorsdudptducookie.

Exemple (bas sur l'exemple prcdent)

<?php
// inclusion du fichier qui contient les fonctions gnrales
include("fonctions.inc");
// tester si c'est le deuxime appel de la page
if (! isset($_GET["retour"])) {
// non ...
// dposer le cookie
setcookie("test[0]","zro");
setcookie("test[1]","un");
// et recharger la page avec une information dans
// l'URL indiquant que c'est le deuxime passage
header("Location: tester_cookie.php?retour=1");
} else {
// oui ...
// tester si le cookie est revenu
if (isset($_COOKIE["test"])) { // oui ...
echo "Cookie accept<BR>";
afficher_tableau($_COOKIE["test"]);
} else { // non ...
echo "Cookie refus";

- 4- ENI Editions - All rigths reserved


}
}
?>

Rsultat

Cookie accept
0 = zro
1 = un

Dans la pratique, il y a en fait plusieurs cookies dposs sur le poste de l'utilisateur, mais les valeurs sont bien
rcupres dans le script PHP sous la forme d'un tableau. Pour dposer un seul cookie contenant plusieurs
valeurs, vous pouvez procder par concatnation, ou utiliser une fonction comme implode (et explode au
retourducookie).

"magicquotes" :leretour

CommepourlesdonnesGETetPOST,lavaleurrcupredansuncookiepeutsubirl'encodage"magicquotes"si
ladirectivedeconfigurationmagic_quotes_gpc(Get/Post/Cookie)eston.

Exemple en reprenant notre script de test de l'acceptation des cookies

<?php
// tester si c'est le deuxime appel de la page
if (! isset($_GET["retour"])) {
// non ...
// dposer le cookie
setcookie("test","c'est l't");
// et recharger la page avec une information dans
// l'URL indiquant que c'est le deuxime passage
header("Location: tester_cookie.php?retour=1");
} else {
// oui ...
// tester si le cookie est revenu
if (isset($_COOKIE["test"])) { // oui ...
echo "Valeur du cookie = $_COOKIE[test]";
} else { // non ...
echo "Cookie refus";
}
}
?>

Rsultat (magic_quotes_gpc = on et magic_quotes_sybase = off)

Valeur du cookie = c\'est l\'t

En consquence, lors de la rcupration d'une information transmise par cookie, il convient ventuellement
d'appeler la fonction stripslashes ou notre fonction gnrique valeur_saisie pour supprimer l'encodage
"magicquotes".

Applicationlagestiondessessions

Les cookies prsentent l'immense avantage, par rapport aux techniques tudies jusqu' maintenant, d'tre
parfaitement indpendants la fois de la navigation par balise <A HREF=...> et de la gestion des formulaires :
grer les sessions l'aide des cookies permet donc de s'affranchir des inconvnients lis aux deux autres
mthodes.

Ilsprsentent,parcontre,ungrosinconvnient :ilspeuventtrerefussparlesinternautes.

Lesprincipesdemiseenuvresontlesmmesquepourlagestionparl'URL.

Nousallonsillustrercesprincipesl'aidede2pages(enmettantl'hypothsequelescookiessontaccepts).

Exemple (avec deux pages et partant de l'hypothse que les cookies sont accepts)

- Script page1.php :

ENI Editions - All rigths reserved - 5-


<?php
// inclusion du fichier qui contient les fonctions gnrales
include("fonctions.inc");
// tester si la session est ouverte, c'est--dire si une
// variable " session " a t transmise par le cookie
if (! isset($_COOKIE["session"]) ) {
// variable " session " vide = pas de session
// => ouvrir la session
// pour cet exemple :
// - identifiant de session
$session = identifiant_unique();
// - date/heure d'ouverture de la session
$date = date("\l\e d/m/Y H:i:s");
// dposer deux cookies pour stocker ces informations
// dure de vie = la session justement !
setcookie("session",$session);
setcookie("date",$date);
// - message
$message = "Nouvelle session : $session - $date";
} else {
// variable " session " non vide = session ouverte
// => rcuprer les informations des cookies
$session = $_COOKIE["session"];
$date = $_COOKIE["date"];
// message
$message = "Session dj ouverte: $session - $date";
}
// dtermination de la date et de l'heure actuelle (pas celle
// de l'ouverture de la session
$actuel = "Nous sommes le ".date("d/m/Y").
" ; il est ".date("H:i:s");
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1 - <?php echo $actuel; ?></B><BR>
<?php echo $message; ?><BR>
<!-- lien vers les autres pages -->
<A HREF="page2.php">Page 2</A>
</BODY>
</HTML>

- Script page2.php (identique l'exception de la partie HTML) :

<?php
...
?>
<HTML>
<HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<B>Page 2 - <?php echo $actuel; ?></B><BR>
<?php echo $message; ?><BR>
<!-- lien vers les autres pages -->
<A HREF="page1.php">Page 1</A>
</BODY>
</HTML>

Rsultat

- Premier appel de l'URL http://.../page1.php :

- Rsultat du clic sur le lien Page 2 :

- 6- ENI Editions - All rigths reserved


- Rsultat du clic sur le lien Page 1 :

EncasdeclicsurleboutonPrcdentedunavigateur,lapagen'estpasmisejourcarelleestdanslecache
dunavigateur.UnesolutionceproblmeestproposedanslepointD4.Remarquesetconclusion.

Avec les cookies, il est possible de naviguer entre les pages et de grer des formulaires sans se soucier des informations de
session : elles sont transmises en parallle.

L'utilisation de cette technique peut tre illustre sur une gestion de session avec authentification des
utilisateurs.

Exemple

- Script login.php pour l'authentification :

<?php
// inclusion du fichier contenant les fonctions gnrales
include("fonctions.inc");
function utilisateur_existe($identifiant,$mot_de_passe) {
// fonction qui vrifie que l'identification saisie est correcte
$requte = sprintf(
"SELECT * FROM utilisateurs WHERE identifiant = '%s'",
vers_base($identifiant));
$erreur = "";
$utilisateur = db_lire_ligne($requte,$erreur);
// l'identification est bonne s'il existe un utilisateur
// ayant l'identifiant saisi (! empty ...) et que le mot
// de passe correspond ($utilisateur ... == ...)
$existe = ((! empty($utilisateur)) and
($utilisateur["mot_de_passe"] == $mot_de_passe));
return $existe;
}
// initialisation des variables
$identifiant = "";
$mot_de_passe = "";
$message = "";
// traitement du formulaire
if (isset($_POST["connexion"])) {
// rcuprer les informations saisies
$identifiant =
valeur_saisie($_POST["identifiant"]);
$mot_de_passe =
valeur_saisie($_POST["mot_de_passe"]);
// vrifier que l'utilisateur existe
if (utilisateur_existe($identifiant,$mot_de_passe)) {
// l'utilisateur existe ...
// => ouvrir la session
$session = identifiant_unique();
$date = date("\l\e d/m/Y H:i:s");
// dposer trois cookies pour stocker ces informations
// dure de vie = la session justement !
setcookie("session",$session);
setcookie("date",$date);
setcookie("identifiant",$identifiant);
header("location: page1.php ");
exit;
} else {

ENI Editions - All rigths reserved - 7-


// l'utilisateur n'existe pas ...
// typiquement, afficher un message et proposer de
// nouveau l'identification
$message = "Identification incorrecte.
Essayez de nouveau.";
// laisser le formulaire s'afficher de nouveau ...
}
}
?>
<HTML>
<HEAD><TITLE>Login</TITLE></HEAD>
<BODY>
<FORM ACTION="login.php" METHOD="POST">
<TABLE BORDER=0>
<TR>
<TD ALIGN="right">Identifiant :</TD>
<TD><INPUT TYPE="text" NAME="identifiant" VALUE=
"<?php echo vers_formulaire($identifiant); ?>"></TD>
</TR>
<TR>
<TD ALIGN="right">Mot de passe :</TD>
<TD><INPUT TYPE="password" NAME="mot_de_passe" VALUE=
"<?php echo vers_formulaire($mot_de_passe); ?>"></TD>
</TR>
<TR>
<TD></TD>
<TD ALIGN="right"><INPUT TYPE="submit" NAME="connexion"
VALUE= "Connexion"></TD>
</TR>
</TABLE>
</FORM>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

- Script page1.php pour une page du site :

<?php
// inclusion du fichier qui contient les fonctions gnrales
include("fonctions.inc");
// tester si la session est ouverte, c'est--dire si une
// variable "session" a t transmise par le cookie
if (! isset($_COOKIE["session"]) ) {
// variable " session " vide = pas de session
// => rediriger l'utilisateur vers la page de login
header("location: login.php");
exit;
} else {
// variable "session" non vide = session ouverte
// => rcuprer les autres informations des cookies
// pour cet exemple :
// - identifiant de session
$session = $_COOKIE["session"];
// - date/heured'ouverture de la session
$date = $_COOKIE["date"];
// - identifiant de l'utilisateur
$identifiant =
valeur_saisie($_COOKIE["identifiant"]);
// message
$message = "Session : $session - $identifiant - $date";
}
// dtermination de la date et de l'heure actuelles (pas celles
// de l'ouverture de la session
$actuel = "Nous sommes le ".date("d/m/Y").
" ; il est ".date("H:i:s");
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1 - <?php echo $actuel; ?></B><BR>
<?php echo $message; ?><BR>
<!-- lien vers les autres pages -->
<A HREF="page2.php">Page 2</A>
</BODY>
</HTML>

Le premier appel de l'URL http://.../page1.php provoque la redirection de l'utilisateur vers la page


d'identification aprs une identification russie, l'utilisateur revient sur la page 1 qui affiche les informations

- 8- ENI Editions - All rigths reserved


suivantes :

Page 1 - Nous sommes le 04/05/2004 ; il est 17:59:08


Session : c0f92baa8180154ca93230d7f40148a0 - heurtel - le 04/05/2004 17:59:08
Page 2

Remarquesetconclusion

Lesutilisateursmalinset/oumalintentionns

Bien que ce soit un peu plus complexe mettre en uvre, un utilisateur (malin et/ou mal intentionn) peut
accder la page 1, en outrepassant le mcanisme d'ouverture de session et, notamment, le passage par la
paged'identificationdansledeuximeexemple.
Comme dans les deux autres cas (URL et formulaire), la solution consiste garder trace, ct serveur, des
sessionsrellementouvertes.

Nepastouttransmettredanslescookies

Lescookiespossdentleurslimites :

- Le nombre de cookies est limit vingt par serveur.

- La taille d'un cookie est limite.

L encore, le mcanisme utilis pour conserver, ct serveur, la trace des sessions ouvertes, peut aussi tre
employpourconserverdesinformationscomplmentairessurlasession.Ainsi,vousn'tespasobligdepasser
touteslesvaleursdansdescookies.

Conclusion

Les cookies sont trs pratiques pour grer les sessions mais ne sont pas forcment accepts par tous les
utilisateurs.

Pour un site destin des utilisateurs identifis (abonns, inscrits), il est possible d'imposer l'acceptation des
cookiespourtremembredusite,l'importanttantdebieninformerlesutilisateursquelecookienerestequele
tempsdelasession.

Pour un site "grand public", il n'est sans doute pas acceptable de fonder une gestion des sessions sur les
cookies.

De toutes les mthodes abordes jusqu' prsent, la technique "cookie" et la technique "URL" peuvent tre
considrescommelesmoinscontraignantes.Unegestiondessessions,danslaquelleseull'identifiantdesession
doittretransmisd'unepagel'autre(lesautresinformationstantstockessurleserveur)peuttremiseen
place relativement facilement en employant les cookies, si l'utilisateur les accepte et en utilisant l'URL dans le
cascontraire.C'estexactementcequeproposelagestiondessessionsdePHPquenousallonsvoirmaintenant :
nenousamusonsdoncpasredveloppercequiexistedj !

Nous allons galement voir dans ce chapitre (cf. G rer les sessions Conserver des informations d'une visite
une autre), que le cookie est un bon outil (sous rserve toujours de l'accord de l'utilisateur) pour stocker une
informationd'unesessionl'autre(enutilisantdoncuncookieayantuneduredeviespcifielacration).

ENI Editions - All rigths reserved - 9-


UtiliserlagestiondessessionsdePHP

Principes

Depuis la version 4, PHP propose un ensemble de fonctions qui facilitent la gestion des sessions. Les principes
sontlessuivants :

- Un identifiant unique est automatiquement attribu chaque session.

- Cet identifiant unique est transmis d'une page l'autre, soit par cookie (si le poste accepte les cookies), soit par l'URL
dans le cas contraire; en tout tat de cause, c'est PHP qui choisit automatiquement la bonne mthode et assure ce
transfert ( quelques rserves prs, lies la configuration).

- Les variables, dont vous souhaitez conserver la valeur d'une page l'autre pendant la dure de la session, sont
indiques PHP qui se charge automatiquement de restituer leurs valeurs au dbut du script, et de les sauvegarder
la fin du script. Par dfaut, la sauvegarde s'effectue sur disque, dans des fichiers temporaires, mais il est possible,
moyennant un peu de dveloppement, de faire sauvegarder ces valeurs par PHP dans une base. Ces variables sont
dsignes sous le terme "variables de session".

Enbref,PHPsechargedetoutelagestion.

Lesfonctions

Lesprincipalesfonctionsdumoduledegestiondessessionssontlessuivantes :

Nom Rle
session_start Ouvre une nouvelle session ou ractive la session
courante.
session_id Retourne (ou ventuellement modifie) l'identifiant de la
session.
session_name Retourne (ou ventuellement modifie) le nom de la
variable utilise pour stocker l'identifiant de la session.
session_register Enregistre une variable dans la session courante.
session_is_registered Indique si une variable est enregistre dans la session.
session_unregister Supprime l'enregistrement de la variable dans la session.
session_unset Supprime l'enregistrement de toutes les variables de la
session.
session_destroy Supprime la session.

session_start

Syntaxe

boolen session_start()

La fonction session_start va interroger l'environnement pour dtecter si une session a dj t ouverte pour
l'utilisateur actuel. Si oui, les variables enregistres dans la session sont restitues. Autrement, une nouvelle
sessionestouverteavecattributiond'unidentifiant.

Lafonctionsession_startretournetoujoursTRUE.

Toutscriptconcernparlagestiondessessionsdoitappeler session_startpouravoiraccsauxvariablesde
session.

Si la session n'est pas encore ouverte, la fonctionsession_startvachercherdposeruncookie,contenant


l'identifiant de session, sur le poste de l'utilisateur : il est donc primordial, comme pour les fonctions header et

ENI Editions - All rigths reserved - 1-


setcookiequeledbutdelapagen'aitpasencoretenvoyaunavigateur.Encasdeproblme,unmessage
dutypesuivantestaffich :

Warning: session_start() [function.session-start]: Cannot send session


cookie - headers already sent by (output started at
d:\scripts php\test.php:1) in d:\scripts php\test.php on line 4

Exemple

<?php
// ouvrir/ractiver la session
session_start();
?>

session_id

Syntaxe

chane session_id([chane nouvelle_valeur])

nouvelle_valeur

Nouvellevaleurattribuel'identifiantdesession.

Appelesansparamtre,lafonction session_idretournelavaleurdel'identifiantdesession.Cettevaleursera
toujoursvidesisession_startn'apastappeledanslescript.
Appele avec un paramtre, la fonction session_id modifie la valeur attribue l'identifiant de session. En
pratique,danslamajoritdescas,celaneprsentepasungrandintrt.

Exemple

<?php
// rcuprer la valeur de session_id avant
$avant = session_id();
// ouvrir/ractiver la session
session_start();
// rcuprer la valeur de session_id aprs
$aprs = session_id();
// affichage
$actuel = date("H:i:s");
echo "Heure : $actuel<BR>";
echo "Avant : $avant<BR>";
echo "Aprs : $aprs<BR>";
?>

Rsultat

- Premier appel :

Heure : 16:48:23
Avant :
Aprs : 5367261e1325076530d5f4c756b55e07

- Deuxime appel (sans quitter le site) :

Heure : 16:48:37
Avant :
Aprs : 5367261e1325076530d5f4c756b55e07

- Troisime appel (aprs avoir quitt le site) :

Heure : 16:49:33
Avant :
Aprs : 124b271be50112948ae2279dbb28e43d

Les trois exemples montrent qu'avant appel la fonction session_start, la fonction session_id retourne une

- 2- ENI Editions - All rigths reserved


chanevide,mmesilasessionadjtouverte(casdudeuximeappel).
Surletroisimeappel,l'identifiantdesessionestnouveaucarc'estunenouvellesession.

session_name

Syntaxe

chane session_name([chane nouvelle_valeur])

nouvelle_valeur

Nouvellevaleurattribueaunomdelavariablequistockel'identifiantdesession.

Appele sans paramtre, la fonction session_name retourne le nom de la variable dans laquelle l'identifiant de
session est stock. La fonction session_nameretourneunrsultatmmesilafonction session_start n'a pas
tappeledanslescript.

Appele avec un paramtre, la fonction session_name modifie le nom de la variable. En pratique, dans la
majoritdescas,celaneprsentepasungrandintrt(ilestremissavaleurpardfautlafinduscript).

Exemple

<?php
// rcuprer la valeur de session_name avant
$avant = session_name();
// ouvrir/ractiver la session
session_start();
// rcuprer la valeur de session_name aprs
$aprs = session_name();
// affichage
echo "Avant : $avant<BR>";
echo "Aprs : $aprs<BR>";
// affichage de la valeur en utilisant la technique de variable variable
echo "$aprs = ${$aprs}<BR>";
?>

Rsultat

Avant : PHPSESSID
Aprs : PHPSESSID
PHPSESSID = 4f7acd051136cafc0464d44583f7ff68

Le nom de la variable est dfini par la directive de configuration session.name. Vous pouvez modifier cette
directivepourutiliserunautrenom.

session_register

Syntaxe

boolen session_register(mixte nom_variable[,...])

nom_variable

Chane(outableau)contenantlenomdela(oudes)variable(s)enregistrerdanslasession.Danslesdeuxcas,
lesnomsdevariablesontindiqussanslecaractre$.

Cette fonction est conserve pour des raisons de compatibilit ascendante et ne fonctionne que lorsque la directive de
configuration register_globals est on (rappel : elle est off par dfaut depuis la version 4.2 et passera dfinitivement
off dans une prochaine version). la place, il est conseill de travailler directement avec le tableau $_SESSION (voir ci-aprs).

Lafonctionsession_registeraccepteplusieursparamtrespermettantainsid'enregistrerplusieursvariablesen
unseulappel.

La fonction session_register fait un appel implicite la fonction session_start pour ouvrir ou ractiver la
session.

ENI Editions - All rigths reserved - 3-


Lafonctionsession_registerretourneTRUE,encasdesuccs,etFALSE,encasd'chec.

Tout type de variable est accept (notamment les tableaux). Des exemples sont donns dans la section
suivante.

Manipulerlesvariablesenregistresdanslasession

Lorsdel'appellafonctionsession_start,touteslesvariablesenregistresdanslasessionsontrestaureset
accessibles selon des mcanismes identiques ceux dj tudis pour les donnes GET et POST ou pour les
cookies.

La valeur de chaque variable enregistre est notamment automatiquement restitue dans le tableau associatif
$_SESSION($HTTP_SESSION_VARSavantla4.1) :lacldutableauestgaleaunomdelavariableenregistre.

En complment, si la directive de configuration register_globals est on, la valeur de chaque variable


enregistre,estautomatiquementrestituedansunevariabledemmenom.

N'oubliez pas que la directive de configuration register_globals est off par dfaut depuis la version 4.2 et qu'elle
passera dfinitivement off dans une prochaine version.

Le tableau $_SESSION prsente une fonctionnalit supplmentaire intressante : toutes les entres stockes
dans ce tableau sont automatiquement enregistres en tant que donnes de session si la fonction
session_start a t appele au pralable, sans avoir besoin d'appeler la fonction session_register.
$_SESSIONnesertdoncpasuniquementrcuprerlesdonnesdesessionmaisaussilesenregistrer.

Exemple (avec session_register)

- Script page1.php qui ouvre une session et enregistre des variables dans la session :

<?php
// ouvrir/ractiver la session
session_start();
// initialiser deux variables
$prnom = "";
$informations = "";
// enregistrer les deux variables dans la session
session_register("prnom");
session_register("informations");
// donner des valeurs aux variables
$prnom = "Olivier";
$informations = array("prnom"=>"Olivier","nom"=>"HEURTEL");
// c'est un tableau associatif
// autre variable non enregistre
$nom = "HEURTEL";
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1</B><BR>
<A HREF="page2.php">Page 2</A>
</BODY>
</HTML>

- Script page2.php qui affiche la valeur des variables de session:

<?php
// appel session_start
session_start();
// affichages
echo '$prnom = ',isset($prnom)?$prnom:'','<BR>';
echo '$_SESSION["prnom"] = ',
isset($_SESSION["prnom"])?$_SESSION["prnom"]:'',
'<BR>';
echo '$nom = ',isset($nom)?$nom:'','<BR>';
echo '$_SESSION["nom"] =',
isset($_SESSION["nom"])?$_SESSION["nom"]:'',
'<BR>';
echo '$informations["nom"] = ',

- 4- ENI Editions - All rigths reserved


isset($informations["nom"])?$informations["nom"]:'',
'<BR>';
echo '$_SESSION["informations"]["nom"] = ',
isset($_SESSION["informations"]["nom"])?
$_SESSION["informations"]["nom"]:'',
'<BR>';
?>

Rsultat sur la page 2 aprs affichage de la page 1 et clic sur le lien


(si register_globals est on)

$prnom = Olivier
$_SESSION["prnom"] = Olivier
$nom =
$_SESSION["nom"] =
$informations["nom"] = HEURTEL
$_SESSION["informations"]["nom"] = HEURTEL

Lavariable$nomn'apasdevaleur,carellen'estpasdfiniedanslescriptpage2.php,nienregistreentantque
variabledesessiondanslescript page1.php.Parcontre,lenomestprsentdansletableauassociatifqui,lui,a
bientenregistr.

Rsultat si session_start est mis en commentaire dans le script page2.php

$prnom =
$_SESSION["prnom"] =
$nom =
$_SESSION["nom"] =
$informations["nom"] =
$_SESSION["informations"]["nom"] =

Lesvariablesdesessionnesontpasrestaures.

Rsultat si register_globals est off

$prnom =
$_SESSION["prnom"] =
$nom =
$_SESSION["nom"] =
$informations["nom"] =
$_SESSION["informations"]["nom"] =

Les variables de session n'ont pas t restaures ... car elles n'ont, en fait, pas t enregistres. Si
register_globalsestoff,session_registernefaitrien(etneditrien).

Remarques:

- La fonction session_register indique PHP le nom des variables sauvegarder dans la session; la valeur
proprement dite de la variable est sauvegarde lorsque le script se termine et non lors de l'appel la fonction
session_register.

- partir du moment o une variable est enregistre, il n'est plus ncessaire d'appeler session_register lorsque la
variable est modifie, quel que soit le script (celui dans lequel la variable a t enregistre ou un autre).

Exemple (avec $_SESSION)

- Script page1.php qui ouvre une session et enregistre des variables dans la session :

<?php
// ouvrir/ractiver la session
session_start();
// enregistrer deux "variables" dans la session
$_SESSION["prnom"] = "Olivier";
$_SESSION["informations"] =
array("prnom"=>"Olivier","nom"=>"HEURTEL");
?>
<HTML>

ENI Editions - All rigths reserved - 5-


<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1</B><BR>
<A HREF="page2.php">Page 2</A>
</BODY>
</HTML>

- Script page2.php qui affiche la valeur des variables de session :

<?php
// appel session_start
session_start();
// affichages
echo '$_SESSION["prnom"] = ',
isset($_SESSION["prnom"])?$_SESSION["prnom"]:'',
'<BR>';
echo '$_SESSION["informations"]["nom"] = ',
isset($_SESSION["informations"]["nom"])?
$_SESSION["informations"]["nom"]:'',
'<BR>';
?>

Rsultat sur la page 2 aprs affichage de la page 1 et clic sur le lien

$_SESSION["prnom"] = Olivier
$_SESSION["informations"]["nom"] = HEURTEL

Cettemthodefonctionnequellequesoitlaconfiguration c'estlamthoderecommande.

Il n'y a aucun encodage (ni mme de "magic quotes" !) sur les donnes stockes dans une variable de session.

Par contre, il existe des diffrences de fonctionnement, premire vue troublantes, selon la valeur de la
directivedeconfigurationregister_globals :

- Si register_globals est off, la variable de session $x n'existe pas a priori; il faut aller la lire dans $_SESSION
["x"]. Pour la mise jour, utiliser $x (mme aprs l'avoir initialis avec $_SESSION ["x"]) est sans effet; pour
PHP, ce n'est pas $x qui contient la valeur sauvegarder; c'est $_SESSION["x"] (qu'il faut donc modifier
directement).

- Si register_globals est on, la variable de session $x existe et rfrence la mme valeur (mme zone mmoire)
que $_SESSION["x"]. Modifier l'une modifie l'autre (et vice versa).

Pour terminer, il existe un problme similaire si les variables de session sont manipules, non pas directement
danslescript,maisdansunefonctionappeledanslescript.Lesvariablesdesessionsont,enfait,implicitement
desvariablesdfiniesdanslescript,c'estdiredesvariablesglobalesvisvisdelafonctionenquestion.

Pour manipuler des variables de session l'intrieur d'une fonction, il faut les traiter en tant que variables
globales, tout en tant confront au mme problme visvis de la valeur de la directive de configuration
register_globals : dclarer la variable $x comme variable (global $x;) dans la fonction, et la lire ou la
modifieralorsqueregister_globalsestoff,esterron.

Heureusement, le tableau $_SESSION est une variable "super globale" : elle est disponible dans la totalit du
script,mmel'intrieurdesfonctions,sansdevoirladclarerglobale(global $_SESSIONestinutile).

En rsum (et en conclusion), utilisez le tableau $_SESSION et laissez la directive de configuration


register_globalsoff(oufaitescommesi).

L'exemple ciaprs, compos de trois scripts, illustre diverses utilisations du tableau $_SESSION. Ce code
fonctionne quelle que soit la configuration, est facile crire et respecte bien les recommandations de la
communautPHPsurlagestiondessessions.

Script page1.php

<?php
// ouvrir/ractiver la session

- 6- ENI Editions - All rigths reserved


session_start();
// enregistrer une variable dans la session
$_SESSION["prnom"] = "Olivier";
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1</B><BR>
<A HREF="page2.php">Page 2</A><BR>
<?php
// afficher un message
echo "Bonjour ". $_SESSION["prnom"];
?>
</BODY>
</HTML>

Script page2.php

<?php
// dfinir une fonction qui "manipule" la session
function manipuler_session() {
// ouvrir/ractiver la session
session_start();
// modifier la valeur de la variable de session
$_SESSION["prnom"] = "Xavier";
}
// appeler la fonction qui manipule la session
manipuler_session();
?>
<HTML>
<HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<B>Page 2</B><BR>
<A HREF="page2.php">Page 3</A><BR>
<?php
// afficher un message
echo "Bonjour ". $_SESSION["prnom"];
?>
</BODY>
</HTML>

Script page3.php

<?php
// dfinir une fonction qui ouvre la session
function activer_session() {
// ouvrir/ractiver la session
session_start();
}
// dfinir une fonction qui affiche l'information de session
function afficher_information_session() {
// afficher un message
echo "Bonjour ". $_SESSION["prnom"];
}
// appeler la fonction qui ouvre la session
activer_session();
?>
<HTML>
<HEAD><TITLE>Page 3</TITLE></HEAD>
<BODY>
<B>Page 3</B><BR>
<A HREF="page1.php">Page 1</A><BR>
<?php

// appeler la fonction qui affiche l'information de session


afficher_information_session();
?>
</BODY>
</HTML>

Rsultat dans la page 1

Page 1
Page 2
Bonjour Olivier

ENI Editions - All rigths reserved - 7-


Rsultat dans la page 2 aprs clic sur le lien de la page 1

Page 2
Page 3
Bonjour Xavier

Rsultat dans la page 3 aprs clic sur le lien de la page 2

Page 3
Page 1
Bonjour Xavier

Si $_SESSION est utilis, il est dconseill d'employer session_register (et nous allons le voir
session_is_registered et session_unregister).

session_is_registered

Syntaxe

boolen session_is_registered(chane nom_variable)

nom_variable

Nomdelavariable(sousformedechanesanslecaractre$)tester.

Cette fonction est conserve pour des raisons de compatibilit ascendante. la place, il est conseill d'utiliser la fonction
isset pour tester la valeur dans le tableau $_SESSION.

La fonction session_is_registered retourne TRUE ou FALSE selon que la variable, dont le nom est pass en
paramtre,estenregistreounon.

Lafonction session_is_registereddoittreappeleaprslafonctionsession_start danslecascontraire,


elleretournetoujoursFALSE.

Exemple

- Script page1.php :

<?php
// ouvrir/ractiver la session
session_start();
// enregistrer une variable dans la session
$_SESSION["nom"] = "Olivier";
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1</B><BR>
<?php echo $_SESSION["nom"]; ?><BR>
<A HREF="page2.php">Page 2</A>
</BODY>
</HTML>

- Script page2.php (avec session_is_registered) :

<?php
// rcuprer la valeur avant appel session_start
$avant = session_is_registered("nom");
// ouvrir/ractiver la session
session_start();
// rcuprer la valeur aprs appel session_start
$aprs = session_is_registered("nom");
// affichage
echo "Avant : ".($avant?"TRUE":"FALSE")."<BR>";
echo "Aprs : ".($aprs?"TRUE":"FALSE")."<BR>";
?>

- 8- ENI Editions - All rigths reserved


- Script page2.php (avec isset) :

<?php
// rcuprer la valeur avant appel session_start
$avant = session_is_registered("nom");
// ouvrir/ractiver la session
session_start();
// rcuprer la valeur aprs appel session_start
$aprs = session_is_registered("nom");
// affichage
echo "Avant : ".($avant?"TRUE":"FALSE")."<BR>";
echo "Aprs : ".($aprs?"TRUE":"FALSE")."<BR>";
?>

Rsultat (dans les deux cas)

Avant : FALSE
Aprs : TRUE

session_unregister

Syntaxe

boolen session_unregister(chane nom_variable)

nom_variable

Nomdelavariable(sousformedechanesanslecaractre$)neplusenregistrerdanslasession.

Cette fonction est conserve pour des raisons de compatibilit ascendante. la place, il est conseill d'utiliser la fonction
unset pour supprimer la valeur dans le tableau $_SESSION.

Lafonctionsession_unregisterretourneTRUE,encasdesuccs,etFALSE,encasd'chec.

Lafonctionsession_unregisterestsanseffetsielleestappeleavantlafonctionsession_start.

Lafonctionsession_unregisternesupprimepaslavariabledanslescriptencours.

Exemple (avec session_unregister)

- Script page1.php inchang

- Script page2.php :

<?php
// ouvrir/ractiver la session
session_start();
?>
<HTML>
<HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<B>Page 2</B><BR>
<?php
// variables avant
echo 'Avant :','<BR>';
echo '$nom = ', isset($nom)?$nom:'','<BR>';
echo '$_SESSION[nom] = ',
isset($_SESSION["nom"])?$_SESSION["nom"]:'','<BR>';
// supprimer l'enregistrement de la variable
session_unregister("nom");
// que sont devenues les variables dans le script ?
echo 'Aprs :','<BR>';
echo '$nom = ', isset($nom)?$nom:'','<BR>';
echo '$_SESSION[nom] = ',
isset($_SESSION["nom"])?$_SESSION["nom"]:'','<BR>';
?>
<A HREF="page3.php">Page 3</A>
</BODY>

ENI Editions - All rigths reserved - 9-


</HTML>

- Script page3.php :

<?php
// ouvrir/ractiver la session
session_start();
?>
<HTML>
<HEAD><TITLE>Page 3</TITLE></HEAD>
<BODY>
<B>Page 3</B><BR>
<?php
// que sont devenues les variables dans le script ?
echo '$nom = ', isset($nom)?$nom:'','<BR>';
echo '$_SESSION[nom] = ',
isset($_SESSION["nom"])?$_SESSION["nom"]:'','<BR>';
?>
</BODY>
</HTML>

Rsultat (si register_globals = on)

- Page 2 :

Page 2
Avant :
$nom = Olivier
$_SESSION[nom] = Olivier
Aprs :
$nom = Olivier
$_SESSION[nom] =
Page 3

- Page 3 :

Page 3
$nom =
$_SESSION[nom] =

Rsultat (si register_globals = off)

- Page 2 :

Page 2
Avant :
$nom =
$_SESSION[nom] = Olivier
Aprs :
$nom =
$_SESSION[nom] =
Page 3

- Page 3 :

Page 3
$nom =
$_SESSION[nom] =

Danscecas,lavariable$nomn'existaitpas(effetderegister_globals = off).

Exemple (avec unset)

- Script page1.php inchang

- Script page2.php :

- 10 - ENI Editions - All rigths reserved


<?php
// ouvrir/ractiver la session
session_start();
?>
<HTML>
<HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<B>Page 2</B><BR>
<?php
// variables avant
echo 'Avant :','<BR>';
echo '$nom = ', isset($nom)?$nom:'','<BR>';
echo '$_SESSION[nom] = ',
isset($_SESSION["nom"])?$_SESSION["nom"]:'','<BR>';
// supprimer l'enregistrement de la variable
unset($_SESSION["nom"]);
// que sont devenues les variables dans le script ?
echo 'Aprs :','<BR>';
echo '$nom = ', isset($nom)?$nom:'','<BR>';
echo '$_SESSION[nom] = ',
isset($_SESSION["nom"])?$_SESSION["nom"]:'','<BR>';
?>
<A HREF="page3.php">Page 3</A>
</BODY>
</HTML>

- Script page3.php inchang>

Lersultatestidentique.

Ne supprimez pas la totalit de la variable $_SESSION (unset($_SESSION)) !

session_unset

Syntaxe

session_unset()

Cette fonction est conserve pour des raisons de compatibilit ascendante. la place, il est conseill d'utiliser la fonction
unset pour supprimer les valeurs dans le tableau $_SESSION, ou de lui affecter un tableau vide (array()).

Lafonction session_unsetsupprimel'enregistrementdetouteslesvariablesdelasessionainsiquelesvariables
ellesmmes(ladiffrencedelafonctionsession_unregister).

Lafonctionsession_unsetestsanseffetsielleestappeleavantlafonctionsession_start.

session_destroy

Syntaxe

boolen session_destroy()

Aprs un appel la fonction session_destroy, la session n'existe plus un appel la fonction session_id
retourneunechanevide,etunappelultrieurlafonctionsession_startvaouvrirunenouvellesession.Par
contre, la fonction session_destroy ne supprime pas les variables de session dans le script en cours. Pour
supprimer immdiatement toutes les donnes de session, appelez la fonction session_unset ou affectez un
tableauvide$_SESSION.
Lafonctionsession_destroyretourneTRUE,encasdesuccs,etFALSE,encasd'chec.
La fonction session_destroy retourne FALSE et affiche une alerte, si elle est appele avant la fonction
session_start.

Exemple

- Script page1.php inchang

- Script page2.php :

ENI Editions - All rigths reserved - 11 -


<?php
// ouvrir/ractiver la session
session_start();
// supprimer l'enregistrement des variables
session_destroy();
// rcuprer l'identifiant de la session aprs
$aprs = session_id();
?>
<HTML>
<HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<B>Page 2</B><BR>
<?php
// affichage de session_id aprs
echo "session_id aprs = $aprs<BR>";
// que sont devenues les variables dans le script ?
echo '$_SESSION[nom] = ',
isset($_SESSION["nom"])?$_SESSION["nom"]:'','<BR>';
?>
<A HREF="page3.php">Page 3</A>
</BODY>
</HTML>

- Script page3.php :

<?php
// ouvrir/ractiver la session
session_start();
?>
<HTML>
<HEAD><TITLE>Page 3</TITLE></HEAD>
<BODY>
<B>Page 3</B><BR>
<?php

// que sont devenues les variables dans le script ?


echo '$_SESSION[nom] = ',
isset($_SESSION["nom"])?$_SESSION["nom"]:'','<BR>';
?>
</BODY>
</HTML>

Rsultat

- Page 2 :

Page 2
session_id aprs =
$_SESSION[nom] = Olivier
Page 3

- Page 3 :

Page 3
$_SESSION[nom] =

Dans la deuxime page, les donnes de sessions ne sont pas encore supprimes. Par contre, dans la troisime
page,lesvariablessontvides(enfait,unenouvellesessionatouverte).

Lescriptpage2.phpsuivantsupprimetoutdesuitelesdonnes :

<?php
// ouvrir/ractiver la session
session_start();
// supprimer l'enregistrement des variables
session_destroy();
// supprimer les donnes de session
$_SESSION = array();
// rcuprer l'identifiant de la session aprs
$aprs = session_id();
?>

- 12 - ENI Editions - All rigths reserved


<HTML>
<HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<B>Page 2</B><BR>
<?php
// affichage de session_id aprs
echo "session_id aprs = $aprs<BR>";
// que sont devenues les variables dans le script ?
echo '$_SESSION[nom] = ',
isset($_SESSION["nom"])?$_SESSION["nom"]:'','<BR>';
?>
<A HREF="page3.php">Page 3</A>
</BODY>
</HTML>

Grersoimmelatransmissiondel'identifiantdesession

Normalement, l'identifiant de session est automatiquement transmis par PHP, soit par cookie soit par l'URL (si
l'utilisateurn'acceptepaslescookies).

Nanmoins,troisdirectivesdeconfigurationpilotentcecomportement :

- session.use_cookie ;

- session.use_trans_id ;

- session.use_only_cookie.

Siladirectivesession.use_cookieestgale0,PHPnetentemmepasd'utiliserlescookiespourtransmettre
l'identifiant de session. Par contre, si la directive est gale 1 (valeur par dfaut), PHP tente d'utiliser les
cookies.

Si la directive session.use_trans_sid est gale 0 (valeur par dfaut), PHP n'utilise pas l'URL pour
transmettre l'identifiant de session. Par contre, si la directive est gale 1 et que l'identifiant de session ne
puisse pas tre transmis par cookie (du fait de la configuration ou d'un refus de l'utilisateur), alors PHP utilise
l'URLpourtransmettrel'identifiantdesession.

Siladirectivesession.use_only_cookieest1,seulslescookiessontutilisspourtransmettrel'identifiantde
session.Pardfaut,ladirectiveest0(compatibilitascendante).

La consquence principale est la suivante : si la directive session.use_trans_sid est gale 0 (valeur par
dfaut) et si l'identifiant de session ne peut pas tre transmis par cookie (du fait de la configuration ou d'un
refusdel'utilisateur),lagestionnefonctionneplus.

En terme de scurit, il est dconseill de permettre la transmission de l'identifiant de session par l'URL. Il est
prfrable d'utiliser des cookies, mais cela ncessite que l'internaute les acceptent. Les valeurs par dfaut des
directivesdeconfigurationvontdanscesens.

Exemple

- Script page1.php :

<?php
// ouvrir/ractiver la session
session_start();
// enregistrer une variable dans la session
$_SESSION["nom"] = "Olivier";
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1</B><BR>
<?php
// afficher l'ID de la session
echo 'session_id = ',session_id(),'<BR>';
// afficher la donne de session
echo 'nom = ',

ENI Editions - All rigths reserved - 13 -


isset($_SESSION["nom"])?$_SESSION["nom"]:'','<BR>';
?>
<A HREF="page2.php">Page 2</A>
</BODY>
</HTML>

- Script page2.php :

<?php
// ouvrir/ractiver la session
session_start();
?>
<HTML>
<HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<B>Page 2</B><BR>
<?php
// afficher l'ID de la session
echo 'session_id = ',session_id(),'<BR>';
// afficher la donne de session
echo 'nom = ',
isset($_SESSION["nom"])?$_SESSION["nom"]:'','<BR>';
?>
</BODY>
</HTML>

Rsultat (premier cas)

- Affichage initial de la page 1 :

Page 1
session_id = d726fe0c341a5318e23ce8fa458f6b2b
nom = Olivier
Page 2

- Affichage de la page 2 aprs un clic sur le lien Page 2 (si l'utilisateur refuse les cookies et que session.use_trans_sid =
0) :

Page 2
session_id = 7ea06105fcd63c888171925e59c973f2
nom =

Les informations de session n'ont pas t transmises et l'appel la fonction session_start a ouvert une
nouvellesession.

Rsultat (deuxime cas)

- Affichage initial de la page 1 :

Page 1
session_id = 508036f27cbd7a7bac0317288c1a2ce0
nom = Olivier
Page 2

- Affichage de la page 1 aprs un clic sur le lien Page 2 si l'utilisateur refuse les cookies et que session.use_trans_sid =
1:

Page 2
session_id = 508036f27cbd7a7bac0317288c1a2ce0
nom = Olivier

Danscecas,lasessionestbienconserve.

RegardonslesourceHMTLdelapremirepagepourcomprendrecequis'estpass :

<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>

- 14 - ENI Editions - All rigths reserved


<B>Page 1</B><BR>
session_id = 508036f27cbd7a7bac0317288c1a2ce0<BR>nom = Olivier<BR>
<A HREF=
"page2.php?PHPSESSID=508036f27cbd7a7bac0317288c1a2ce0">
Page 2</A>
</BODY>
</HTML>

La balise <A HREF> >a t automatiquement rcrite par PHP, pour intgrer la transmission de l'identifiant de
session (nomm PHPSESSID par dfaut). Si un paramtre avait t prsent dans l'URL, PHP aurait ajout le
paramtrePHPSESSIDdansl'URL(&PHPSESSID=...).

Parcontre,unproblmeseposeencasderetoursurlapage1,parleboutonPrcdentedunavigateur :

Page 1
session_id = e0d99af15c40395379681f47a27393af
nom = Olivier
Page 2

Comme l'identifiant de session n'est pas retransmis lors de l'appel cette page, une nouvelle session est
ouverte.

De la mme manire, si une page propose un formulaire, une zone cache est automatiquement ajoute par
PHP,pourtransmettrel'identifiantdesessionlorsdelasoumissionduformulaire.

Exemple

<input type="hidden" name="PHPSESSID" value="556e46fb45de467e0b2a18ce46855


016" />

Parcontre,l'informationn'estpastransmiselorsd'uneredirectionaveclafonctionheader.

Sil'identifiantn'estpasautomatiquementtransmisparPHP,ilconvientd'assurersoimmecettetransmission,le
plussimpletantdelefaireparl'URL(commePHPlefaitquandl'optionestactive).

Le nom de l'identifiant de session est dfini par une directive de configuration et utiliser "en dur" la valeur
PHPSESSIDpeutconduireducodenonportable.

Une premire possibilit consiste employer les fonctions session_name et session_id, pour construire le
paramtreinsrerdansl'URLsouslaformenom_identifiant=valeur_identifiant.

La deuxime possibilit (plus simple), consiste utiliser une constante, nomme SID, qui est automatiquement
initialiseparPHP,avecunechanenom_identifiant=valeur_identifiant.

Exemple (si les cookies ne sont pas utiliss)

<?php
// ouvrir/ractiver la session
session_start();
// construire la chane soi-mme
echo "Mon SID : ".session_name()."=".session_id()."<BR>";
// afficher la constante SID
echo "SID : ".SID;;
?>

Rsultat

Mon SID : PHPSESSID=9716743bd5071180629fbd66156001d1


SID : PHPSESSID=9716743bd5071180629fbd66156001d1

Silenomdelavariableestmodifidanslefichierphp.ini,laconstanteSIDentientcompte.

Rsultat

SID : ID_SESSION=af15b302ccf0e48620ac7ab8b0b6b671

ENI Editions - All rigths reserved - 15 -


Cetteconstante,tellequ'elleestdfinie,peuttreutilisedirectementpourconstruireuneURL,transmettantla
valeurdel'identifiantdesession.

Exemples

- Dans une balise <A HREF=...> :

<A HREF="page2.php?<?php echo SID; ?>">Page 2</A>

- Dans l'option ACTION de la balise <FORM> :

<FORM ACTION="page2.php?<?php echo SID; ?>" METHOD"POST">

- Dans une zone cache du formulaire (dans ce cas, il faut utiliser les fonctions session_name et session_id) :

<INPUT TYPE = "hidden"


NAME="<?php echo session_name(); ?>"
VALUE="<?php echo session_id(); ?>">

- Dans une redirection avec la fonction header :

header("Location: page2.php?".SID);

La constante SID n'est pas renseigne si le cookie est accept, sauf dans le script qui vient juste d'ouvrir la session (car PHP
ne sait pas encore si le cookie est accept par le client).
Intgrer un SID vide dans une URL n'est pas trs lgant mais ne pose pas de problme (<A HREF="page2.php?"> est
valide).
Si vous intgrez systmatiquement le SID dans les URL et que la transmission automatique fonctionne (soit par cookie, soit
par l'URL), ce n'est pas non plus trs lgant mais cela ne pose pas de problme.

Pourcrireducodeportableetlgant,ilconvientdoncden'intgrer,soimme, le SID dans l'URL que lorsque


celaestncessaire.
Une fonction gnrique peut trs bien se charger de cette tche, en testant la directive de configuration et la
constanteSID.

Exemple

<?php
function url($url) {
// si la directive de configuration session.use_trans_sid
// est 0 (pas de transmission automatique par l'URL) et
// si SID est non vide (le poste a refus le cookie) alors
// il faut grer soi-mme la transmission
if ((get_cfg_var("session.use_trans_sid") == 0)
and (SID != "")) {
// ajouter la constante SID derrire l'URL avec un ?
// s'il n'y a pas encore de paramtre ou avec un & dans le cas contraire
$url .= ((strpos($url,"?") === FALSE)?"?":"&").SID;
}
return $url;
}
// ouvrir/ractiver la session
session_start();
// quelques tests
echo url("page2.php")."<BR>";
echo url("page3.php?nom=Olivier")."<BR>";
?>

Rsultat

- Si session.trans_id = 0 et cookie refus :

page2.php?PHPSESSID=27c63e18284afaffb658d3495149d295
page3.php?nom="Olivier"&PHPSESSID=
27c63e18284afaffb658d3495149d295

- 16 - ENI Editions - All rigths reserved


- Si session.trans_id = 0 et cookie accept (mais premier appel) :

page2.php?PHPSESSID=5a32506a14cc7d42a88fc7f4fec7ede0
page3.php?nom=Olivier&PHPSESSID=
5a32506a14cc7d42a88fc7f4fec7ede0

- Si session.trans_id = 0 et cookie accept (mais deuxime appel) :

page2.php
page3.php?nom=Olivier

- Si session.trans_id = 1 et cookie accept ou refus :

page2.php
page3.php?nom=Olivier

Danslederniercas,lorsquelecookieestrefus,c'estPHPquiajouteautomatiquementleSIDdansl'URL(carla
directivesession.trans_ideston).
Cette fonction peut ensuite tre appele partout o il faut construire une URL susceptible de transmettre
l'identifiantdesession.

Quelle que soit la configuration, cette fonction doit tre utilise lors d'une redirection avec la fonction header (car PHP ne
rcrit jamais les URL appeles par cette fonction).

Quelquesdirectivesdeconfigurationsupplmentaires

Encomplmentdecellesdjcites,ilestbondeconnatrelesdirectivesdeconfigurationsuivantes :

session.save_path

Rpertoiredanslequellesfichierstemporairescontenantlesinformationsdesessionsontenregistrs.

session.auto_start

Sielleestpositionne1,lafonction session_startestautomatiquementappeleaudbutdechaquescript
(pouruncodeportable,ilestprfrabled'appelerexplicitementlafonctionsession_start).

session.cookie_lifetime

Duredeviedescookiesdposssurlepostedel'utilisateur.Lavaleur0proposepardfaut,estbienadapte
pouruncookiedesession.

session.cache_limiter

Dtermine le comportement visvis du cache de toutes les pages concernes par la gestion des sessions
envoyes au navigateur. Valeurs possibles : nocache, private, public. Cette information est transmise dans
l'enttedelarponseduserveurWeb. nocachepardfaut.

session.cookie_path

Cheminsurleserveurdanslequellecookiedesessionestdisponible(voirlafonctionsetcookie)./pardfaut.

session.cookie_domain

Domaineauquellecookieestrenvoy(voirlafonctionsetcookie).Videpardfaut.

session.cookie_secure

Indiquesilecookienedoittretransmisqueviauneconnexionscurise(voirlafonction setcookie).Off par


dfaut.

ENI Editions - All rigths reserved - 17 -


session.cache_expire

Duredevieenminutesdespagesdanslecache.180pardfaut.Sanseffetsilavaleur nocacheestspcifie
danssession.cache_limiter.

Applicationlagestiondessessions

Les principes dfinis avec les autres techniques vont s'appliquer de manire similaire, lors de l'utilisation de la
fonctionnalitdegestiondessessionsdePHP4.

Le principe essentiel est de systmatiquement appeler la fonction session_start au dbut de chaque script,
soit pour ouvrir une session lors d'une premire visite, soit pour ractiver un contexte de session lors de la
poursuitedelanavigation.

Exemple (avec deux pages)

- Script page1.php :

<?php
// inclusion du fichier qui contient les fonctions gnrales
include("fonctions.inc");
// ouvrir/ractiver la session
session_start();
// tester si la session est nouvelle (i.e. ouverte par
// l'appel session_start ci-dessus) ou ancienne (i.e ouverte
// par un appel antrieur session_start)
// le mieuxest de tester si une de nos variables de session
// est dj enregistre
if (! isset($_SESSION["date"])) {
// variable " date " pas encore enregistre
// => nouvelle session
// => ouvrir la session au niveau applicatif
// pour cet exemple :
// - dterminer la date/heure d'ouverture
// de la session
$date = date("\l\e d/m/Y H:i:s");
// - enregistrer la date/heure d'ouverture
// de la session
$_SESSION["date"] = $date;
// - rcuprer l'identifiant de la session (pour info)
$session = session_id();
// - message
$message = "Nouvelle session : $session - $date";
} else {
// variable " date " dj enregistre
// => ancienne session
// => rcuprer les variables de session (uniquement
// celles utilises dans ce script)
// pour cet exemple :
// - date/heure d'ouverture de la session
$date = $_SESSION["date"];
// - rcuprer l'identifiant de la session (pour info)
$session = session_id();
// message
$message = "Session dj ouverte: $session - $date";
}
// dtermination de la date et de l'heure actuelle (pas celle
// de l'ouverture de la session
$actuel = "Nous sommes le ".date("d/m/Y").
" ; il est ".date("H:i:s");
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1 - <?php echo $actuel; ?></B><BR>
<?php echo $message; ?><BR>
<!-- lien vers les autres pages
utiliser notre fonction gnrique url() pour tre
certain que l'identifiant de session est transmis
quelles que soient les conditions -->
<A HREF="<?php echo url("page2.php"); ?>">Page 2</A>
</BODY>
</HTML>

- 18 - ENI Editions - All rigths reserved


- Script page2.php (identique l'exception de la partie HTML) :

<?php
...
?>
<HTML>
<HEAD><TITLE>Page 2</TITLE></HEAD>
<BODY>
<B>Page 2 - <?php echo $actuel; ?></B><BR>
<?php echo $message; ?><BR>
<!-- lien vers les autres pages -->
<A HREF="<?php echo url("page1.php"); ?>">Page 1</A>
</BODY>
</HTML>

Rsultat

- Premier appel de l'URL http://.../page1.php :

- Rsultat du clic sur le lien Page 2 :

- Rsultat du clic sur le lien Page 1 :

- Rsultat du clic sur le bouton Prcdente du navigateur :

Le fait que cette page soit mise jour est li la directive de configuration session.cache_limiter qui est
gale nocache sur l'exemple : les pages concernes par la gestion des sessions ne sont pas mises dans le
cachedunavigateuretsontdoncsystmatiquementrafrachies.

Le code commun toutes les pages est bien entendu dfini dans une fonction, appele par les diffrents scripts.

L'utilisation de cette technique peut tre illustre sur une gestion de sessions avec authentification des
utilisateurs.

Exemple

ENI Editions - All rigths reserved - 19 -


- Script login.php pour l'authentification :

<?php
// inclusion du fichier contenant les fonctions gnrales
include("fonctions.inc");
function utilisateur_existe($identifiant,$mot_de_passe) {
// fonction qui vrifie que l'identification saisie est correcte
$requte = sprintf(
"SELECT * FROM utilisateurs WHERE identifiant = '%s'",
vers_base($identifiant));
$erreur = "";
$utilisateur = db_lire_ligne($requte,$erreur);
// l'identification est bonne s'il existe un utilisateur
// ayant l'identifiant saisi (! empty ...) et que le mot
// de passe corresponde ($utilisateur ... == ...)
$existe = ((! empty($utilisateur)) and
($utilisateur["mot_de_passe"] == $mot_de_passe));
return $existe;
}
// traitement du formulaire
if (isset($_POST["connexion"])) {
// rcuprer les informations saisies
$identifiant =
valeur_saisie($_POST["identifiant"]);
$mot_de_passe =
valeur_saisie($_POST["mot_de_passe"]);
// vrifier que l'utilisateur existe
if (utilisateur_existe($identifiant,$mot_de_passe)) {
// l'utilisateur existe ...
// => ouvrir la session au niveau applicatif
// pour cet exemple :
// - ouvrir la session
session_start();
// - enregistrer les donnes de session
$_SESSION["date"] = date("\l\e d/m/Y H:i:s");
$_SESSION["identifiant"] = $identifiant;
// puis rediriger l'utilisateur vers la page1 en
// appelant la fonction gnrique url pour tre
// certain que l'identifiant de session est transmis
// quelles que soient les conditions
header("location: ".url("page1.php"));
exit;
} else {
// l'utilisateur n'existe pas ...
// typiquement, afficher un message et proposer de nouveau
// l'identification
$message = "Identification incorrecte.
Essayez de nouveau.";
// laisser le formulaire s'afficher de nouveau ...
}
}
?>
<HTML>
<HEAD><TITLE>Login</TITLE></HEAD>
<BODY>
<FORM ACTION="login.php" METHOD="POST">
<TABLE BORDER=0>
<TR>
<TD ALIGN="right">Identifiant :</TD>
<TD><INPUT TYPE="text" NAME="identifiant" VALUE=
"<?php echo vers_formulaire($identifiant); ?>"></TD>
</TR>
<TR>
<TD ALIGN="right">Mot de passe :</TD>
<TD><INPUT TYPE="password" NAME="mot_de_passe" VALUE=
"<?php echo vers_formulaire($mot_de_passe); ?>"></TD>
</TR>
<TR>
<TD></TD>
<TD ALIGN="right"><INPUT TYPE="submit" NAME="connexion"
VALUE= "Connexion"></TD>
</TR>
</TABLE>
</FORM>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

- 20 - ENI Editions - All rigths reserved


- Script page1.php pour une page du site :

<?php
// inclusion du fichier qui contient les fonctions gnrales
include("fonctions.inc");
// ouvrir/ractiver la session
session_start();
// tester si la session est nouvelle (i.e. ouverte par
// l'appel session_start ci-dessus) ou ancienne (i.e ouverte
// par un appel antrieur session_start)
// le mieux est de tester si l'une de nos variables de session
// est dj enregistre
if (! isset($_SESSION["identifiant"])) {
// variable " identifiant " pas encore enregistre
// => l'utilisateur n'est pas connect
// => rediriger l'utilisateur vers la page de login
header("location: login.php");
exit;
} else {
// variable " identifiant" dj enregistre
// => l'utilisateur est connect
// => rcuprer les variables de session (uniquement
// celles utilises dans ce script)
// pour cet exemple :
// - date/heure d'ouverture de la session
$date = $_SESSION ["date"];
// - identifiant de l'utilisateur
$identifiant = $_SESSION["identifiant"];
// - rcuprer l'identifiant de la session (pour info)
$session = session_id();
// message
$message = "Session : $session - $identifiant - $date";
}
// dtermination de la date et de l'heure actuelle (pas celle
// de l'ouverture de la session
$actuel = "Nous sommes le ".date("d/m/Y").
" ; il est ".date("H:i:s");
?>
<HTML>
<HEAD><TITLE>Page 1</TITLE></HEAD>
<BODY>
<B>Page 1 - <?php echo $actuel; ?></B><BR>
<?php echo $message; ?><BR>
<!-- lien vers les autres pages
utiliser notre fonction gnrique url() pour tre
certain que l'identifiant de session est transmis
quelles que soient les conditions -->
<A HREF="<?php echo url("page2.php"); ?>">Page 2</A>
</BODY>
</HTML>

Le premier appel de l'URL http://.../page1.php provoque la redirection de l'utilisateur vers la page


d'identification aprs une identification russie, l'utilisateur revient sur la page 1 qui affiche les informations
suivantes :

Page 1 - Nous sommes le 05/05/2004 ; il est 10:18:43


Session : me74227cos2tk96l04t7chdks3 - heurtel - le 05/05/2004 10:18:43
Page 2

Remarquesetconclusion

Lesutilisateursmalinsoumalintentionns

Lepassagedel'identifiantdesessionparl'URLpeutposerdesproblmesdescurit.

Considronslescriptpage.phpsuivant :

<?php
// ouvrir/ractiver la session
session_start();
// afficher l'id de session
echo 'session_id = ',session_id();
?>

ENI Editions - All rigths reserved - 21 -


Si l'URL http://_/page.php?PHPSESSID=abc est appele, et si la directive session.use_only_cookie est
0,nousobtenonslersultatsuivant :

session_id : abc

La valeur donne la variable PHPSESSID dans l'URL a t prise comme identifiant de session. Cela peut
permettreunutilisateur(malinet/oumalintentionn)defairecroirevotreapplicationqu'iladjunesession
ouverte,oud'utiliserunesessionouverteparunautreutilisateur.

Ce phnomne se produit mme si la directive session.use_trans_id est 0, ce qui interdit PHP de


transmettrel'identifiantdesessiondansl'URL,maispasdelerecevoir.

Pourempchercephnomne,ilfautmettreladirectivedeconfiguration session.use_only_cookies1,afin
de forcer l'utilisation d'un cookie pour la transmission de l'identifiant de session. L'inconvnient est que
l'utilisateurpeutrefuserlescookiesetquecettemthoden'est,detoutesfaons,pascompltementscurise
laseulesolutionvraimentsreconsisteutiliseruneconnexionscurise.

Indpendamment de cela, il est relativement simple de se prmunir contre l'emploi d'un faux identifiant de
session,soitenmmorisantctserveurlesidentifiantsdessessionsouvertes,soitentestantl'existenced'une
donnedesessiondans$_SESSION.

<?php
// ouvrir/ractiver la session
session_start();
if (! isset($_SESSION["identifiant"])) {
// si la donne de session "identifiant"
// n'existe pas, c'est que la session n'a
// pas t rellement ouverte par l'application
// faire ce qu'il faut ...
// pour cet exemple :
// - afficher un message
echo "Session non ouverte","<BR>";
// - simuler l'ouverture applicative de la session
$_SESSION["identifiant"] = "123";
} else {
// si la donne de session "identifiant" existe,
// c'est que la session a rellement t ouverte
// par l'application
echo "Session ouverte","<BR>";
echo "identifiant = ",$_SESSION["identifiant"],"<BR>";
}
// afficher l'id de session
echo 'session_id = ',session_id(),'<BR>';
?>

Rsultat:

- Premier appel du type http://.../page.php?PHPSESSID=abc :

Session non ouverte


session_id = abc

- Deuxime appel (sans fermer le navigateur) :

Session ouverte
identifiant = 123
session_id = abc

PHP a conserv l'identifiant de session initial. En cas de besoin, la fonction session_regenerate_id peut tre
appelepourrgnrerunidentifiantdesession.

Exemple:

<?php
// ouvrir/ractiver la session
session_start();
if (! isset($_SESSION["identifiant"])) {
// si la donne de session "identifiant"

- 22 - ENI Editions - All rigths reserved


// n'existe pas, c'est que la session n'a
// pas t rellement ouverte par l'application
// faire ce qu'il faut ...
// pour cet exemple :
// - rgnrer un identifiant de session
session_regenerate_id();
// - afficher un message
echo "Session non ouverte","<BR>";

// - simuler l'ouverture applicative de la session


$_SESSION["identifiant"] = "123";
} else {
// si la donne de session "identifiant" existe,
// c'est que la session a rellement t ouverte
// par l'application
echo "Session ouverte","<BR>";
echo "identifiant = ",$_SESSION["identifiant"],"<BR>";
}
// afficher l'id de session
echo 'session_id = ',session_id(),'<BR>';
?>

Rsultat:

- Premier appel du type http://_/page.php?PHPSESSID=abc :

Session non ouverte


session_id = 69r09ddjnjjo5c5227rp2kls22

- Deuxime appel (sans fermer le navigateur) :

Session ouverte
identifiant = 123
session_id = 69r09ddjnjjo5c5227rp2kls22

Cettetechniquenemetpasl'abridel'utilisationabusive,paruninternaute,d'unidentifiantdesessiond'unautre
internaute.

Rsultat:

- Un premier utilisateur effectue un appel du type http://.../page.php :

Session non ouverte


session_id = ed63nvl9mbtv11muljg826r3q7

- Un deuxime utilisateur russit rcuprer l'identifiant de session du premier utilisateur et effectue un appel du type :
http://_/page.php?PHPSESSID=ed63nvl9mbtv11muljg826r3q7

Session ouverte
identifiant = 123
session_id = ed63nvl9mbtv11muljg826r3q7

Si vous avez besoin d'un haut niveau de scurit, utilisez une connexion scurise.

Conclusion

Moyennantunpeuderigueurdanslecode,lafonctionnalitdegestiondessessionsdePHPestfacilemettre
en uvre et indpendante des techniques de navigation utilises (liens, formulaires). Pour des besoins de
scurit avance, elle peut tre facilement employe dans le cadre d'une connexion scurise dans ce cas, il
s'agitsurtoutd'uneproblmatiquedeconfigurationduserveurwebetiln'yariendeparticulierfaireauniveau
dePHP.

ENI Editions - All rigths reserved - 23 -


Conserverdesinformationsd'unevisite
uneautre

Si vous souhaitez conserver des informations sur un utilisateur d'une visite l'autre (ventuellement trs
loignesdansletemps),ilexistedeuxsolutionsprdominantes :

- dposer un cookie sur son poste (si possible avec son accord pralable) ;

- stocker les informations ct serveur (le plus pratique tant d'utiliser une base de donnes), et associer ces
informations une identification (typiquement un nom et un mot de passe) que l'utilisateur devra saisir chaque
visite.

Une solution intermdiaire, lgante et respectueuse de l'utilisateur, est employe par certains sites cette
solution consiste proposer l'utilisateur de dposer sur son poste un cookie qui ne contient qu'une ou deux
informations permettant la connexion automatique au site (sans saisir de nom et de mot de passe), les
informationscomplmentairestantrcupresdansunebase.

Nousallonsillustrercettesolutionl'aidededeuxpages :

- une page de personnalisation (script personnaliser.php) qui permet l'utilisateur d'activer ou de dsactiver la
connexion automatique ;

- une page d'identification (script login.php) qui, selon le cas, effectue la connexion automatique ou demande
l'utilisateur de se connecter.

Chaqueconnexiondel'utilisateurestunesession.

Exemple

- Script personnaliser.php :

<?php
// inclusion du fichier contenant les fonctions gnrales
include("fonctions.inc");
// ouvrir/ractiver la session
session_start();
// initialisation des variables
$message = "";
// la session a-t'elle t ouverte au niveau applicatif ?
if (isset($_SESSION["identifiant"])) { // oui
// rcuprer les variables de session
$identifiant = $_SESSION["identifiant"];
$mot_de_passe = $_SESSION["mot_de_passe"];
// le script est-il appel en traitement du formulaire ?
if (isset($_POST["activer"])) { // oui
// activer la connexion automatique
// dposer deux cookies d'une dure de vie de 30 jours
// un pour l'identifiant de l'utilisateur et un pour son mot de passe
$expiration = time()+ (30 * 24 * 3600);
setcookie("identifiant",$identifiant,$expiration);
setcookie("mot_de_passe",$mot_de_passe,$expiration);
// prparer un message
$message = "Connexion automatique active";
} elseif (isset($_POST["dsactiver"])) { // oui
// dsactiver la connexion automatique
// supprimer les deux cookies
setcookie("identifiant");
setcookie("mot_de_passe");
// prparer un message
$message = "Connexion automatique dsactive";
}
} else { // session non ouverte au niveau applicatif
// rdiriger l'utilisateur vers la page de login
header("Location: login.php");
exit;
}
?>

ENI Editions - All rigths reserved - 1-


<HTML>
<HEAD><TITLE>Personnaliser</TITLE></HEAD>
<BODY>
<!-- Formulaire simple avec deux boutons -->
<FORM METHOD="POST">
<INPUT TYPE="submit" NAME="activer" VALUE="Activer la connexion
automatique"><BR>
<INPUT TYPE="submit" NAME="dsactiver" VALUE="Dsactiver la connexion
automatique"><BR>
</FORM>
<!-- Affichage du message ventuel -->
<FONT COLOR="green"><?php echo $message; ?></FONT>
</BODY>
</HTML>

- Script login.php (variante simple de la version prcdente) :

<?php
// inclusion du fichier contenant les fonctions gnrales
include("fonctions.inc");
function utilisateur_existe($identifiant,$mot_de_passe) {
// fonction qui vrifie que l'identification saisie
// est correcte
$requte = sprintf(
"SELECT * FROM utilisateurs WHERE identifiant = '%s'",
vers_base($identifiant));
$erreur = "";
$utilisateur = db_lire_ligne($requte,$erreur);
// l'identification est bonne s'il existe un utilisateur
// ayant l'identifiant saisi (! empty _) et que le mot
// de passe correspond ($utilisateur _ == _)
$existe = ((! empty($utilisateur)) and
($utilisateur["mot_de_passe"] == $mot_de_passe));
return $existe;
}
// initialisation des variables
$message = "";
$identifiant = "";
$mot_de_passe = "";
$action = "";
// le script est-il appel en validation du formulaire
if (isset($_POST["connexion"])) { // oui
// => connexion manuelle
// rcuprer les information saisies
$identifiant =
valeur_saisie($_POST["identifiant"]);
$mot_de_passe =
valeur_saisie($_POST["mot_de_passe"]);

// indiquer l'action effectuer pour la suite


$action = "connexion";
// prparer un message en cas de problme
$message = "Identification incorrecte.
Essayez de nouveau.";
// sinon, existe-t'il un cookie " identifiant " ?
} elseif (isset($_COOKIE["identifiant"])) { // oui
// => connexion automatique
// rcuprer les informations des cookies
$identifiant =
valeur_saisie($_COOKIE["identifiant"]);
$mot_de_passe =
valeur_saisie($_COOKIE["mot_de_passe"]);
// indiquer l'action effectuer pour la suite
$action = "connexion";
// prparer un message en cas de problme
$message = "Identification automatique incorrecte.
Essayez manuellement.";
}
// finalement, que fait-on ?
if ($action == "connexion") { //tenter une connexion
// vrifier que l'utilisateur existe
if (utilisateur_existe($identifiant,$mot_de_passe)) {
// l'utilisateur existe _
// => ouvrir la session au niveau applicatif
session_start();
session_regenerate_id(); // au cas ou ...
$_SESSION["identifiant"] = $identifiant;
$_SESSION["mot_de_passe"] = $mot_de_passe;

- 2- ENI Editions - All rigths reserved


// rediriger l'utilisateur vers une autre page du site
// (il n'y en a qu'une !)
header("location: ".url("personnaliser.php"));
exit;
} // utilisateur_existe
}// $action == "connexion"
// si c'est le premier appel, ou si la connexion manuelle
// ou automatique a chou, laisser le formulaire s'afficher
?>
<HTML>
<HEAD><TITLE>Login</TITLE></HEAD>
<BODY>
<FORM ACTION="login.php" METHOD="POST">
<TABLE BORDER=0>
<TR>
<TD ALIGN="right">Identifiant :</TD>
<TD><INPUT TYPE="text" NAME="identifiant" VALUE=
"<?php echo vers_formulaire($identifiant); ?>"></TD>
</TR>
<TR>
<TD ALIGN="right">Mot de passe :</TD>
<TD><INPUT TYPE="password" NAME="mot_de_passe" VALUE=
"<?php echo vers_formulaire($mot_de_passe); ?>"></TD>
</TR>
<TR>
<TD></TD>
<TD ALIGN="right"><INPUT TYPE="submit" NAME="connexion"
VALUE= "Connexion"></TD>
</TR>
</TABLE>
</FORM>
<FONT COLOR="red"><?php echo $message; ?></FONT>
</BODY>
</HTML>

Rsultat

- Premier appel :

- Connexion manuelle errone :

- Aprs une connexion russie :

- Clic sur le bouton Activer :

- Quitter puis revenir sur une des deux pages: arrive directe sur la page de personnalisation (une connexion

ENI Editions - All rigths reserved - 3-


automatique s'est effectue) :

- Clic sur le bouton Dsactiver :

>

- Quitter puis revenir sur une des deux pages: la page d'identification est propose (plus de connexion automatique) :

- Refaire la squence d'activation puis revenir sur l'une des deux pages, aprs avoir supprim le compte de l'utilisateur
(la connexion automatique choue) :

Il est prfrable de stocker le mot de passe de l'utilisateur sous forme crypte ou d'utiliser un identifiant de connexion
automatique associ l'utilisateur. De cette manire, dans les deux cas, le mot de passe de l'utilisateur n'est pas expos aux
regards indiscrets.

- 4- ENI Editions - All rigths reserved


PetitesynthsesurlesvariablesGPCS

Depuis le dbut de cet ouvrage, nous avons rencontr des variables "particulires" : celles associes des
donnes de formulaire, des donnes transmises par une URL, des donnes d'un cookie ou encore, des
donnesdesessions.

CesdiffrentstypesdevariablessontdsignssousletermedevariablesGPCS(Get/Post/Cookie/Session).

Nousavonsvuquecesvariablesfonctionnaientselonlesmmesprincipes :

- Elles sont accessibles directement sous la forme $x, si la directive de configuration register_globals est on.

- Les variables Get/Post/Cookie peuvent aussi tre explicitement importes dans le script grce la fonction
import_request_variables (utile si register_ globals est off).

- Elle sont aussi accessibles par l'intermdiaire de tableaux associatifs $_GET, $_POST, $_COOKIE et $_SESSION. En
complment, le tableau associatif $_REQUEST regroupe le contenu des tableaux $_GET, $_POST et $_COOKIE.

Pourchaquetype,leconseilestlemme :utiliserdeprfrencel'accsparletableauassociatifcorrespondant.
Deuxraisonsjustifientceconseil :

- C'est la seule manire d'tre certain que l'information lue arrive bien par le moyen attendu.

- La directive de configuration register_globals est off par dfaut et passera dfinitivement off dans une
prochaine version de PHP.

Eneffet,quesepassetilsi,danslemmescript,ilexistedesvariablesGPCSportantlemmenom ?

Exemple

- Script page1.php :

<?php
// ouvrir une session et enregistrer une variable de
// session nomme " x " de valeur " SESSION "
session_start();
session_register("x"); // dconseill
$x = "SESSION";
// dposer un cookie nomm " x " de valeur " COOKIE "
setcookie("x","COOKIE");
?>
<!-- Dans le formulaire, mettre une variable nomme " x " de
valeur " GET " dans l'URL de ACTION -->
<FORM ACTION="page2.php?x=GET" METHOD="POST">
<!-- et une zone nomme " x " de valeur " POST " -->

<INPUT TYPE="hidden" NAME="x" VALUE="POST">


<!-- Plus un bouton pour aller sur la page 2 -->
<INPUT TYPE="submit" NAME="OK" VALUE="Page 2">
</FORM>

- Script page2.php :

<?php
// ractiver la session
session_start();
// afficher $x directement
echo '$x = ',isset($x)?$x:'','<BR>';
// afficher les valeurs de " x " partir des tableaux
echo '$_GET["x"] = ',
isset($_GET["x"])?$_GET["x"]:'','<BR>';
echo '$_POST["x"] = ',
isset($_POST["x"])?$_POST["x"]:'','<BR>';
echo '$_COOKIE["x"] = ',

ENI Editions - All rigths reserved - 1-


isset($_COOKIE["x"])?$_COOKIE["x"]:'','<BR>';
echo '$_SESSION["x"] = ',
isset($_SESSION["x"])?$_SESSION["x"]:'','<BR>';
echo '$_REQUEST["x"] = ',
isset($_REQUEST["x"])?$_REQUEST["x"]:'','<BR>';
?>

Rsultat de l'affichage de la page 1 et du clic sur le bouton Page 2

- Si la directive register_globals est on :

$x = SESSION
$_GET["x"] = GET
$_POST["x"] = POST
$_COOKIE["x"] = COOKIE
$_SESSION["x"] = SESSION
$_REQUEST["x"] = COOKIE

- Si la directive register_globals est off :

$x =
$_GET["x"] = GET
$_POST["x"] = POST
$_COOKIE["x"] = COOKIE
$_SESSION["x"] =
$_REQUEST["x"] = COOKIE

Cetexemplepermettroisconstatations :

- Les valeurs des diffrentes variables x sont bien accessibles simultanment, sans ambigut dans leur tableau
respectif. La seule exception concerne la donne de session enregistre avec session_register lorsque
register_globals est off: dans ce cas, nous avons dj vu que session_register ne faisait rien. Si la
donne avait t enregistre sous la forme $_SESSION["x"] = "SESSION", le problme ne se produirait pas et la
donne serait prsente l'arrive dans $_SESSION.

- La variable $x n'est pas forcment initialise et, lorsqu'elle l'est, elle est gale la valeur de la variable de session.
Mais estce toujours le cas?

- Le tableau $_REQUEST contient uniquement la valeur COOKIE. Mais estce toujours le cas?

Si nous refaisons la manipulation sans la variable de session, nous obtenons le rsultat suivant (si
register_globalseston) :

$x = COOKIE
$_GET["x"] = GET
$_POST["x"] = POST
$_COOKIE["x"] = COOKIE
$_SESSION["x"] =
$_REQUEST["x"] = COOKIE

Cette fois, c'est la valeur du cookie qui est prise en compte. Si nous enlevons le cookie, le rsultat est le
suivant :

$x = POST
$_GET["x"] = GET
$_POST["x"] = POST
$_COOKIE["x"] =
$_SESSION["x"] =
$_REQUEST["x"] = POST

Ici, c'est la valeur de la zone formulaire (POST) qui est prise en compte. Si nous enlevons cette dernire, le
rsultatestlesuivant :

$x = GET
$_GET["x"] = GET
$_POST["x"] =
$_COOKIE["x"] =

- 2- ENI Editions - All rigths reserved


$_SESSION["x"] =
$_REQUEST["x"] = GET

Ilneresteplusquelavaleurtransmiseparl'URL.

Ceuxquilesouhaitentpeuventraliserletest,lersultatobtenun'estpasliunquelconqueordred'apparition
desinformations,nidanslapage1nidanslapage2.

Enfait,encasdeconflit,letypedevariablequialaprioritetquicraselesautresestdfiniparladirectivede
configuration variables_order. Cette directive est une chane compose des caractres G, P, C et S,
correspondant aux types dj voqus, et d'un cinquime caractre, E, correspondant aux variables
d'environnement.

Les variables d'environnement correspondent aux variables d'environnement du systme d'exploitation qui sont
rendues disponibles dans l'environnement PHP, soit directement sous la forme $x, soit travers le tableau
associatf$_ENV.

L'ordred'apparitiondeslettresEGPCSdansladirective,correspondunordredeprioritcroissant.

Lersultatobtenuprcdemmentestdlavaleursuivantedeladirective :

variables_order="GPCS"

Lavariable$xestbiend'abordgalelavaleurdelavariabledesession,puiscelleducookie,etc.

Unproblmesimilairepeutseproduirelorsdel'utilisationdelafonction import_request_variables.Lepremier
paramtre de cette fonction indique les types de variables importer, sous la forme d'une combinaison des
lettresG, PetC : PCparexemple.Lesvariablessontimportesdansl'ordreindiquetcrasentlesvariablesde
mmenomprcdemmentimportes.Dansnotreexemple,lesvariables COOKIEcraserontlesvariablesPOST de
mme nom pralablement importes. Pour viter ce genre de problme, il est possible d'appeler plusieurs fois la
fonction,enindiquantchaquefoisunprfixediffrentpourlenomdelavariable(deuximeparamtre).

Ce n'est pas une bonne habitude de programmation d'utiliser le mme nom pour plusieurs informations ; un dveloppeur sens
ne sera pas confront ce problme.
Cette situation carte, il faut avoir conscience qu'un utilisateur (malin et/ou mal intentionn) peut assez facilement fournir une
valeur, par un moyen donn (GPC en l'occurrence), une variable dont vous pensez contrler l'origine.
crire du code dont le fonctionnement est li une certaine valeur de la directive variables_order n'est sans doute pas,
non plus, une bonne ide du point de vue de la portabilit et de la maintenabilit.

Leconseilavis,donnparl'quipededveloppementdePHP,estdonclesuivant :

Rcuprez les valeurs "EGPCS" par les tableaux associatifs pour viter tout problme.

C'estpourcelaqueladirectiveregister_globals est offpardfaut,etqu'elleseraforcedfinitivement


offdansuneprochaineversiondePHP.

ENI Editions - All rigths reserved - 3-


Vued'ensemble

Un site interactif a souvent besoin d'envoyer des messages lectroniques aux utilisateurs, par exemple pour
confirmerunachat,uneinscriptionouenvoyerunelettred'information.

La fonction mail, propose par PHP, permet de rpondre simplement ce genre de besoin. Cette fonction est
dtaille dans ce chapitre, d'abord, pour envoyer des messages textes (sans pice jointe), puis pour envoyer
desmessagesauformatMIME(MultipurposeInternetMailExtensions).

En complment, PHP propose une bibliothque puissante, mais plus complexe d'utilisation, pour grer des
messages selon le protocole IMAP (Internet Message Access Protocol). Cette bibliothque ne sera pas aborde
danscetteouvragecarellen'estpasindispensablepourrpondreaubesoinvoquprcdemment.

ENI Editions - All rigths reserved - 1-


Envoyerunmessagetextesanspicejointe

Lafonctionmailpermetd'envoyerunmessagelectronique.

Syntaxe

booleen mail(chane destinataire, chane objet, chane message


[, chane entte])

destinataire

Adresse email du destinataire. Des destinataires multiples peuvent tre indiqus en les sparant par des
virgules.

objet

Objetdumessage.

message

Textedumessage.

entte

Enttessupplmentaires.

La fonction mail envoie le message caractris par les diffrents paramtres un serveur de messagerie dfini
parlesdirectivesdeconfigurationsuivantes :

Win32 SMTP Adresse du serveur SMTP (Simple Mail Transfer


Protocol) auquel envoyer le message :
smtp.wanadoo.fr
sendmail_from Adresse e-mail de l'metteur. Exemple :
webmaster@monsite.com
Cette directive doit tre prsente, mme vide.
Unix sendmail_path Chemin d'accs vers l'excutable du serveur de
messagerie (peut comprendre des paramtres).
Exemple : sendmail -t -i

LafonctionmailretourneTRUEsilemessageaputreenvoyauserveur(cequinegarantitpasquecedernier
apul'envoyeravecsuccs)et FALSEdanslecascontraire.Iln'yaaucunmoyendesavoirsilemessageat
envoyavecsuccs cettevrificationdoittreraliseendehorsdePHP.

Le quatrime paramtre permet de spcifier des informations supplmentaires qui sont envoyes dans l'entte
dumessage desinformationsmultiplesdoiventtresparesparlasquence\r\n.

La squence utiliser comme sparateur d'en-tte est souvent source de problme (et de dbat dans les forums de
discussion). Trs souvent, la squence \n seule fonctionne ; parfois, la squence \r\n ne fonctionne pas.

Exemple de message simple

<?php
// destinataire
$destinataire = "contact@olivier-heurtel.fr";
// objet
$objet = "Inscription monSite.com";
// message
$message =
"Monsieur Heurtel,
Nous vous remercions pour votre inscription sur note site monSite.com.
Nous esprons que ce site rpondra vos attentes.
Le webmaster.";

ENI Editions - All rigths reserved - 1-


// envoi
$ok = mail($destinataire,$objet,$message);
?>

Cet exemple montre que le message peut tre directement crit sur plusieurs lignes il est aussi possible de le
construireparconcatnation.

Exemple de message plus complexe

<?php
// deux destinataires spars par une virgule
$destinataires = "olivier@diane.com,xavier@zeus.fr";
// objet
$objet = "Rservation d'un court de squash";
// message
$message .= "";
$message .= "Olivier, Xavier,\r\n";
$message .= "Nous vous confirmons votre rservation pour\r\n";
$message .= "un court de squash le lundi 10 septembre de\r\n";
$message .= "18h30 19h30.\r\n\r\n";
$message .= "Le CSM.\r\n";
// en-ttes supplmentaires
$enttes .= "";
$enttes .= "From: \"Rservation CSM\" <resa@csm.fr>\r\n";
$enttes .= "Reply-To: \"Rservation CSM\" <resa@csm.fr>\r\n";
$enttes .= "X-Priority: 1\r\n";
// envoi
$ok = mail($destinataires,$objet,$message,$enttes);
?>

Lesenttessupplmentairessontspcifissouslaformemot_cl: valeur.

Lesentteslespluscourantssontlessuivants :

From: Origine du message sous la forme ["nom en clair"]


<adresse e-mail>. Exemples :
"Olivier HEURTEL" <contact@olivier-heurtel.fr>
<contact@olivier-heurtel.fr>
To: Destinataire(s) (mme format que l'en-tte From).
Reply-To: Adresse de rponse (mme format que l'en-tte From).
X-Priority: Priorit du message.
1 = priorit la plus haute
2 = priorit haute
3 = priorit normale
4 = priorit basse

Dans le paramtre destinataire, il n'est pas possible de spcifier une adresse sous la forme ["nom en clair"]
<adresse e-mail>. Par contre, il est possible d'indiquer des adresses sous cette forme en les envoyant dans l'en-tte To:,
en doublon du paramtre destinataire.

- 2- ENI Editions - All rigths reserved


EnvoyerunmessageauformatMIME

Prambule

Danscettepartie,nousallonstudiercommentenvoyerdesmessagesauformatMIMEouplusgnralementau
formatMultipartMIME.

LeformatMIMEpermetd'envoyerunmessageayantunautreformatquedutexte :formatHTML,image...

Le format Multipart MIME permet d'envoyer un message compos de plusieurs parties ayant chacune un format
diffrent(dutexteplusuneimage,parexemple),unedes"parties"pouvanttreunepicejointe.

L'objectif de ce point, sans rentrer dans le dtail du format MIME (les amateurs peuvent se pencher sur les
nombreuses RFC qui traitent du sujet), est de montrer concrtement comment procder sur deux cas typiques,
l'envoid'unmessageauformatHTMLetl'envoid'unmessageavecunepicejointe.

MessageauformatHTML

Lecasdel'envoid'unmessageauformatHTMLpermetd'illustrerl'utilisationduformatMIMEsimple.

Exemple(sourced'unmessageMIMEauformatHTML):

From: "Olivier" <olivier@diane.com>


To: "Xavier" <xavier@zeus.fr>
Subject: Bonjour !
Date: Mon, 10 Sep 2001 09:24:13 -0100
Message-ID: <3b9c6a403d9f000b@hermes.diane.com>
MIME-Version: 1.0
Content-Type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
<HTML>
<HEAD><TITLE>Bonjour !</TITLE></HEAD>
<BODY>
<FONT COLOR="green">Bonjour !</FONT>
</BODY>
</HTML>

Un message MIME simple comprend d'abord les enttes standard d'un message, puis, trois lignes d'enttes
supplmentaires (en gras) indiquant que le message est au format MIME, et enfin, le corps du message
proprementdit.

Lestroislignesd'enttessupplmentairessontlessuivantes :

MIME-Version

IndiquequelemessageestauformatMIMEetprciselaversion.

Content-Type

IndiqueletypeMIMEducontenu.

Content-Transfer-Encoding

Indiqueletyped'encodage.

QuelquestypesMIMEusuels :

text/plain

Textesimple.Lejeudecaractresutilispeuttrespcifiparl'optioncharset(parexempleiso88591).

text/html

ENI Editions - All rigths reserved - 1-


DocumentauformatHTML.Lejeudecaractresutilispeuttrespcifiparl'option charset(parexempleiso
88591).

image/jpeg

ImageauformatJPEG.

application/octet-stream

Donnesbinaires.

Quelquestypesd'encodagesusuels :

7bit

Encodagedutextesur7bits.

8bit

Encodagedutextesur8bits(utiliserpourconserverlescaractresaccentus).

base64

Encodagepourlesdonnesbinaires(voirfonctionbase64_encode).

Classiquement, pour les types MIME text/*, un type d'encodage 7bit ou 8bit est utilis et le corps du
message contient le texte en clair. Il est aussi possible d'employer un encodage base64 et de placer dans le
corpsdumessagedesdonnesencodesenconsquence(voirlafonctionbase64_encodeplusloin).

PourlestypesMIMEcorrespondantdesdonnesbinaires(image,son,documentPDF...),unencodagebase64
est utilis et le corps du message contient les donnes encodes en consquence (voir la fonction
base64_encodeplusloin).

EnvoyerunmessageauformatHTMLaveclafonctionmailestrelativementsimple.
Ilfaut :

- placer les lignes adquates dans l'entte ;

- mettre les donnes HTML dans le corps du message.

Exemple

<?php
// destinataires
$destinataires = "xavier@zeus.fr";
// objet
$objet = "Bonjour !";
// en-ttes supplmentaires
$enttes .= "";
$enttes .= "From: \"Olivier\" <olivier@diane.com>\r\n";
$enttes .= "MIME-Version: 1.0\r\n";
$enttes .= "Content-Type: text/html; charset=iso-8859-1\r\n";
$enttes .= "Content-Transfer-Encoding: 8bit\r\n";
// message (HTML)
$message .= "";
$message .= "<HTML>\r\n";
$message .= "<HEAD><TITLE>Bonjour !</TITLE></HEAD>\r\n";
$message .= "<BODY>\r\n";
$message .= "<FONT COLOR=\"green\">Bonjour !</FONT>\r\n";
$message .= "</BODY>\r\n";
$message .= "</HTML>\r\n";
// envoi
$ok = mail($destinataires,$objet,$message,$enttes);
?>

Sivousutilisezunencodage base64,vouspouvezappelerlafonctionbase64_encodepoureffectuerl'encodage

- 2- ENI Editions - All rigths reserved


desdonnes.

Syntaxe

chane base64_encode(chane donnes)

donnes

Donnesencoder.

Cettefonctionretournelesdonnesencodes.

En complment, pour se conformer aux spcifications, il faut dcouper les donnes encodes en base64 en
morceauxde76octetssparsparunesquence\r\n.

Cetteoprationseraralisetrssimplementgrcelafonctionchunk_split.

Syntaxe

chane chunk_split (chane donnes, entier longueur, chane sparateur)

donnes

Donnesdcouper.

longueur

Longueurdesmorceaux(76pardfaut).

sparateur

Sparateurdesmorceaux(\r\npardfaut).

Lafonctionchunk_splitretournelachanedcoupe.

Exemple

<?php
// message
$message .= "";
$message .= "<HTML>\n";
$message .= "<HEAD><TITLE>Bonjour !</TITLE></HEAD>\n";
$message .= "<BODY>\n";
$message .= "<FONT COLOR=\"green\">Bonjour !</FONT>\n";
$message .= "</BODY>\n";
$message .= "</HTML>\n";
// encodage et dcoupage du message
$message = chunk_split(base64_encode($message));
// affichage du message
echo $message;
?>

Rsultat

PEhUTUw+CjxIRUFEPjxUSVRMRT5Cb25qb3VyICE8L1RJVExFPjwvSEVBRD4KPEJPRFk+CjxGT05U
IENPTE9SPSJncmVlbiI+Qm9uam91ciAhPC9GT05UPgo8L0JPRFk+CjwvSFRNTD4K

Exemple

<?php
// lecture d'une image
$fichier = fopen("logo.gif","r");
$donnes = fread($fichier,filesize("logo.gif"));
fclose($fichier);
// encodage et dcoupage des donnes

ENI Editions - All rigths reserved - 3-


$donnes = chunk_split(base64_encode($donnes));
// affichage des donnes
echo $donnes;
?>

Rsultat

R0lGODlhCgEkAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwMDcwKbK8EAgAGAgAIAgAKAgAMAg
AOAgAABAACBAAEBAAGBAAIBAAKBAAMBAAOBAAABgACBgAEBgAGBgAIBgAKBgAMBgAOBgAACAACCA
AECAAGCAAICAAKCAAMCAAOCAAACgACCgAECgAGCgAICgAKCgAMCgAOCgAADAACDAAEDAAGDAAIDA
...
AAj/AP8JHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmyZUp7
CchJI0BAWjsEC2EeILfNpc+fQIO2I0DO3kB75IgitEezKbmgGw80nap0oFSqNHv+u4q1a82B27wS
MMi16YGtYqWRS3CQqdiu0tC+pQ==

Exemple d'utilisation pour l'envoi d'un message

<?php
// destinataires
$destinataires = "xavier@zeus.fr";
// objet
$objet = "Bonjour !";
// en-ttes supplmentaires
$enttes = "";
$enttes .= "From: \"Olivier\" <olivier@diane.com>\r\n";
$enttes .= "MIME-Version: 1.0\r\n";
$enttes .= "Content-Type: text/html; charset=iso-8859-1\r\n";
$enttes .= "Content-Transfer-Encoding: base64\r\n";
// message
$message = "";
$message .= "<HTML>\n";
$message .= "<HEAD><TITLE>Bonjour !</TITLE></HEAD>\n";
$message .= "<BODY>\n";
$message .= "<FONT COLOR=\"green\">Bonjour !</FONT>\n";
$message .= "</BODY>\n";
$message .= "</HTML>\n";
// encodage et dcoupage
$message = chunk_split(base64_encode($message));
// envoi
$ok = mail($destinataires,$objet,$message,$enttes);
?>

Messageavecpicejointe

Lecasdel'envoid'unmessageavecpicejointepermetd'illustrerl'utilisationduformatMultipartMIME.

Exemple (source d'un message avec pice jointe au format Multipart MIME)

From: "Olivier" <olivier@diane.com>


To: "Xavier" <xavier@zeus.fr>
Subject: Bonjour !
Date: Mon, 10 Sep 2001 09:24:13 -0100
Message-ID: <3b9c6a403d9f000b@hermes.diane.com>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=O=L=I=V=I=E=R="

--=O=L=I=V=I=E=R=
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

Voir la pice jointe.


--=O=L=I=V=I=E=R=
Content-Type: application/octet-stream; name="PJ.DOC"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="PJ.DOC"
0M8R4KGxGuEAAA...
AAAAAAAAAAAAAAAAAAAAAAAAAA==

--=O=L=I=V=I=E=R=--

Un message Multipart MIME contient d'abord les enttes standards d'un message, puis, deux lignes d'enttes
supplmentaires(engras)indiquantquelemessageestauformatMultipartMIME,etenfinlesdiffrentesparties

- 4- ENI Editions - All rigths reserved


dumessage chaquepartiepossdesonpropreentteindiquantsonformat(typeMIMEetencodage).

Dans l'entte du message, nous retrouvons les deux lignes MIME-Version et Content-Type. Pour un message
Multipart MIME, Content-Type est gal multipart/mixed suivi d'une option boundary qui donne la chane
utilisepourmarquerledbutdesdiffrentespartiesdumessage(=O=L=I=V=I=E=R=surnotreexemple).

Chaque partie du message commence par deux signes "moins" suivis de la chane donne par boundary (
=O=L=I=V=I=E=R=,surnotreexemple).

Dansl'enttedechaquepartie,nousretrouvonslesdeuxlignesContent-TypeetContent-Transfer-Encoding
quiprcisentletypeMIMEetl'encodagedelapartie.

Lesdonnesdelapartieviennentensuite.

Lafindumessageestmarquepardeuxsignes"moins",suivisdelachanedonneparboundarysuiviededeux
signes"moins"(--=O=L=I=V=I=E=R=--,surnotreexemple).

La chane donne par boundary doit tre choisie avec soin pour viter d'tre confondue avec des donnes, ce
quiconduiraitunemauvaiseinterprtationdumessage.

Dans l'entte de chaque partie, il est possible d'indiquer une ligne d'entte supplmentaire (Content-
Disposition)quivasuggrerauclientdemessagerieunemaniredeprsenterlesdonnescorrespondantes
l'utilisateur :lesdeuxvaleurspossiblessontinline(lesdonnessontprsentesdirectementdanslemessage)
ou attachment (les donnes sont prsentes en picejointe) dans ce cas, un nom de fichier peut tre
suggrgrcel'optionfilename.

Exemple

Content-Disposition: attachment; filename="PJ.DOC"

Pour envoyer un message Multipart MIME avec la fonction mail, il faut construire les diffrentes parties du
message dans le paramtre message, en respectant la structure indique prcdemment le paramtre entte
de la fonction mail contient les enttes standard, y compris l'entte indiquant qu'il s'agit d'un message au
formatMultipartMIME.

Les diffrentes parties du message doivent tre spares par une ligne vide (\r\n). Au sein de chaque partie, il en est de
mme entre l'en-tte de la partie et les donnes. Voir la remarque dans le chapitre Envoyer un courrier lectronique - Envoyer un
message texte sans pice jointe au sujet de la squence \r\n.

Exemple d'envoi d'un message avec pice jointe

<?php
// destinataires
$destinataires = "xavier@zeus.fr";
// objet
$objet = "Bonjour !";
// en-ttes supplmentaires
$enttes = "";
// - origine du message
$enttes .= "From: \"Olivier\" <olivier@diane.com>\r\n";
// - message au format Multipart MIME
$enttes .= "MIME-Version: 1.0\r\n";
$enttes .= "Content-Type: multipart/mixed; ";
$enttes .= "boundary=\"=O=L=I=V=I=E=R=\"\r\n";
// message
$message = "";
// - premire partie du message (texte proprement dit)
// - en-tte de la partie
$message .= "--=O=L=I=V=I=E=R=\r\n";
$message .= "Content-Type: text/plain; ";
$message .= "charset=iso-8859-1\r\n ";
$message .= "Content-Transfer-Encoding: 8bit\r\n";
$message .= "\r\n"; // ligne vide
// - donnes de la partie
$message .= "Voir la pice jointe.\r\n";
$message .= "\r\n"; // ligne vide
// - deuxime partie du message (pice-jointe)

ENI Editions - All rigths reserved - 5-


// - en-tte de la partie
$message .= "--=O=L=I=V=I=E=R=\r\n";
$message .= "Content-Type: application/octet-stream; ";
$message .= "name=\"PJ.DOC\"\r\n";
$message .= "Content-Transfer-Encoding: base64\r\n";
$message .= "Content-Disposition: attachment; ";
$message .= "filename=\"PJ.DOC\"\r\n";
$message .= "\r\n"; // ligne vide
// - lecture du fichier correspond la pice jointe
$fichier = fopen("pj.doc","rb");
$donnes = fread($fichier,filesize("pj.doc"));
fclose($fichier);
// - encodage et dcoupage des donnes
$donnes = chunk_split(base64_encode($donnes));
// - donnes de la partie (intgration dans le message)
$message .= "$donnes\r\n";
$message .= "\r\n"; // ligne vide
// dlimiteur de fin du message
$message .= "--=O=L=I=V=I=E=R=--\r\n";
// envoi du message
$ok = mail($destinataires,$objet,$message,$enttes);
?>

Plusieurs pices jointes peuvent tre envoyes en rptant, autant de fois que ncessaire, les lignes de code
correspondantes.

En thorie, la totalit du message pourrait tre construite dans l'en-tte (paramtre message gal une chane vide). Dans la
pratique, et en rgle gnrale, cela fonctionne sur plate-forme Linux, mais pas sur plate-forme Windows.

- 6- ENI Editions - All rigths reserved


Manipulerlesfichierssurleserveur

PHPproposeungrandnombredefonctionspermettantdemanipulerlesfichierssurleserveur.
Lesfonctionslesplusutilessontlessuivantes:

Nom Rle
fopen Ouvrir un fichier
fclose Fermer un fichier
fread Lire le contenu d'un fichier (dans une chane)
file Lire le contenu d'un fichier (dans un tableau)
fwrite crire dans un fichier
file_get_contents Ouvrir, lire et fermer un fichier
file_put_contents Ouvrir, crire et fermer dans un fichier
copy Copier un fichier
unlink Supprimer un fichier
rename Renommer un fichier
file_exists Tester l'existence d'un fichier
filesize Lire la taille d'un fichier
chdir Changer de rpertoire courant
opendir Ouvrir un rpertoire
closedir Fermer un rpertoire
readdir Lire le contenu d'un rpertoire

Certaines de ces fonctions vont prendre comme paramtre un nom de fichier ou de rpertoire. Sur une plate
forme Windows, pour spcifier un chemin d'accs dans une chane de caractres dlimite par des guillemets,
vousdevezchapperl'antislash(parunantislash=\\)ouvouspouvezutiliserunenotationtype"Unix",avec
des slashs (/). Par exemple, le chemin c:\temp\info.txt peut tre crit "c:\\temp\\info.txt" ou
"c:/temp/info.txt".Siaucuncheminn'estindiqu,c'estlerpertoirecourantquiestutilis.Desnomsrelatifs
peuvent tre spcifis en utilisant le caractre .(point)pourdsignerlerpertoirecourant,et .. (deux points)
pourdsignerlerpertoiresuprieur.

La constante prdfinie DIRECTORY_SEPARATOR donne le caractre de sparation utilis dans les noms de
rpertoirepourlaplateformesurlaquellePHPestinstall.

Parailleurs,plusieursfonctionspossdentunparamtre(appel utiliser_inclusiondanslessyntaxesdecet
ouvrage) qui permet de rechercher le fichier dans les rpertoires spcifis par la directive de configuration
include_path.

fopen

Lafonctionfopenpermetd'ouvrirunfichier.

Syntaxe

ressource fopen(chane nom_fichier, chane mode


[, entier utiliser_inclusion])

nom_fichier

Chemind'accsaufichierouvrir.

mode

Moded'ouverturedufichier
r=lectureseule

ENI Editions - All rigths reserved - 1-


r+=lecture/criture
w=critureseule(videlefichiers'ilexiste,lecres'iln'existepas)
w+=lecture/criture(videlefichiers'ilexiste,lecres'iln'existepas)
a=critureseule(enajoutcrelefichiers'iln'existepas)
a+=lecture/criture(enajoutcrelefichiers'iln'existepas)
x=critureseuleaveccrationpralabledufichier(gnreuneerreursilefichierexistedj)
x+=lecture/critureaveccrationpralabledufichier(gnreuneerreursilefichierexistedj)
Sous Windows, ajouter un b pour manipuler les fichiers binaires (cette option, si prsente, est ignore sous
Unix)utiliseruntlaplacedubspcifieunmodetexte(lessquences\nsontautomatiquementremplaces
parun\r\n).

utiliser_inclusion

Mettre 1 (ou TRUE) pour rechercher le fichier dans les rpertoires spcifis par la directive de configuration
include_path.

LafonctionfopenretourneunpointeurdefichierencasdesuccsetFALSEencasd'chec.

fclose

Lafonctionfclosepermetdefermerunfichier.

Syntaxe

boolen fclose(ressource fichier)

fichier

Pointeurdefichierpralablementouvert.

LafonctionfcloseretourneTRUEencasdesuccsetFALSEencasd'chec.

fread

Lafonctionfreadpermetdelirelecontenud'unfichier(dansunechane).

Syntaxe

chane fread(ressource fichier, entier longueur)

fichier

Pointeurdefichierpralablementouvert.

longueur

Nombred'octetsliredanslefichier.

LafonctionfreadretournelesdonnesluesouFALSEencasd'chec.

file

Lafonctionfilepermetdelirelecontenud'unfichier(dansuntableau).

Syntaxe

tableau file(chane nom_fichier [, entier utiliser_inclusion])

nom_fichier

Chemind'accsaufichierlire.

- 2- ENI Editions - All rigths reserved


utiliser_inclusion

Mettre1 (ou TRUE) pour rechercher le fichier dans les rpertoires spcifis par la directive de configuration include_path.

La fonction file ouvre le fichier dont le nom est pass en paramtre, et le retourne dans un tableau, chaque
lignedutableaucorrespondantunelignedufichier.LafonctionretourneFALSEencasd'erreur.

fwrite

Lafonctionfwritepermetd'criredansunfichier.

Syntaxe

entier fwrite(ressource fichier, chane donnes[, entier longueur])

fichier

Pointeurdefichierpralablementouvert.

donnes

Donnescriredanslefichier.

longueur

Siprcis,indiquelenombred'octetscrire(toutelachanedonnespardfaut).

Lafonctionfwriteretournelenombred'octetscritsouFALSEencasd'chec.

file_get_contents

Lafonctionfile_get_contentspermetdelirelecontenud'unfichier(dansunechane).

Syntaxe

chane file_get_contents(chane nom_fichier [, entier utiliser_inclusion])

Avec

nom_fichier

Chemind'accsaufichierlire.

utiliser_inclusion

Mettre 1 (ou TRUE) pour rechercher le fichier dans les rpertoires spcifis par la directive de configuration
include_path.

La fonction file_get_contents ouvre le fichier dont le nom est pass en paramtre et le retourne dans une
chane.LafonctionretourneFALSEencasd'erreur.

Utiliser cette fonction se rvle plus performant qu'ouvrir le fichier (fopen), le lire (fread) et le refermer
(fclose).

file_put_contents

La fonction file_put_contents permet d'crire le contenu d'une chane dans un fichier. Cette fonction est
apparueenversion5.

Syntaxe

ENI Editions - All rigths reserved - 3-


entier file_put_contents(chane nom_fichier, chane donnes [, entier mode])

Avec

nom_fichier

Chemind'accsaufichierlire.

donnes

Donnescriredanslefichier.

mode

Constante FILE_USE_INCLUDE_PATH pour crire dans le premier rpertoire spcifi dans la directive de
configurationinclude_path.
ConstanteFILE_APPENDpourajouterlesdonneslafindufichier,s'ilexistedj.
Spcifierlasommedesdeuxconstantespourcombinerlesdeuxoptions.

La fonction file_put_contents ouvre le fichier dont le nom est pass en paramtre, crit le contenu de la
chanepasseenparamtrepuisfermelefichier.

Si le fichier n'existe pas, il est cr. Si le fichier existe, son contenu est remplac, sauf si la constante
FILE_APPENDestspcifieentroisimeparamtre auquelcaslesdonnessontajouteslafindufichier.

Lafonctionretournelenombred'octetscritsdanslefichier,ouFALSEencasd'erreur.

copy

Lafonctioncopypermetdecopierunfichier.

Syntaxe

boolen copy(chane source, chane destination)

source

Emplacementdufichiersource.

destination

Emplacementdufichierdestination.

LafonctioncopyeffectuelacopieetretourneTRUEencasdesuccsetFALSEencasd'chec.

unlink

Lafonctionunlinkpermetdesupprimerunfichier.

Syntaxe

boolen unlink(chane nom_fichier)

nom_fichier

Emplacementdufichiersupprimer.

Lafonctionunlinksupprimelefichier,retourneTRUEencasdesuccsetFALSEencasd'chec.

rename

- 4- ENI Editions - All rigths reserved


Lafonctionrenamepermetderenommerunfichier.

Syntaxe

boolen rename(chane ancien_nom, chane nouveau_nom)

ancien_nom

Emplacementdufichierrenommer.

nouveau_nom

Nouveaunomdufichier.

LafonctionrenamerenommelefichieretretourneTRUEencasdesuccsetFALSEencasd'chec.

file_exists

Lafonctionfile_existspermetdetesterl'existenced'unfichier.

Syntaxe

boolen file_exists(chane nom_fichier)

nom_fichier

Emplacementdufichiertester.

Lafonctionfile_existsretourneTRUEsilefichierexisteetFALSEdanslecascontraire.

filesize

Lafonctionfilesizepermetdelirelatailled'unfichier.

Syntaxe

entier filesize(chane nom_fichier)

nom_fichier

Emplacementdufichier.

LafonctionfilesizeretournelatailledufichierouFALSEencasd'chec.

chdir

Lafonctionchdirpermetdechangerderpertoirecourant.

Syntaxe

boolen chdir(chane chemin)

chemin

Rpertoiresouhait.

LafonctionchdirretourneTRUEencasdesuccsetFALSEencasd'chec.

opendir

Lafonctionopendirpermetd'ouvrirunrpertoire.

ENI Editions - All rigths reserved - 5-


Syntaxe

ressource opendir(chane chemin)

chemin

Rpertoireouvrir.

Lafonctionopendirouvreunrpertoireenvuedelirecequ'ilcontientetretourneunpointeursurledossier,ou
FALSEencasd'chec.

closedir

Lafonctionclosedirpermetdefermerunrpertoire.

Syntaxe

closedir(ressource rpertoire)

rpertoire

Pointeurderpertoirepralablementouvert.

Lafonctionclosedirfermeunpointeurderpertoirepralablementouvert.

readdir

Lafonctionreaddirpermetdelirelecontenud'unrpertoire.

Syntaxe

chane readdir(ressource rpertoire)

rpertoire

Pointeurderpertoirepralablementouvert.

La fonction readdir retourne le nom du fichier suivant dans le rpertoire (sans ordre particulier), ou FALSE s'il
n'yaplusdenomdefichierliredanslerpertoire.

Exemplesd'utilisation

Quelques oprations de base sur les fichiers

<?php
// ouvrir un fichier
$f = fopen("e:/info.txt","w");
// crire dans le fichier
fwrite($f, "Olivier HEURTEL");
// fermer le fichier
fclose($f);
// copier un fichier
copy("e:/info.txt","e:/temp/info.txt");
// supprimer un fichier
unlink("e:/info.txt");
// renommer un fichier
rename("e:/temp/info.txt","e:/temp/auteur.txt");
// ouvrir un fichier
$f = fopen("e:/temp/auteur.txt","r");
// lire dans le fichier
$texte = fread($f, filesize("e:/temp/auteur.txt"));
// fermer le fichier
fclose($f);
// afficher les informations lues
echo $texte;

- 6- ENI Editions - All rigths reserved


?>

Rsultat

Olivier HEURTEL

Affichage du contenu d'un rpertoire

<?php
// ouvrir le rpertoire
$dir = opendir("e:/temp");
// parcourir le rpertoire en lisant le nom d'un fichier chaque itration
while($fichier = readdir($dir)) {
echo "$fichier<BR>";
}
// ferme le rpertoire
closedir($dir);
?>

Rsultat

.
..
lisez-moi.txt
auteur.txt

La fonctionreaddirpermetdercuprerlenomdesfichiersetdesrpertoirescontenusdansunrpertoire.Le
rpertoire courant et le rpertoire suprieur sont aussi retourns avec les symboles . (point) et .. (deux
points).

ENI Editions - All rigths reserved - 7-


magicquotes

Si la directive de configuration magic_quotes_runtime est on, les donnes lues dans les fichiers subiront le
dsormaistraditionnelencodage"magicquotes".

Exemple

<?php
// criture d'une information dans un fichier
$f = fopen("e:/temp/info.txt","w");
fwrite($f, "C'est l't");
fclose($f);
// lecture du contenu du fichier
$f = fopen("e:/temp/info.txt","r");
$texte = fread($f, filesize("e:/temp/info.txt"));
fclose($f);
// affichage des informations lues
echo $texte;
?>

Rsultat si magic_quotes_runtime = off

C'est l't

Rsultat si magic_quotes_runtime = on (et magic_quotes_sybase = off)

C\'est l\'t

Comme nous l'avons vu dans le chapitre sur l'accs aux bases de donnes (Accder aux bases de donnes), il
esttrsfaciledemodifierlavaleurdeladirectivemagic_quotes_runtimeencoursdescriptgrcelafonction
set_magic_quotes_runtime.

Exemple

<?php
// criture d'une information dans un fichier
$f = fopen("e:/temp/info.txt","w");
fwrite($f, "C'est l't");
fclose($f);
// mettre magic_quotes_runtime off (0)
set_magic_quotes_runtime(0);
// lecture du contenu du fichier
$f = fopen("e:/temp/info.txt","r");
$texte = fread($f, filesize("e:/temp/info.txt"));
fclose($f);
// affichage des informations lues
echo $texte;
?>

Rsultat (quelle que soit la valeur de la directive magic_quotes_runtime)

C'est l't

Ilestdonctrsfaciled'crireuncodequisoitindpendantdelaconfigurationetafinquetoutedonneluedans
unfichiersoitencode"magicquotes"ounon.

Encomplment,lafonctionstripslashespeuttreutiliseencasdebesoinpoursupprimerl'encodage.

Les donnes lues dans une base et les donnes lues dans un fichier ont le mme comportement visvis de la
fonctionnalit"magicquotes".

Par ailleurs, il faut remarquer le comportement de la fonction fwrite visvis de la directive


magic_quotes_runtime:si magic_quotes_runtimeestonetsileparamtrelongueurdelafonctionfwrite
n'estpasspcifi,lesantislashssontautomatiquementsupprimsdesdonnescrites.

ENI Editions - All rigths reserved - 1-


Le tableau suivant montre le rsultat de l'criture de la chane "e:\temp\info.txt" dans un fichier selon les
cas :

magic_quotes_runtime

on off

fwrite($f, e:\temp\info.txt e:\temp\info.txt


"e:\\temp\\info.txt", 100)

fwrite($f, e:tempinfo.txt e:\temp\info.txt


"e:\\temp\\info.txt")

Si ce comportement n'est pas dsir, il convient donc de mettre magic_quotes_runtime off (dans le script
oudansladirectivedeconfiguration)oudesystmatiquementappelerfwriteenspcifiantlalongueur.

- 2- ENI Editions - All rigths reserved


Tlchargerunfichierpartirduclient"fileupload"

CertainssitespeuventproposerauxutilisateursdetransfrerdesdocumentsdeleurposteversleserveurWeb :
dposer un CV sur un site (site de recherche d'emploi), mettre une pice jointe dans un message (site de
messagerie)ousimplementstockerledocumentsurleserveur(sitedestockage).

Dans la terminologie anglosaxonne, cette fonctionnalit s'appelle le "file upload" ( opposer au "download" qui
permetdetlchargerundocumentduserveurverssonposte).

Cettefonctionnalit,trssimplemettreenuvreenPHP,prsentedeuxexigences :

- dans un formulaire, proposer une zone permettant l'utilisateur de dsigner l'emplacement du fichier sur son poste ;

- dans le script de traitement du formulaire, rcuprer le fichier envoy par l'utilisateur et en faire quelque chose.

DanslechapitreGestiondesformulaires,nousavonsvoqulapossibilitdemettredansunformulaireunezone
permettantd'indiquerl'emplacementd'unfichiersursonposte(TYPE="file") :

Exemple :

<?php
// inclusion du fichier qui contient les fonctions gnrales
include("fonctions.inc");
// traitement du formulaire
$fichier = "";
if (isset($_POST["fichier"])) {
$fichier = valeur_saisie($_POST["fichier"]);
}
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST">
Fichier : <INPUT TYPE="file" NAME="fichier"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<?php
echo vers_page($fichier);
?>
</BODY>
</HTML>

Rsultat

- Affichage initial :

- Localisation d'un fichier et clic sur le bouton OK :

- Affichage aprs traitement du formulaire :

ENI Editions - All rigths reserved - 1-


Leformulaire,telqu'ilestactuellementconstruit,neprovoquepasletransfertproprementditdufichier seulela
valeursaisiedanslazonedetypefileesttransmise.

Pour provoquer le transfert du fichier, il suffit d'ajouter l'option ENCTYPE="multipart/form-data"danslabalise


<FORM>:

<FORM ACTION="saisie.php" METHOD="POST"


ENCTYPE="multipart/form-data">

Cette technique ne fonctionne qu'avec les formulaires qui utilisent la mthode POST.

Encomplment,ilestpossibled'ajouterunezonecachedansleformulaireafindelimiterlatailledesfichiersqui
peuvent tre envoys vers le serveur. Cette zone cache, obligatoirement situe avant la zone de type file
doits'appelerMAX_FILE_SIZE(optionNAME)etprciserlataillemaximumenoctetsdansl'optionVALUE:

Exemple de zone cache pour limiter la taille des fichiers 10 Ko:

<INPUT TYPE="hidden" NAME="MAX_FILE_SIZE" VALUE="10240">

La valeur prcise dans cette zone ne peut pas tre suprieure la valeur de la directive de configuration
upload_max_filesize (2 Mo par dfaut). Si la zone cache n'est pas prsente, c'est la taille spcifie dans la
directiveupload_max_filesizequis'applique.

Parailleurs,letlchargementn'estpossiblequesiladirectivedeconfigurationfile_uploadseston.

Exemple de formulaire complet

<FORM ACTION="saisie.php" METHOD="POST"


ENCTYPE="multipart/form-data">
<INPUT TYPE="hidden" NAME="MAX_FILE_SIZE" VALUE="10240">
Fichier : <INPUT TYPE="file" NAME="fichier"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>

Lorsqu'un fichier est envoy avec un formulaire, des informations sur ce fichier sont accessibles, dans le script
PHP,grcelavariable$_FILES etlavaleursaisieparl'utilisateurn'estplusdisponibledans$_POST.

$_FILESestuntableauassociatifmultidimensionnel lapremireclestgaleaunomdelazonedetype file


duformulaire(fichiersurnotreexemple)etletableauassociatifcorrespondantprsentecinqlignes :

Cl Valeur

name Nom du fichier (sans chemin d'accs)


type Type MIME du fichier (fourni par le navigateur)
size Taille du fichier en octets
tmp_name Nom du fichier temporaire cr sur le serveur (chemin complet)
error Code d'erreur. Une des constantes suivantes :
UPLOAD_ERR_OK (0) : pas d'erreur
UPLOAD_ERR_INI_SIZE (1) : taille du fichier suprieure la
taille dfinie par la directive de configuration
upload_max_filesize
UPLOAD_ERR_FORM_SIZE (2) : taille du fichier suprieure la
taille dfinie par l'option MAX_FILE_SIZE du formulaire
UPLOAD_ERR_PARTIAL (3) : le fichier a t charg

- 2- ENI Editions - All rigths reserved


partiellement
UPLOAD_ERR_NO_FILE (4) : aucun fichier saisi
5 (pas de nom de constante) : erreur dans le fichier saisi (nom,
chemin)

Sur le serveur, le fichier transfr est un fichier temporaire portant un nom du type php*.tmp, situ dans le
rpertoiredfiniparladirectivedeconfigurationupload_tmp_dir.

La structure de $_FILES permet d'avoir plusieurs zones de type file dans le formulaire et donc d'autoriser le
chargementdeplusieursfichiers.

Exemple (le formulaire contient deux zones de type file nommes fichier1 et fichier2 :

fichier1 name Photo.gif


type image/gif
tmp_name d:\temp\phpB.tmp
size 2376
fichier2 name cv.pdf
type application/pdf
tmp_name d:\temp\php12.tmp
size 52147

Silefichiertemporairecrsurleserveurn'estpasexploit(renomm/copi/dplac)parlescriptPHPquitraite
leformulaire,ilestsupprimautomatiquementlafinduscript.DanslescriptPHP,ilconvientdoncdemanipuler
lefichiertemporaireselonlesbesoinsdel'application.

Exemple complet

<?php
// inclusion du fichier qui contient les fonctions gnrales
include("fonctions.inc");
// initialisation de la variable de message
$message = "";
// traitement du formulaire
if (isset($_POST["OK"])) {
// rcuprer les informations sur le fichier
$informations = $_FILES["fichier"];
// en extraire
// - son nom
$nom = valeur_saisie($informations["name"]);
// - son type MIME
$type_mime = $informations["type"];
// - sa taille
$taille = $informations["size"];
// - l'emplacement du fichier temporaire
$fichier_temporaire = $informations["tmp_name"];
// - le code d'erreur
$code_erreur = $informations["error"];
// contrles et traitement
switch ($code_erreur) {
case UPLOAD_ERR_OK :
// fichier bien reu
// dterminer sa destination finale
$destination = "e:/temp/$nom";
// copier le fichier temporaire (tester le rsultat)
if (copy($fichier_temporaire,$destination)) {
// copie OK => mettre un message de confirmation
$message = "Transfert termin - Fichier = $nom ";
$message .= "Taille = $taille octets ";
$message .= "Type MIME = $type_mime.";
} else {
// problme de copie => mettre un message d'erreur
$message = "Problme de copie sur le serveur.";
}
break;
case UPLOAD_ERR_NO_FILE :
// pas de fichier saisi

ENI Editions - All rigths reserved - 3-


$message = "Pas de fichier saisi.";
break;
case UPLOAD_ERR_INI_SIZE :
// taille fichier > upload_max_filesize
$message = "Fichier '$nom' non transfr ";
$message .= " (taille > upload_max_filesize).";
break;
case UPLOAD_ERR_FORM_SIZE :
// taille fichier > MAX_FILE_SIZE
$message = "Fichier '$nom' non transfr ";
$message .= " (taille > MAX_FILE_SIZE).";
break;
case UPLOAD_ERR_PARTIAL :
// fichier partiellement transfr
$message = "Fichier '$nom' non transfr ";
$message .= " (problme lors du tranfert).";
break;
case 5 :
// fichier partiellement transfr
$message = "Fichier '$nom' non transfr ";
$message .= " (non trouv).";
break;
default :
// erreur non prvue !
$message = "Fichier non transfr ";
$message .= " (erreur inconnue : $code_erreur ).";
}
}
?>
<HTML>
<HEAD><TITLE>Saisie</TITLE></HEAD>
<BODY>
<FORM ACTION="saisie.php" METHOD="POST"
ENCTYPE="multipart/form-data">
<INPUT TYPE="hidden" NAME="MAX_FILE_SIZE" VALUE="10240">
Fichier : <INPUT TYPE="file" NAME="fichier"><BR>
<INPUT TYPE="submit" NAME="OK" VALUE="OK">
</FORM>
<?php
echo vers_page($message);
?>
</BODY>
</HTML>

- 4- ENI Editions - All rigths reserved


Tlchargerunfichierpartirduserveur:"download"

Pourtlchargerunfichierpartirduserveur,ilestpossibled'utiliserlamthodeclassiquequiconsisteutiliser
unlien(balise<A>).

Exemple

<A HREF="cv.pdf">Tlcharger</A>

Cettetechniquepeutposerdesproblmes :

- C'est le navigateur qui dcide de proposer l'utilisateur un dialogue d'enregistrement ou d'afficher directement le
document s'il sait comment faire.

- Les fichiers qui sont interprts par le serveur (.php par exemple) ou par le navigateur (.htm par exemple) ne
peuvent pas tre chargs de cette manire.

Une autre technique est utilisable, si vous souhaitez forcer le navigateur proposer l'utilisateur un dialogue
d'enregistrement,etce,pourn'importequeltypededocument.

Cette technique consiste envoyer certains enttes particuliers l'aide de la fonction header, suivie du
documentproprementdit.

Il n'est pas garanti que la technique dcrite prcdemment fonctionne correctement, ou de la mme manire, avec tous les
navigateurs. En effet, elle est base sur une fonctionnalit non standard du protocole HTTP qui est implmente par les
navigateurs. C'est aussi la raison pour laquelle, vous trouverez de nombreuses variantes de cette mthode dans les forums de
discussion.

Lesenttesminimumsenvoyersontlessuivants :

Content-Disposition: Cet en-tte suggre au navigateur de traiter le


attachment; filename=... document comme une pice jointe (attachment) et
de proposer l'utilisateur de l'enregistrer sous le
nom dfini par filename.
Content-Type: ... Cet en-tte communique au navigateur le type
MIME du document.

QuelquestypesMIMEcourants :

Type MIME Nature du document

application/msword Document Microsoft Word


application/octetstream Gnrique
application/pdf Document PDF
application/vnd.ms-excel Document Microsoft Excel
application/vnd.ms-powerpoint Document Microsoft PowerPoint
application/zip Document Zip
image/bmp Image au format bitmap
image/gif Image au format GIF
image/jpeg Image au format JPEG
image/tiff Image au format TIFF
image/png Image au format PNG
text/html Document HMTL
text/plain Document texte

ENI Editions - All rigths reserved - 1-


En mettant n'importe quoi comme type MIME (x/y par exemple), le navigateur doit normalement se dbrouiller
avecl'extensiondudocument.

Aprs l'envoi des enttes, il ne reste plus qu' envoyer le document "directement" dans la page, soit par une
lecture(fread)suivied'unecho,soitplussimplementl'aidedelafonctionreadfilequilitunfichieretl'envoie
directementverslasortie.

Syntaxe

entier readfile(chane nom_fichier [, entier utiliser_inclusion])

nom_fichier

Chemind'accsaufichierlire.

utiliser_inclusion

Mettre 1 (ou TRUE) pour rechercher le fichier dans les rpertoires spcifis par la directive de configuration
include_path.

Lafonctionreadfileretournelenombred'octetslusouFALSEencasd'erreur.

Cette technique va tre illustre l'aide d'un script download.php qui propose une liste de documents en
tlchargement.Cescriptgnreunformulairequioffreunboutondetype"image"(TYPE="image")pourchaque
fichierproposentlchargement,lenomduboutontantgalaunumrodudocument.
Comme nous l'avons vu dans le chapitre Constantes, variables, types et tableaux, nous allons rcuprer dans
$_POST deux variables n_x et n_y donnant respectivement la position relative horizontale et verticale du clic
l'intrieurdel'image(ntantlenomdel'imageclique,dansnotrecas,unnumro).

Exemple

<?php
// liste des documents (viendrait sans doute d'une
// base de donns dans une vraie application)
$documents = array("cv.pdf","photo.gif");
// traitement du formulaire si $_POST nom vide
if (! empty($_POST)) {
// rcuprer le numro du document
// - prendre la cl de la premire ligne de
// $_POST (normalement du type n_x,
// n tant le numro du document)
list($numro) = each($_POST);
// - convertir la chane en entier => seul le n reste
$numro = (integer) $numro;
// en dduire le nom du document
$NomFichier = $documents[$numro];
// envoyer l'en-tte d'attachement
$header = "Content-Disposition: attachment; ";
$header .= "filename=$NomFichier\n" ;
header($header);
// envoyer l'en-tte du type MIME (ici, " inconnu ")
header("Content-Type: x/y\n");
// envoyer le document
// - pas d'encodage magic quotes
set_magic_quotes_runtime(0);
// - lire le document
readfile($NomFichier);
}
?>
<HTML>
<HEAD><TITLE>Download</TITLE></HEAD>
<BODY>
<FORM ACTION="download.php" METHOD="POST">
<TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0>
<TR ALIGN="center" BGCOLOR="lemonchiffon">
<TH>Document</TH><TH>Tlcharger</TH>
</TR>
<?php
// un petit bout de code PHP pour gnrer les lignes du

- 2-