Informatique pour le web

D. Fournier

official logo PHP

Introduction à official logo PHP

  • PHP : PHP Hypertext Preprocessor
  • Langage de script HTML interprété coté serveur
  • Différent de Javascript qui s'exécute coté client

Structure d'un script PHP

  • Délimité par les balises d'échappement <?php et ?>
  • Composé d'instructions terminées par un point-virgule ;
  • Bloc d'instructions délimité par des accolades { }
  • Associé à des commentaires :
    // Commentaires de fin de ligne
       /* Commentaires 
           longs */

Variables PHP

  • En PHP, les variables sont représentées par un signe dollar "$" suivi du nom de la variable. Le nom est sensible à la casse (ie : $x != $X).
  • Un nom de variable valide doit commencer par une lettre ou un souligné (_), suivi de lettres, chiffres ou soulignés (une lettre peut être une des lettres minuscules (a à z) ou majuscules (A à Z), et les caractères ASCII de 127 à 255).
<?php
  $var = 'Jean';
  $Var = 'Paul';
  echo ('$var, $Var'); // affiche 'Jean, Paul'
  $4site = 'pas encore'; // invalide : commence par un nombre
  $_4site = 'pas encore';  // valide : commence par un souligné
  $maïs = 'jaune'; // valide; 'ï' est ASCII 239.
?>

Variables prédéfinies

  • Il en existe trop pour les lister : $SERVER_NAME, $REMOTE_ADDR, ...
  • Pour la liste complète il faut utiliser la fonction phpinfo() :
    <?php
         phpinfo();
    ?>
  • Cette fonction renseigne également sur la configuration du module PHP.

Portée des variables

  • La portée d'une variable dépend du contexte dans lequel la variable est définie. Le plus souvent elle concerne la totalité du script php. Cependant :
    $a = 1; /* portée globale */
    function test() {
       echo $a; /* portée locale */
    }
    test(); /* n'affichera rien car utilise la variable locale $a */
  • Le mot-clé global permet de référencer localement dans un bloc des variables globales :
    $a = 1; /* portée globale */
    function test() {
       global $a;  /* $a référence la variable globale $a */
       echo $a;
    }
    test(); /* affichera 1 car utilise la variable globale $a */

Les constantes

  • Une constante est un identifiant (un nom) qui représente une valeur simple.
  • Elle ne peuvent jamais être modifiée ou détruite durant l'exécution du script.
  • Vous pouvez définir une constante en utilisant la fonction define().
  • Seuls les types de données scalaires peuvent être placés dans une constante : booléen, entier, double et chaîne de caractères.
<?php
  define('CONSTANTE', 'Bonjour le monde.');
  echo CONSTANTE; // affiche 'Bonjour le monde.'
  echo Constante; /* affiche 'Constante' et une note
                     d'exécution (message d'erreur). */
  defined(CONSTANTE); // retourne TRUE
  // pour afficher les constantes déjà définies
  print_r(get_defined_constants());
?>

