php

Deuxième partie : communication entre pages web

Précédent : php, la génération de code html

 

Chaque fois que l'on utilise un moteur de recherche sur le web, des mots-clés sont être transmis au "serveur" (Google ou autre). Le serveur va chercher les mots-clés dans ses bases de données, extraire les url des pages correspondantes, puis devra transmettre le résultat de ses recherches au butineur "client".
Or le protocole support du web, http, est conçu pour télécharger des pages web depuis un serveur, les unes après les autres, de façon totalement indépendante, sans aucun système de liaison. Alors des techniques comme les formulaires (et aussi les cookies, les sessions) sont apparues pour répondre au besoin de liaisons entre pages web.

 

Les formulaires html

Les formulaires sont à la base de l'interactivité des pages web. Un formulaire, écrit en html, permet l'entrée de données par l'utilisateur. Ces données sont transmises à un script de traitement (php, cgi...). Elles peuvent être aussi transmises par envoi de courriel.

Exemple : le formulaire Formulaire.html, ci contre, permet l'entrée de deux valeurs, un nom et un âge ( exemple ) :

En voici le code html :
<FORM NAME="saisie" ACTION="TraiteFormulaire.php" METHOD="GET">
  Votre nom :   <INPUT TYPE="text" NAME="nom">
  Votre âge : <INPUT TYPE="text" NAME="age">
  <INPUT type="submit" name="OK" value="OK">
</FORM>

Votre nom :
Votre âge :
Ce formulaire étant du code html standard, il peut être facilement créé avec un outil wysiwyg, tel que BlueGriffon :

La balise html <FORM> a trois attributs principaux :
NAME : le nom de l'objet formulaire ;
ACTION : l'url à activer. A cette url correspond la page web qui sera exécutée après la validation du formulaire ;
METHOD : GET ou POST ; GET transmet les paramètres dans l'URL, de façon visible par l'internaute; POST les transmet de façon cachée, dans les headers de la requête http.

La balise <INPUT> définit un champ de saisie, qui peut être principalement:

<input type="text" : champ de saisie, un texte
<input type="checkbox" : boîte à cocher (plusieurs boîtes peuvent être cochées) beurre  
argent du beurre
<input type="radio" : bouton radio (un seul bouton peut être coché) oui  
non  
ne se prononce pas
<input type="file" : fichier
<input type="hidden" : champ invisible
<input type="submit" : bonton de validation, ou de remise à zéro

Il y a d'autre champs de saisie possibles :

<select name="select">...</select>   : menu déroulant, c'est une liste à choix multiples
<textarea></textarea> : zone de texte multilignes

En fait, il parait peu utile de connaître dans le détail le codage html des formulaires, un logiciel de création de pages web comme BlueGriffon ou DreamWeaver faisant cela très bien pour nous...

 

Transmission des valeurs entrées, du formulaire vers un script

Lorsque l'attribut "action" d'un formulaire est un fichier contenant un script php, cela signifie que le script recevra les valeurs saisies dans le formulaire. Ainsi le formulaire décrit au paragraphe précédant <FORM NAME="saisie" ACTION="TraiteFormulaire.php" METHOD="GET"> transmet au script contenu dans le fichier de nom TraiteFormulaire.php les valeurs entrées dans les champs "nom" et "age". Le bouton "OK" du formulaire lance le script, en lui passant dans l'url les champs du formulaire :
http://.../TraiteFormulaire.php?nom=mathusalem&age=969&OK=OK

Le script php récupère les valeurs des paramètres dans des variables php nommées $_GET[nom du champ du formulaire]
Le script de notre exemple TraiteFormulaire.php reçoit les valeurs $_GET["nom"] et $_GET["age"], puis les affiche :
<?php
$nom = @$_GET["nom"];

$age = @$_GET["age"];

/* on met "@" pour bloquer les messages d'erreur, et ainsi ne pas afficher les messages d'avertissement dans le cas où le paramètre n'existerait pas */
echo <<<AFFICH
  Bonjour $nom<br>
  Vous avez $age ans<br><br>
  <a href="Formulaire.html">Retour au formulaire</a><br>
AFFICH;
?>

Comment ça marche ? Les URL peuvent contenir, outre le chemin d'accès au fichier contenant la page web, un certain nombre de paramètres situés après le signe "?"

