Déroulement réel des cours

La « pensée » du samedi 17 août 2019, 14h35m09s :
La paranoïa n'est qu'une façon optimiste de voir la vie.
1 : semaine du lendi 21 janbier 2008
 Cours n°1 (Cumul=2h) : [Voir le CM n°1]
 TD n°1 (Cumul=3h) : [Voir le TD n°1]
2 : semaine du lendi 28 janbier 2008
 Cours n°2 (Cumul=4h) : [Voir le CM n°2]
 TD n°2 (Cumul=6h) : [Voir le TD n°2]
3 : semaine du lendi 4 fébrier 2008
 Cours n°3 (Cumul=6h) : [Voir le CM n°3]
 TD n°3 (Cumul=9h) : [Voir le TD n°3]
4 : semaine du lendi 11 fébrier 2008
 Cours n°4 (Cumul=8h) : [Voir le CM n°4]
 TD n°4 (Cumul=12h) : [Voir le TD n°4]
5 : semaine du lendi 25 fébrier 2008
 Cours n°5 (Cumul=10h) : [Voir le CM n°5]
 TD n°5 (Cumul=15h) : [Voir le TD n°5]
6 : semaine du lendi 3 môrs 2008
 Cours n°6 (Cumul=12h) : [Voir le CM n°6]
 TD n°6 (Cumul=18h) : [Voir le TD n°6]
7 : semaine du lendi 10 môrs 2008
 Cours n°7 (Cumul=14h) : [Voir le CM n°7]
 TD n°7 (Cumul=21h) : [Voir le TD n°7]
8 : semaine du lendi 17 môrs 2008
 Cours n°8 (Cumul=16h) :
