Aller au menu - Aller au contenu

Icône Transmettre des données avec les formulaires

Mise à jour : 03/04/2010
Difficulté : Intermédiaire Intermédiaire Creative Commons BY-NC-SA
166 173 visites depuis 7 jours, dont 9 240 sur ce chapitre, classé 3/795
Les formulaires sont le principal moyen pour vos visiteurs de rentrer des informations sur votre site. Les formulaires permettent de créer l'interactivité.

Par exemple, sur un forum on doit rentrer du texte puis cliquer sur un bouton pour envoyer son message. Sur un livre d'or, sur un mini-chat, pareil. On a besoin des formulaires partout pour échanger des informations avec nos visiteurs.

Vous allez voir qu'il y a de nombreux rappels de HTML dans ce chapitre... Et ce n'est pas un hasard : ici le PHP et le HTML sont très liés. Le HTML permet de créer le formulaire, tandis que le PHP permet de traiter les informations que le visiteur a entrées dans le formulaire.

Ce chapitre est particulièrement important, nous réutiliserons ce que nous avons appris ici dans toute la suite du cours. Soyez attentifs !
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Créer la base du formulaire

En HTML, pour insérer un formulaire on se sert de la balise <form>. On l'utilise de la manière suivante :

Code : HTML
1
2
3
4
5
6
7
<form method="post" action="cible.php">
 
<p>
    On insèrera ici les éléments de notre formulaire.
</p>
 
</form>


On écrira le contenu de notre formulaire entre les balises <form> et </form>. Si vous avez lu mon cours de HTML/CSS vous verrez qu'une bonne partie de ce chapitre ne sera que des rappels puisque je vais vous présenter comment on insère les champs du formulaire dans la page. Cependant, et ce sera nouveau, nous allons aussi découvrir comment traiter en PHP les données qui ont été envoyées par le visiteur.


Je souhaite attirer votre attention sur la toute première ligne de ce code. Il y a 2 attributs très importants à connaître pour la balise <form> : la méthode (method) et la cible (action). Il est impératif que vous compreniez à quoi ils servent.

La méthode



Il faut savoir qu'il y a plusieurs moyens d'envoyer les données du formulaire (plusieurs "méthodes"). Les 2 méthodes possibles sont :

  • get : les données transiteront par l'URL comme on l'a appris précédemment. On pourra les récupérer grâce à l'array $_GET. Cette méthode est assez peu utilisée car on ne peut pas envoyer beaucoup d'informations dans l'URL (je vous disais dans le chapitre précédent qu'il était préférable de ne pas dépasser 256 caractères).
  • post : les données ne transiteront pas par l'URL, l'utilisateur ne les verra donc pas passer dans la barre d'adresse. Cette méthode permet d'envoyer autant de données que l'on veut, ce qui fait qu'on la privilégie le plus souvent. Néanmoins, les données ne sont pas plus sécurisées qu'avec la méthode GET et il faudra toujours vérifier si tous les paramètres sont bien présents et valides comme on l'a fait dans le chapitre précédent. On ne doit pas plus faire confiance aux formulaires qu'aux URL.


C'est à vous de choisir par quelle méthode vous souhaitez que les données du formulaire soient envoyées. Si vous hésitez, sachez que dans 99% des cas la méthode que l'on utilise est post, vous écrirez donc method="post" comme je l'ai fait.

La cible



L'attribut action sert à définir la page appelée par le formulaire. C'est cette page qui recevra les données du formulaire et qui sera chargée de les traiter.

Imaginons le schéma suivant :

Appel page formulaire