Ce mécanisme de transmission de paramètres entre pages web est largement exploité. Les moteurs de recherche l'utilisent intensivement. Voici un exemple (réel) où l'url contient de nombreux paramètres :
http://www.maporama.fr/share/iti.asp?SESSIONID=%7B5D2104E9-9531-462F-B1CA-9051621C6A96%7D&
ITI_START_COUNTRYCODE=FR&ITI_START_ADDRESS=&ITI_START_ZIPCODE=24170&
ITI_START_STATE=&ITI_START_CITYNAME=PONT-L%27%C9TROIT&ITI_END_COUNTRYCODE=
FR&ITI_END_ADDRESS=&ITI_END_ZIPCODE=91690&ITI_END_STATE=&ITI_END_CITYNAME=
BOISSY-LA-RIVI%C8RE&ITI_MODE=vehicule&ITI_MODE_OPTION_vehicule=Distance&
NumberStepMore=0&SEARCH_ITI2.x=13&SEARCH_ITI2.y=9


Et un autre exemple plus simple :
https://duckduckgo.com/?q=artem&kl=fr-fr
 
Le moteur de recherche d'Amazon utilise un formulaire qui transmet les paramètres dans l'url, la recherche d'un quadricoptère génère l'url:
http://www.amazon.fr/s/ref=nb_sb_noss_1?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&url=search-alias%3Daps&field-keywords=quadricopt%C3%A8re&rh=i%3Aaps%2Ck%3Aquadricopt%C3%A8re
On peut y ajouter manuellement le paramètre correspondant à la demande d'une taux de réduction de plus de 50% : &pct-off=50-100
http://www.amazon.fr/s/ref=nb_sb_noss_1?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&url=search-alias%3Daps&field-keywords=quadricopt%C3%A8re&rh=i%3Aaps%2Ck%3Aquadricopt%C3%A8re&pct-off=50-100
et Amazon nous répondra "16 résultats pour Réduction de 50 % à 100 % : "quadricoptère"", c'est un moyen simple de contourner l'absence d'un champ de demande de réduction dans le formulaire de recherche...

 

Les paramètres sont accessibles par le "tableau associatif super global" $_GET (pour la méthode GET, ou $_POST pour la méthode POST).

Le code intégral du script TraiteFormulaire.php est alors :

<?php   // script_TraiteFormulaire.php
// appel par GET : http://.../TraiteFormulaire.php?nom=Rigobert&age=21&OK=OK

// récupérer les valeurs des paramètres transmis par la méthode GET
$nom = @$_GET["nom"];
$age = @$_GET["age"];

// générer l'en-tête html de la page web
echo <<<TETE
  <html>
  <head>
  <title>Prenom - age</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
TETE;

// script php : générer un texte à afficher
echo <<<AFFICH
  Bonjour $nom<br>
  Vous avez $age ans<br><br>
  <a href="Formulaire.html">Retour au formulaire</a><br>
AFFICH;

// générer le pied de page html
echo <<<PIED
  </body>
  </html>
PIED;

?>

En résumé, pour envoyer par un formulaire des données à un script PHP, il suffit de mettre le nom du fichier PHP qui réceptionnera les informations en tant que valeur de l'attribut ACTION de la balise FORM.

 

Transmission directe de variables entre scripts

Rien n'empêche dans un script php de coder directement une url avec les paramètres requis, sans mettre en oeuvre un formulaire, comme ceci :
Affichage :   Cliquer ici pour commander.
Code html :  Cliquer <a href="http://www.boutique.com?produit=$produit&quantite=$quantite">ici</a> pour commander.  
Les données "forcées" sont alors transmises par la méthode GET.

 

GET ou POST ?

La méthode GET transmet les paramètres dans l'url de façon visible, comme ci-dessus. La méthode POST les transmet cachés.
De façon générale, que faut-il choisir, GET ou POST ?
POST masquant les paramètres est préférable
, les risques de piratage s'en trouveront un peu réduits.

NB : Les valeurs de paramètres doivent être codées, comme dans toute URL : pas d'espace, ni de lettre accentuée, etc. Les caractères dans une url peuvent être les caractères alphabétiques (a-Z;A-Z) et numériques (0-9), ainsi que les caractères "_" et "-", tandis que le caractère espace doit être remplacé par plus "+". Les autres caractères doivent être codés par le signe % suivi du code hexadécimal du caractère... La fonction urlencode() code ainsi les paramètres pour les transmettre, la fonction urldecode() les décode.

 

Transmission de variables entre scripts : forme normale