Types PHP

  • PHP est un langage faiblement typé : le typage est implicite.
    • bool pour les booléens TRUE, FALSE (i.e. 0,'','0')
    • int pour les entiers
    • floatpour les flottants
    • stringpour les chaînes de caractères (entre " ou ')
    • arraypour les tableaux
    • objectpour les objets de classe indeterminée

Les chaînes de caractères

  • PHP accepte les simples quotes (apostrophe : ') et les doubles quotes (guillemet : ") comme délimiteurs de chaînes de caractères
  • Les guillemets permettent l'interpolation de variables : une variable simple est remplacée par sa valeur dans la chaîne :
    $varInt = 42;
    $chaine = "L'âge du capitaine est $varInt ans !"
    La valeur de $$chaine est L'âge du capitaine est 42 ans !
  • Les simples quotes (apostrophes) n'opèrent aucune interprétation du contenu de la chaîne :
    $varInt = 42;
    $chaineBis = 'L\'âge du capitaine est $varInt ans !'
    La valeur de $chaineBis est L'âge du capitaine est $varInt ans !
  • Caractère d'échappement : Le backslash (\)
    N.B. : Dans les chaînes simples (non interpolées) seules \' et \\ sont utilisables ;
    les \n, \t, ... sont à réserver aux chaînes interpolables.
  • L'utilisation des simples quotes est à privilégier dès que possible car elles consomment (un peu) moins de ressources systèmes
  • Attention : l'interpolation de variables ne fonctionne pas avec les tableaux ni avec les appels de fonctions

L'indexation des tableaux

  • PHP met à disposition deux types de tableaux :
    • les tableaux traditionnels indexés automatiquement,
    • les tableaux associatifs indexant les données à l'aide d'une clé de type chaîne de caractères.
  • Exemple :
    <?php
     $tab1 = array(1,2,3,4); // automatique
     $tab2 = array('couleur' => 'rouge',
                   'gout' => 'sucre', // associative
                   'forme' => 'rond',
                   'nom'  => 'pomme');
     echo ($tab1[0]); // affiche 1
     echo ($tab2['gout']); // affiche sucre
     echo ($tab2[0]); // Ne fonctionne pas (plus depuis un certain temps...)
    ?>
  • Contrairement à Java ou C, les tableaux PHP autorisent le stockage de données hétérogènes (de différents types).
  • Ils peuvent être considéré comme des cartes (Map).

Opérateurs arithmétiques

OpérateurOpérationDescription
+AdditionSomme des 2 opérandes
-SoustractionDifférence des 2 opérandes
*MultiplicationProduit des 2 opérandes
/DivisionQuotient des 2 opérandes
%ModuloReste de la division entière

Opérateurs de comparaison

OpérateurNom
==égal
!=différent
<>
<inférieur
<=inférieur ou égal
>supérieur
>=supérieur ou égal
===identique (valeur et type)
!==différent
<=>combiné (spaceship)
  • PHP opère des opérations de transtypages (cast) de façon transparente et pas forcément souhaitée.
  • Exemple :
    $int3 = 3; // variable associée à une valeur de type entier
    $str3 = '3'; // variable associée à une valeur de type string
    echo "<h3>évaluation de l'expression ($int3 == $str3)</h3>";
    if ($int3 == $str3) {
        echo "<p>Le test a réussi car PHP a automatiquement transformé le type
        d'une des deux variables !</p>";
    }
    echo "<h3>évaluation de l'expression ($int3 != $str3)</h3>";
    if ($int3 != $str3) {
        echo "<p>C'est l'effet inverse, le test échoue à cause du transtypage
        automatique réalisé par PHP.</p>";
    }
    else {
        echo "<p>Le test ($int3 != $str3) a échoué !</p>";
    }
    Résultat :
    évaluation de l'expression (\$int3 == \$str3)"; if ($int3 == $str3) { echo "

    Le test a réussi car PHP a automatiquement transformé le type d'une des deux variables !

    "; } echo "

    évaluation de l'expression (\$int3 != \$str3)

    "; if ($int3 != $str3) { echo "

    C'est l'effet inverse, le test échoue à cause du transtypage automatique réalisé par PHP.

    "; } else { echo "

    Le test (\$int3 != \$str3) a échoué !

    "; } ?>
  • Les opérateurs === et !== permettent d'éviter les conversions de types indésirables.
  • Exemple :
    echo "<h3>évaluation de l'expression ($str3 === $int3)</h3>";
    if ($str3 === $int3) {
        echo "<p>Ce test ne réussira pas car les deux valeurs ne sont pas du même type.</p>";
    }
    else {
        echo "<p>Le test ($str3 === $int3) a échoué car les variables comparées
          n'ont pas le même type</p>";
    }
        echo "<h3>évaluation de l'expression ($str3 !== $int3)</h3>";
    if ($str3 !== $int3) {
        echo "<p>Le test réussit, un entier et une chaîne sont différents</p>";
    }
    Résultat :
    évaluation de l'expression (\$str3 === \$int3)"; if ($str3 === $int3) { echo "

    Ce test ne réussira pas les deux valeurs ne sont pas du même type.

    "; } else { echo '

    Le test ($str3 === $int3) a échoué car les variables comparées n\'ont pas le même type

    '; } echo "

    évaluation de l'expression (\$str3 !== \$int3)

    "; if ($str3 !== $int3) { echo "

    Le test réussit, un entier et une chaîne sont différents

    "; } ?>
  • L'opérateur combiné <=> retourne un entier positif, nul ou négatif dont le signe correspond à celui de la différence des deux termes :
    $var = 10<=>2; // $var vaut 1
    $var = 2<=>10; // $var vaut -1
    $var = 2<=>"2"; // $var vaut 0

Opérateurs booléens

OpérateurNom
andet
&&
orou
||
xorou exclusif
!non

Opérateurs incrémentaux

  • Fonctionne aussi sur les caractères et les chaînes!!
OpérateurNom
$a++post-incrémentation
++$apré-incrémentation
$a--post-décrémentation
--$apré-décrémentation

Assignations et Concaténation et ...

OpérateurNom
=Affectation (de droite à gauche)
.Concaténation
+= -= *= /= .=Assignation combinés
@Opérateur de contrôle d'erreur

Lorsque @ est ajouté en préfixe d'une expression PHP, les éventuels messages d'erreurs générés sont ignorés.

Structures de contrôle

  • if/ if .. else / if .. elseif ...
  • while / do .. while
  • for / foreach
  • switch
  • break / continue

Structures de contrôle : if et switch

  • if-then-else :
    <?php
    if ($i == 0) {
      print 'i vaut 0';
    }
    elseif ($i == 1) {
      print 'i vaut 1';
    } elseif ($i == 2) {
        print 'i vaut 2';
      }
      else { 
        print 'i différent';
    }
    ?>
    
  • switch :
    <?php
    switch ($i) {
      case 0: print 'i vaut 0';
              break;
      case 1: print 'i vaut 1';
              break;
      case 2: print 'i vaut 2';
              break;
      default: print 'i différent';
    }
    ?>
    

Structures de contrôle : for

  • La boucle for dans tous ses états !
  • Version classique avec ses trois clauses présentes
    for($i=1;$i<=10;$i++){
       print $i;
    } // fin du for
  • Version sans condition de continuation
    for ($i=1;;$i++) {
       if ($i > 10) { // traitement de la condition d'arrêt
         break;
       } // fin du if
       print $i;
    }
    
  • Version sans aucune clause !
    $i = 1;
    for (;;) {
       if ($i > 10) {break;}
       print $i;
       $i++;
    }
  • Version avec les instructions dans la troisième clause !
    for ($i = 1; $i <= 10; print $i, $i++);
    
  • Le premier usage est sans conteste celui qu'il faut privilégier !

Structures de contrôles : foreach

  • Avec foreach on peut itérer automatiquement sur une tableau (entre autres...)
    $tab=array('a','b','c');
    foreach($tab as $val) {
      echo "valeur:$val\n" ;
      }
  • Résultat :
  • Ce qui simplifie largement le code équivalent suivant :
    for($i=0;$i<sizeof($tab);$i++) {
      echo("valeur:$tab[$i]\n");
        }
  • Avec les tableaux associatifs on peut récupérer les clés et les valeurs qui organisent la structure de données :
    $assoc=array('Entrée' => 'Crudités' ,'Plat' => 'Steack frites' ,
          'Dessert' => 'Tiramisu');
    foreach($assoc as $key => $val) {
      echo "$key : $val\n";
      }
  • Résultat :
     'Crudités' ,'Plat' => 'Steack frites' ,
          'Dessert' => 'Tiramisu');
    foreach($assoc as $key => $val) {
      echo "$key : $val\n";
      } ?>

Structures de contrôles : while et do while

  • while
    $tab=['a','b','c'];
    $i = 0;
    while ($i < sizeof(tab)) {
    	echo $tab[$i]."\n";
        $i++;
    }
  • Affiche :
  • do while
    $i = 0;
    do {
        echo "$tab[$i]\n";
        $i++;
    } while ($i < sizeof($tab))
  • Affiche :

Production de code HTML

Génération de fichiers HTML

FFF : Fonctions, Fichiers et Formulaires

  • Les fonctions
  • Les fichiers
  • Gestion de formulaires en PHP

Les Fonctions en PHP (1)

  • Une fonction peut être définie en utilisant la syntaxe suivante :
    <?php
    function nom_fonction ([[type_1] $param_1, ..., [type_n] $param_n]) [: type] {
    	instruction_1;
    	// ...
    	instruction_m;
    	[return $resultat;]
    }
    ?>
    
  • function : mot clé annonçant la définition d'une fonction,
  • nom_fonction() : nom de la fonction, servira à son appel,
  • type_i : type du paramètre d'entrée numéro i (optionel),
  • : type : le type de retour de la fonction (optionel),
  • return : mot clé permettant d'associer un résultat à la fonction.

Exemples de fonctions

  • Exemples de fonctions sans gestion des types d'entrée/sortie (pas recommandé)
  • Avant PHP7, seule façon de faire.
  • function alea()
    {
    $choix = rand(0,100);
    return $choix;
    }
    
    
    function aleaN($Nombre)
    {
    $choix = rand(0,$Nombre);
    return $choix;
    }
    
  • // Utilisation :
    
    $valalea = alea();
    printf("%d \n",$valalea);
    printf("%d \n",alea());
    $max = 20;
    $valeuralea = aleaN($max);
    printf("%d \n",$valeuralea);
    printf("%d \n",aleaN(50));
    
  • Exemple de trace d'éxécution :
    4
    41
    1
    39
    

Les Fonctions en PHP (2)

  • Depuis PHP7, il est possible de préciser le type des paramètres et le type de retour des fonctions.
  • Les principaux types des paramètres possibles sont : array, bool, int, float, string
  • Associer NULL comme valeur par défaut à un paramètre permet de le rendre facultatif.
  • Les mêmes types (et void depuis PHP 7.1) sont disponibles pour exprimer le type de retour d'une fonction.
  • Le typage systématique des paramètres et des fonctions est vivement recommandé !
  • Exemple :
    // alea retourne un entier
    function alea() : int
    {
        $choix = rand(0,100);
        return $choix;
    }
    
    // aleaN prend un entier entrée et retourne un entier
    function aleaN(int $Nombre) : int
    {
        $choix = rand(0,$Nombre);
        return $choix;
    }
    

Valeurs par défaut

  • Vous pouvez définir, comme en C++, des valeurs par défaut pour les arguments de type scalaire :
<?php
 // À Marseille la fonction servir_apero est définie ainsi :
function servir_apero (string $type = "Pastis"): string {
    return "Servir un verre de $type.\n";
}

echo servir_apero();
echo servir_apero("Jus de fruits");
?>

Fonctions standards

  • PHP met à notre disposition un très grand nombre de fonctions : http://www.php.net/
  • Sur les chaînes de caractères,
  • sur les tableaux, sur les fichiers,
  • ...
  • Utilisez-les!

Fonctions sur les chaînes

DescriptionAction
strlen( string $str): intRetourne la longueur de la chaîne.
explode( string $delimiteur, string $string [, int $limit]): arrayRetourne une tableau de chaînes : chacune d'entre elle est une sous-chaîne de string découpée selon le délimiteur.
substr( string $string, int $offset [, int $length]): stringRetourne un morceau d'une chaîne en fonction d'une position de départ et d'une éventuelle longueur.
ltrim( string $str):string
rtrim( string $str): string
trim( string $str): string
Retire les espaces blancs de début ou/et de fin de chaîne, et retourne la chaîne nettoyée. Les espaces blancs sont : "\n", "\r", "\t", "\v", "\0", et " " (espace).
http://www.php.net/manual/fr/ref.strings.php

Fonctions sur les tableaux

DescriptionAction
sizeof( array $array): intRetourne le nombre d'éléments d'un tableau.
sort( array &$array): voidTrie le tableau array dans l'ordre croissant.
array_pop( array &$array): mixedDépile et retourne le dernier élément du tableau array, le raccourcissant d'un élément.
array_push ( array &$array, mixed $var [, mixed ...]): intEmpile les variables passées en paramètres à la fin de array.
http://www.php.net/manual/fr/ref.array.php

Les références en PHP

  • En PHP, les références sont destinées à appeler le contenu d'une variable avec un autre nom.
<?php
  $a='old';
  $b=&$a;
  $a='new';//La valeur de $b devient new
  $c=$b;// copie de valeur simple
  $a='new new';//$b devient 'new new, $c reste 'new'
  $a[0]='old';
  $b=&$a;
  $c=$b;//copie simple
  $a[0]='new';/* $b[0] devient new $c[0] reste 'old' */
?>

Passage d'arguments par référence (1)

  • Par défaut, les arguments sont passés à la fonction par valeur.
  • Si vous voulez qu'un argument soit toujours passé par référence, vous pouvez ajouter un '&' devant l'argument dans la déclaration de la fonction :
  • Attention, dans ce cas les éventuelles modifications de la variable d'entrée à l'intérieur de la fonction affectent la variable initiale.
  • Exemple :
    <?php
      function ajouteDuBlahblah(&$string) {
         $string .= ', et du blahblah.';
      }
    
      $str = 'Ceci est une chaîne';
      ajouteDuBlahblah($str); // le symbole & n'est pas nécessaire, la passage par référence
      // est défini une fois pour toute lors de la déclaration de la fonction
      echo $str; /* affiche 'Ceci est une chaîne, et du blahblah. */
    ?>
    

Passage d'arguments par référence (2)

  • Si vous souhaitez passer une variable par référence à une fonction mais de manière ponctuelle, vous pouvez ajouter un '&' devant l'argument lors de l'appel de la fonction :
  • Usage néanmoins à éviter car source potentielle de mauvaise surprise...
  • Si on a besoin d'une fonction avec passage par référence d'un paramètre d'entrée, on le fera systématiquement (diapo précédente)
<?php
  function fctBlah2 ($bar) {
    $bar .= ', et blah blah.';
  }
  $str = 'Ceci est une chaîne';
  fctBlah2 ($str);
  echo $str;// affiche 'Ceci est une chaîne'
  fctBlah2 (&$str);
  echo $str; /* affiche 'Ceci est une chaîne, et blah blah. */
?>

Les Fichiers

  • Comment y accéder ?
    • Par le nom relatif : "../../images/logo.gif"
    • Par le nom absolu : "/users/src2/dupont/file.txt"
    • Par une URL : "http://www.site.org/index.html"
  • Pourquoi faire ?
    • Charger des bibliothèques de fonctions
    • Inclure un élément récurrent dun site web
    • Créer des éléments dynamiques dans une page
    • ...

Les fonctions require et require_once

  • La commande require(string nom_fichier) se remplace elle-même par le contenu du fichier.
  • Utile pour charger en mémoire un script contenant des fonctions usuelles.
  • Une erreur d'évaluation du fichier génère une erreur terminale lors d'un require.
  • L'usage de require_once évite de charger plusieurs fois le même fichier.

Les fonctions include et include_once

  • La fonction include(string nom_fichier) inclus et évalue le fichier spécifié en argument.
  • Utile pour insérer un en-tête ou pied de page récurrent dans un site web, pour exécuter un script selon certaines conditions, ...
  • À la différence de require, une erreur d'évaluation du fichier génère un warning avec un include.

Ouvrir et Fermer un fichier

  • Ouverture d'un fichier :
    • Plusieurs modes d'ouverture existent : lecture, écriture, lecture/écriture, ...
    • fopen(string nom_fichier, string mode): resource
    • Si le nom commence par "http" réalise une connexion HTTP
    • Retourne un pointeur de fichier ou FALSE en cas d'échec.
    • Modes possibles : 'r', 'w', 'a', 'w+', 'a+'
  • Fermeture d'un fichier :
    • Libère la ressource ouverte avec fopen()
    • fclose( resource fp): bool
    • Retourne TRUE en cas de succès, et FALSE en cas d'échec.
    • Le pointeur de fichier doit être valide, et avoir été correctement ouvert par fopen()

Lire dans un fichier

  • fgets( resource fp [, int length]): string retourne une chaîne contenue dans le fichier pointé par fp.
    • Si la longueur length est fournie, la lecture s'arrêtera après length - 1 octets, ou à la fin de la ligne en cours de lecture (le premier des deux).
    • Sinon la ligne complète est récupérée.
  • feof( resource fp): bool
    retourne un booléen indiquant si la fin de fichier a été atteinte lors du dernier appel à fgets().
  • file_get_contents( string filename [, int use_include_path [,...]]): string
    retourne la totalité du contenu d'un fichier dans une chaîne de caractères.
  • file( string filename [, int use_include_path]): array
    retourne le fichier dans un tableau de chaînes de caractères. Chaque élément du tableau correspond à une ligne du fichier, et les retours-chariots sont placés en fin de ligne.
  • fread(resource $stream, int $length): string|false
    Similaire à fgets() mais dédiée aux flux binaires (voir détail).

Écrire dans un fichier

  • fwrite( resource $fp, string $string [, int $length]): int écrit le contenu de la chaîne string dans le fichier pointé par fp.
    • Si la longueur length est fournie, l'écriture s'arrêtera après length octets, ou à la fin de la chaîne (le premier des deux).
    • Sinon la chaîne complète est écrite
  • fputs( resource $fp, string $str [, int $length]): int idem
  • file_put_contents( string $filename, mixed $data [, ...]): int écrit le contenu de $data dans le fichier, $data peut être une chaîne de caractères ou un tableau ; retourne le nombre d'octet écrit ou FALSE en cas d'échec. Pour en savoir plus.

Exemple 1 : la fonction fgets

  • Lecture de fichier.txt avec fgets
  • Code PHP :
    $fp=fopen('fichier.txt','r');
    $codeHTML ='';
    if(! $fp) { // vérifie que le pointeur de fichier est valide
    	exit('Impossible d\'ouvrir fichier.txt');
    }
    else {
      while (!feof($fp)) { // répète jusqu'à la fin de fichier
        $ligne = fgets($fp); // lit une ligne
        $ligne = rtrim($ligne); // enlève le retour chariot de fin de ligne
        $codeHTML .= "$ligne<br />";
      }
      fclose($fp);
    }
    echo $codeHTML;
    
  • Résultat d'exécution :
    "; } fclose($fp); } echo $codeHTML; ?>

Exemple 2 : la fonction file

  • Lecture de fichier.txt avec file
  • Code PHP :
    $tabLignes=file('fichier.txt');
    $extraitHTML = '<pre>';
    if(is_array($tabLignes)) { // vérifie que le traitement du fichier s'est bien passé
    	foreach ($tabLignes as $ligne) { // traitement itératif de chaque ligne
    		$ligne = rtrim($ligne); // enlève le retour chariot de fin de ligne
    		$extraitHTML .= "$ligne\n";
    	}
    }
    $extraitHTML .= '</pre>';
    print $extraitHTML;
    
  • Résultat d'exécution :
    '; if(is_array($tabLignes)) { // vérifie que le traitement du fichier s'est bien passé foreach ($tabLignes as $ligne) { // traitement itératif de chaque ligne $ligne = rtrim($ligne); // enlève le retour chariot de fin de ligne $extraitHTML .= "$ligne\n"; } } $extraitHTML .= ''; print $extraitHTML; ?>

Les Chaînes de caractères

  • Différences entre les délimiteurs : contrairement au contenu des chaînes délimitées par des doubles quotes " celui des chaînes délimitées par de simple quote ' n'est pas interprété.
    $variable = ' Albus';
    $chSimple = '$variable\tdans\n une chaîne entre simple quote';
    $chDouble = "$variable\tdans\n une chaîne entre double quote';";
    echo "<pre>".$variable."<br />".$chSimple."<br />".$chDouble."</pre>";
    
    Résultat : ".$variable."
    ".$chSimple."
    ".$chDouble.""; ?>
  • Concaténation
    $chaines1 = $chSimple.$chDouble;
    $chaines2 = implode(array(" Albus", ' Percival', "Wulfric"));
    $chaines3 = implode(' ; ',array(" Albus", ' Percival', "Wulfric"));
    echo implode(array("<p>",$chaines1,"<br />", $chaines2,"<br />",$chaines3,"</p>"));
    $implodeCh = implode(array("<p>",$chaines1,"<br />", $chaines2,"<br />",$chaines3,"</p>"));
    
    Résultat : ",$chaines1,"
    ", $chaines2,"
    ",$chaines3,"

    ")); $implodeCh = implode(array("

    ",$chaines1,"
    ", $chaines2,"
    ",$chaines3,"

    ")); ?>
  • Découpage d'une chaîne
    $stringArray = explode(';', $chaines3);
    foreach($stringArray as $ch) {
       echo "*".$ch."*"; // pas de traitement des espaces
       }
    echo "<br />";
    foreach($stringArray as $ch) {
       echo "*".trim($ch)."*"; // suppression des espaces en début et fin de chaine
    }
    
    Résultat :
    "; foreach($stringArray as $ch) { echo "*".trim($ch)."*"; // suppression des espaces en début et fin de chaine } ?>
  • À voir aussi strlen, strpos, substr, str_rot13, ...

Les tableaux en PHP

  • Création 
    /* création d'un tableau indexé automatiquement */
    $tableauStr = array ('un', 'ensemble', 'de', 'chaînes', 'de', 'caractères');
    $tableauInt = array (12, 54, 658, 16);
    $tableauMixte = array (1, 'ensemble', 2, 'données', 2, '!=', 'types');
    
    /* ou encore */
    $tableau = ['azer', 'qsdf', 'wxcv'];
    
    /* création d'un tableau associatif (indexation clé/valeur) */
    $tableauAssoc = array ('entree' => 'Tomate Moza',
                              'plat' => 'Pizza Vivaldi',
                              'dessert' => 'Tiramisu');
    
  • Lecture/Écriture
    echo $tableauStr[0]; // affiche 'un'
    echo $tableauAssoc['dessert']; // affiche 'Tiramisu'
    
    /* Modification d'un élément de tableau */
    $tableauMixte[5] = 'différents';
    $tableauAssoc['plat'] = 'Pizza Calzone';
    
  • Manipulations
    /* Extension du tableau (par la fin) */
    $tableau[3] = 'tyui';
    $tableau[count($tableau)] = 'ghjk';
    $tableau[] = 'oplm';
    array_push($tableau, 'bn', '1234', '5678','90');
    
    /* insertion en tête */
    array_unshift($tableau, 'AZER');
    
    /* Suppression/récupération de la queue */
    $queue = array_pop($tableau);
    
    /* Suppression/récupération de la tête */
    $tete = array_shift($tableau);
    
  • Tris des tableaux
    /* tri d'un tableau dans l'ordre croissant */
    /* (voir ksort et asort pour les tableaux associatifs) */
    sort($tableauInt);
    
    /* tri d'un tableau dans l'ordre décroissant*/
    rsort($tableauInt);
    
  • Décomposition d'un tableau associatif
    /* Clés d'un tableau associatif (ou pas) */
    $tableauCles = array_keys($tableauAssoc);
    
    /* Valeurs contenues dans un tableau */
    $tableauValeurs = array_values($tableauAssoc);
    
'Tomate Moza', 'plat' => 'Pizza Vivaldi', 'dessert' => 'Tiramisu'); echo $tableauStr[0]; // affiche 'un' echo '
'; echo $tableauAssoc['dessert']; // affiche 'Tiramisu' echo '
'; $tableauMixte[5] = 'différents'; $tableauAssoc['plat'] = 'Pizza Calzone'; $tableau[3] = 'tyui'; $tableau[count($tableau)] = 'ghjk'; $tableau[] = 'oplm'; array_push($tableau, 'bn', '1234', '5678','90'); print_r($tableau); echo '
'; /* insertion en tête */ array_unshift($tableau, 'AZER'); print_r($tableau); echo '
'; /* Suppression/récupération de la queue */ $queue = array_pop($tableau); print_r($queue); echo '
'; print_r($tableau); echo '
'; /* Suppression/récupération de la tête */ $tete = array_shift($tableau); print_r($tete); echo '
'; print_r($tableau); echo '
'; /* tri d'un tableau dans l'ordre croissant*/ sort($tableauInt); print_r($tableauInt); echo '
'; /* tri d'un tableau dans l'ordre décroissant*/ rsort($tableauInt); print_r($tableauInt); echo '
'; /* Clés d'un tableau associatif (ou pas) */ $tableauCles = array_keys($tableauAssoc); print_r($tableauCles); echo '
'; /* Valeurs contenues dans un tableau */ $tableauValeurs = array_values($tableauAssoc); print_r($tableauValeurs); echo '
'; ?>

Génération de page HTML

Architecture d'un site web avec PHP

Architecture dun site web avec PHP

Attention!

  • Un fichier HTML contenant un script PHP doit avoir l'extension ".php".
  • Un fichier PHP est toujours interprété au niveau du serveur.
  • Pour qu'un script PHP soit exécuté, il faut y accéder via un serveur web et le protocole HTTP ou HTTPS.
  • Configuration d'un serveur web apache

Fichier PHP (coté serveur)

<!DOCTYPE html>
<html lang="fr">
<head>
	<meta charset="utf-8" />
</head>
<body>
    <?php
      echo '<h1>Bonjour, je suis un script PHP!</h1>';
    ?>
</body>
</html>

Pour tester ce script en ligne de commande s'il est contenu dans un fichier bonjour.php

dominique@HAL9000:~/public_html/PHP/src$ php -f bonjour.php
<!DOCTYPE html>
<html lang="fr">
<head>
	<meta charset="utf-8" />
</head>
<body>
<h1>Bonjour, je suis un script PHP!</h1>
</body>
</html>

dominique@HAL9000:~/public_html/PHP/src$

Fichier PHP (coté client)

Accès par l'url : http://localhost/~dominique/PHP/src/bonjour.php

<!DOCTYPE html>
<html lang="fr">
<head>
	<meta charset="utf-8" />
</head>
<body>
    <h1>Bonjour, je suis un script PHP!</h1>
  </body>
</html>

Gestion de formulaires en PHP

  • Les variables d'environnement <?php phpinfo(); ?> :
  • Plusieurs variables prédéfinies en PHP sont "superglobales" : $GLOBALS, $_SERVER, $_GET, $_POST, $_FILES, $_COOKIE, $_SESSION, $_REQUEST, $_ENV
  • $_SERVER['QUERY_STRING'] : récupère l'ensemble des informations transmises depuis une url (visibles au niveau du navigateur en utilisant la méthode GET)
  • $_SERVER['REQUEST_METHOD'] : GET ou POST
  • $_POST ou $_GET : Tableaux associatifs globaux contenant les données transmises
  • $_REQUEST : tableau associatif constitué du contenu de $_GET, $_POST et $_COOKIE

Common Gateway Interface (CGI)

  • CGI est une interface standardisée (RFC 3875) qui décrit comment un serveur HTTP et un programme peuvent échanger des données. Les programmes qui traitent l'information sont appelés CGI
  • Un CGI est un programme écrit dans un langage (C, C++, Perl, Shell, ...) qui implante cette interface,recueille les données et les transforme
  • Cette interface est un élément fondamental pour la gestion de formulaires dans un site web, elle demeure néanmoins transparente à l'usage via PHP.

Fonctionnement

  1. Le visiteur remplit le formulaire et soumet les données au serveur HTTP
  2. Le serveur http reçoit les données et les fournit au CGI
  3. Le CGI crée un nouveau document HTML et le renvoie au client

Soumission du résultat

  • Soumission par clic sur un bouton de type submit
  • 2 méthodes possibles :
    • GET : les données sont ajoutées automatiquement à la ligne de commande appelant le programme
      http://URL/prog?name1=value1&name2=value2&name3=value3
    • POST : cette méthode envoie un message à part entière et n'utilise pas l'URL
  • La méthode GET limite la quantité de données transmissibles, en pratique 8000 octets minimum (voir rfc2730), la limite réelle dépend du serveur HTTP
  • La méthode POST permet de transmettre un plus gros volume de données, la limitation dépend de la configuration du serveur HTTP, par défaut apache 2 n'impose pas de limite !

Document HTML contenant un formulaire (élément FORM)

<form action="prog" method="post|get" enctype="type" target="nom">...</form>
  • L'attribut action indique l'URL du programme utilisé pour traiter le données transmise par le formulaire.
  • L'attribut method indique la méthode utilisée pour envoyer les données au programme (paires nom/valeur).
  • L'attribut enctype donne la méthode d'encodage MIME (valable uniquement avec POST) qui sera utilisée pour envoyer les données au programme. Par défaut sa valeur est application/x-www-form-urlencoded.
  • L'attribut target désigne dans quelle fenêtre ou frame le résultat du traitement du formulaire sera affiché (optionel).
  • Le texte encadré par le couple de balises <form>...</form> peut contenir un ensemble d'éléments : input, select, textarea.
  • Les élements HTML pour les formulaires en détail.
  • Les apports de HTML 5.

Gestion des champs textuels (1/2)

<form action="coursPHP40.php" method="get">
  <p><b>Nom : </b>
  <input type="text" name="nom" size="10" /></p>
  <p><b> Prénom : </b>
  <input type="text" name="prenom" size="10" /></p>
  <p><input type="submit" name="envoi"   
         value="Clic" /></p>
</form>

Nom :

Prénom :

Gestion des champs textuels (2/2)

  • Source de coursPHP40.php :
    <html>
     <body>
    <?php
        echo('QUERY_STRING: ');
        echo($_SERVER['QUERY_STRING']);
        echo("<br />\n");
        echo('Nom: '.$_GET['nom']." <br />\n");
        echo('Prenom: '.$_GET['prenom']." <br/> \n");
        echo('Envoi: '.$_GET['envoi']." <br /> \n");
    ?>
    </body>
     </html>
  • Résultat :
    QUERY_STRING: nom=Ripley&prenom=Hellen&envoi=Clic
    Nom : Ripley
    Prenom : Hellen
    Envoi : Clic
    

Gestion de liste de sélection (1/2)

<form action="coursPHP42.php" method="get">
<p>Nom : <input type="text" name="nom" value="Dupond" size="10" />
Ville : <select size="3" name="ville">
          <option value="Amiens" > Amiens </option>
          <option value="Bordeaux" selected="selected" > Bordeaux</option>
          <option value="Caen"> Caen</option>
          <option value="Lille"> Lille</option>
        </select>
<input type="submit" name="enregistrement" value="Envoyer" />  
<input type="reset" name="annuler" value="Effacer" />
</p></form>

Nom : Ville :

Gestion de liste de sélection (2/2)

  • Fichier coursPHP42.php
    <?php
    echo('Nom : '.$_GET['nom']);
    echo(" <br /> \n");
    echo('Ville : '.$_GET['ville']);
    echo("<br />\n");
    ?>
    
  • Résultat :
    Nom : Dupond
    Ville : Amiens
    

Gestion de bouton radio (1/2)

  • Combien de radios peut-on écouter simultanément sur un poste ?
<form action="coursPHP44.php" method="get">
<p>Nom : <input type="text" name="nom"  size="10" /> </p>
<p>Département : 
    Calvados <input type="radio" name="dpt" 
                    value="14" checked="checked"  />
    Manche <input type="radio" name="dpt"     
                  value="50" />
    Orne <input type="radio" name="dpt" 
                value="61" /> </p>
<p><input type="submit" name="enregistrement" value="Envoyer" /> </p>
</form>

Nom :

Département : Calvados Manche Orne

Gestion de bouton radio (2/2)

  • Fichier coursPHP44.php
    <?php
        echo('Nom : '.$_GET['nom']);
        echo("<br /> \n");
        echo('Département : '.$_GET['dpt']);
        echo("<br />\n");
    ?>
    
  • Résultat :
    Nom :
    Département : 14
    

Gestion des choix multiples (1/2)

<form action="coursPHP46.php" method="get">
<p>Nom : <input type="text" name="nom" size="10" /> <br />
Cadeaux : <br />
Livre  <input type="checkbox" name="cadeaux[]" 
                 value="livre" checked="checked" />   
Tee-shirt <input type="checkbox" name="cadeaux[]"    
                    value="tee-shirt" />
Sac <input type="checkbox" name="cadeaux[]" 
              value="sac" checked="checked" />
Sweat  <input type="checkbox" name="cadeaux[]" 
                 value="sweat" /></p>
<p><input type="submit" name="enregistrement" value="Envoyer" /></p>
</form>

Nom :
Cadeaux :
Livre Tee-shirt Sac Sweat

Gestion des choix multiples (2/2)

  • Fichier coursPHP46.php
    <?php
        echo('Nom : '.$_GET['nom']." <br />");
        if (isset($_GET['cadeaux']) and is_array($_GET['cadeaux'])) {
        $cadeaux = $_GET['cadeaux']; // pour alléger l'utilisation de la variable
        echo('Liste des cadeaux:<ul>');
        foreach($cadeaux as $elem) {
            echo("<li> $elem </li>\n");
        }
        echo("</ul>\n");
    }
    ?>
  • Nom : Toto
    Liste de cadeaux :
    • livre
    • sac

Sélections multiples (1/2)

<form action="coursPHP48.php" method="get">
<p>Nom : <input type="text" name="nom"  size="10" /></p>
<p>Musique : <select multiple="multiple" size="5" name="musique[]">
	       <option value="Electro" selected="selected"> Electro</option>
               <option value="Indus"> Indus</option>
               <option value="Pop" selected="selected"> Pop</option>
               <option value="Rap" selected="selected"> Rap</option>
               <option value="Rock"> Rock</option>
            </select></p>
<p><input type="submit" name="enregistrement" value="Envoyer" /></p>
</form>

Nom :

Musique :

Sélections multiples (2/2)

  • Fichier coursPHP48.php
    <?php
        echo 'Nom : '.$_GET['nom'].' <br />';
        if (isset($_GET['musique']) && is_array($_GET['musique'])) {
            $musique = $_GET['musique'];
            echo('Gouts musicaux :<ul>');
            foreach($musique as $elem) {
                echo("<li> $elem </li>\n");
            }
        echo("</ul>\n");
    }
    ?>
    
  • Résultat :
    Nom : Toto
    Gouts musicaux :
    • electro
    • pop
    • rap
  • Gestion identique aux checkbox.
  • Si absence de vérification du tableau :
     Warning: Invalid argument supplied
    for foreach() in
    /.../src_form4_erreur.php
    on line 18

Gestion des zones textuelles (1/2)

<form action="coursPHP50.php" method="get">
<p>  <b>Message : </b>
  <textarea cols="14" rows="4" name="nom" /></p>
<p>  <input type="submit" name="envoi"   
         value="Clic" /></p>
</form>

Message :

Gestion des zones textuelles (2/2)

  • Fichier coursPHP50.php
    <?php
    echo('<p>');
    echo(htmlentities($_GET['nom']));
    echo("\n</p>");
    ?>
  • Résultat :

    Texte avec des voyelles accentuées à côté du symbole €

    <p>Texte avec des voyelles
     accentu&eacute;es &agrave;
     c&ocirc;t&eacute; du symbole
    &euro;
     </p>

Upload de fichiers (1/2)

  • Utilisation de la méthode POST obligatoire.
  • Côté HTML :
    <form action="coursPHP52.php" enctype="multipart/form-data" method="post">
    <p>  <b>Fichier : </b>
      <input type="file" name="nom" size="10" /><br />
      <input type="submit" name="envoi"   
             value="Clic" /></p>
    </form>
    
  • Côté Navigateur :

    Fichier :

  • Côté PHP :
    if (isset($_FILES['nom'])) {
      echo 'Nom d'origine : '.$_FILES['nom']['name'];
      echo '<br />';
      echo 'Stockage temporaire : '.$_FILES['nom']['tmp_name'];
      echo '<br />';
      $nomF = $_FILES['nom']['tmp_name'];
      print_r(file($nomF));
    }
    

Upload de fichiers (2/2)

  • Résultats dans le tableau associatif $_FILES
  • $_FILES['nom']['name']
  • $_FILES['nom']['type']
  • $_FILES['nom']['size']
  • $_FILES['nom']['tmp_name']
  • $_FILES['nom']['error']
  • Voir les fonctions is_uploaded_file() et move_uploaded_file()
  • Dans le fichier php.ini on peut configurer la taille maximale des données transmises par POST, autoriser ou non les uploads de fichier, etc.
  • L'upload de fichier est à réaliser avec précaution, car la sécurité du serveur peut être rapidement mise en cause.

Autres éléments de formulaire

  • Autres types d'input :
    • Champs cachés : type="hidden"
    • Champs pour saisie de mot de passe type="password"
    • Champs image (pour personnaliser les boutons) type="image"
  • Élément label pour associer des étiquettes aux composants du formulaire.
  • Élément fieldset pour regrouper des champs de formulaire.
  • Élément legend pour étiqueter un fieldset.

Gestion de champs obligatoires

(avant html5 et l'attribut required)

  • Objectif : valider un formulaire uniquement si un minimum d'informations est renseigné.
  • Comment :
    • Vérifier l'état des éléments obligatoires avant de traiter les informations.
    • Renvoyer le formulaire en cas d'échec
    • Récupérer les informations déjà renseignées

Séquence de gestion des erreurs

Script d'orientation

Vérification des champs obligatoires

  • Regrouper le nom des éléments obligatoires dans un tableau
  • Vérifier que ces variables sont renseignées dans $_GET ou $_POST
    function valideForm($method, $tabCles) {
    	foreach ($tabCles as $cle) {
    	   if (!isset($method[$cle])) 
    	     return FALSE;
            }
    	return TRUE;
    }
    
  • Cette fonction vérifie l'existence d'une information, pas sa validité...

Script d'orientation

<?php
  // noms des champs obligatoires
  $tab = array('nom', ...);
  if (valideForm($_GET, $tab)) {
        // script de traitement des données
	include('traite_formulaire.php');
  }
  else {
        // retour au formulaire avec récupération des saisies
        include('formulaire.php');
  }
?>

Exemple complet.

Récupérer les infos déjà saisies

  • Directement dans le formulaire : attention, le formulaire devient un script php !
<form action='script.php' method='get'>
 Nom (*): <input type='text' name='nom'
        <?php if(isset($_GET['nom'])) echo("value='".$_GET['nom']."'");  ?>
        size='10' />
...
</form>

Interface PHP / SGBD

  • PHP et les SGBD
  • Connexion à PostgreSQL
  • Connexion à Oracle
  • MySQLi
  • PDO

Accès aux Bases de Données

  • MySQL, PostgreSQL, Sybase, mSQL, Oracle, ODBC, etc.
  • Méthodes très similaires quelque soit le SGBD interrogé.
  • En général, il faut suivre la séquence :
    1. Connexion à la BD et récupération d'un "pointeur" de connexion.
    2. Exécution de la requête exprimée en SQL et récupération d'un "pointeur" de résultats.
    3. Vérification de la bonne exécution de la requête.
    4. Exploitation des éventuels résultats.
    5. Libération des ressources.
    6. Fermeture de la connexion.

Connexion à un serveur PostgreSQL

  • Paramètres de connexion:
    • Nom ou adresse IP du serveur
    • Port d'écoute du serveur
    • Nom dun utilisateur répertorié
    • Mot de passe de cet utilisateur
  • pg_connect( string $connection_string [, int $connect_type ]): resource
    • Etablir une connexion avec serveur (PostgreSQL), pour un compte utilisateur, et de mot de passe secret.
    • Renvoie une valeur (entier positif) qui peut être utilisée ensuite pour dialoguer avec le serveur.
    • Renvoie false en cas d'échec
    • Doc officielle
    • Exemple :
      include 'connex.php'; /* Par sécurité, il ne faut pas écrire directement
              les informations de connexions dans la chaine $strConnex. Il est
              préférable d'inclure ces variables depuis un script séparé même
              si ça ne résout pas tout les risques.*/
      $strConnex="host=$dbHost dbname=$dbName user=$dbUser password=$dbPassword";
      $ptrDB = pg_connect($strConnex);
      if ($ptrDB) {
        print '<p>Connexion établie !</p>';
      } else {
        print '<p>Erreur lors de la connexion ...</p>';
        exit;
      }
    • Fichier de connex.php :
      $dbHost='localhost';
      $dbName='xy123456';
      $dbUser='xy123456';
      $dbPassword='**************';
  • pg_pconnect( string $connection_string [, int $connect_type ]): resource établit une connexion persistante (non refermée à la fin du script)

Exécuter une requête

  • pg_query([ resource $connection ], string $query ): resource
    • Adresse une requête SQL au serveur PostgreSQL.
    • Renvoie un identificateur de résultat
    • Vrai (≠false) si la requête réussit
  • Dans le cas d'une clause SELECT, PostgreSQL retourne un identifiant de résultat qui sera utilisé ultérieurement dans les opérations de consultation.
  • Utilisation :$ptrQuery=pg_query($ptrDB, $query); le résultat de la requête n'est pas stocké dans $ptrQuery mais est accessible via la variable $ptrQuery.

Exploiter les résultats d'une requête (v1)

  • pg_fetch_row( resource $ptrQuery [, int $row ] ): array
  • Récupère une des lignes du résultat, et positionne le curseur sur la ligne suivante.
  • La ligne est représentée sous forme d'un tableau (une liste de valeurs).
  • Accès aux données : $Tableau[$Indice] où les indices correspondent aux champs utilisés dans la requête
  • Exemple :
    $ptrDB = pg_connect($strConnex);
    if (!$ptrDB) { exit('pb de connection'); }
    else {
      $requete = 'select * from collectivite';
      $ptrQuery = pg_query($ptrDB,$requete);
      $blocHTML = "<div>\n";
      if ($ptrQuery) {
        $numLig = 0;
        while($ligne = pg_fetch_row($ptrQuery,$numLig)) {
          $blocHTML .= '<p>';
          for ($j=0;$j<count($ligne);$j++) {
            $blocHTML .= $ligne[$j].' ';
          }
          $numLig++;
          $blocHTML .= "</p>\n";
        }
      }
      $blocHTML .= '</div>';
      echo $blocHTML;
    }
  • Produit le message d'erreur suivant en tentant le fetch sur la ligne 101 qui n'existe pas :
    Warning: pg_fetch_row(): Unable to jump to row 101 on PostgreSQL result index 139711950000216 in /path/pgFetchRowSample.php on line 14
  • Résultat :
    <div>
    <p>1 Ain 588853 5762 Rhône-Alpes </p>
    <p>10 Aube 303298 6004 Champagne-Ardenne </p>
    <p>11 Aude 353980 6139 Languedoc-Roussillon </p>
    <p>12 Aveyron 277048 8735 Midi-Pyrénées </p>
    <p>13 Bouches-du-Rhône 1967299 5087 Provence-Alpes-Côte d'Azur </p>
    ...
    </div>

Exploiter les résultats (v2)

  • pg_fetch_assoc( resource $result [, int $row ] ): array
  • Transforme la ligne courante en un tableau associatif
  • Accès aux données : $Tableau["Nom_colonne"]
  • Exemple :
    $ptrDB = pg_connect($strConnex);
    if (!$ptrDB) { exit('pb de connection'); }
    else {
      $requete = 'select * from collectivite';
      $ptrQuery = pg_query($ptrDB,$requete);
      $blocHTML = "<div>\n";
      if ($ptrQuery) {
        while($ligne = pg_fetch_assoc($ptrQuery)) {
          $blocHTML .= '<p>';
          $blocHTML .= $ligne['col_code'].'; '.$ligne['col_nom'].'; '.$ligne['col_region'];
          $blocHTML .= "</p>\n";  // retour à la ligne pour plus de lisibilité du code html produit
        }
      }
      $blocHTML .= '</div>';
    }
    
  • Comme avec pg_fetch_row() on peut se passer du numéro de ligne.
  • Résultat :
    <div>
    <p>1; Ain; Rhône-Alpes</p>
    <p>10; Aube; Champagne-Ardenne</p>
    <p>11; Aude; Languedoc-Roussillon</p>
    <p>12; Aveyron; Midi-Pyrénées</p>
    <p>13; Bouches-du-Rhône; Provence-Alpes-Côte d'Azur</p>
    <p>14; Calvados; Basse-Normandie</p>
    <p>15; Cantal; Auvergne</p>
    <p>16; Charente; Poitou-Charentes</p>
    <p>17; Charente-Maritime; Poitou-Charentes</p>
    ...
    </div>

Exploiter les résultats (v3)

  • pg_fetch_array( resource $result [, int $row [, int $result_type = PGSQL_BOTH ]] ): array
  • Transforme la ligne courante en un tableau de type mixte : associatif (clé/valeur) et indicé.
  • Accès aux données : $Tableau["Nom_Colonne"] ou $Tableau[$Num_Colonne]
  • Exemple :
    $ptrDB = pg_connect($strConnex);
    if (!$ptrDB) { echo('pb de connection'); }
    else {
      $requete = 'select * from collectivite';
      $ptrQuery = pg_query($ptrDB,$requete);
      if ($ptrQuery) {
        while($ligne = pg_fetch_array($ptrQuery)) {
          echo '<p>';
          echo $ligne['code'].' '.$ligne[1].' '.$ligne['region'];
          echo '</p>';
        }
      }
    }
    

Récupérer tous les résultats

  • pg_fetch_all( resource $result ): array
  • Récupère l'ensemble des lignes du résultat et les place dans un tableau
  • À utiliser avec modération sur les tables très volumineuses...
  • Exemple :
    $requete = 'select * from region';
    $ptrQuery = pg_query($ptrDB,$requete);
    if ($ptrQuery) {
        $resultat = pg_fetch_all($ptrQuery);
        foreach ($resultat as $ligne) {
            foreach ($ligne as $colonne)
                echo $colonne.',';
            echo "<br />\n";
        }
    }
    
  • Résultat :

Quantifier les résultats

  • Deux fonctions permettent de connaître la quantité d'informations renvoyé par un SELECT
    • pg_num_rows( resource $result ): int
    • pg_num_fields( resource $result ): int
    • Exemple :
          $requete = 'select * from region';
          $ptrQuery = pg_query($ptrDB,$requete);
          if ($ptrQuery) {
              $numRows = pg_num_rows ( $ptrQuery );
              $nbColonnes= pg_num_fields ( $ptrQuery);
              echo '<p>La requête a retourné $numRows lignes décrites par $nbColonnes champs;</p>';
          }
  • pg_affected_rows( resource $result ): int renseigne sur le nombre de lignes concernées par un UPDATE, INSERT ou un DELETE
  • Exemple :
        $requete = "DELETE from departement WHERE region='Neustrie'";
        $ptrQuery = pg_query($ptrDB,$requete);
        $nbLignes= pg_affected_rows ( $ptrQuery);
        echo '<p>La requête a supprimé $nbLignes ligne(s).</p>';
    

Traitement des erreurs

  • pg_last_error([ resource $connection ] ): string
  • Lit le dernier message d'erreur sur la connexion
  • Exemple :
    $requete = 'select id, nom_region from region';
    $ptrQuery = pg_query($ptrDB,$requete);
    if (!$ptrQuery) {
      echo pg_last_error($ptrDB);
    }
    
  • Retourne :
    ERROR: column "id" does not exist LINE 1: select id, nom_region from region ^

Libérer la mémoire et fermer la connexion

  • L'éxecution de multiples requêtes peut surcharger le SGBD interrogé, il convient donc de libérer explicitement l'espace mémoire mobilisé plutôt que d'attendre le timeout du système.
  • pg_free_result( resource $result ): bool : libère la mémoire allouée au résultat d'une requête. L'identifiant ne peut plus être employé.
  • La fermeture de la connexion au SGBD réalise un "ménage complet" avant de mettre fin à la connexion.
  • pg_close([ resource $connection ] ): bool : ferme la connexion associée à $connection ou par défaut la dernière connexion ouverte.

Préparer puis exécuter une requête

  • Les requêtes récurentes ne méritent pas d'être analysées et planifiées systématiquement par le SGBD.
  • Le mécanisme de préparation permet d'éviter ce surplus de calcul.
  • Il permet également de rendre paramétrable les requêtes à l'aide de variables notées $i directement intégrés dans la chaîne de caractères mémorisant la requête SQL.
  • La réalisation de la requête se fait en deux temps :
    1. préparation de la requête avec pg_prepare([ resource $connection ], string $stmtname , string $query ): resource
    2. exécution avec pg_execute([ resource $connection ], string $stmtname , array $params ): resource
  • Exemple :
      $requete = 'SELECT * FROM departement WHERE nom LIKE $1 OR region LIKE $2';
      pg_prepare($ptrDB,'reqPrep1',$requete);
      $ptrQuery = pg_execute($ptrDB, 'reqPrep1', array('S%', '%Nor%'));
      if ($ptrQuery) {
        $resultat = pg_fetch_all($ptrQuery);
        foreach ($resultat as $ligne) {
          foreach ($ligne as $colonne)
            echo $colonne.',';
            echo "<br />\n";
          }
        }
      echo "<br />\n";
      $ptrQuery = pg_execute($ptrDB, 'reqPrep1', array('D%', '%oi%'));
      if ($ptrQuery) {
        $resultat = pg_fetch_all($ptrQuery);
        foreach ($resultat as $ligne) {
          foreach ($ligne as $colonne)
            echo $colonne.',';
          echo "<br />\n";
        }
      }
  • Exemple :
    27,Eure,582822,6040,Haute-Normandie,<br />
    50,Manche,497762,5938,Basse-Normandie,<br />
    59,Nord,2571940,5743,Nord-Pas-de-Calais,<br />
    61,Orne,292210,6103,Basse-Normandie,<br />
    62,Pas-de-Calais,1461257,6671,Nord-Pas-de-Calais,<br />
    71,Saône-et-Loire,554720,8575,Bourgogne,<br />
    72,Sarthe,561050,6206,Pays de Loire,<br />
    73,Savoie,411007,6028,Rhône-Alpes,<br />
    76,Seine-Maritime,1250120,6278,Haute-Normandie,<br />
    77,Seine-et-Marne,1313414,5915,Ile-de-France,<br />
    80,Somme,569775,6170,Picardie,<br />
    93,Seine-Saint-Denis,1515983,236,Ile-de-France,<br />
    <br />
    16,Charente,351563,5956,Poitou-Charentes,<br />
    17,Charente-Maritime,616607,6864,Poitou-Charentes,<br />
    24,Dordogne,412082,9060,Aquitaine,<br />
    25,Doubs,525276,5234,Franche-Comté,<br />
    26,Drôme,482984,6530,Rhône-Alpes,<br />
    44,Loire-Atlantique,1266358,6815,Pays de Loire,<br />
    49,Maine-et-Loire,780082,7166,Pays de Loire,<br />
    53,Mayenne,305147,5175,Pays de Loire,<br />
    58,Nièvre,220199,6817,Poitou-Charentes,<br />
    72,Sarthe,561050,6206,Pays de Loire,<br />
    79,Deux-Sèvres,366339,5999,Poitou-Charentes,<br />
    85,Vendée,626411,6720,Pays de Loire,<br />
    86,Vienne,426066,6990,Poitou-Charentes,<br />

Description d'une table

  • pg_meta_data( resource $connection , string $table_name [, bool $extended ] ): array
  • Exemple :
      $tabDpt = pg_meta_data($ptrDB, 'departement', false);
      echo '<ul>';
      foreach ($tabDpt as $key => $val)  {
          echo "<li><b>$key</b> => (";
          foreach ($val as $k => $v)
              echo $k.'='.$v.',';
          echo ')</li>';
      }
      echo '</ul><br />';
      $tabReg = pg_meta_data($ptrDB, 'region', true);
      echo '<ul>';
      foreach ($tabReg as $key => $val)  {
          echo "<li><b>$key</b> => (";
          foreach ($val as $k => $v)
              echo $k.'='.$v.',';
          echo ')<li>';
      }
      echo '</ul>';
    
  • Résultat :
    • code => (num=1,type=varchar,len=-1,not null=,has default=,array dims=0,is enum=,)
    • nom => (num=2,type=varchar,len=-1,not null=,has default=,array dims=0,is enum=,)
    • population => (num=3,type=int4,len=4,not null=,has default=,array dims=0,is enum=,)
    • superficie => (num=4,type=int4,len=4,not null=,has default=,array dims=0,is enum=,)
    • region => (num=5,type=varchar,len=-1,not null=,has default=,array dims=0,is enum=,)

    • id_region => (num=1,type=varchar,len=-1,not null=1,has default=,array dims=0,is enum=,is base=1,is composite=,is pesudo=,description=,)
    • nom_region => (num=2,type=varchar,len=-1,not null=1,has default=,array dims=0,is enum=,is base=1,is composite=,is pesudo=,description=,)
    • nom_2016 => (num=3,type=varchar,len=-1,not null=1,has default=,array dims=0,is enum=,is base=1,is composite=,is pesudo=,description=,)

Exemple complet

  • Plein d'autres fonctions dans l'API complète : http://fr.php.net/manual/fr/ref.pgsql.php
  • Code php :
     $ptrDB = pg_connect($strConnex);
      if (!$ptrDB) {
          echo('pb de connection');
          }
      else {
          $requete = 'select * from region';
          $ptrQuery = pg_query($ptrDB,$requete);
          if ($ptrQuery) {
              $numLig = 0;
              $tabReg = pg_meta_data($ptrDB, 'region', true);
              $colnames = array_keys($tabReg);
              echo '<table><tr>';
              foreach ($colnames as $col){
                  echo '<th>$col</th>';
              }
              echo "</tr>\n";
              while($ligne = pg_fetch_array($ptrQuery)) {
                  echo '<tr>';
                  foreach($colnames as $col)
                      echo '<td>'.$ligne[$col]."</td>\n";
                  echo "</tr>\n";
              }
              echo '</table>';
              pg_free_result($ptrQuery);
          }
          else { echo(pg_last_error($ptrDB)); }
          pg_close($ptrDB);
      }
  • Résultat :
    id_regionnom_regionnom_2016
    0 Nords-Pas de Calais Hauts-de-France
    1 Picardie Hauts-de-France
    2 Haute-Normandie Normandie
    3 Basse-Normandie Normandie
    4 Ile de France Ile de France
    5 Champagne-Ardenne Grand Est
    7 Lorraine Grand Est
    8 Alsace Grand Est
    9 Bretagne Bretagne
    10 Pays de la Loire Pays de la Loire
    11 Centre Centre-Val de Loire
    12 Bourgogne Bourgogne Franche-Comté
    13 Franche-Comté Bourgogne Franche-Comté
    14 Poitou-Charentes Nouvelle-Aquitaine
    15 Limousin Nouvelle-Aquitaine
    16 Aquitaine Nouvelle-Aquitaine
    17 Midi-Pyrénées Occitanie
    18 Languedoc-Roussillon Occitanie
    19 Auvergne Auvergne Rhône-Alpes
    20 Rhône-Alpes Auvergne Rhône-Alpes
    21 Provence-Alpes-Côte d’Azur Provence-Alpes-Côte d’Azur
    22 Corse Corse
    23 Guadeloupe DROM
    24 Guyane DROM
    25 Martinique DROM
    26 Mayotte DROM
    27 La Réunion DROM

Persistance des données : les sessions

  • Problème : La durée de vie d'une variable PHP est limité à une seule URL.
  • Pourtant : la persitance des données est un mécanisme nécessaire pour développer des applications web
  • Comment transmettre des informations entre différentes pages ?
    • Avec des formulaires et des champs cachées : seulement valable pour des données simples et des volumes limités.
    • Avec des bases de données : mécanisme lourd
    • Avec des données de session...
  • L'identifiant de session est transmis par un cookie.

Création d'une session

  • session_start(): bool (renvoie toujours TRUE)
  • Initialise ou prolonge une session en utilisant un SID (identifiant de session généré automatiquement).
  • La constante SID est une chaîne vide si les cookies sont activés
  • session_start() doit être appel avant tout affichage dans le navigateur (utilise l'en-tête de requête HTTP).
  • Source session1.php :

Les données de la session

  • Accessibles via la superglobale $_SESSION
  • Création d'une variable de session : $_SESSION['nomVariable'] = valeur
  • La fonction bool isset(nom) permet de vérifier si une variable est définie.
  • La fonction void unset(nom) détruit une variable.
  • La fonction void session_unset(void) détruit toutes les variables de session.
    Exemple :Suppression d'une variable de session : unset($_SESSION['nomvariable']

  • Simplification des noms de variables à l'aide des références (à utiliser avec modération) :
    <?php
    session_start();
    $nom = &$_SESSION['nom'];
    ?>
  • Exemple (valable si une session est en cours) :
    <?php
    if (!isset($_SESSION['heure'])) {
        $date = getdate();
        $heure = $date['hours'].":".$date['minutes'];
        $_SESSION['heure']= $heure;
        }
    echo $_SESSION['heure']; ?>

Entretien d'une session

  • Source session2.php :
  • Quelle heure était-il lors de l'accès à la diapo précédente ?
    <?php
    if (isset($_SESSION['heure']))
        echo $_SESSION['heure']; ?>
  • Lors de la lecture de la page précédente il était

Fin de session

  • La fonction session_destroy() détruit toutes les données associées à la session courante.
  • Cette fonction ne détruit pas les variables globales associées à la session, de même, elle ne détruit pas le cookie de session.
  • Avant de clore une session, il faut la réactiver !
  • Source session3.php :
  • Exemple :
    <?php
        session_destroy();
        if (isset($_SESSION['heure']))
            echo 'Les variables de session restent accessibles malgré le session_destroy ! '. $_SESSION['heure'];
        else
            echo "Plus de date en mémoire après le reload.";
    ?>

L'identifiant de session

  • Transmis par cookie ou par paramètre de l'URL.
  • Accès à l'id avec la fonction session_id() ou parfois avec la constante SID
  • Il esr possible d'imposer un identifiant de session :
    • session_id(string $identifiant) remplace l'identifiant généré automatiquement par l'argument.
    • Doit être appelé avant le premier session_start()
    • Ne doit utiliser que des lettres ou des chiffres, la virgule ou le signe moins.

Durée du cache

  • session_cache_expire ( [int new_cache_expire]): int
  • Retourne la valeur courante associée à la durée accordée au cache mémoire (en minutes)
  • Le paramètre optionel permet de redéfinir cette durée (180mn par défaut)
  • S'utilise avec session_cache_limiter(string cache_policy): string pour identifier le limiteur de cache utilisé par le navigateur (none, nocache, private, private_no_expire, public)

A propos du cookie de session

  • session_get_cookie_params(void): array : retourne un tableau contenant les données associé au cookie de la session courante
    • 'lifetime' : durée de vie
    • 'path' : chemin où sont rangées les infos
    • 'domain' : domaine du cookie
    • 'secure' : pour la sécurité des connexions

Agir sur le cookie de session

  • session_set_cookie_params(int lifetime [,string path [,string domain [,bool secure]]]): void
  • Surtout utile pour agir sur la durée de la session.
  • N'est valide que le temps du script où elle est appelée.
  • Doit être appelée avant session_start()

Autres API

  • session_write_close() : mémorise les données de session et termine la session courante.
  • session_encode() : retourne une chaine linéarisée des variables de session
  • session_decode() : décode une chaine et alimente $_SESSION
  • session_abort()
  • ...

Histoire des Serveurs Web

Apache HTTP Server

Installation Apache HTTP Server sous Ubuntu

Configuration Apache HTTP Server

Association Apache-PHP

URL vs Système de fichiers

Configuration d'un environnement apache2-php-postgresql

Liste des packages ubuntu pour installer un environnement web (ici apache2) :

Liste des packages pour installer php

Liste des packages pour associer php et apache2

Liste des packages pour installer postgresql

Liste des packages pour associer postgresql et php

Liste des packages pour installer mysql (pas nécessaire pour InfoWeb en L2)

Liste des packages pour associer mysql et php (pas nécessaire pour InfoWeb en L2)

Pour activer le module php de apache

Configuration d'un environnement web sous Mac ou sous Windows

XAMPP (Cross Apache MariaDB Perl PHP)

MAMP Sous MacOS

WAMP Sous MS-Windows

openclassroom

Le Protocole IETF Badge HTTP

  • Origine : inventé avec les URL et HTML par Tim Berners-Lee en 1989-90
  • Web conçu autour de trois piliers :
    • HTTP : le protocole de communication,
    • HTML : le format de document initiant la notion d'hypertexte,
    • URL : le système d'adressage des documents
  • HTTP est un protocole sans état mis à disposition par un serveur httpd
  • Principe de fonctionnement : on émet une requête et on reçoit une réponse <point c'est tout !>.
  • HTTP : les versions du protocole
    • HTTP[/0.9] : version initiale ultra basique avec une seule requête possible GET /fichier.html et qui retourne exclusivement une page HTML
    • HTTP/1.0 : version extensible, introduction des méthodes POST et HEAD, mise en place des en-têtes, gestion des codes MIME (devenus Media type RFC 6838) et retourne un code d'état en plus du document demandé
    • HTTP/1.1 : version standardisée toujours extensible
    • HTTP/2 : version optimisée issue SPDY proposé par Google

Les Requêtes IETF Badge HTTP

  • Les méthodes de requête indiquent l'action que l'on souhaite réaliser sur la ressource indiquée.
  • Les méthodes sont souvent appelées verbes HTTP.
  • Principaux verbes :
    • GET demande une représentation de la ressource spécifiée. Les requêtes GET doivent uniquement être utilisées afin de récupérer des données.
    • POST est utilisée pour envoyer une entité vers la ressource indiquée. Cela entraîne généralement un changement d'état ou des effets de bord sur le serveur.
    • HEAD demande une réponse identique à une requête GET pour laquelle on aura omis le corps de la réponse (on a uniquement l'en-tête).
    • PUT remplace toutes les représentations actuelles de la ressource visée par le contenu de la requête.
    • DELETE supprime la ressource indiquée.
    • Mais aussi CONNECT, OPTIONS, TRACE, PATCH...

Les en-têtes IETF Badge HTTP

  • Elles permettent de préciser des informations en plus des requêtes ou des réponses, il s'agit en quelque sorte de paramètres
  • Syntaxe : nomEntete: valeur
  • Liste détaillée des en-têtes disponibles : RFC4229
  • Plus de détails
  • Exemple d'en-tête de requête :
    Host: tools.ietf.org
    User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate, br
    Referer: http://localhost/~dominique/PHP/coursHTTP.php?page=3
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
  • Exemple d'en-tête de réponse :
    Date: Sun, 18 Feb 2018 20:17:01 GMT
    Server: Apache/2.2.22 (Debian)
    Content-Location: rfc4229.html
    Vary: negotiate,Accept-Encoding
    TCN: choice
    Last-Modified: Sun, 11 Feb 2018 09:01:19 GMT
    ETag: "3ca206-220af-564ec013715c0;56582426c5330"
    Accept-Ranges: bytes
    Cache-Control: max-age=604800
    Expires: Sun, 25 Feb 2018 20:17:01 GMT
    Content-Encoding: gzip
    Strict-Transport-Security: max-age=3600
    X-Frame-Options: SAMEORIGIN
    X-Xss-Protection: 1; mode=block
    X-Content-Type-Options: nosniff
    X-Clacks-Overhead: GNU Terry Pratchett
    Content-Length: 16953
    Content-Type: text/html; charset=UTF-8

Structure d'un message

  • Les requêtes
    • Un message est constitué d'une requête sur une ligne, puis suivi d'en-têtes sur des lignes séparées.
      schéma d'une requête
    • la présence d'une ligne vide (avec un CRLF) déclenche l'envoie de la requête
    • Exemple :
      $ telnet localhost 80
      Trying 127.0.0.1...
      Connected to localhost.
      Escape character is '^]'.
      HEAD /~dominique/PHP/index.php HTTP/1.0
      Accept-language: fr,en
      Accept-Encoding: utf-8
      
      
  • Les réponses
    • La première ligne de la réponse est composée de la version de protocole utilisé, du code de réponse qui indique l'éventuel bon déroulement de la requête et d'un message de statut de la réponse. Les lignes suivantes sont des en-têtes puis vient la ressource demandée s'il y en a une.
      schéma d'une réponse
    • Exemple :
      HTTP/1.1 200 OK
      Date: Sun, 18 Feb 2018 21:19:05 GMT
      Server: Apache/2.4.18 (Ubuntu)
      Connection: close
      Content-Type: text/html; charset=UTF-8
      
      Connection closed by foreign host.

Code des réponses

  • Ces codes indiquent si la requête s'est déroulée normalement, ils sont codés sur 3 chiffres dont le plus connu est le 404...
  • Il existe 5 classes de codes indiqué par le premier chiffre.
  • Classe 1xx : réponses informatives
    • 100 Continue Jusqu'ici tout va bien...
    • 101 Switching Protocol
    • ...
  • Classe 2xx : réponses de succés
    • 200 OK
    • 201 Created
    • 204 No Content
    • ...
  • Classe 3xx : redirections
    • 301 Moved Permanently
    • 304 Not Modified
    • ...
  • Classe 4xx : erreurs du client
    • 400 Bad Request
    • 401 Unauthorized
    • 403 Forbidden
    • 404 Not Found
    • 405 Method Not Allowed
    • 418 I'm a teapot Voir RFC 2324
    • ...
  • Classe 5xx : erreurs du serveur
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • ...

Générer un en-tête en PHP

  • void header ( string $header [, bool $replace = TRUE [, int $http_response_code ]] )
  • Cette fonction permet de générer des en-têtes http et en particulier dans le cadre des redirections automatiques (détails et RFC HTTP/1.1).
  • Important : Lors d'un header, il est impératif qu'aucun contenu n'ait été envoyé avant.
  • Fichier test/testHeader.php :
     if (isset($_GET['coffee'])) {
        header("HTTP/1.1 418 I'm a teapot");
        echo "\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">
    <html><head>
    <title>418 I'm a teapot</title>
    </head><body>
    <h1>I'm a teapot</h1>
    <p>The requested URL <b>". $_SERVER['SCRIPT_NAME']."?". $_SERVER['QUERY_STRING']. "</b> tried to brew coffee with a teapot !</p>
    </body></html>";
    }
    else {
        header("HTTP/1.1 301 Moved Permanently");
        if (isset($_GET['page'])) {
            header('Location: /~dominique/PHP/coursHTTP.php?page=' . $_GET['page']);
        }
        else
            header('Location: /~dominique/PHP/coursHTTP.php?page=0');
    }
    
  • Où me mènent ces liens :
  • https://www.google.com/teapot/
  • https://http.cat/418

Retour sur le traitement des formulaires en PHP

GET ou POST ?

Répétions de requêtes

Illustrations des incohérences produites :

Cas 1 : édition et méthode GET

Cas 2 : passage à la méthode POST

Code PHP (version GET)

try {
    if (isset($_GET['action'])) {
        $dbs1 = $dbh->prepare('INSERT INTO nom(nom) VALUES(:nom)');
        $dbs1->bindValue(':nom', $_GET['nom']);
        $dbs1->execute();
    }
    else {
        $dbs1 = $dbh->query('DROP TABLE IF EXISTS nom ');
        $dbs1 = $dbh->query('CREATE TABLE nom (id integer auto_increment PRIMARY KEY, 
                                               nom varchar(25))');
        $dbs1 = $dbh->query("INSERT INTO nom(nom) VALUES ('nom 1'),('nom 2'),('nom 3')");
    }

    $dbs1 = $dbh->query('SELECT * from nom');
    $tab = $dbs1->fetchAll($fetch_style = PDO::FETCH_ASSOC);

    echo "<h1>Contenu de la table nom</h1>";
    echo "<table border='1'>\n";
    $colnames = array_keys($tab[0]);
    echo "<tr>\n";
    foreach ($colnames as $col) {
        echo "<th>" . $col . "</th>";
    }
    echo "</tr>\n";

    foreach ($tab as $ligne) {
        echo "<tr>\n";
        foreach ($ligne as $col) {
            echo "<td>" . $col . "</td>";
        }
        echo "</tr>\n";
    }
    echo "</table>\n";
} catch (PDOException $e) {
    print "<br />Erreur !: " . $e->getMessage() . "<br/>";
    die();
}
echo "<h2>Formulaire utilisant la méthode GET</h2>";
echo "<form action='' method=get>
<input type='text' name='nom' />
<input type='submit' name='action' value='inserer'/>
</form>";

Une solution : scinder actions et états

Code PHP de la page proposant le formulaire

try {
    echo file_get_contents('util/debutSkelHtml5.html');
    if (!isset($_GET['message'])) {
        $dbs1 = $dbh->query('DROP TABLE IF EXISTS nom ');
        $dbs1 = $dbh->query('CREATE TABLE nom (id integer auto_increment PRIMARY KEY, nom varchar(25))');
        $dbs1 = $dbh->query("INSERT INTO nom(nom) VALUES ('nom 1'),('nom 2'),('nom 3')");
    }

    $dbs1 = $dbh->query('SELECT * from nom');
    $tab = $dbs1->fetchAll($fetch_style = PDO::FETCH_ASSOC);

    echo '<h1>Contenu de la table nom</h1>';
    echo '<table border='1'>';
    $colnames = array_keys($tab[0]);
    echo '<tr>';
    foreach ($colnames as $col) {
        echo '<th>' . $col . '</th>';
    }
    echo '</tr>';

    foreach ($tab as $ligne) {
        echo '<tr>';
        foreach ($ligne as $col) {
            echo "<td> $col </td>";
        }
        echo '</tr>';
    }
    echo '</table>\n';

} catch (PDOException $e) {
    print '<br />Erreur !: ' . $e->getMessage() . '<br/>';
    die();
}

echo '<h2>Formulaire utilisant la méthode POST et traitement par script tiers</h2>';
echo "<form action='actionInserer.php' method='post'>
    <input type='text' name='nom' />
    <input type='submit' name='action' value='inserer'/>
    </form>";

echo file_get_contents('util/finSkelHtml5.html');

Code PHP de la page traitant le formulaire

try {
    if (isset($_POST['action'])) {
        $dbs1 = $dbh->prepare('INSERT INTO nom(nom) VALUES(:nom)');
        $dbs1->bindValue(':nom', $_POST['nom']);
        $dbs1->execute();
    }
    header('HTTP/1.1 303 See Other');
    header('Location: insererForm_v3.php?message=Coucou de la part de actionInserer.php');
    exit;
} catch (PDOException $e) {
    print '<br />Erreur !: ' . $e->getMessage() . '<br/>';
    die();
}

Les cookies

Usages courants

Où sont-ils stockés ?

Format d'un cookie

Cookies et HTTP

Cookies et PHP

CRUD

Opérations de lecture

Exemples sur la table Collectivite

Opérations d'édition

Insertion

Modification

Suppression

Formulaires d'insertion et d'édition

col_code
col_nom
col_population
col_superficie
col_region
vil_num
vil_nom
vil_population
vil_statut préfecture
sous-préfecture
col_code

CRUD : Organisation de la navigation

Détails de quelques actions

Détails de quelques états