Tour d'horizon des notions utiles pour le projet :
  1. Afficher les résultats d'une requête par pages de 20 lignes (ou plus, ou moins...).
    Complément SQL :
    La commande SELECT accepte deux paramètres qui permettent de contrôler le résultat de la requête :
    • LIMIT qui précise le nombre maximal de lignes à afficher ;
    • OFFSET qui précise quelle est la première ligne qui sera affichée.
    Ainsi la requête
    SELECT * FROM t LIMIT 10 OFFSET 4
    affichera 10 lignes de la table t, en commençant par la 5ème (un OFFSET de 0 correspond à la 1ère ligne, un OFFSET de 1 correspond à la 2ème, etc.)
    Exemple :
    1. <?php
    2. // connexion à la base
    3. $db=new PDO('pgsql:host=masterid;dbname=teniraq','****', '****') ;
    4. // pour SAFE MODE
    5. $offset=$_GET["offset"] ;
    6. // nbre de lignes par page
    7. $limit=10 ;
    8. // le nom du prog lui-même
    9. $prg=basename($_SERVER['PHP_SELF']);
    10. // si offset pas valable, retour au départ
    11. if ( ($offset<=0)                     // tentative de débuter avant le début
    12.     ||                                // ou
    13.      (gettype(1*$offset)!="integer")  // valeur non entière pour offset
    14.    )
    15.     $offset=0 ;
    16. // exécution de la requête et récupération des données
    17. $res = $db->query("SELECT numbadge,nom,prenom FROM badges ORDER BY nom,prenom OFFSET $offset LIMIT $limit") ;
    18. $data = $res->fetchAll() ;
    19. // début de liste
    20. echo "<ul>\n" ;
    21. // affichage des données reçues
    22. foreach ($data as $l)
    23.     echo "<li>".$l["nom"]." ".$l["prenom"]." (".$l["numbadge"].")\n" ;
    24. // fin de liste
    25. echo "</ul>\n" ;
    26. // si on est plus loin que le premier, lien vers les précédents
    27. if ($offset>0)
    28.     echo "<a href=\"$prg?offset=".($offset-$limit)."\">prcdt</a>\n" ;
    29. // si on a reçu autant que demandé, on peut supposer qu'il en reste
    30. // donc lien vers les suivants
    31. if ($limit==count($data))
    32.     echo "<a href=\"$prg?offset=".($offset+$limit)."\">svt</a>\n" ;
    33. ?>
  2. Modifications d'un enregistrement : pré-remplir le formulaire, y compris les listes déroulantes.
    Comment modifier les renseignements d'une personne ?
    Le principe est théoriquement très simple : on choisit dans une liste la personne à modifier, et cela nous envoie sur un formulaire qui contient les valeurs à modifier. Mais un problème se pose : il ne faut pas que ce soit une création, mais une vraie modification des valeurs qui existent dans la base.
    Comment les afficher dans le formulaire ?
    En utilisant :
    • l'attribut value des contrôles de type text,
    • l'attribut checked des contrôles de type checkbox ou radio,
    • l'attribut selected d'option dans les contrôles de type select.
  3. Sécurité/surveillance : logger les accès à la base.
    Si vous voulez surveiller les différentes modifications de la base, et éventuellement pouvoir réparer les erreurs, cela peut être une bonne idée de logger toutes les actions faites sur la base : on ajoute une table dans laquelle on enregistre chaque requête exécutée.
    Pour un maximum de surveillance, enregistrer aussi l'identité de l'utilisateur (il est de bon ton de prévenir les utilisateurs dans ce cas) et la date.
    Si la base est fréquemment utilisée en consultation, il n'est peut-être pas utile d'enregistrer les requêtes de type SELECT : on arriverait vite à un incombrement gênant.
  4. La date en PHP.
    La fonction de base est date().
    Mais il existe aussi strftime() pour un affichage suivant les paramètres locaux. (Si ça ne marche pas, exécutez d'abord l'instruction « setlocale(LC_ALL,"fr_FR"); ».
    On peut les utiliser avec mktime() pour contruire une valeur de type date.
    Par exemple :
    • « echo date("F j, Y, g:i a"); » produira « August 17, 2019, 2:35 pm »
    • « echo date("F j, Y, g:i a", mktime(0, 0, 0, 12, 22, 1978)); » produira « December 22, 1978, 12:00 am »
    • « echo strftime("%A %e %B %Y"); » produira « samedi 17 août 2019 »
    • « echo strftime("%A %e %B %Y", mktime(0, 0, 0, 12, 22, 1978)); » produira « vendredi 22 décembre 1978 »
    Il existe beaucoup d'autres fonctions qui parlent d'heure, de date et de temps.
  5. Espionner vos visiteurs : informations sur leur navigateur, informations sur leur origine, les suivre à la trace (cookies).
    Les informations que vous pouvez obtenir sans douleur sur vos visiteurs.
    1. Les informations sur leur navigateur :
      • Le navigateur que vous utilisez : .
      • La version de votre navigateur : .
      • Votre système d'exploitation : .
      • est-ce qu'il accepte les cookies (le vôtre n'accepte pas les cookies) ;
      • est-ce qu'il gère les applets java, javascript, VBscript, les CSS ? (Le vôtre ne gère pas les applets java, ne gère pas javascript, ne gère pas VBscript, ne gère pas les CSS.)
      La fonction à utiliser est get_browser().
      La liste des informations qu'on peut obtenir est la suivante  :
      Remarque :
      La fonction get_browser() nécessite que la directive de configuration browscap dans le fichier php.ini pointe vers le fichier browscap.ini de votre système. Ce fichier contient les caractéristiques des navigateurs, et il doit bien entendu être à jour.
      S'il vous est impossible de vous en assurer, vous pouvez vous rabattre sur la variable $_SERVER['HTTP_USER_AGENT'] qui contient un sous-ensemble de ces informations, mais d'une manière moins lisible. Pour vous on obtient « CCBot/2.0 (https://commoncrawl.org/faq/) ».
    2. Les informations sur l'origine de vos visiteurs :
      • la page d'où ils viennent, par la variable $_SERVER['HTTP_REFERER'] ;
      • l'adresse de la machine de vos visiteurs, avec $_SERVER['REMOTE_ADDR'] pour l'adresse IP (pour vous il s'agit de « 35.172.165.39 »), et avec gethostbyaddr($_SERVER['REMOTE_ADDR']) pour son adresse domainisée (pour vous il s'agit de « ec2-35-172-165-39.compute-1.amazonaws.com »).
        En plus le nom de la machine permet peut-être de deviner votre pays.
    3. Les cookies :
      Les cookies doivent être vus comme des variables qui peuvent être conservées entre deux exécutions de la page. Ils sont enregistrés sur la machine cliente. La seule restriction est qu'ils doivent être enregistrés avant l'envoi de tout texte, donc en début de page.
      La fonction qui s'en charge est setcookie().
      Une utilisation pourrait être par exemple de mettre en tête de ce programme :
      1. <?php
      2.     $compteurdevisites = $_COOKIE['compteurdevisites']+1;
      3.     $dernierevisite = $_COOKIE['dernièrevisite'];
      4.     setcookie("compteurdevisites", "$compteurdevisites");
      5.     setcookie("dernièrevisite", time());
      6. ?>
      et il suffirait d'utiliser dans votre page
      1. <?php
      2.   echo "C'est votre <em>$compteurdevisites</em>° visite";
      3.     if ($dernierevisite != "") {
      4.         echo ", la dernière c'était le <em>"
      5.           .strftime("%A %e %B %Y", $dernierevisite)
      6.           ."</em>, à <em>"
      7.           .strftime("%Hh %Mm %Ss", $dernierevisite)
      8.           ."</em>";
      9. }
      10.     echo ".";
      11. ?>
      pour obtenir cet affichage :
      C'est votre 1° visite.
    4. En tant qu'internaute, ces indiscrétions sont-elles dangereuses ?
      Elles permettent en tout cas pas mal de choses :
      • N'importe quel site marchand peut vous pister ainsi, et garder l'historique de vos connexions. Il lui suffit d'enregistrer un identifiant sur votre machine, et d'enregistrer dans ses bases de données l'historique de vos actions dans ses pages (vos clics, vos déplacements, ce que vous remplissez dans les formulaires, le temps passé sur chaque page que vous visitez, etc.).
      • N'oubliez pas que votre fournisseur d'accès connaît toutes les pages que vous avez consultées par son intermédaire.
      Il y a quand même des bonnes nouvelles dans tout ça :
      • Si vous vous connectez à internet par l'intermédiaire d'un fournisseur d'accès, votre adresse IP (35.172.165.39) change à chaque connexion... Votre machine devient beaucoup moins facilement identifiable, en tout cas sans la complicité de votre fournisseur d'accès (qui, lui, sait toujours à tout moment à quel utilisateur correspond chaque adresse IP).
        Il faut remarquer que c'est de moins en moins vrai avec les connexions par cable ou ADSL.
      • Grâce aux cookies, un site est en effet capable de savoir si vous êtes déjà venu le voir, MAIS :
        • Il ne sait pas réellement qui vous êtes : il sait seulement que vous êtes l'utilisateur n°X ; cela lui permet de savoir ce que vous avez fait d'autre chez lui, en tant qu'utilisateur n°X, mais c'est tout.
          Il n'est pas capable de deviner ce que vous n'avez pas dit : votre nom, votre numéro de carte de crédit, votre numéro de téléphone, l'endroit où vous vivez (bien que l'adresse IP de votre machine lui permette sans doute de deviner votre pays, voir plus haut).
          Attention : si vous donnez ce genre de renseignements (nom, numéro de carte de crédit, numéro de téléphone, endroit où vous vivez) quelque part, ne vous étonnez pas qu'on s'en souvienne...
        • Il suffit de les désactiver, pour que les cookies deviennent inoffensifs (voir ci-dessous).
    5. Comment s'en protéger ?
      • Il est facile de se protéger des cookies. Vous pouvez, au choix :
        • régler votre navigateur pour qu'il refuse les cookies ; cependant certains sites ne vous laissent pas entrer si vous avez désactivé l'option Cookies. Vous allez peut-être avoir envie de laisser les cookies actifs pour visiter ces sites ; si vous êtes vraiment certain que cela en vaut la peine, vous avez peut-être intérêt à regarder les deux points suivants ;
        • régler votre navigateur pour qu'il accepte les cookies, mais qu'il les efface à chaque nouvelle session ;
        • effacer vous-même à la main les cookies ; par exemple dans Firefox, vous allez dans la suite de menus Outils/Effacer mes traces, et vous pouvez effacer les cookies (et d'autres choses).
      • Le reste fait partie de la norme HTML. C'est ce qui concerne l'identification de votre machine, de son système d'exploitation et de son navigateur, des pages qui ont été visitées, de votre provenance. La protection est beaucoup plus difficile.
    6. Plus de lecture : « Madame Irma voit tout sait tout » et la CNIL avec en particulier leurs pages intitulées « Découvrez comment vous êtes pistés sur internet ».
  6. Récursivité.
    Il arrive parfois, surtout quand on manipule certains types de données (par exemple les arbres) qu'une fonction se définisse aisément en utilisant dans sa dénition-même un ou plusieurs appels à la fonction elle-même. On dit alors que la fonction est récursive.
    De telles définitions sont en général très concises et très claires. On s'accorde pour reconnaître que le procédé est très élégant. Bien employé il peut être d'une efficacité difficile à surpasser, c'est-à-dire que les meilleurs programmes non-récursifs et remplissant la même tâche seront à peine plus rapides. Dans ces cas, la version non-récursive paraît bien souvent très peu claire surtout quand on la compare la version récursive.
    Malheureusement, le procédé récursif cache de nombreux pièges. Tout d'abord, il est fréquent qu'en voulant faire une définition récursive on ne définisse rien du tout ! Un autre écueil est l'utilisation injustifiée du procédé récursif là où une construction itérative est mieux adaptée.
    • Un mauvais exemple : factorielle
      On veut construire une fonction qui calcule la factorielle d'un nombre entier (pas trop grand) :
      n! = n × n(n-1) × n(n-2) × 3 × 2 × 1 pour n>0, et 0! = 1
      c'est-à-dire que, pour tout entier n non nul on a :
      n! = n × (n-1)!
      On en arrive donc la fonction :
      1. <?php
      2.   function fact($n) {
      3.      if ($n==0) return 1;
      4.      return ($n*fact($n-1));
      5.   }
      6. ?>
      L'écriture de fact(n-1) est un appel de la fonction qu'on est en train de définir. Autrement dit, si l'on regarde d'un œil trop distrait, on peut croire que pour pouvoir calculer une factorielle, il faut d'abord savoir calculer une factorielle. En fait il est seulement écrit que pour calculer n! il faut d'abord calculer (n-1)!, ce qui est déjà plus compréhensible. Cette manière de programmer est permise si cela a un sens.
    • Danger des fonctions récursives
      Une erreur fréquente consiste à écrire une fonction récursive bien construite mais qui ne fonctionne pour aucune valeur :
      1. <?php
      2.   function factFausse($n) {
      3.      return ($n*factFausse($n-1));
      4.   }
      5. ?>
      Ici la boucle récursive ne peut jamais s'arrêter.
      Dans un cas aussi trivial, l'erreur saute aux yeux, mais la répétition d'un grand nombre d'erreurs de ce type montre qu'en général c'est beaucoup moins évident.
    • Exercices.
      1. Écrire une fonction récursive qui renvoie XN.
      2. Écrire une fonction récursive qui écrit une chaîne (reçue en paramètre) à partir du dernier de ses caractères.
      3. Écrire une fonction récursive qui écrit les chiffres d'un entier un par un, dans n'importe quelle base.
        Remarque : L'entier naturel et la base seront évidemment écrits en base 10. Donner deux versions, une qui les écrit dans le bon ordre, une autre dans l'ordre inverse.
      4. Fonction de Cadiou.
        On donne la fonction de Cadiou définie pour x et y entiers :
        Cadiou(x,y)=1si x=0
        =x × Cadiou(x-1,Cadiou(x,y+1)) sinon

        Écrire le programme correspondant.
        Indication : pour vous permettre de vérifier facilement vos calculs, sachez que Cadiou(4,2) vaut 24 et Cadiou(3,π) vaut 6.
      5. Les Tours de Hanoï.
        À Hanoï, d'après la légende, il existe un monastère où des prêtres manipulent des plateaux empilés sur 3 axes. Le seul déplacement autorisé est celui d'un plateau du sommet d'une pile vers le sommet d'une autre pile, à la condition impérative que le plateau déplacé soit plus petit que celui qui va le recevoir.
        Toujours d'après la légende, quand les prêtres auront réussi à faire passer tous les plateaux de la première la dernière tour ce sera la fin du monde.
        Écrivez un programme (récursif) qui fait passer les plateaux de la première la dernière tour.
    • Solution des exercices.
      1. Puissances
        1. <?php
        2.     function puissance($x,$n) {
        3.        if ($n<=0) return 1;
        4.        return $x*puissance($x,$n-1);
        5.     }
        6.  
        7.     for ($a=0;$a<=4;$a++) {
        8.         for ($b=0;$b<=4;$b++)
        9.             echo "$a<sup>$b</sup>=".puissance($a,$b)." ; ";
        10.         echo "<br />\n";
        11.     }
        12. ?>
      2. Envers.
        1. <?php
        2.     function envers($s) {
        3.        if (strlen($s)==0) return;
        4.        envers(substr($s,1));
        5.        echo substr($s,0,1);
        6.     }
        7.  
        8.     envers ("abcdefg");
        9. ?>
      3. Bases.
        1. <?php
        2.     function baseenvers($n,$b) {
        3.         if ($n<$b) {
        4.           echo $n;
        5.         } else {
        6.           echo $n%$b;
        7.           baseenvers(floor($n/$b),$b);
        8.         }
        9.     }
        10.     function baseendroit($n,$b) {
        11.         if ($n>=$b) {
        12.           baseendroit(floor($n/$b),$b);
        13.           echo $n%$b;
        14.         } else {
        15.           echo $n;
        16.         }
        17.     }
        18.  
        19.     baseendroit (15897,10); echo "<br />";
        20.     baseenvers (15897,10); echo "<br />";
        21.     baseendroit (256,2); echo "<br />";
        22.     baseenvers (256,2); echo "<br />";
        23. ?>
      4. La définition de la fonction de Cadiou est piégée : si on la programme telle qu'elle est écrite, on déclenche des appels récursifs sans fin (car y+1 ne possède pas de critère d'arrêt).
        Par contre elle se programme très facilement quand on se rend compte que le deuxième paramètre (y) ne sert à rien et qu'il ne faut pas calculer les appels récursifs de la fonction. En réalité :

        Cadiou(x,y) = x!

      5. Les Tours de Hanoï.
        1. <?php
        2.     function affichage() {
        3.        global $tours,$max;
        4.        $blanc=str_repeat (" ",$max);
        5.        echo "<pre>";
        6.        for ($t=$max;$t>=0;$t--) {
        7.            for ($i=0;$i<=2;$i++) {
        8.                $largeur=substr($tours[$i],$t,1);
        9.                echo str_repeat (" ",$max-$largeur+2)
        10.                 .str_repeat ("=",$largeur)
        11.                 ."||"
        12.                 .str_repeat ("=",$largeur)
        13.                 .str_repeat (" ",$max-$largeur+2);
        14.            }
        15.            echo "\n";
        16.        }
        17.        echo "</PRE><br />";
        18.     }
        19.     function deplaceUn($depuis,$vers) {
        20.        global $tours;
        21.        $tours[$vers].=substr($tours[$depuis],-1);
        22.        $tours[$depuis]=substr($tours[$depuis],0,-1);
        23.        affichage();
        24.     }
        25.  
        26.     function deplace($nbre,$depuis,$vers,$interm) {
        27.         if ($nbre>=1) {
        28.             deplace($nbre-1,$depuis,$interm,$vers);
        29.             deplaceUn($depuis,$vers);
        30.             deplace($nbre-1,$interm,$vers,$depuis);
        31.         }
        32.     }
        33.  
        34.     $max=5;
        35.     for ($i=1;$i<=$max;$i++) $tours[0]=$i.$tours[0];
        36.     $tours[1]=$tours[2]="";
        37.     affichage();
        38.     deplace(strlen($tours[0]),0,2,1);
        39. ?>
Dernière modification : 25/8/2016
 TD n°8 (Cumul=24h) : [Voir le TD n°8]
9 : semaine du lendi 24 môrs 2008
 Cours n°9 (Cumul=18h) : [Voir le CM n°9]
 TD n°9 (Cumul=27h) : [Voir le TD n°9]
10 : semaine du lendi 31 môrs 2008
 Cours n°10 (Cumul=20h) : [Voir le CM n°10]
 TD n°10 (Cumul=30h) : [Voir le TD n°10]
11 : semaine du lendi 21 averil 2008
 TD n°11 (Cumul=33h) : [Voir le TD n°11]
12 : semaine du lendi 28 averil 2008
 TD n°12 (Cumul=36h) : [Voir le TD n°12]
Dernière modification : 25/8/2016