Plutôt que de séparer le formulaire de son traitement, en deux page web, il est recommandé pour simplifier la programmation de les placer dans le même script. La variable globale PHP_SELF contient le nom du fichier en cours d'exécution, la ligne html d'en-tête du formulaure pourra alors s'écrire de façon générale  :
<form action="$_SERVER['PHP_SELF'] method="POST" enctype="multipart/form-data">
Voici un exemple de script "forme.php" :

<html>
<head>
<title>exemple de forme normale des formulaires</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>

<?php  
// script   forme.php
 
ini_set ("display_errors", TRUE); error_reporting (E_ALL) ; // pour afficher les messages d'erreur
 

// si le script a été invoqué par le formulaire, traiter le formulaire
$z6 = $_POST["z6"];
if
($z6 != "") { // le champ transmis dans l'url n'est pas vide, il s'agit donc d'un appel du script par le formulaire
   // le code qui suit n'est exécuté que dans le cas où le script est invoqué par le formulaire
   // effectuer les actions requises, conséquences de la validation du formulaire
   echo "la valeur fournie est = $z6<br>\n";
};

// le code qui suit est toujours exécuté, que le script soit invoqué directement ou par le formulaire
 
// afficher le formulaire
echo <<<FORMULAIRE
<form action="$_SERVER['PHP_SELF']" method="POST">
     <input type=text name="z6" value="$z6">
</form>
FORMULAIRE;

?>

</body>
</html>

NB : l'attribut value de la balise <input> indique une valeur initiale, affichée par défaut.
NB: $_SERVER['PHP_SELF'] fournit le chemin d'accès au fichier en cours d'exécution.

Si ce script est dans le fichier "forme.php", l'action demandée par le formulaire est l'exécution à nouveau du même script  : "forme.php". Au premier appel du script, appel direct non provoqué par le formulaire, la variable $z6 n'est pas définie, la valeur initiale du champ est nulle; au second appel du script, invoqué par le formulaire, la variable $z6 prend la valeur entrée dans le formulaire.
Cette façon de procéder
- permet d'éviter d'avoir une multitude de fichiers dans un projet php,
- n'oblige plus l'utilisateur à cliquer sur le bouton Précédent du butineur pour revoir le formulaire,
- n'oblige plus l'utilisateur à resaisir toutes les valeurs en cas d'erreur dans un champ,
- facilite l'affichage de messages d'erreur adaptés aux champs erronés, préremplis,
- simplifie le traitement des valeurs par défaut des champs puisque le formulaire et le script de traitement se trouvent dans la même page php.

De façon plus générique, la forme normale php peut se décrire par :

  1. Si le script est invoqué par POST ou GET
    1. vérifier la validité des données
    2. s'il y a des erreurs dans les données
      1. afficher un message d'erreur le plus explicite possible
    3. sinon s'il n'y a pas d'erreur dans les données
      1. effectuer le traitement demandé
      2. afficher un message de confirmation du succès de l'opération
  2. Dans tous les cas, toujours afficher le formulaire, avec les champs préremplis par les valeurs entrées

Exemple : nom_age.php contient le code

<html>
<head>
<title>formulaire nom et age</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<?php
// script_nom_age.php
// récupérer les paramètres transmis dans l'url

$nom = @$_GET["nom"];
$age = @$_GET["age"];

if ($nom == "") { // le nom n'a pas encore été entré : afficher le formulaire
  echo <<< FORM
    <form NAME="saisie" ACTION="nom_age.php" METHOD="GET">
    Votre nom : <input TYPE=text NAME=nom>
    Votre âge : <input TYPE=text NAME=age>
    <input type="submit" name="OK" value="OK">
  </form>
FORM;
}
else {
// le nom a été saisi, l'afficher
  echo <<< AFFICH
    Bonjour $nom<br>
    Vous avez $age ans<br><br>
    <a href="nom_age.php">Retour au formulaire</a><br>
AFFICH;
}
?>
</body>
</html>


 

 

Problèmes d'encodage

Apostrophes
Des problèmes d'apostrophes vont apparaitre... Toute apostrophe saisie dans un formulaire est transmise backslashée : le nom D'ALLEMBERT est transmis comme D\'ALLEMBERT, s'il est retransmis, il devient D\\\'ALLEMBERT, puis D\\\\\\\'ALLEMBERT, etc.
La solution est de filtrer les entrées avec la fonction stripslashes, qui enlève ces backslashes; le script de réception des saisies d'un formulaire comportera alors : $nom = stripslashes($_POST["nom"]);
...mais Microsoft Word génère de "fausses apostrophes", arrondies, qui ne sont pas backslashées, ni reconnues comme des apostrophes dans les bases de données. Tout texte copié dans un formulaire web depuis MSWord risque de créer des problèmes inextricables qui vont empirer dèq que l'on utilisera une base de données.

