Pour insérer un formulaire on utilise l'élément HTML <form>.
<form method="post" action="cible.php"> <p> On insèrera ici les éléments de notre formulaire. </p> </form>
Les attributs les plus importants de l'élément HTML <form> sont :
C'est ce qui va déterminer la manière d'envoyer les données du formulaire.
Attention : Que l'on utilise la méthode get ou post on ne dois JAMAIS plus faire confiance aux formulaires qu'aux URL !
Dans 99% des cas on utilise la méthode post pour envoyer les données du formulaires.
L'attribut action sert à définir la page cible, c'est à dire la page qui recevra les données du formulaire et qui sera chargée de les traiter.
Le nom de la page cible est défini grâce à l'attribut action.
Attention : La page cible peut être aussi celle qui envoie les donnée si l'attribut action est réglé comme ceci action=“#“
Une fois de plus on fait du Ping-Pong
Dans un formulaire on peut insérer pas mal d'éléments différents comme :
Mais pour ces différents type de formulaires il y a deux attributs à connaître obligatoirement :
<form action="cible.php" method="post"> <p> <input type="text" name="prenom" /> <input type="submit" value="Valider" /> </p> </form>
Rappel de HTML : le champ <input type=“submit” /> permet de créer le bouton de validation du formulaire qui commande l'envoi des données, et donc la redirection du visiteur vers la page cible.
<textarea name="message" rows="8" cols="45"> Votre message ici. </textarea>
Les attributs rows et cols permettent de définir la taille de la zone de texte en hauteur et en largeur respectivement.
<select name="choix"> <option value="choix1">Choix 1</option> <option value="choix2">Choix 2</option> <option value="choix3">Choix 3</option> <option value="choix4">Choix 4</option> </select>
Vous pouvez aussi définir le choix par défaut de la liste. Normalement c'est le premier, mais si vous rajoutez l'attribut selected=“selected” à une balise <option>, alors ce sera le choix par défaut.
<input type="checkbox" name="case" id="case" /> <label for="case">Ma case à cocher</label>
L'utilisation de la balise <label> n'est pas obligatoire mais je la recommande fortement. Elle permet d'associer le libellé à la case à cocher qui a le même id que son attribut for, ce qui permet de cliquer sur le libellé pour cocher la case. On y gagne donc en ergonomie.
Là encore, on donne un nom à la case à cocher via l'attribut name (ici : « case »).
Ce nom va générer une variable dans la page cible, par exemple $_POST['case'].
Vous pouvez faire un test avec isset($_POST['case']) pour vérifier si la case a été cochée ou non.
<input type="radio" name="frites" value="oui" id="oui" checked="checked" /> <label for="oui">Oui</label> <input type="radio" name="frites" value="non" id="non" /> <label for="non">Non</label>
<input type="hidden" name="pseudo" value="Mateo21" />
On croit par erreur que, parce que ces champs sont cachés, le visiteur ne peut pas les voir. C'est faux ! En effet, n'importe quel visiteur peut afficher le code source de la page et voir qu'il y a des champs cachés en lisant le code HTML.
Mieux, il peut même modifier la valeur du champ caché s'il a les outils appropriés.
Que faut-il retenir ? Ce n'est pas parce que le champ est caché que vous devez considérer qu'il est inviolable. N'importe quel visiteur (un peu malin) peut le lire, modifier sa valeur et même le supprimer.
Ne faites pas confiance aux données envoyées par le visiteur !
La règle d'or: Ne jamais faire confiance au visiteur, aux données d'URL, aux données de formulaire !
Vu qu'un utilisateur peut avoir accès aux code HTML avec un simple clic droit “Afficher la source” ou en utilisant sous Mozilla le plugin “Firebug” lui permettant de lire et de modifier le code HTML, cela lui permet de:
XSS pour: pour cross-site scripting, est une faille qui permet d'injecter du code HTML contenant du JavaScript dans vos pages pour le faire exécuter à vos visiteurs mais également du code SQL permettant d’interroger la base de données si les variables ne sont pas protégés.
C'est facile : il faut protéger le code HTML en l'échappant, c'est-à-dire en affichant les balises (ou en les retirant) plutôt que de les faire exécuter par le navigateur.
Pour échapper le code HTML, il suffit d'utiliser la fonction htmlspecialchars() qui va transformer les chevrons des balises HTML <> en < et > respectivement.
Cela provoquera l'affichage de la balise plutôt que son exécution.
<p>Je sais comment tu t'appelles, hé hé. Tu t'appelles <?php echo htmlspecialchars($_POST['prenom']); ?> !</p>
Il faut penser à utiliser cette fonction sur tous les textes envoyés par l'utilisateur qui sont susceptibles d'être affichés sur une page web.
Sur un forum par exemple, il faut penser à échapper les messages postés par vos membres, mais aussi leurs pseudos (ils peuvent s'amuser à y mettre du HTML !) ainsi que leurs signatures.
Bref, tout ce qui est affiché et qui vient à la base d'un visiteur, vous devez penser à le protéger avec la fonction htmlspecialchars().
htmlspecialchars() — Convertit les caractères spéciaux en entités HTML
Si vous préférez retirer les balises HTML que le visiteur a tenté d'envoyer plutôt que de les afficher, utilisez la fonction strip_tags().
strip_tags() — Supprime les balises HTML et PHP d'une chaîne
Comment cela se passe ?
Procédure :
Dès l'instant où votre formulaire propose aux visiteurs d'envoyer un fichier, il faut ajouter l'attribut enctype=“multipart/form-data” à la balise <form>.
<form action="cible_envoi.php" method="post" enctype="multipart/form-data"> <p>Formulaire d'envoi de fichier</p> </form>
Grâce à enctype, le navigateur du visiteur sait qu'il s'apprête à envoyer des fichiers.
Maintenant que c'est fait, nous pouvons ajouter à l'intérieur du formulaire une balise permettant d'envoyer un fichier.
C'est une balise très simple de type <input type=“file” />. Il faut penser comme toujours à donner un nom à ce champ de formulaire (grâce à l'attribut name) pour que PHP puisse reconnaître le champ par la suite.
<form action="cible_envoi.php" method="post" enctype="multipart/form-data"> <p> Formulaire d'envoi de fichier :<br /> <input type="file" name="monfichier" /><br /> <input type="submit" value="Envoyer le fichier" /> </p> </form>
On peut ajouter d'autres champs plus classiques au formulaire (champ de texte, cases à cocher).
On peut aussi proposer d'envoyer plusieurs fichiers en même temps.
le formulaire pointe vers une page PHP qui s'appelle cible_envoi.php. Le visiteur sera donc redirigé sur cette page après l'envoi du formulaire.
C'est maintenant que ça devient important. Il faut que l'on écrive le code de la page cible_envoi.php pour traiter l'envoi du fichier.
« Traiter l'envoi du fichier » ? C'est-à-dire ?
Si le fichier a été envoyé sur le serveur c'est bon, non ?
Qu'est-ce que PHP aurait besoin de faire ?
En fait, au moment où la page PHP s'exécute, le fichier a été envoyé sur le serveur mais il est stocké dans un dossier temporaire.
C'est à vous de décider si vous acceptez définitivement le fichier ou non. Vous pouvez par exemple vérifier si le fichier a la bonne extension (si vous demandiez une image et qu'on vous envoie un « .txt », vous devrez refuser le fichier).
Si le fichier est bon, vous l'accepterez grâce à la fonction move_uploaded_file(), et ce, d'une manière définitive.
Mais comment je sais si « le fichier est bon » ?
Pour chaque fichier envoyé, une variable $_FILES['nom_du_champ'] est créée. Dans notre cas, la variable s'appellera $_FILES['monfichier'].
Cette variable est un tableau qui contient plusieurs informations sur le fichier :
Si vous avez mis un second champ d'envoi de fichier dans votre formulaire, il y aura une seconde variable $_FILES['nom_de_votre_autre_champ'] découpée de la même manière que le tableau qu'on vient de voir ici.
$_FILES['nom_de_votre_autre_champ']['size'] contiendra donc la taille du second fichier, et ainsi de suite.
Je vous propose de faire les vérifications suivantes pour décider si l'on accepte le fichier ou non.
On commence par vérifier qu'un fichier a été envoyé. Pour cela, on va tester si la variable $_FILES['monfichier'] existe avec isset().
On vérifie dans le même temps s'il n'y a pas d'erreur d'envoi.
<?php // Testons si le fichier a bien été envoyé et s'il n'y a pas d'erreur if (isset($_FILES['monfichier']) AND $_FILES['monfichier']['error'] == 0) { } ?>
On veut interdire que le fichier dépasse 1 Mo, soient environ 1 000 000 d'octets (j'arrondis pour simplifier). On doit donc tester $_FILES['monfichier']['size'] :
<?php // Testons si le fichier a bien été envoyé et s'il n'y a pas d'erreur if (isset($_FILES['monfichier']) AND $_FILES['monfichier']['error'] == 0) { // Testons si le fichier n'est pas trop gros if ($_FILES['monfichier']['size'] <= 1000000) { } } ?>
On peut récupérer l'extension du fichier dans une variable grâce à ce code :
<?php $infosfichier = pathinfo($_FILES['monfichier']['name']); $extension_upload = $infosfichier['extension']; ?>
La fonction pathinfo() renvoie un array contenant entre autres l'extension du fichier dans $infosfichier['extension']. On stocke ça dans une variable $extension_upload.
Une fois l'extension récupérée, on peut la comparer à un tableau d'extensions autorisées (un array) et vérifier si l'extension récupérée fait bien partie des extensions autorisées à l'aide de la fonction in_array().
Ouf ! On obtient ce code au final :
<?php // Testons si le fichier a bien été envoyé et s'il n'y a pas d'erreur if (isset($_FILES['monfichier']) AND $_FILES['monfichier']['error'] == 0) { // Testons si le fichier n'est pas trop gros if ($_FILES['monfichier']['size'] <= 1000000) { // Testons si l'extension est autorisée $infosfichier = pathinfo($_FILES['monfichier']['name']); $extension_upload = $infosfichier['extension']; $extensions_autorisees = array('jpg', 'jpeg', 'gif', 'png'); if (in_array($extension_upload, $extensions_autorisees)) { } } } ?>
Si tout est bon, on accepte le fichier en appelant move_uploaded_file(). Cette fonction prend deux paramètres :
Je propose de placer le fichier dans un sous-dossier « uploads ».
On gardera le même nom de fichier que celui d'origine. Comme $_FILES['monfichier']['name'] contient le chemin entier vers le fichier d'origine (C:\dossier\fichier.png par exemple), il nous faudra extraire le nom du fichier. On peut utiliser pour cela la fonction basename() qui renverra juste « fichier.png ».
<?php // Testons si le fichier a bien été envoyé et s'il n'y a pas d'erreur if (isset($_FILES['monfichier']) AND $_FILES['monfichier']['error'] == 0) { // Testons si le fichier n'est pas trop gros if ($_FILES['monfichier']['size'] <= 1000000) { // Testons si l'extension est autorisée $infosfichier = pathinfo($_FILES['monfichier']['name']); $extension_upload = $infosfichier['extension']; $extensions_autorisees = array('jpg', 'jpeg', 'gif', 'png'); if (in_array($extension_upload, $extensions_autorisees)) { // On peut valider le fichier et le stocker définitivement move_uploaded_file($_FILES['monfichier']['tmp_name'], 'uploads/' . basename($_FILES['monfichier']['name'])); echo "L'envoi a bien été effectué !"; } } } ?>
Lorsque vous mettrez le script sur Internet à l'aide d'un logiciel FTP, vérifiez que le dossier « uploads » sur le serveur existe et qu'il a les droits d'écriture. Pour ce faire, sous FileZilla par exemple, faites un clic droit sur le dossier et choisissez « Attributs du fichier ». Cela vous permettra d'éditer les droits du dossier (on parle de CHMOD). Mettez les droits à 733, ainsi PHP pourra placer les fichiers uploadés dans ce dossier.
Ce script est un début, mais en pratique il vous faudra sûrement encore l'améliorer. Par exemple, si le nom du fichier contient des espaces ou des accents, ça posera un problème une fois envoyé sur le Web. D'autre part, si quelqu'un envoie un fichier qui a le même nom que celui d'une autre personne, l'ancien sera écrasé !
La solution consiste en général à « choisir » nous-mêmes le nom du fichier stocké sur le serveur plutôt que de se servir du nom d'origine. Vous pouvez faire un compteur qui s'incrémente : 1.png, 2.png, 3.jpg, etc.
Soyez toujours très vigilants sur la sécurité, vous devez éviter que quelqu'un puisse envoyer des fichiers PHP sur votre serveur.