Dans ce chapitre, nous allons voir comment traiter des formulaires en PHP. Pour comprendre le fonctionnement, on va reprendre un exercice simple : faire deviner un chiffre à l'utilisateur, puis utiliser ce principe pour construire un formulaire plus complet qui permet de composer une glace et d'en calculer le prix.
Créer un premier formulaire
On commence par créer une page jeu.php avec une valeur à deviner.
L'objectif est de permettre à l'utilisateur de saisir une valeur, puis de lui indiquer si le chiffre proposé est trop petit, trop grand ou correct.
En ligne de commande, on pouvait utiliser readline(). Dans le cadre d'un site web, l'interaction avec l'utilisateur passe par un formulaire HTML.
La balise form accepte notamment deux attributs importants :
action, qui indique la page appelée lors de la soumission du formulaire. Si on ne met rien, la page courante est appelée ;method, qui indique la méthode HTTP utilisée. On peut utilisergetoupost. Par défaut, si rien n'est précisé, la méthode estget.
Le champ input possède aussi un attribut important : name. C'est ce nom qui sera utilisé par PHP pour retrouver la valeur envoyée par le formulaire.
Récupérer les données avec $_GET
Avec une méthode get, les données du formulaire apparaissent dans l'URL après un point d'interrogation.
Par exemple, si l'utilisateur saisit 100, on obtient une URL qui ressemble à ceci :
PHP met automatiquement ces valeurs à disposition dans la variable globale $_GET.
On récupère alors un tableau où la clé correspond au nom du champ (chiffre) et la valeur correspond à ce que l'utilisateur a saisi.
Attention : même si le champ HTML est de type number, la valeur récupérée dans $_GET reste une chaîne de caractères. Si on veut travailler avec un entier, il faudra donc convertir la valeur.
Afficher un message à l'utilisateur
On peut maintenant comparer la valeur proposée avec le chiffre à deviner.
Cette première version fonctionne, mais elle pose rapidement deux problèmes :
- si l'utilisateur arrive sur la page sans paramètre dans l'URL,
$_GET['chiffre']n'existe pas ; - si on réaffiche directement une valeur saisie par l'utilisateur dans le HTML, on peut casser la structure de la page.
Ne jamais faire confiance à l'utilisateur
Si on veut réafficher la valeur saisie dans le champ, on peut être tenté d'écrire :
Le problème, c'est que l'utilisateur peut modifier directement l'URL et envoyer n'importe quelle valeur. Par exemple, il pourrait injecter des guillemets ou des balises HTML, ce qui peut casser le code de la page.
Il faut donc toujours filtrer ou convertir les données venant d'un formulaire ou de l'URL.
Dans notre cas, si on attend un entier, on peut convertir la valeur :
Pour un champ texte, on ne peut pas simplement convertir en chaîne. Il faut échapper les caractères HTML avec une fonction comme htmlentities().
Cela convertit les caractères spéciaux en entités HTML. Par exemple, un guillemet ou un chevron ne sera plus interprété comme du code HTML.
Vérifier l'existence d'une valeur
Quand on arrive sur la page /jeu.php sans paramètre, le tableau $_GET est vide. Si on essaie de lire $_GET['chiffre'], PHP peut afficher une alerte Undefined index chiffre suivant la configuration des erreurs.
Pour éviter ce problème, on vérifie d'abord que la clé existe avec isset().
Il faudra aussi appliquer cette vérification lorsqu'on réaffiche la valeur dans le champ.
Séparer la logique de l'affichage
Mélanger beaucoup de PHP et de HTML peut rendre le code difficile à lire. Une bonne habitude consiste à placer la logique en haut du fichier, puis à utiliser des variables simples dans la partie HTML.
Ensuite, dans le HTML, on se contente d'afficher ces variables.
On obtient un code plus simple à relire : en haut, on prépare les variables ; dans le HTML, on affiche le résultat.
GET ou POST ?
Un formulaire peut aussi utiliser la méthode post.
Avec post, les données ne sont plus visibles dans l'URL. Elles sont envoyées dans le corps de la requête. On peut le voir dans l'onglet Réseau / Network de l'inspecteur du navigateur.
Côté PHP, on récupère alors les données avec $_POST au lieu de $_GET.
Le tableau fonctionne de la même manière : la clé correspond au nom du champ, et la valeur correspond à ce qui a été saisi.
Pour choisir entre get et post, on peut retenir cette règle :
- utilisez
getsi les paramètres peuvent apparaître dans l'URL et si l'URL doit pouvoir être partagée, comme pour une recherche ; - utilisez plutôt
postsi les informations ne doivent pas apparaître dans l'URL, par exemple pour un formulaire de connexion.
Avec post, si on recharge une page issue d'une soumission de formulaire, le navigateur peut demander une confirmation pour renvoyer les données.
Envoyer plusieurs valeurs
Certains champs peuvent envoyer plusieurs valeurs. C'est le cas des cases à cocher lorsqu'on autorise plusieurs choix.
Avec ce code, si on coche plusieurs cases, on ne récupère qu'une seule valeur. Pour indiquer à PHP que le champ doit être traité comme un tableau, on ajoute des crochets au nom.
On récupère alors un tableau dans $_GET ou $_POST.
Cela fonctionne avec les checkbox, mais aussi avec d'autres champs si plusieurs champs portent le même nom avec des crochets.
Attention cependant : si aucune case n'est cochée, rien n'est envoyé à PHP. La clé n'existera donc pas dans le tableau.
Conserver les cases cochées
Après la soumission du formulaire, les cases se décochent par défaut. Pour les conserver, il faut ajouter l'attribut checked lorsque la valeur fait partie des données envoyées.
Pour éviter de répéter beaucoup de conditions dans le HTML, on peut créer une fonction.
La fonction in_array() permet de vérifier si une valeur existe dans un tableau. Elle prend en premier paramètre la valeur recherchée, puis le tableau dans lequel on cherche.
Pour un champ radio, la logique est proche, mais il n'y a qu'une seule valeur possible. On compare donc directement la valeur envoyée.
Exemple : composer une glace
Pour pratiquer, on peut créer un formulaire qui permet de composer une glace. On part de plusieurs tableaux de configuration.
Les parfums et les suppléments sont affichés avec des checkbox, car l'utilisateur peut en choisir plusieurs. Le cornet est affiché avec des boutons radio, car on ne peut choisir qu'un pot ou un cornet.
On utilise la méthode get, car l'objectif est de pouvoir partager l'URL de la glace composée.
Dans l'URL, on retrouvera les différents choix de l'utilisateur, ce qui permet de copier le lien et de partager exactement la même composition.
Calculer le prix
Pour calculer le prix, on peut préparer deux variables :
Ensuite, on parcourt les choix de l'utilisateur. Il faut toujours vérifier que les valeurs reçues existent bien dans nos tableaux de configuration. Sinon, quelqu'un pourrait modifier l'URL à la main et envoyer une valeur qui n'existe pas, ce qui provoquerait une erreur Undefined index.
On peut ensuite afficher le récapitulatif.
Il est possible d'optimiser ce code pour éviter les répétitions entre les parfums, les suppléments et le cornet. Mais cette optimisation rend la logique plus abstraite. Si vous débutez, l'important est surtout de comprendre les étapes : récupérer les données, vérifier qu'elles sont valides, puis calculer le total.