Jeu de caractères
Et les problèmes d'apostrophes, droites ou microsoftesques, ne sont pas les seules difficultés, le codage des jeux de caractères n'est pas simple :
"J'ai un souci d'affichage du texte, au lieu de marquer "école", il y a iso-utfcole" ou bien "il s'affiche îcole"
Il s'agit d'un problème de codage des caractères. Les données ont probablement été enregistrées (dans le code html ou dans le fichier texte) au format ISO 8859-1, et le navigateur les affiche en pensant avoir affaire à de l'UTF-8 (balise meta "charset" de la page web).
Voir le mémo sur les problèmes d'encodage

 

 

 

Tableaux

PHP admet plusieurs façons de manipuler les tableaux, principalement la forme indexée et la forme associative.

La forme indexée est assez semblable à celle d'autres langages, Java ou C, où les index sont des entiers positifs :
  $jour = array ("lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche") ;
  for ( $i=0; $i<sizeof($jour); $i++ ) {
    echo "$i : $jour[$i]<br>\n";
  }

Il y a une écriture plus compacte pour parcourir le tableau, avec l'instruction foreach (foreach passe en renue le tableau : à chaque itération la valeur de l'élément courant est assignée à $v ; à l'itération suivante on accéde à l'élément suivant ; au lancement des itérations le premier élément est sélectionné) :

  foreach ( $jour as $v ) {
    echo "$v<br>\n";   // l'élément courant
  }
  foreach ( $jour as $k => $v ) {
    echo "$k : $v<br>\n";   // la clé de l'élément courant
  }

La forme associative permet une écriture plus naturelle :
  $unite = array ( "pommes" => "kilo", "RAM" => "Mo", "galaxies" => "parsec", "livre" => "pages", "reseau" => "Mbps", "Mineur" => "kro" ) ;
  foreach ( $unite as $i => $v) {
    echo "$i : $v<br>\n";
  }

Citons encore une façon de parcourir les tableaux en utilisant un curseur, positionné sur le premier élément et incrémenté par la fonction each(). Cette fonction each() retourne une liste de deux valeurs, la paire (clé, résultat). Par exemple :
  $unite = array ( "pommes" => "kilo", "RAM" => "Mo", "galaxies" => "parsec", "livre" => "pages", "reseau" => "Mbps", "Mineur" => "kro" ) ;
  reset($unite);
   while
( list($i, $v) = each($unite) ) {
    echo "$i : $v<br>\n";
  }

Remarquons alors que les exemples fonctionnent de manière identique à ceux utilisant foreach :

  reset($jour);
  while (list(, $v) = each ($jour)) {
    echo "$v<br>\n";
  }
  reset($jour);
  while (list($k, $v) = each ($jour)) {
    echo "$k: $v<br>\n";
  }

Enfin, signalons que PHP propose des fonctions de tri sur les tableaux, qu'ils soient indexés ou associatifs.

void asort (array tab) Tri d'un tableau associatif en ordre croissant   void sort (array tab) Tri d'un tableau en ordre croissant
void arsort (array tab) Tri d'un tableau associatif en ordre croissant   void rsort (array tab) Tri d'un tableau en ordre décroissant
void ksort (array tab) Tri d'un tableau associatif dans l'ordre croissant des clés   void shuffle (array tab) Mélange aléatoire des élements d'un tableau
void krsort (array tab) Tri d'un tableau associatif dans l'ordre décroissant des clés   void usort (array tab) Tri d'un tableau dans l'ordre fixé par la fonction cmp
void uasort (array tab, function cmp) Tri d'un tableau associatif dans l'ordre fixé par la fonction cmp   void uksort (array tab) Tri d'un tableau dans l'ordre des clés fixé par la fonction cmp

 

 

Exercices  

  1er exercice : Créer un script php de traitement de formulaire
Dans un fichier convertisseur.php, écrire et tester un script de conversion euros-dollars.
On pourra s'inspirer des scripts suivants :

