.
[hacks/simpleWebSlides.git] / unix_prog_web / unix_prog_web_07.xhtml
1 <?xml version="1.0" encoding="utf-8" ?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
4           >
5 <html xmlns="http://www.w3.org/1999/xhtml" >
6   <head>
7     <title>PHP : expressions régulières, fichiers, sessions</title>
8
9     <meta http-equiv="Content-Type"
10           content="text/html; charset=utf-8" />
11     <meta name="copyright"
12           content="Copyright &#169; 2014 Kim Nguyễn" />
13
14     <!-- Load jQuery -->
15     <script src="../jquery-2.0.3.min.js" type="text/javascript" ></script>
16     <script src="../libs/raphael-min.js" type="text/javascript" ></script>
17     <!-- Load the library -->
18     <script src="../simpleWebSlides.js" type="text/javascript" ></script>
19
20     <link rel="stylesheet" href="../simpleWebSlides.css" type="text/css"  media="all" />
21     <!-- Load a custom Theme, the class-element marks this style-sheet
22          a "theme" that can be swtiched dynamicaly -->
23     <link class="sws-theme" rel="stylesheet"  title="U-Psud style"  href="../themes/uPsud.css" type="text/css" />
24
25     <!-- Customize some templates and initialize -->
26
27     <script type="text/javascript">
28       SWS.Config['sws-slide-change'] = SWS.Effects.slideChangeFadeOutIn;
29       SWS.Config['sws-object-deactivate'] =  SWS.Effects.objectDeactivateFadeOut;
30       SWS.Config['sws-object-activate'] = SWS.Effects.objectActivateFadeIn;
31
32       //Ensures that we load SWS at the very end, after MathJax has
33       //been initialized
34
35       $(window).load(SWS.Presentation.init);
36     </script>
37   </head>
38   <body>
39     <a href="unix_prog_web_06.xhtml" class="sws-previous"/>
40     <div class="sws-slide sws-cover sws-option-nofooter">
41       <h1>Programmation Internet</h1>
42       <h1>Cours 7</h1>
43       <a href="mailto:kn@lri.fr">kn@lri.fr</a><br/>
44       <a href="http://www.lri.fr/~kn/">http://www.lri.fr/~kn</a>
45     </div>
46
47     <h1>Manipulation des chaînes et expressions régulières</h1>
48     <div class="sws-slide">
49       <h1>Quelques fonctions utilitaires sur les chaînes</h1>
50       <dl>
51         <dt><tt>explode($delim, $entree)</tt></dt>
52         <dd>Découpe la chaîne <tt>$entre
53 e</tt> suivant la
54         sous-chaîne <tt>$delim</tt> et renvoie les morceaux dans un
55         tableau.</dd>
56         <dt><tt>implode($delim, $tab)</tt></dt>
57         <dd>Réunit les chaînes se trouvant dans le
58         tableau <tt>$tab</tt> en les séparant par la
59         chaîne <tt>$delim</tt>.
60         </dd>
61         <dt><tt>ltrim($entree)</tt></dt>
62         <dd>Retire les caractères blancs en début de chaîne.</dd>
63         <dt><tt>rtrim($entree)</tt></dt>
64         <dd>Retire les caractères blancs en fin de chaîne.</dd>
65         <dt><tt>trim($entree)</tt></dt>
66         <dd>Retire les caractères blancs en début et en fin de
67         chaîne.</dd>
68         <dt><tt>htmlspecialchars($entree)</tt></dt>
69         <dd>convertit les caractères <tt>&amp;</tt>, <tt>&quot;</tt>,
70           <tt>&apos;</tt>, <tt>&lt;</tt> et <tt>&gt;</tt> en
71           <tt>&amp;amp;</tt>, <tt>&amp;quot;</tt>,
72           <tt>&amp;apos;</tt>, <tt>&amp;lt;</tt> et <tt>&amp;gt;</tt>.
73         </dd>
74
75       </dl>
76     </div>
77     <div class="sws-slide">
78       <h1>Expressions régulières : syntaxe</h1>
79       <p>Les expressions régulières de PHP sont au format PCRE (Perl
80       Common Regular Expressions) <tt><em>'/r/'</em></tt>
81       où <tt>r</tt> est une expression de la forme:</p>
82 <code>      <table style="margin:0em 2em">
83     <tr>
84       <td>r ::=</td>    <td>    <it>a</it>    </td>         <td>    (un caractère)</td></tr>
85     <tr><td>    |</td>     <td>    <em>.</em></td>        <td>    (n'importe quel caractère)</td></tr>
86     <tr><td>    |</td><td>    r<sub>1</sub> <em>|</em> r<sub>2</sub></td> <td>    (r<sub>1</sub> ou r<sub>2</sub>)</td></tr>
87     <tr><td>    |</td><td>    r<em>?</em></td><td>    (r répétée au plus 1 fois)</td></tr>
88     <tr><td>    |</td><td>    r<em>*</em></td><td>    (r répétée 0 fois ou plus)</td></tr>
89     <tr><td>    |</td><td>    r<em>+</em></td><td>    (r répétée 1 fois ou plus)</td></tr>
90     <tr><td>    |</td><td>    <em>[</em>c<sub>1</sub> … c<sub>n</sub><em>]</em></td> <td>    (un caractère parmis c<sub>1</sub>, …, c<sub>n</sub>)</td></tr>
91     <tr><td>    |</td><td>    <em>[</em>c<sub>1</sub><em>-</em>c<sub>n</sub><em>]</em></td> <td>    (un caractère parmis c<sub>1</sub>, …, c<sub>n</sub>)</td></tr>
92     <tr><td>    |</td><td>    <em>[^</em>c<sub>1</sub> … c<sub>n</sub><em>]</em></td> <td>    (un caractère sauf c<sub>1</sub>, …, c<sub>n</sub>)</td></tr>
93     <tr><td>    |</td><td>    <em>[^</em>c<sub>1</sub><em>-</em>c<sub>n</sub><em>]</em></td> <td>    (un caractère sauf c<sub>1</sub>, …, c<sub>n</sub>)</td></tr>
94     <tr><td>    |</td>     <td>    <em>^</em></td>        <td>    (début de texte)</td></tr>
95     <tr><td>    |</td>     <td>    <em>$</em></td>        <td>    (fin de texte)</td></tr>
96     <tr><td>    |</td>     <td>    <em>(</em>r<em>)</em></td>        <td>    (r elle même)</td></tr>
97
98 <!--       |    <em>(</em>r<em>)</em>       (r elle même)
99 -->
100 </table>
101 </code>
102     </div>
103 <div class="sws-slide">
104   <h1>Expressions régulières : recherche</h1>
105   <code style="text-align:center"> <em>preg_match</em>($regexp, $chaine)</code>
106   <p>renvoie <em>1</em> si une sous-chaine de <tt>$chaine</tt>
107   correspond à <tt>$regexp</tt>, <em>0</em> si aucune sous-chaine ne correspond
108   et <s><tt>FALSE</tt></s> en cas de problème (attention,
109   utiliser <tt>===</tt> pour tester le résultat).
110 </p>
111 <code style="margin: 0em 2em">&lt;?php
112     $chaine = <u>"ABCDEFABCDEF"</u>;
113     echo preg_match(<em>'/ABC/'</em>, $chaine);       <span class="sws-pause">// affiche 1</span>
114     <span>echo preg_match(<em>'/DEF/'</em>, $chaine);</span>       <span class="sws-pause">// affiche 1</span>
115     <span>echo preg_match(<em>'/^ABC/'</em>, $chaine);</span>      <span class="sws-pause">// affiche 1</span>
116     <span>echo preg_match(<em>'/^DEF/'</em>, $chaine);</span>      <span class="sws-pause">// affiche 0</span>
117     <span>echo preg_match(<em>'/ABC$/'</em>, $chaine);</span>      <span class="sws-pause">// affiche 0</span>
118     <span>echo preg_match(<em>'/DEF$/'</em>, $chaine);</span>      <span class="sws-pause">// affiche 1</span>
119     <span>echo preg_match(<em>'/(ABC...)+/'</em>, $chaine);</span> <span class="sws-pause">// affiche 1</span>
120     <span>echo preg_match(<em>'/[^A-Z]+/'</em>, $chaine);</span>   <span class="sws-pause">// affiche 0</span>
121     <span>echo preg_match(<em>'/[^A-Z]*/'</em>, $chaine);</span>   <span class="sws-pause">// affiche 1 !</span>
122     <span>echo preg_match(<em>'/^[^A-Z]*$/'</em>, $chaine);</span> <span class="sws-pause">// affiche 0</span>
123 ?&gt;</code>
124 </div>
125 <div class="sws-slide">
126   <h1>Expressions régulières : substitution</h1>
127   <code style="text-align:center"> <em>preg_replace</em>($regexp, $motif, $chaine)</code>
128   <p>recherche toutes les sous-chaînes de <tt>$chaine</tt> reconnues
129   par <tt>$regexp</tt> et les remplace par <tt>$motif</tt>. Ce dernier
130   peut contenir <tt>$<em>i</em></tt> pour référencer
131   le <em>i<sup>ème</sup></em> groupe de parenthèses</p>
132   <code style="margin: 0em 2em;background:white;">&lt;?php
133     $chaine = "<em>10</em>-<s>31</s>-<s style='color:blue'>1981</s>";
134     $reg1 = "/<em>(</em>[0-9]+<em>)</em>-<s>(</s>[0-9]+<s>)</s>-<s style='color:blue'>(</s>[0-9]+<s style='color:blue'>)</s>/";
135     echo preg_replace($reg1, "<em>$2</em>/<s>$1</s>/<s style='color:blue'>$3</s>", $chaine);
136     // affiche 31/10/1981
137
138     $reg2 = "/1/";
139     echo preg_replace($reg2, "toto", $chaine);
140     // affiche toto0-3toto-toto98toto
141
142     $reg3 = "/[0-9]([0-9]*)/"
143     echo preg_replace($reg3, "$1", $chaine);
144     // affiche 0-1-981 (* déplie la regexp le plus possible)
145 ?&gt;</code>
146 </div>
147 <div class="sws-slide">
148   <h1>Expressions régulières : séparation</h1>
149   <code style="text-align:center"> <em>preg_split</em>($regexp, $chaine)</code>
150   <p>renvoie un tableau des sous-chaine de <tt>$chaine</tt> séparées
151   par <tt>$motif</tt> (équivalent à <tt>explode</tt> pour
152   des <tt>$regexp</tt> constantes).</p>
153   <code style="margin: 0em 2em;background:white;">&lt;?php
154         $chaine = "Une phrase, c'est plusieurs mots.";
155         print_r (preg_split("/[ ,.']+/", $chaine));
156         //Affiche:
157         //Array ( [0] => Une [1] => phrase [2] => c [3] => est
158         //        [4] => plusieurs [5] => mots [6] => )
159 ?&gt;</code>
160 </div>
161 <div class="sws-slide">
162   <h1>Expressions régulières : recherche exhaustive</h1>
163
164   <code style="text-align:center"> <em>preg_match_all</em>($regexp, $chaine, &amp;$resultat)</code>
165   <p><tt><em>&amp;$resultat</em></tt> est un tableau <em>passé par
166   référence</em>. Après l'appel, <tt>$resultat[0]</tt> contient un
167   tableau avec <em>toutes</em> les sous-chaines reconnues
168   et <tt>$resultat[i]</tt> contient tous les résultats reconnus par le
169   i<sup>ème</sup> groupe de parenthèses. Renvoie le nombre de chaines
170   trouvées (<i>i.e.</i> la longueur de <tt>$resultat[0]</tt>).
171 </p>
172   <code style="margin: 0em 2em;background:white;">&lt;?php
173     $res = array();
174     $chaine = "ABC ACD AEF AB DEF";
175     echo preg_match_all("/A([A-Z]*)/", $chaine, $res);
176     //Affiche 4
177     print_r ($res);
178     /*Affiche
179     Array ( [0] =>
180               Array ( [0] => ABC [1] => ACD [2] => AEF [4] => AB)
181             [1] =>
182               Array ( [0] => BC  [1] => CD  [2] => EF  [4] => B)
183             )
184 */?&gt;</code>
185 </div>
186 <h1>Manipulation de fichiers</h1>
187 <div class="sws-slide">
188   <h1>Envoi d'un fichier au serveur (1/2)</h1>
189   <p>On utilise la méthode <tt><em>post</em></tt> pour les
190   formulaires. Les valeurs sont envoyées dans la requête HTTP (et non
191   pas encodées dans l'URL)</p>
192   <code>
193        &lt;form action="cible.php" <em>method="post"</em>
194              <em>enctype="multipart/form-data"</em>&gt;
195              &lt;input <em>type="file" <s>name="fichier"</s></em> size="20"/&gt;
196              &lt;button type="sumbit"&gt;Uploader le fichier&lt;/button&gt;
197       &lt;/form&gt;
198 </code>
199 <p>Apperçu:</p><form style="margin: 0em 1em" action="" method="post"
200                      enctype="multipart/form-data">
201   <input type="file" name="fichier" size="20"/>
202   <button type="submit">Uploader le fichier</button>
203 </form>
204 <p>Coté serveur, la variable <tt><em>$_FILES</em></tt> est
205   définie.  <tt><em>$_FILES[<s>"fichier"</s>]</em></tt> contient un
206   tableau avec des informations sur le fichier envoyé. Les autres
207   champs (par exemple valeur d'un champ texte) sont stockés dans la
208   variable <tt>$_POST</tt> (au lieu de <tt>$_GET</tt>).
209 </p>
210 </div>
211 <div class="sws-slide">
212   <h1>Envoi d'un fichier au serveur (2/2)</h1>
213   <p>Étant donné un formulaire avec un champ <i>input</i> de
214   type <i>file</i> et de nom <tt>"fichier"</tt> on a accès aux
215   information suivantes:</p>
216   <dl>
217     <dt><tt>$_FILES["fichier"]["error"]</tt></dt> <dd>Code d'erreur
218     (0 si tout c'est bien passé, <tt>></tt> 0 si une erreur s'est produite. Les
219     autres champs ne sont définis que si "error" vaut 0).
220     </dd>
221     <dt><tt>$_FILES["fichier"]["tmp_name"]</tt></dt><dd>Nom du fichier
222     temporaire sur le serveur où a été sauvegardé le contenu du
223     fichier envoyé</dd>
224     <dt><tt>$_FILES["fichier"]["name"]</tt></dt><dd>Nom original du fichier</dd>
225     <dt><tt>$_FILES["fichier"]["size"]</tt></dt><dd>Taille du
226     fichier</dd>
227     <dt><tt>$_FILES["fichier"]["type"]</tt></dt><dd>Le type MIME du fichier</dd>
228   </dl>
229 </div>
230 <div class="sws-slide">
231   <h1>Ouverture d'un fichier</h1>
232 <code style="text-align:center"> <em>fopen</em>($nomfichier, $mode)</code>
233 <p>Ouvre un fichier dont on donne le nom avec un <i>mode</i>
234   particulier. Les modes sont: <em><tt>"r"</tt></em>
235   (lecture), <em><tt>"r+"</tt></em> (lecture/écriture),
236   <em><tt>"w"</tt></em> (écriture),
237   <em><tt>"w+"</tt></em> (lecture/écriture, création si non-existant),
238   <em><tt>"a"</tt></em> (écriture, ajout à la fin si existant),
239   <em><tt>"a+"</tt></em> (lecture/écriture, création si non-existant,
240   ajout à la fin si existant). <em><tt>fopen</tt></em> renvoie un
241   descripteur de fichier que l'on peut utiliser pour manipuler le
242   fichier.
243 </p>.
244 </div>
245 <div class="sws-slide">
246   <h1>Lecture/écriture/fermeture d'un fichier</h1>
247 <code style="text-align:center"> <em>fread</em>($desc, $taille)</code>
248 <p>Lit au maximum <em><tt>$taille</tt></em> caractères dans un fichier
249   dont le descripteur (renvoyé par <tt>fopen</tt>)
250   est <tt>$desc</tt>. La fonction renvoie un chaine d'au
251   plus <tt>$taille</tt> caractères ou <tt>FALSE</tt> en cas d'erreur.
252 </p>
253 <code style="text-align:center"> <em>fwrite</em>($desc, $chaine)</code>
254 <p>Écrit la chaine de caractères à la position courante dans le
255   fichier dont le descripteur est <tt>$desc</tt>. Renvoi le nombre
256   d'octets écrits ou <tt>FALSE</tt> en cas d'erreur.
257 </p>
258 <code style="text-align:center"> <em>fclose</em>($desc)</code>
259 <p>Ferme le fichier dont le descripteur est <tt>$desc</tt>
260 </p>
261 </div>
262 <div class="sws-slide">
263   <h1>Déplacement dans un fichier</h1>
264   <code style="text-align:center"> <em>fseek</em>($desc, $offset, $orig)</code>
265   <p>Déplace le pointeur interne de position du fichier dont le
266   descripteur est <tt>$desc</tt> de <tt>$offset</tt> octets. Le
267   paramètre <tt>$orig</tt> donne l'origine: <tt>SEEK_CUR</tt>
268   (décalage à partir de la position courante), <tt>SEEK_SET</tt>
269   (position absolue dans le fichier), <tt>SEEK_END</tt> (décalage à
270   partir de la fin de fichier).
271 </p>
272 </div>
273 <div class="sws-slide">
274 <h1>Interface simplifiée</h1>
275 <code style="text-align:center"> <em>file_get_contents</em>($nomfichier)</code>
276 <p>Ouvre un fichier dont on donne le nom et renvoie son contenu sous
277   forme d'une chaine de caractères</p>
278 <code style="text-align:center"> <em>file</em>($nomfichier)</code>
279 <p>Renvoie un tableau avec une case par ligne dans le fichier. Chaque
280   entrée contient le "\n" terminal.</p>
281 </div>
282     <h1>En-tête de requêtes HTTP</h1>
283
284     <div class="sws-slide">
285       <h1>Retour sur le protocole HTTP</h1>
286       <ul><li><em>Client : </em>
287 <code>GET <em>/~kn/index.html</em> HTTP/1.1
288 Host: www.lri.fr
289 </code> </li>
290 <li><em>Serveur : </em><br/>
291   <code style="display:inline-block;width:60%;vertical-align:top;">HTTP/1.1 200 OK
292 Server: nginx/1.4.1 (Ubuntu)
293 Date: Sun, 17 Nov 2013 16:44:48 GMT
294 Content-Type: <em>text/html</em>
295 Content-Length: 2038
296 <![CDATA[
297 <html>
298   <head><title>Homepage</title> </head>
299   <body>
300     …
301 ]]>
302   </code>
303 <code style="display:inline-block;
304              black;width:30%;vertical-align:top;">} ← <em>code de retour</em>
305
306
307 } ← <em>type de contenu</em>
308 } ← <em>longueur du contenu</em>
309 <span style="font-size:400%;vertical-align:middle;">}</span> <span>←</span> <em>contenu (2038 octets)</em>
310 </code>
311 </li>
312       </ul>
313     </div>
314
315     <div class="sws-slide">
316       <h1>Retour sur le protocole HTTP (2)</h1>
317       <ul><li><em>Client : </em>
318 <code>GET <em>/~kn/fichier.pdf</em> HTTP/1.1
319 Host: www.lri.fr
320 </code> </li>
321 <li><em>Serveur : </em><br/>
322   <code >HTTP/1.1 200 OK
323 Server: nginx/1.4.1 (Ubuntu)
324 Date: Sun, 17 Nov 2013 16:44:48 GMT
325 Content-Type: <em>application/pdf</em>
326 Content-Length: 103449
327 <![CDATA[
328 %PDF-1.2
329 %
330 8 0 obj
331 <</Length 9 0 R/Filter /FlateDecode>>
332 stream
333 ………
334  ]]>
335   </code>
336
337 </li>
338       </ul>
339     </div>
340 <div class="sws-slide">
341 <h1>Modifier le <em>content-type</em> en PHP</h1>
342 <p>Fichier <tt>notes_csv.php</tt>:</p>
343 <code>  &lt;?php<em>
344     header('Content-type: application/csv');
345     header('Content-Disposition: attachement; filename="notes.csv"');</em>
346     echo "Nom, Note\n";
347     foreach ($NOTES as $nom => $note)
348        echo $nom . ", " . $note . "\n";
349
350   ?&gt;</code>
351 <p class="sws-pause"><b style="color:red">&#9888; Attention!</b></p>
352 <ul>
353   <li>Les appels à la fonction <em><tt>header()</tt></em> doivent se
354   trouver <s>avant</s> le premier <tt>echo()</tt> du code PHP</li>
355   <li>
356     Le code PHP doit générer (avec <tt>echo()</tt>) du contenu
357     compatible avec le type annoncé (et pas du HTML)
358   </li>
359 </ul>
360 </div>
361
362 <div class="sws-slide">
363 <h1>Quelques en-tête utiles</h1>
364 <p>En tête utilisés par le serveur dans ses réponses</p>
365 <dl>
366   <dt><tt>Content-type</tt></dt><dd>type MIME du contenu envoyé par le
367   serveur</dd>
368   <dt><tt>Content-Disposition</tt></dt><dd>permet de mentionner un nom de
369   fichier : <em><tt>attachment; filname="foobar.baz"</tt></em></dd>
370   <dt><tt>Cache-Control</tt></dt><dd>permet de forcer le client à
371   retélécharger la page: <em><tt>no-cache, must-revalidate</tt></em>
372   </dd>
373   <dt><tt>Last-Modified</tt></dt><dd>date de dernière modification du
374   contenu demandé</dd>
375 </dl>
376 <p>En tête utilisés par le client dans ses requêtes</p>
377 <dl>
378   <dt><tt>Range</tt></dt><dd>permet de ne récupérer qu'un intervale
379   d'octets donné dans un fichier: <em><tt>bytes=500-999</tt></em>
380   </dd>
381   …
382 </dl>
383
384 </div>
385 <div class="sws-slide">
386   <h1>Retour sur le protocole HTTP (3)</h1>
387   <p>On rappelle que HTTP est un protocole <em><i>stateless</i></em>
388   (sans état, <i>i.e.</i> le serveur Web ne conserve pas d'information
389   entre les connexions). Quel problème cela pose-t-il ?</p>
390   <ul >
391     <li class="sws-pause">Pas de partage d'information entre plusieur
392     pages</li>
393     <li class="sws-pause">Pas de mécanisme de reprise sur panne
394     </li>
395     <li class="sws-pause">Pas de persistance de l'information</li>
396     <li class="sws-pause">Pas d'authentification (impossible de savoir
397     que deux connexions successives ont été faites par le même
398     client)</li>
399   </ul>
400   <p class="sws-pause">⇒ difficle de réaliser une « application »
401     moderne répartie sur plusieurs pages</p>
402 </div>
403
404 <h1>Cookies</h1>
405 <div class="sws-slide">
406 <h1>Cookies</h1>
407 <p>Un <em><i>cookie</i></em> est un paquet de données envoyé par le
408   serveur, stocké par le client (navigateur Web) et renvoyé au serveur
409   lors d'une nouvelle connexion. Les propriétés d'un cookie sont:
410 </p>
411 <dl>
412   <dt>Son nom</dt><dd>une chaîne de caractères</dd>
413   <dt>Sa valeur</dt><dd>une chaîne de caraceres</dd>
414   <dt>Sa durée de vie</dt><dd>jusqu'à la fin de la « session » ou pour
415   une période donnée</dd>
416   <dt>Son domaine</dt><dd>Le nom du site web émetteur du cookie</dd>
417   <dt>Son chemin</dt><dd>Le sous-répertoire (par rapport à la racine
418   du site) pour lequel le cookie est valide</dd>
419 </dl>
420 <p><b style="color:red">&#9888; Attention!</b> seul le domaine qui a
421   déposé le cookie est capable de le relire</p>
422 </div>
423 <div class="sws-slide">
424 <h1>Cookies en PHP</h1>
425 <p>Créer ou mettre à jour un cookie sur le client:</p>
426 <code style="text-justify:center">
427                      setcookie(<em>$nom</em>, <em>$val</em>, <em>$date</em>);
428 </code>
429 <dl>
430   <dt><tt>$nom</tt></dt><dd>nom du cookie</dd>
431   <dt><tt>$val</tt></dt><dd>valeur du cookie</dd>
432   <dt><tt>$date</tt></dt><dd>date d'expiration en secondes
433   depuis <i>epoch</i> (1<sup>er</sup> janvier 1970 00:00:00)
434   ou <tt>NULL</tt> pour une expiration automatique.</dd>
435 </dl>
436 <p>(on peut récupérer le nombre de secondes depuis <i>epoch</i> avec
437   la fonction <tt>time()</tt>).<br/>
438   Exemple:
439 </p>
440 <code>  setcookie("mon_cookie", "42", time() + 3600 * 24 * 30);</code>
441 </div>
442 <div class="sws-slide">
443 <h1>Petite digression sur «<i>epoch</i>» </h1>
444 <p>Représenter le temps (une date) dans un programme informatique est
445   quelque chose de compliqué. Quels problèmes cela pose-t-il ?
446 </p>
447 <ul>
448   <li class="sws-pause">Fuseaux horaires</li>
449   <li class="sws-pause">Conversion de temps (de fuseau)</li>
450   <li class="sws-pause">Taille des entiers (Bug de l'an 2000, de l'an
451   2038, de l'an 292 277 026 596)</li>
452   <li class="sws-pause">Secondes intercalaires (« <i>leap second</i> »)</li>
453 </ul>
454 <p>Ce n'est pas encore quelque chose de bien maîtrisé !</p>
455 </div>
456 <div class="sws-slide">
457   <h1>Cookies en PHP</h1>
458   <p>On peut récupérer la valeur d'un cookie depuis PHP:
459   </p>
460   <code>                   <em>$_COOKIE["mon_cookie"]</em></code>
461   <p>Un cookie <tt>"foo"</tt> existe (<i>i.e.</i> a été défini
462   auparavant) si une entrée correspondante existe dans le tableau
463   global <em><tt>$_COOKIE</tt></em>. On peut tester qu'une entrée
464   existe dans un tableau avec <em><tt>isset()</tt></em>.
465   </p>
466   <p><b style="color:red">&#9888; Attention!</b> </p>
467   <ul>
468     <li>On ne peut pas écrire dans <em>$_COOKIE</em> (par
469     exemple <tt>$_COOKIE["foo"] = 42</tt>), il faut
470     utiliser <em><tt>setcookie()</tt></em>.
471     </li>
472     <li><em><tt>setcookie()</tt></em>
473     utilise <em><tt>header()</tt></em> et doit donc être appelé avant
474     le premier <em><tt>echo()</tt></em> du fichier.
475     </li>
476     <li>Pour effacer un cookie, on peut lui donner une date
477     d'expiration antérieure à l'instant présent (<tt>0</tt> par exemple)</li>
478   </ul>
479 </div>
480
481 <div class="sws-slide">
482   <h1>Avantages et inconvénients des cookies</h1>
483 <ul style="list-style-type:none;">
484   <li class="sws-pause"><b>+</b> stockage persistant</li>
485   <li class="sws-pause"><b>+</b> interface simple d'utilisation (une
486   variable pour la lecture et <tt>setcookie</tt> pour l'écriture)</li>
487   <li class="sws-pause"><b>-</b> limité en taille </li>
488   <li class="sws-pause"><b>-</b> limité en nombre par domaine</li>
489   <li class="sws-pause"><b>-</b> type de donnée limité à des chaînes
490   (on ne peut pas stocker un tableau PHP par exemple)</li>
491 <li class="sws-pause"><b>+/-</b> stocké sur le client</li>
492 </ul>
493 </div>
494 <h1>Sessions</h1>
495 <div class="sws-slide">
496 <h1>Sessions</h1>
497   <p>Une <em>session HTTP</em> est un ensemble de requêtes/réponses HTTP
498     entre un serveur et un <em>même</em> client.<br/>
499     Exemple d'un sondage en ligne:
500   </p>
501   <ol> <li>Le visiteur arrive sur la page <tt>q1.php</tt> en cliquant sur
502     le lien « commencer le sondage » (<em>Début de session</em>)
503     </li>
504     <li> Sur <tt>q1.php</tt>, l'utilisateur coche des choix dans un formulaire et appuie
505     sur un boutton de soumission qui l'envoie sur <tt>q2.php</tt>
506     </li>
507     <li>…</li>
508     <li> Sur <tt>q10.php</tt>, l'utilisateur coche des choix dans un
509     formulaire et appuie sur un bouton de soumission qui l'envoie
510     sur <tt>resultat.php</tt></li>
511     <li> Sur <tt>resultat.php</tt>, le résultat global du sondage (%
512       par question, nombre de participants jusqu'à présent etc...) est
513       affiché (<em>Fin de session</em>)
514     </li>
515   </ol>
516  
517 </div>
518 <div class="sws-slide">
519   <h1>Variables de session</h1>
520   <p>Pour programmer une application Web, on souhaîte avoir accès à
521   des <em>variables de session</em> c'est à dire des variables qui
522   sont:
523   </p>
524   <ul><li>Globale au serveur, et accessibles depuis plusieurs pages
525   PHP différentes</li>
526     <li>Spécifiques à un « utilisateur » (c'est à dire à une session
527     particulière)
528     </li>
529   </ul>
530   <p>Les variables de sessions sont donc propres à chaque client et
531   persistent le temp de la session (le temps de session est décidé par
532   le serveur)</p>
533 </div>
534 <div class="sws-slide">
535   <h1>Variables de session en PHP</h1>
536   <p>On initie une session avec la fonction:</p>
537   <code>                         <em>session_start();</em> </code>
538   <p>Une fois appelée, la variable <em><tt>$_SESSION</tt></em>
539     contient un tableau que l'on peut utiliser entre plusieurs
540     pages. Les valeurs contenues dans le tableau persistent jusqu'à la
541     fin de la session. Une session se termine:
542   </p>
543   <ul><li>Quand le client se déconnecte</li>
544     <li>Après un certain temps (« votre session a expiré, veuillez
545     vous reconnecter»)</li>
546     <li>Quand le code PHP
547     appelle <em><tt>session_end();</tt></em></li>
548   </ul>
549 <p><b style="color:red">&#9888;
550     Attention!</b> <em><tt>session_start()</tt></em> doit être appelé
551     avant le premier <tt>echo</tt> du fichier.</p>
552 </div>
553 <div class="sws-slide">
554   <h1>Variables de session en PHP (2)</h1>
555 <code style="border:  2pt dashed gray;margin:5pt;">
556   &lt;?php /* Fichier page1.php */
557     <em>session_start();
558     $_SESSION["Valeur"] = 42;</em>
559   ?&gt;
560   <![CDATA[<html>
561     <body>
562       Veuillez cliquer sur le <a href=]]><em>"page2.php"</em><![CDATA[>lien</a>
563     </body>
564   </html>
565 ]]></code>
566 <code style="border:  2pt dashed gray;margin:5pt;">  <![CDATA[<html>
567     <body>
568       La valeur est <?php]]> <em>echo $_SESSION["Valeur"];</em> <![CDATA[?>
569       <!-- affiche 42 -->
570     </body>
571   </html>
572 ]]></code>
573 </div>
574 <div class="sws-slide">
575   <h1>Avantages et inconvénients des session</h1>
576 <ul style="list-style-type:none;">
577   <li class="sws-pause"><b>+</b> Informations stockées sur le serveur</li>
578   <li class="sws-pause"><b>+</b> Pas de limite de taille</li>
579   <li class="sws-pause"><b>+</b> Pas limité à des chaînes de caractères</li>
580   <li class="sws-pause"><b>-</b> Valeurs perdues en fin de session</li>
581   <li class="sws-pause"><b>-</b> <s>Nécessite des cookies</s></li>
582 </ul>
583 </div>
584 <div class="sws-slide">
585   <h1>Sessions PHP: détails d'implantation</h1>
586   <div class="twocol">
587     <div><em>Coté client</em><br/>
588 <br/>
589 <br/>
590 <br/>
591 <br/>
592 <br/>
593 <br/>
594 <br/>
595 <br/>
596 <br/>
597 Connexion à une page PHP (envoie du cookie ("php_ssid", "12345"))
598
599
600     </div>
601     <div><em>Coté serveur (PHP)</em><br/>
602       <tt>session_start();</tt><br/>
603       - génération d'un ID unique "12345"<br/>
604       - dépot d'un cookie "php_ssid", valeur "12345", durée 10 minutes
605       - création dans un tableau global d'une entrée:<br/>
606         <tt>$_GLOBAL["12345"] = Array();</tt><br/>
607         <br/>
608         <tt>$_SESSION = $_GLOBAL[$_COOKIE["php_ssid"]]</tt>
609     </div>
610   </div>
611 </div>
612
613 <div class="sws-slide">
614   <h1>Dans la vraie Vie<sup>TM</sup></h1>
615   <p>Mélange de variables de sessions, cookies et bases de données.<br/>
616     Scénario réaliste: site de commerce en ligne
617   </p>
618   <ul>
619     <li>Login/mot de passe stocké dans
620       une <em style="color:blue;">BD</em> </li>
621     <li>Panier courant stocké dans une <em>variable de
622         session</em></li>
623     <li>Login, date de dernière visite, dernière page visitée stockés
624       dans un <em style="color:orange">en cookie</em></li>
625     </ul>
626   <p class="sws-pause">Pourquoi ?</p>
627   <ul>
628     <li><em style="color:blue;">BD</em>: information persistante,
629       côté serveur (mais la mise à jour, récupération de l'info est
630       coûteuse (en temps))
631     </li>
632     <li><em>Variables de sessions</em> : le panier n'a pas forcément
633       besoin d'être conservé entre deux sessions, mais on ne veut pas
634       que le client puisse fabriquer un panier frauduleux
635     </li>
636     <li><em style="color:orange">Cookie</em> : persistante à faible
637     coût (stocké sur le client), ce n'est pas grave si les
638     informations sont perdues ou corrompues
639     </li>
640   </ul>
641
642   </div>
643   </body>
644
645 </html>