Dans cet exemple, le formulaire se trouve dans la page formulaire.php. Cette page ne fait aucun traitement particulier, mais une fois le formulaire envoyé (lorsqu'on a cliqué sur le bouton "Envoyer"), le visiteur est redirigé vers la page cible.php qui reçoit les données du formulaire.

Envoi de données du formulaire


Le nom de la page cible est défini grâce à l'attribut action.

La page cible ne doit pas forcément s'appeler cible.php. J'utilise ce nom dans mes exemples simplement pour que vous compreniez bien que c'est la page qui est appelée.
En théorie, rien n'empêche d'ailleurs le formulaire de s'appeler lui-même. Il suffirait d'écrire action="formulaire.php". Dans ce cas, la page du formulaire doit être capable aussi bien d'afficher le formulaire que de traiter les données. C'est tout à fait possible à faire mais afin de ne pas compliquer les choses trop vite, on va éviter de faire comme ça ici. ;)


Retenez donc bien que vous travaillez normalement sur 2 pages différentes : la page qui contient le formulaire (formulaire.php dans notre exemple), et celle qui reçoit les données du formulaire pour les traiter (cible.php).

Les éléments du formulaire

Dans un formulaire, vous le savez peut-être déjà, on peut insérer beaucoup d'éléments différents : zones de textes, boutons, cases à cocher, etc.
Je vais ici tous les lister et vous montrer comment vous servir de chacun d'eux dans la page cible.php qui fera le traitement. Vous allez voir, c'est vraiment très simple : au lieu de recevoir un array $_GET vous allez recevoir un array $_POST contenant les données du formulaire !

Les petites zones de texte



Une zone de texte ressemble à ceci : Image utilisateur

En HTML, on l'insère tout simplement avec la balise :

Code : HTML
1
<input type="text" />


Pour les mots de passe, vous pouvez utiliser type="password", ce qui aura pour effet de cacher le texte rentré par le visiteur. A part ce détail, le fonctionnement reste le même.


Il y a 2 attributs à connaître que l'on peut ajouter à cette balise :

  • name (obligatoire) : c'est le nom de la zone de texte. Choisissez-le bien, car c'est lui qui va produire une variable. Par exemple :
    <input type="text" name="pseudo" />
  • value (facultatif) : c'est ce que contient la zone de texte au départ. Par défaut, la zone de texte est vide. Mais il peut être pratique de pré-remplir le champ. Exemple :
    <input type="text" name="pseudo" value="M@teo21" />


Oui, je sais que vous commencez à vous inquiéter car vous n'avez pas encore vu de PHP pour le moment mais n'ayez pas peur. Le fonctionnement est tout simple et a un air de déjà vu. Le texte que le visiteur aura rentré sera disponible dans cible.php sous la forme d'une variable appelée $_POST['pseudo'].

Pour l'exemple, je vous propose de créer un formulaire qui demande le prénom du visiteur et qui l'affiche ensuite fièrement sur la page cible.php. On va donc distinguer 2 codes sources : celui de la page du formulaire et celui de la page cible.

Voici le code de la page formulaire.php :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<p>
    Cette page ne contient que du HTML.<br />
    Veuillez taper votre prénom :
</p>

<form action="cible.php" method="post">
<p>
    <input type="text" name="prenom" />
    <input type="submit" value="Valider" />
</p>
</form>


Rappel du 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.


Maintenant, je vous propose de créer la page cible.php. Cette page va recevoir le prénom dans une variable nommée $_POST['prenom'].

Code : PHP
1
2
3
4
5
<p>Bonjour !</p>

<p>Je sais comment tu t'appelles, hé hé. Tu t'appelles <?php echo $_POST['prenom']; ?> !</p>

<p>Si tu veux changer de prénom, <a href="formulaire.php">clique ici</a> pour revenir à formulaire.php</p>


Ce lien ouvre la page formulaire.php pour que vous puissiez tester :



Dans cible.php on a affiché une variable $_POST['prenom'] qui contient ce que l'utilisateur a rentré dans le formulaire.


Les grandes zones de texte