script "convertisseur-parametres.php"
<?php
ini_set ("display_errors", TRUE); error_reporting (E_ALL) ;
$choix = @$_GET["choix"]; // récupérer la valeur du paramètre "choix" transmis par la méthode GET (dans l'url)
$valeur = @$_GET["valeur"];// récupérer la valeur du paramètre "valeur" transmis par la méthode GET (dans l'url)
?>

script "convertisseur-formulaire.html" (le formulaire a été entré dans BlueGiffon, qui a généré le code html)
<form action="convertisseur.php" method="GET">
  <!-- GET pour passer les paramètres dans l'url de façon visible -->
  <div align='center'><font size="+1">Entrer la valeur &agrave; convertir : </font>
  <input type='text' name='valeur' size='15'></div><br><br>
  <div align='center'><font size=+1>Choisir le mode de conversion</font><br>
  <table border=1><tr><td>
    <input type="checkbox" name="choix" value="Dollars"> Euros vers Dollars</td></tr><tr><td>
    <input type="checkbox" name="choix" value="Euros"> Dollars vers Euros</td></tr>
  </table><br>
  <input type='submit' value='Convertir'>
  </div>
</form>

script "convertisseur-traitement.php"
<?php
if ($choix) {
  /* traitement du formulaire : cette partie du script n'est exécutée que si
  le paramètre choix est non vide, donc si le script est appelé par le formulaire */

  $taux_de_change = 1.3558; // 2013-10-14
  $resultat = $choix=="Euros" ? $valeur/$taux_de_change : $valeur*$taux_de_change ;
  $monnaie= $choix=="Dollars" ? "Euros" : "Dollars" ;
  echo "<div align='center'><font size='5'><b>
  $valeur $monnaie = $resultat $choix</b></font></div>";
}
?>

squelette du programme global "convertisseur.php" (code html recopié depuis BlueGriffon)
<html> <!-- convertisseur.php : convertisseur euros - dollars -->
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Convertisseur euros - dollars</title>
</head>
<body>
<div align='center'><b><font color="#FF0000" size="4">CONVERTISSEUR EUROS - DOLLARS</font></b></div>
<br>
  . . .
</body>
</html>

Corrigé : exécution du convertisseur   code source

 

 

  2ème exercice : Dans l'exercice 4 de la séance précédente (entrée de définitions dans le fichier texte du jargon), des valeurs issues de la saisie dans un formulaire ont été transmises à un script php (voir le script "saisir.php").
- Modifier le script "saisir.php" pour que votre nom soit proposé par défaut (attribut "value" dans le formulaire).

 

  3ème exercice : Mettre en application la forme normale de transmission de variables entre scripts par formulaire :
faire un script contenu dans le fichier inscription.php pour saisir (méthode GET) les coordonnées d'un visiteur : nom et prénom, âge, adresse de courriel.
- Observer l'inscription des paramètres dans l'url.
- Modifier le script pour utiliser la méthode de transmission POST, et observer l'url.

Corrigé :
- inscription
- paramètres dans l'url :
http://tisserant.org/cours/php/tdphp2/inscription.php?nom=mathusalem&age=999&courriel=mathusalem%40mafia.org&Submit=Envoyer 
- code source
inscription.php

 

 

  4ème exercice : Dans le script de l'exercice précédant, inscription.php, vérifier que les coordonnées du visiteur âge et adresse de courriel sont plausibles (âge : entier positif, inférieur à 123, courriel : de la forme chaine@chaine.chaine), refuser la saisie si les données ne sont pas valides.

Corrigé : inscription avec vérification
+ code source

 

 

 5- facultatif :
Développer un script php affichant un formulaire d'inscription et vérifiant les données saisies.
Le formulaire doit comporter les champs suivants :
• Nom
• Prénom
• Nom de l'entreprise
• Nom du chef de service
• Adresse mail
• Téléphone
• Test pour éviter que le formulaire soit rempli automatiquement.
De plus, pour valider l'inscription le site devra envoyer un mail de confirmation à cette personne et à un responsable administrateur pour éviter que des personnes externes accèdent aux informations qui seront divulguées.

Un second script doit pouvoir entrer les paramètres suivants :
• Date, lieu et durée de la réunion
• Sujet de la réunion
• Informations sur la réunion
• Références des participants
• Pièces jointes

Suite : valider les données - les expressions régulières

Ecole des Mines de Nancy

Alain Tisserant
Document : http://tisserant.org/cours/php/php2.html
Dernière mise à jour : octobre 2014