Ce chapitre est consacré aux passages de données à un fichier PHP.
Pour transmettre les données d'un internaute à un fichier PHP, le plus simple est de les transmettre dans l'URL.
Après avoir un peu étudié le HTML, nous savons que nous pouvons indiquer une
ancre (une position unique dans le fichier). Le nom du fichier est alors suivi
d'un caractère spécial (#) suivi de la valeur d'un attribut id
.
Lorsque les données sont transmises via l'URL, il faut également respecter des conventions.
- Les données sont transmises sous la forme clé=valeur.
- Le caractère spécial (?) suit le nom du fichier PHP et précède les couples de clé=valeur
- Le caractère spécial (&) sépare deux couples de clé=valeur.
- Le caractère spécial (=) sépare la clé de sa valeur.
On comprend aisément que ces caractères spéciaux ne peuvent pas faire partie d'un nom de clé ou d'une valeur.
URL : caractères autorisés
Exemple d'URL :
http://www.pigné.be:80/chemin/vers/mon_fichier.php?cle1=valeur1&cle2=valeur2#valeurID
Une URL est composée de :
- Un nom de protocole. Par exemple,
http://
- Un nom de domaine. Par exemple,
www.pigné.be
- Éventuellement, un numéro de port. Par exemple,
:80
- Généralement, un chemin vers le fichier. Par exemple,
/chemin/vers/mon_fichier.php
- Éventuellement, les paramètres. Par exemple,
?cle1=valeur1&cle2=valeur2
- Éventuellement, une ancre. Par exemple,
#valeurID
https://
est le nom du protocole lorsque la communication
entre le client (le navigateur web) et le serveur est cryptée. Ce qui sort de votre
ordinateur (et y entre) est alors crypté.
Le www.
peut souvent être omis.
Certains caractères accentués sont autorisés (selon l'extension)
Ainsi, dans un domaine .be
, le caractère (é) n'a été autorisé
que depuis le 11 juin 2013 (10 heures)
Le numéro du port (de communication du serveur) n'est quasi jamais indiqué. Le numéro du port = le numéro de la porte d'entrée. Rappel : Un ordinateur dispose d'environ 65.000 "portes" (d'entrées et de sorties). Lorsque le protocole est http://, le port par défaut est 80.
Lorsque le fichier est PHP, une ancre est rarement indiquée.
Une URL (= Uniform Resource Locator) = protocole + URI. (Voir URL)
Un protocole est un ensemble de règles de communication entre un client et un
serveur.
Lorsque le client est un navigateur web, le protocole est "http://" ou
"https://" (Voir http)
Lorsque le serveur est le système de fichiers, le protocole est "file:///"
URI = le chemin vers la ressource (le fichier).
La RFC 3986 définit, dans la section
2.3, les caractères autorisés dans le "path".
foo://example.com:8042/over/there?name=ferret#nose \_/ \______________/\_________/ \_________/ \__/ | | | | | scheme authority path query fragment
2.3. Unreserved Characters
Characters that are allowed in a URI but do not have a reserved purpose are called unreserved. These include uppercase and lowercase letters, decimal digits, hyphen, period, underscore, and tilde. unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
Des problèmes peuvent survenir avec des fichiers enregistrés sur le disque dur lorsqu'ils sont ensuite placés sur un serveur. En effet, dans le nom d'un fichier, l'OS de Microsoft autorise des caractères qui ne le sont pas dans la RFC 3986; tel que l'espace, les caractères accentués, ...
Il est hautement recommandé d'enregistrer, sur son disque dur, ses fichiers en respectant la RFC 3986.
Les 19 caractères suivants sont spéciaux, car ils ont une signification
particulière :
# ? = & : / [ ] @ ! $ ' ( ) * + , ; %
Passage de paramètres
Pour passer une donnée à un fichier PHP, on peut créer un lien comme ceci :
<a href="tests/bonjour.php?prenom=Thibaut">Afficher Bonjour</a>
Ce qui suit le nom du fichier PHP est ?prenom=Thibaut
.
Le ? indique que ce qui suit sont des couples de clé/valeur.
La clé et la valeur sont séparées par le signe =; la clé précède le signe =,
la valeur le suit.
bonjour.php (code complet)
<?php $prenom=$_GET['prenom']; echo "Bonjour, ".$prenom." !"; ?>
Tout ce qui est passé par l'URL se trouve dans la super-variable $_GET.
Ce qui est passé par l'URL est prenom=Thibaut
La valeur de $_GET['prenom']
est Thibaut
.
On constate que s'affiche dans la barre des URLs du navigateur : [...]tests/bonjour.php?prenom=Thibaut
. Et, comme vous pouvez taper ce que vous
voulez dans cette barre, vous pouvez la modifier et remplacer, par exemple, Thibaut
par Marc
; puis exécuter la page en tapant
sur la touche Enter). Si, au lieu d'afficher un message, le script PHP permet de
modifier le contenu de la base de données, l'internaute peut modifier la base de données.
La sécurité est donc relative à la complexité de la valeur transmise. Si, dans un
courriel, on vous demande de cliquer sur un lien pour confirmer votre inscription sur le
site et que, dans la barre des URLs, s'affiche
[...]tests/confirm.php?key=2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
, modifier
cette valeur n'affectera pas la base de données, car votre nouvelle clé n'existe pas dans
la base de données. Ici, la sécurité est donc excellente.
Pour passer plusieurs données par l'URL, il faut que chaque couple clé/valeur soit séparé par &.
<a href="tests/bonjour.php?nom=PIGN%C3%89&prenom=Thibaut">Afficher un bonjour complet</a>
Les trois caractères principaux caractères spéciaux sont : ? = &
<?php /* Il n'est pas obligatoire de récupérer les paramètres dans l'ordre qui ont été donnés dans l'URL */ $prenom=$_GET['prenom']; $nom=$_GET['nom']; /* Évidemment, on peut utiliser les variables dans l'ordre qu'on veut Ici, le prénom puis le nom (alors que, dans l'URL, on donne le nom puis le prénom) */ echo "Bonjour, ".$prenom." ".$nom." !"; ?>
Pourquoi PIGN%C3%89
et non PIGNÉ
?
É
ne fait pas partie des 66
caractères que vous pouvez choisir sans risque ... Si votre navigateur est
"occidental" ainsi que le serveur, il est très probable que les caractères accentués seront
correctement interprétés. Cependant, la RFC 3986 est faite pour le monde entier. Ne pas la
respecter, c'est prendre un risque. Pour vos visiteurs asiatiques, il est probable que
votre code ne fonctionne pas correctement.
Après avoir compris la signification des quatre caractères spéciaux - # ? = &
- vous en découvrez un cinquième (%). Sa
signification sera découverte lorsque nous aborderons la fonction urlencode().
urlencode()
La fonction urlencode() permet d'encoder les caractères accentués, les espaces, ...
Normalement, la clé ne devrait pas être encodée, car son nom devrait respecter les règles de nommage d'une variable (JavaScript, C, C++, ...). Pensez comme un programmeur !
Pour encoder une valeur (voire un nom de domaine, un chemin de fichier, une clé), cliquez ici
Dans une URL, la valeur ne doit pas être entourée de guillemets ou d'apostrophes, même si c'est un mot. Mais, si c'est une phrase, n'oubliez pas d'encoder le caractère espace.
La fonction PHP urlencode() remplace souvent les caractères spéciaux par une séquence de caractères débutant par le caractère spécial (%)
L'URL encodée n'a pas besoin d'être décodée. Elle est tout simplement correcte et il n'est pas nécessaire de décoder ce qui est bon, compréhensible (pour le navigateur web).
Dans une URL, le nom de domaine est insensible à la casse (mais pas le reste de l'URL).
Bref, vous l'avez compris passer des paramètres contenant des caractères "spéciaux" dans une URL, c'est à vos risques et périls.
Après avoir récupéré la donnée (dans le code PHP), celle-ci est souvent utilisée pour construire une requête SQL ou comme paramètre d'une fonction.
L'avantage du passage de paramètres par l'URL est qu'il n'est pas nécessaire de créer préalablement un formulaire dans le fichier HTML. Cette méthode convient si la clé est simple (tel que le nom d'une variable en C) et que la valeur est simple (nombre entier ou nom d'une variable en C).
Au prochain chapitre, un exemple de cette méthode sera vu. En l'occurrence, on transmet au fichier PHP dédié à la suppression d'un enregistrement (dans une table précise) le numéro de l'enregistrement à supprimer.
Inconvénients :
- La clé et la valeur sont lisibles (puisque contenues dans l'URL). Une personne mal-intentionnée pourrait facilement modifier les valeurs envoyées au fichier PHP.
- Le clé et la valeur doivent être "simples".
2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 est une valeur "simple" (sans caractères spéciaux) - Une URL étant limitée à 2.048 caractères, la taille des données passées par URL est donc limitée. Par exemple, il est donc impossible, sans risque, d'envoyer, via un formulaire, le contenu d'un champ de type textarea s'il contient plus de 2.048 caractères.
Méthode GET
L'avantage du formulaire est que le navigateur crée une URL correcte (avec
method="get"
). Il applique automatiquement la fonction
urlencode().
Regardez l'URL après avoir cliqué sur le bouton.
<form method="get" action="tests/bonjour.php"> <p> Prénom : <input name="prenom" /> <input type="submit" /> </p> </form>
<form action="tests/bonjour2.php"> <p> Nom : <input name="nom" value="D'Hainaut" /><br /> Prénom : <input name="prenom" value="Xavier François" /> <input type="submit" /> </p> </form>
Si la méthode n'est pas précisée, method="get"
sera utilisée (par le
navigateur).
Regardez l'URL après avoir cliqué sur le bouton.
La méthode suivante est performante.
Méthode POST
https
Toute donnée sensible doit être envoyée en utilisant le protocole https.
La plupart des hébergeurs offre cette possibilité gratuitement. Utilisez-la !
Les données sont alors cryptées entre le navigateur et le serveur avec lequel il
communique.
L'envoi de données ne peut se faire, en toute sécurité, que via le protocole https
Lorsque la méthode POST est utilisée, les données sont envoyées dans l'entête du fichier; ce qui, pratiquement, ôte toute limitation de taille.
Si method="post"
est indiqué mais que l'attribut action est absent, le
fichier s'appelle lui-même. Ceci est parfois utile. Le code ci-dessus illustre ce cas.
urlencode.php (extrait)
<form method="post"> <p>URL d'un fichier, clé ou valeur (dans une URL) :<br> <input size="70" name="url" required="required" pattern="[^#?=&:/\x5B\x5D@!$'()*+,;%]+" /> </p> <!--Concernant la valeur de l'attribut pattern => voir : http://pigné.be/Thibaut/cours/LeWeb/mini_cours_javascript/annexRegExpr.htm --> <p>Sont interdits, dans le champ ci-dessus, les 19 caractères -
# ? = & : / [ ] @ ! $ ' ( ) * + , ; % - car ils ont une signification spéciale et ne doivent, dès lors, pas être encodés..</p> <p> <input type="submit" /> </p> <p> <?php if (isset($_POST['url'])) { $old=$_POST['url']; $new=urlencode($old); echo "Dans une URL, <code class='code'>$old</code> doit s'écrire <code class='code'>$new</code>"; } ?> </p> </form>
Dans une balise <form>
, on écrit method="post"
ou
method="get"
(sans majuscule).
Code HTML :
<form method="post" action="tests/bonjour3.php"> <p> Prénom : <input name="prenom"> <input type="submit"> </p> </form>
L'attribut action
permet d'indiquer le nom du fichier (PHP) situé sur le
serveur qui devra traiter les données qui lui seront envoyés après le clic sur le bouton.
bonjour3.php (code complet)
<?php $prenom=$_POST['prenom']; echo "Bonjour, ".$prenom." !"; ?>
Le nom d'une super-variable pré-définie ne s'écrit pas en minuscule.
Au prochain chapitre, un exemple de cette méthode sera vu. En l'occurrence, on transmet au fichier PHP dédié à l'insertion d'un enregistrement (dans une table précise).
Lors de l'étude du mini-cours sur le JavaScript, un type d'<input
/> n'a pas été vu le type="hidden"
. Et, pour cause, car
il permet d'envoyer une donnée "cachée" (= qui n'apparaît pas à l'écran, mais bien dans
le code source du fichier).
Code HTML :
<form method="post" action="tests/bonjour4.php"> <p> Prénom : <input name="prenom" /> <input type="hidden" name="secret" value="0123" /> <input type="submit" /> </p> </form>
bonjour4.php (code complet)
<?php $prenom=$_POST['prenom']; $secret=$_POST['secret']; echo "Bonjour, le mot de passe de ".$prenom." est : ".$secret." !"; ?>
Une utilisation non-triviale du champ caché sera vue au prochain chapitre.
empty()
La fonction empty()
permet de savoir si une variable est définie et
vide
. Elle est souvent utilisée avec les super-variables $_GET et $_POST car
un formulaire renvoie toujours une string (et jamais un nombre).
Elle est souvent préférable à la fonction isset()
Extrait de https://phppot.com/php/isset-vs-empty-vs-is_null/
"" | "string" | NULL | false | 0 | undefined | |
empty() | true | false | true | true | true | true |
is_null() | false | false | true | false | false | error |
isset() | true | true | false | true | true | false |
if(!empty($_POST["pseudo"]) AND !empty($_POST["passwd"])) { $pseudo=htmlspecialchars($_POST["pseudo"]); $passwd=htmlspecialchars($_POST["passwd"]); } /* input type="number" */ $isDataValid=true; if(empty($_POST["num_fard"])){$isDataValid=false;} else{$num_fard=intval($_POST["num_fard"],10); if($num_fard<1) $isDataValid=false; } /* La base doit être précisée (ici, 10 pour une base décimale) pour éviter que "042" (en base octale) soit converti en 34 (en base décimale) */ /* intval() retourne 0 en cas d'échec (ou les premiers caractères numériques entier) */ /* Si la valeur doit être un entier positif non nul (cas des clés étrangères), => ajouter une condition : if($num_fard<1) ... */ } /* input type="date" => AAAA-MM-JJ */ if(!empty($_POST["dateProduct"])) { $dateProduct=$_POST["date1"]; $tab=explode("-",$dateProduct); if(!preg_match("/^[0-9]{4}$/",$tab[0])) $tab[0]="2000"; if(!preg_match("/^(0[1-9]|1[0-2])$/",$tab[1])) $tab[1]="02"; if(!preg_match("/^(0[1-9]|[1-2][0-9]|3[0-1])$/",$tab[2])) $tab[2]="31"; if(!checkdate($tab[1],$tab[2],$tab[0])) $isDataValid=false; } /* input type="number" step="0.01" */ if(!empty($_POST["nombreReel"])) { /* = nombre ayant un POINT décimal */ /* Si la chaîne de caractères ne contient aucun '.', 'e', ou 'E', et que la valeur numérique est dans l'intervalle de représentation des entiers (notamment, qu'elle est plus petite que PHP_INT_MAX), alors la chaîne de caractères sera transformée en entier. Dans les autres cas, elle sera interprétée comme un nombre décimal. La valeur est fournie par la portion initiale de la chaîne de caractères. Si la chaîne de caractères commence par une donnée numérique valide, ce sera la valeur utilisée. Sinon, la valeur sera de 0 (zéro). Une donnée numérique valide est un signe optionnel, suivi par un ou plusieurs chiffres (contenant, optionnellement, un point décimal), suivi par, éventuellement, un exposant. L'exposant est un 'e' ou 'E' suivi par un ou plusieurs chiffres. $foo = 1 + "10.5"; // $foo est un nombre à virgule flottante (11.5) $foo = 1 + "-1.3e3"; // $foo est un nombre à virgule flottante (-1299) $foo = 1 + "bob-1.3e3"; // $foo est un entier (1) $foo = 1 + "bob3"; // $foo est un entier (1) $foo = 1 + "10 Small Pigs"; // $foo est un entier (11) $foo = 4 + "10.2 Little Piggies"; // $foo est un nombre à virgule flottante (14.2) $foo = "10.0 pigs " + 1; // $foo est un nombre à virgule flottante (11) $foo = "10.0 pigs " + 1.0; // $foo est un nombre à virgule flottante (11) */ }
empty(), htmlspecialchars(), intval().
isset()
La fonction isset()
permet de savoir si une variable est définie et est
différente de NULL
. Elle est souvent utilisée avec les super-variables $_GET et
$_POST. Elle permet de savoir si la clé existe.
exit()
La fonction exit()
permet d'afficher un message et termine le script
courant. La fonction die()
est un alias (un autre nom pour le même code).
mail()
Il est possible d'envoyer un courriel. Ceci est utile pour envoyer par exemple un courriel de confirmation d'une commande, de validation d'une adresse e-mail, un message depuis un formulaire (pour garder son adresse e-mail secrète), ...
Rappel. La production et l'envoi de courriels par programmation permet de faire du "spamming". Envoyer un courriel à une personne qui ne souhaite pas recevoir vos courriels est une agression. Les actes méchants sont punissables.
Il n'est pas possible de tester l'envoi de courriels en local (sauf si vous avez installé un serveur de mail sur votre ordinateur, tel que Mercury). Si votre site est hébergé par un hébergeur (payant), il vous est possible d'envoyer des courriels (limités en taille et en nombre).
Code PHP (complet)
<?php $destinataire="xxx@yyy.be"; $sujet="Test de la fonction mail()"; $message="Test réussi !"; //mail($destinataire, $sujet, $message); ?>
Il suffit de remplacer xxx@yyy.be par votre adresse e-mail.
Pour éviter le spamming, la fonction mail()
a été mise en
commentaire.
L'utilisation de la fonction mail()
est très facile. La fonction
mail()
retourne true
, si le courriel est envoyé.
Le fait que le courriel soit envoyé n'implique pas qu'il sera reçu. Notamment, si l'adresse e-mail est erronée, si la boîte aux lettres du destinataire est pleine. De plus, votre courriel peut être mis dans le dossier "spam".
Il est possible d'envoyer les données d'un formulaire dans un courriel. Et donc, de créer un formulaire de contact.
Code HTML (ci-dessus)
<fieldset> <form action="tests/mail2.php" method="post"> <p> Sujet : <input name="sujet" /><br /> Message : <textarea name="message" rows="10" cols="70"> </textarea><br /> Mon adresse e-mail : <input name="emailExpediteur" type="email" /> (facultatif)<br /> <input type="submit" /><br /> <span class="note">Pour éviter le spamming, la fonction <code>mail()</code> a été mise en commentaire.</span> </p> </form> </fieldset>
mail2.php (code complet)
<?php $sujet=""; if (isset($_POST['sujet'])) $sujet=$_POST['sujet']; $message=""; if (isset($_POST['message'])) $message=$_POST['message']; $de=""; if (isset($_POST['emailExpediteur'])) $de=$_POST['emailExpediteur']; if ( empty($sujet) || empty($message) ) exit("Message non envoyé !"); $destinataire="xxx@yyy.be"; $headers = "From: ".$de; //if(mail($destinataire, $sujet, $message, $headers)) echo("Message envoyé."); ?>
$headers = "From: ".$de;
: ce code est donné tel que. Ces
codes HTML et PHP sont minimalistes afin de se concentrer sur l'essentiel.
Pour plus d'info sur la fonction mail()
, cliquez ici.
De plus, dans le cadre de ce mini-cours, ne sont pas abordés l'envoi de courrier au
format HTML, l'envoi de pièce jointes, ni l'input de type="file"
, ni les
moyens de distinguer un humain d'un robot (reCaptcha), ni la vérification des données,
côté serveur, via des expressions
régulières, ...