La grande zone de texte (qu'on appelle aussi "Zone de saisie multiligne" ^^ ), ressemble à ceci :

Image utilisateur

On peut y écrire autant de lignes que l'on veut. C'est plus adapté si le visiteur doit écrire un long message par exemple.

On va utiliser le code HTML suivant pour insérer cette grosse zone de texte :

Code : HTML
1
2
3
<textarea name="message" rows="8" cols="45">
Votre message ici.
</textarea>


Là encore, on a un attribut name qui va définir le nom de la variable qui sera créée dans cible.php. Dans notre cas, ce sera la variable $_POST['message'].

Vous remarquerez qu'il n'y a pas d'attribut value. En fait, le texte par défaut est ici écrit entre le <textarea> et le </textarea>. Si vous ne voulez rien mettre par défaut, alors n'écrivez rien entre <textarea> et </textarea>.

Les attributs rows et cols permettent de définir la taille de la zone de texte en hauteur et en largeur respectivement.



La liste déroulante



La liste déroulante, c'est ça :

Image utilisateur


On utilise le code HTML suivant pour construire une liste déroulante :

Code : HTML
1
2
3
4
5
6
<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>


Tout bêtement, on utilise la balise <select> à laquelle on donne un nom (ici : "choix"). On écrit ensuite les différentes options disponibles... Puis on referme la balise avec </select>.

Ici, une variable $_POST['choix'] sera créée, et elle contiendra le choix qu'a fait l'utilisateur. S'il a choisi "Choix 3", la variable $_POST['choix'] sera égale au value correspondant, c'est-à-dire "choix3".

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. On pourrait par exemple écrire :

Code : PHP
1
<option value="choix3" selected="selected">Choix 3</option>


Les cases à cocher



Une case à cocher ressemble à ceci :

Image utilisateur

On utilisera le code suivant pour afficher des cases à cocher :

Code : HTML
1
<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 d'utilisation. Pour en savoir plus, référez-vous au chapitre sur les formulaires du cours sur HTML et CSS.


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'].

  • Si la case est cochée, alors $_POST['case'] aura pour valeur "on".
  • Si elle n'est pas cochée, alors $_POST['case'] n'existera pas. Vous pouvez faire un test avec isset($_POST['case']) pour vérifier si la case a été cochée ou non.


Si vous voulez que la case soit cochée par défaut, il faudra lui rajouter l'attribut checked="checked". Par exemple :

Code : HTML
1
<input type="checkbox" name="case" checked="checked" />


Les boutons d'option



Les boutons d'option fonctionnent par groupes de 2 minimum. Par exemple :

Image utilisateur


Le code correspondant à cet exemple est le suivant :

Code : HTML
1
2
3
Aimez-vous les frites ?
<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>


Comme vous pouvez le voir, les deux boutons d'option ont le même nom ("frites"). C'est très important, car les boutons d'options fonctionnent par groupes : tous les boutons d'option d'un même groupe doivent avoir le même nom. Cela permet au navigateur de savoir quels boutons d'option désactiver quand on active un autre bouton d'option du groupe. Il serait bête en effet de pouvoir sélectionner "Oui" et "Non" à la fois. :D

Pour pré-cocher l'un de ces boutons d'option, faites pareil que pour les cases à cocher : rajoutez un attribut checked="checked". Ici, comme vous pouvez le voir, "Oui" est sélectionné par défaut.

Dans la page cible, une variable $_POST['frites'] sera créée. Elle aura la valeur du bouton d'option choisi par le visiteur, issue de l'attribut value. Si on aime les frites, alors on aura $_POST['frites'] = 'oui'.

Il faut bien penser à remplir l'attribut value du bouton d'option car c'est lui qui va déterminer la valeur de la variable. :)

Les champs cachés



Les champs cachés sont un type de champ à part. En quoi ça consiste ? C'est un code dans votre formulaire qui n'apparaîtra pas aux yeux du visiteur, mais qui va quand même créer une variable avec une valeur. On peut s'en servir pour transmettre des informations fixes.

Je m'explique : supposons que vous ayez besoin de "retenir" que le pseudo du visiteur est "Mateo21". Vous allez taper ce code :

Code : HTML
1
<input type="hidden" name="pseudo" value="Mateo21" />


A l'écran, sur la page web on ne verra rien. Mais dans la page cible, une variable $_POST['pseudo'] sera créée, et elle aura la valeur "Mateo21" !

C'est apparemment inutile, mais vous verrez que vous en aurez parfois besoin.

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 ! Vous vous souvenez de cette règle dont je vous ai parlé dans le chapitre précédent, elle est plus que jamais d'actualité.

Ne faites jamais confiance aux données reçues : la faille XSS

Vous vous souvenez des mises en garde que j'avais faites dans le chapitre précédent ? Elles ne concernaient pas que les paramètres qui transitent par l'URL : tout cela vaut aussi pour les formulaires !

Mais... autant je vois comment on peut modifier l'URL, autant je ne comprends pas comment peut faire un visiteur pour modifier le formulaire de mon site et trafiquer les données ? :o


On a tendance à croire que les visiteurs ne peuvent pas "bidouiller" le formulaire mais c'est faux. Je vais vous montrer dans un premier temps pourquoi les formulaires ne sont pas plus sûrs que les URL, puis je vous parlerai d'un autre danger important : la faille XSS. Avec ça, nous aurons vraiment fait le tour de ce qu'il faut savoir pour être tranquille par la suite ! :)

Pourquoi les formulaires ne sont pas sûrs



Tout ce que nous avons appris dans le chapitre précédent sur les URL reste valable ici. Tout ce qui vient de l'utilisateur, à savoir les données de $_GET et de $_POST, doit être traité avec la plus grande méfiance.

Vous ne pouvez pas supposer que vous allez recevoir ce que vous attendiez.

Cette règle est très simple, mais je vous propose un exemple concret pour bien visualiser le problème. Imaginez que vous demandez à vos visiteurs dans un champ leur date de naissance "au format JJ/MM/AAAA". Combien vont respecter cette mise en forme ? Combien vont se tromper par erreur ? Je vous garantis que parmi tous vos visiteurs, alors que vous attendiez quelque chose comme "04/10/1987", vous allez tomber sur un type qui va écrire "Je suis né le 4 octobre 1987". C'est un exemple un peu extrême mais ça va vous arriver, soyez-en sûrs. Par conséquent, quand vous ferez le traitement de la date en PHP, il faudra bien vérifier qu'elle respecte le format que vous avez indiqué.

Pour vérifier si une chaîne de texte correspond à un certain format, comme JJ/MM/AAAA, on peut utiliser une validation par expression régulière. Les expressions régulières feront l'objet de 2 chapitres vers la fin de ce cours car il s'agit d'un sujet assez complexe.


De la même manière, comme dans le chapitre précédent, même si vous demandez un nombre compris entre 1 et 100 il y aura bien quelqu'un pour écrire "48451254523". Soyez donc vigilants et n'ayez jamais confiance dans ce qui vient de l'utilisateur, à savoir les données issues des array $_GET et $_POST.

Avec les formulaires, vous ne pouvez pas non plus supposer qu'on va vous envoyer tous les champs que vous attendiez. Un visiteur peut très bien s'amuser à supprimer un champ de texte, et dans ce cas votre page cible.php ne recevra jamais le texte qu'elle attendait ! Il faudra impérativement qu'elle vérifie que toutes les données qu'elle attendait sont bien là avant d'effectuer des opérations.

Puisque la page du formulaire se trouve sur mon site, comment peut faire un visiteur pour modifier ma page web ? Il peut voir les sources mais pas les modifier !


En effet, vos visiteurs ne peuvent pas modifier vos pages web sur le serveur... Mais ils peuvent les reprendre et les modifier ailleurs. Souvenez-vous de ce schéma :

Envoi de données du formulaire


La page formulaire.php contient le formulaire et cible.php traite les données qu'on lui a envoyées. Autant le code PHP n'est jamais visible par vos visiteurs, autant le code HTML du formulaire, lui, peut être vu par tout le monde.

A partir de là, qu'est-ce qui empêche quelqu'un de créer une copie légèrement modifiée de votre formulaire et de la stocker sur son serveur ?

Le formulaire modifié


Sur le schéma ci-dessus, le "méchant" (nous l'appellerons comme ça, parce que ça lui va bien :p ) a pris le code HTML de votre formulaire, l'a modifié et l'a enregistré sur son serveur (ou même sur son ordinateur). L'attribut action a été modifié pour indiquer l'adresse absolue (donc complète) de votre page cible :

Code : PHP
1
<form method="post" action="http://www.monsite.com/cible.php">


Le méchant peut maintenant modifier votre formulaire, ajouter des champs, en supprimer, bref faire ce qu'il veut avec ! Votre page cible.php n'y verra que du feu car il est impossible de savoir avec certitude de quel formulaire vient le visiteur.

Ces explications sont assez techniques. En fait, on les réserve normalement aux personnes plus expérimentées que les débutants. Cependant, je tenais volontairement à vous montrer comment c'est possible. Même si tout n'est pas totalement clair dans votre tête, vous avez au moins l'idée du mode de fonctionnement.

S'il y a une chose à retenir ici, c'est que les formulaires sont modifiables par tous les visiteurs contrairement à ce qu'on pourrait penser. Par conséquent, votre page cible.php devra être aussi vigilante que nous l'avons été dans le chapitre précédent et ne pas faire confiance aux données de l'utilisateur. Souvenez-vous de cette maxime de programmeur : Never trust user input. ;)

Il y a un moyen encore plus simple de modifier le formulaire de votre site sans avoir accès à votre serveur. Internet Explorer 8 et Google Chrome embarquent des "outils pour les développeurs" qui permettent de modifier le code HTML de la page que l'on visite en temps réel. Firefox peut aussi faire de même avec son célèbre plugin Firebug.


La faille XSS : attention au code HTML que vous recevez !



Il reste un dernier point important à voir ensemble et après j'arrête de vous faire peur, promis ! :)

La faille XSS (pour cross-site scripting) est vieille comme le monde (euh, comme le Web :-° ) et on la trouve encore sur de nombreux sites web, même sur des sites web professionnels ! C'est une technique qui consiste à injecter du code HTML contenant du Javascript dans vos pages pour le faire exécuter à vos visiteurs.

Reprenons la page qui affiche le prénom qu'on lui envoie. Elle contient notamment le code suivant :

Code : PHP
1
<p>Je sais comment tu t'appelles, hé hé. Tu t'appelles <?php echo $_POST['prenom']; ?> !</p>


Si le visiteur décide d'écrire du code HTML à la place de son prénom, cela fonctionnera très bien ! Par exemple, imaginons qu'il écrive dans le champ "Prénom" le code : <strong>Badaboum</strong>. Le code source HTML qui sera généré par PHP sera le suivant :

Code : HTML
1
<p>Je sais comment tu t'appelles, hé hé. Tu t'appelles <strong>Badaboum</strong> !</p>


Et alors ? S'il veut mettre son prénom en gras c'est son problème non ?


Outre le fait qu'il peut insérer n'importe quel code HTML (et rendre votre page invalide), ce qui n'est pas le plus grave, il peut aussi ouvrir des balises de type <script> pour faire exécuter du code Javascript au visiteur qui visualisera la page !

Code : HTML
1
<p>Je sais comment tu t'appelles, hé hé. Tu t'appelles <script type="text/javascript">alert('Badaboum')</script> !</p>


Tous les visiteurs qui arriveront sur cette page verront une boîte de dialogue Javascript s'afficher. Plutôt gênant.

Exécution de Javascript par la faille XSS


Les choses deviennent vraiment critiques si le visiteur est assez malin pour récupérer vos cookies de cette façon-là. Les cookies stockent des informations sur votre session et parfois des informations plus confidentielles comme votre pseudonyme et votre mot de passe sur le site ! Il est possible de forcer le visiteur qui lira le code Javascript à vous envoyer tous les cookies qu'il a enregistrés pour votre site web, ce qui peut conduire au vol de son compte sur ce site.
Je ne rentrerai pas dans le détail de cette méthode car on s'éloignerait un peu trop du sujet, mais sachez que c'est possible et qu'il faut donc à tout prix éviter qu'un visiteur puisse injecter du code Javascript dans vos pages !


Résoudre le problème 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.

Eviter la faille XSS en échappant le HTML


Pour échapper le code HTML, il suffit d'utiliser la fonction htmlspecialchars qui va transformer les chevrons des balises HTML <> en &lt; et &gt; respectivement. Cela provoquera l'affichage de la balise plutôt que son exécution.

Code : PHP
1
<p>Je sais comment tu t'appelles, hé hé. Tu t'appelles <?php echo htmlspecialchars($_POST['prenom']); ?> !</p>


Le code HTML qui en résultera sera propre et protégé car les balises HTML insérées par le visiteur auront été échappées :

Code : HTML
1
<p>Je sais comment tu t'appelles, hé hé. Tu t'appelles &lt;strong&gt;Badaboum&lt;/strong&gt; !</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 à mettre du HTML dedans !) 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 htmlspecialchars.


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.

L'envoi de fichiers

Vous saviez qu'on pouvait aussi envoyer des fichiers grâce aux formulaires ? Vous aurez besoin de lire cette section si vous voulez que vos visiteurs puissent envoyer (on dit aussi uploader) des images, des programmes ou tout autre type de fichier sur votre site.

Cette section est un peu plus complexe que le reste du chapitre. Sa lecture n'est d'ailleurs pas obligatoire pour la bonne compréhension de la suite du cours.
Par conséquent, n'hésitez pas à revenir la lire plus tard, lorsque vous en aurez besoin, si vous ne voulez pas vous attaquer de suite à une partie un peu "difficile".


Là encore, ça se passe en 2 temps :

  1. Le visiteur arrive sur votre formulaire et le remplit (en indiquant le fichier à envoyer). Une simple page HTML suffit pour créer le formulaire.
  2. PHP réceptionne les données du formulaire et, s'il y a des fichiers dedans, il les "enregistre" dans un des dossiers du serveur.

Attention : l'envoi du fichier peut être un peu long si celui-ci est gros. Il faudra dire au visiteur de ne pas s'impatienter pendant l'envoi.


On va commencer par créer le formulaire permettant d'envoyer un fichier (une simple page HTML).
Nous verrons ensuite comment traiter l'envoi du fichier côté serveur avec PHP.


Le formulaire d'envoi de fichier



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>.

Code : HTML
1
2
3
<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 après.

Code : HTML
1
2
3
4
5
6
7
<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>


Voilà, c'est suffisant :)

Vous pouvez ajouter d'autres champs plus classiques au formulaire (champ de texte, cases à cocher). Vous pouvez aussi proposer d'envoyer plusieurs fichiers en même temps.
Là on va se contenter d'un seul champ (envoi de fichier) pour rester simple.


Le traitement de l'envoi en PHP



Comme vous avez dû le remarquer, 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 définitivement grâce à la fonction move_uploaded_file.


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 :

VariableSignification
$_FILES['monfichier']['name'] Contient le nom du fichier envoyé par le visiteur.
$_FILES['monfichier']['type'] Indique le type du fichier envoyé. Si c'est une image gif par exemple, le type sera image/gif.
$_FILES['monfichier']['size'] Indique la taille du fichier envoyé. Attention : cette taille est en octets. Il faut environ 1 000 octets pour faire 1 Ko, et 1 000 000 octets pour faire 1 Mo.
Attention, la taille de l'envoi est limitée par PHP. Par défaut, il est impossible d'uploader des fichiers de plus de 8 Mo.
$_FILES['monfichier']['tmp_name'] Juste après l'envoi, le fichier est placé dans un répertoire temporaire sur le serveur en attendant que votre script PHP décide si oui ou non il accepte de le stocker définitivement. Cette variable contient l'emplacement temporaire du fichier (c'est PHP qui gère ça).
$_FILES['monfichier']['error'] Contient un code d'erreur permettant de savoir si l'envoi s'est bien effectué ou s'il y a eu un problème, et si oui lequel.
La variable vaut 0 s'il n'y a pas eu d'erreur.

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 là.
$_FILES['nom_de_votre_autre_champ']['size'] contiendra ainsi la taille du second fichier, et ainsi de suite.


Je vous propose de faire les vérifications suivantes pour décider si on accepte le fichier ou non :

  1. Vérifier tout d'abord si le visiteur a bien envoyé un fichier (en testant la variable $_FILES['monfichier'] avec isset) et s'il n'y a pas eu d'erreur d'envoi (grâce à $_FILES['monfichier']['error'])
  2. Vérifier si la taille du fichier ne dépasse pas 1 Mo par exemple (environ 1 000 000 d'octets) grâce à $_FILES['monfichier']['size']
  3. Vérifier si l'extension du fichier est autorisée (il faut interdire à tout prix que les gens puissent envoyer des fichiers PHP, sinon ils pourraient exécuter des scripts sur votre serveur !). Dans notre cas, nous autoriserons seulement les images (fichiers .png, .jpg, .jpeg et .gif).
    Nous analyserons pour cela la variable $_FILES['monfichier']['name'].


Nous allons donc faire une série de tests dans notre page cible_envoi.php.

1/ Tester si le fichier a bien été envoyé



On commence par vérifier qu'un fichier a été envoyé en testant 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.

Code : PHP
1
2
3
4
5
6
7
<?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)
{
 
}
?>



2/ Vérifier la taille du fichier



On veut interdire que le fichier dépasse 1 Mo, soit environ 1 000 000 d'octets (j'arrondis pour simplifier). On doit donc tester $_FILES['monfichier']['size'] :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?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)
        {
 
        }
}
?>


3/ Vérifier l'extension du fichier



On peut récupérer l'extension du fichier dans une variable grâce à ce code :

Code : PHP
1
2
3
4
<?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 ! Ca donne ça au final :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?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))
                {
                
                }
        }
}
?>



4/ Valider l'upload du fichier



Si tout est bon, on accepte le fichier en appelant move_uploaded_file().
Cette fonction prend 2 paramètres :

  • Le nom temporaire du fichier (on l'a avec $_FILES['monfichier']['tmp_name']).
  • Le chemin est le nom sous lequel sera stocké le fichier de façon définitive. On peut utiliser le nom d'origine du fichier $_FILES['monfichier']['name'] ou générer un nom au hasard.


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" :)

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?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 le net à 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 des 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.


Pour aller plus loin, je vous recommande de lire le tutoriel de DHKold sur l'upload de fichiers par formulaire. Il est plus complet que le mien et vous expliquera mieux certains détails.

Bonne lecture ;)

Q.C.M.

Si on ne met pas d'attribut action au formulaire, que va-t-il se passer ?
Quelle variable sera créée avec cette zone de texte
Code : HTML
1
<input type="text" name="ville" />
Quelle sera la variable créée, et quelle sera sa valeur, si on ne change pas le texte par défaut de la grosse zone de texte ci-dessous ?
Code : HTML
1
2
3
<textarea name="news" rows="8" cols="45">
Tapez la news ici.
</textarea>
Quel est l'attribut à rajouter à une case à cocher pour qu'elle soit cochée par défaut ?
Quelle est la valeur d'une variable correspondant à une case à cocher cochée ?
Que va produire ce code HTML ?
Code : HTML
1
<input type="hidden" name="age" value="18" />
Que fait un visiteur qui tente d'exploiter une faille XSS ?
Quel est le nom de l'array qui contient des informations sur les fichiers envoyés via le formulaire ?

Statistiques de réponses au QCM

Chapitre précédent Sommaire Chapitre suivant

Partager

156 commentaires pour "Transmettre des données avec les formulaires"
Note moyenne : 3.61 / 4 (2409 votes)
Pseudo Commentaire
Hors ligne wizzor # Posté le 28/10/2011 à 16:13:19
Avatar

Bonjour,

il me semble qu'il a une erreur dans le code sur la page "transmettre des données avec les formulaires", rubrique "l'envoi de fichiers > le traitement de l'envoi en php > 3/vérifier l'extension du fichier. Dans cette partie en effet, le premier code affiche les variables $_FILES et $extension_upload avec l'underscore, mais dans le code suivant, dans la partie surlignée en jaune, ces underscore disparaissent sur les 3 premières lignes ($ FILES, $extension upload, extension autorisees).

Est-ce bien une erreur de code ou est-ce que j'ai raté quelque chose dans le cours?

Merci

Tout le monde est un génie, mais si vous jugez un poisson par son habileté à grimper aux arbres, il vivra toute sa vie pensant être stupide.
 
Hors ligne Meeshkah # Posté le 06/11/2011 à 23:42:37

Ville : Courbevoie
Pays : France métropolitaine
Études : ISBS-Paris

Bonjour,

Je poste ici parce que je pense qu'il pourrait être intéressant de le savoir ou de le faire savoir :

Est-il possible d'utiiser les variables $_GET et $_POST en même temps ?



Explication :


On précise un fichier d'action de formulaire en faisant passer des information dans l'URL.

Démonstration :


On utilise par exemple un fichier index.php?cat=<cat> où <cat> est un id qui identifie un autre fichier php à appeler dans un include() un peu plus loin.
Bon.
Maintenant si on veut faire cet appel dans un form :
Code : PHP
1
<form action="index.php?id=6" method="post">

Eh bien j'ai l’impression que ce n'est pas possible. Mais je rate peut-être quelque chose.


Encore une fois, désolé si ce n'est pas le bon endroit pour poser cette question.
Et une ènième fois : bravo pour le tuto, je ne m'en lasse jamais, j'y reviens très régulièrement, c'est une référence pour moi.

Meeshkah
Hors ligne julioss # Posté le 18/11/2011 à 19:22:58

Citation : simabd
j'ai un petit problème ,je n'arrive pas a récupérer le prénom ,la page cible n'affiche rien , j'ai utiliser les mêmes fichiers du tutoriel et encore ça donne le même problème.


Idem :(
Hors ligne gefften # Posté le 04/12/2011 à 01:20:09

Ville : Bouscat
Pays : France métropolitaine
Études : UTT

Citation : julioss
Citation : simabd
j'ai un petit problème ,je n'arrive pas a récupérer le prénom ,la page cible n'affiche rien , j'ai utiliser les mêmes fichiers du tutoriel et encore ça donne le même problème.


Idem :(


Idem. Un peu d'aide svp !

Merci
Hors ligne abdae # Posté le 20/01/2012 à 14:01:07
Programmeur (pour en jeux en )

Citation : gefften
Citation : julioss
Citation : simabd
j'ai un petit problème ,je n'arrive pas a récupérer le prénom ,la page cible n'affiche rien , j'ai utiliser les mêmes fichiers du tutoriel et encore ça donne le même problème.


Idem :(


Idem. Un peu d'aide svp !

Merci


salut,

avez vous copie sa dans le fichier cible ? :


Code : PHP
1
2
3
4
5
<p>Bonjour !</p>

<p>Je sais comment tu t'appelles, hé hé. Tu t'appelles <?php echo $_POST['prenom']; ?> !</p>

<p>Si tu veux changer de prénom, <a href="formulaire.php">clique ici</a> pour revenir à formulaire.php</p>

Voir tous les commentaires