IV. Formulaire réparti sur plusieurs pages▲
L'un des thèmes récurrents de nos forums est « j'ai un formulaire sur plusieurs pages, comment faire pour… » : après avoir lu ce tutoriel jusqu'ici, vous devriez savoir que la majorité des formulaires peuvent être présentés en une seule page (notamment à l'aide de la balise >fieldset<)..
Cependant, certaines situations nécessitent un formulaire tellement long qu'il est préférable de le découper en plusieurs étapes, chacune étant située sur sa propre page. Nous allons voir ici plusieurs méthodes pour y parvenir.
Prenons un exemple concret : un site de recherche d'emploi. Chaque postulant doit renseigner plusieurs dizaines d'informations, ce qui rendrait le tout impossible à gérer si nous ne proposions qu'un unique formulaire. Il est préférable d'y aller par étapes.
Voici ce sur quoi nous allons nous fonder :
- Informations de connexion
- Informations personnelles
- Études
- Expérience
- Connaissances
- Alertes
Je vous propose d'utiliser un fichier d'index et plusieurs fichiers à inclure. Cela permet d'avoir nos formulaires HTML dans des fichiers séparés du code PHP. Pour les connaisseurs, cette méthode est très similaire à l'utilisation d'un moteur de gabarits et vous n'aurez aucun mal à l'adapter.
Arborescence du site :
- /index.php
- /forms/1-connection-data.php
- /forms/2-personal-data.php
- /forms/3-studies.php
- /forms/4-summary.php
IV-A. Les formulaires▲
Mon objectif ici n'est pas de construire un site de recherche d'emploi, je ne vais donc pas étudier toutes les étapes en détail. Les trois premières suffiront et je ne vais proposer ici que des formulaires simples.
Informations de connexion▲
Ce premier formulaire concerne l'arrivée de l'internaute sur notre page : ses informations de connexion (nom d'utilisateur et mot de passe) et comment il nous a connus.
<
form method
=
"
post
"
action
=
"
<?php
echo CFG_FORM_ACTION;
?>
?stage=
<?php
echo CFG_STAGE_ID+
1
;
?>
"
>
<
fieldset>
<
legend>
Informations de connexion<
/legend
>
<
label>
Adresse e-mail :
<
input type
=
"
text
"
name
=
"
e-mail
"
value
=
"
<?php
echo $_SESSION
[
'forms'
][
CFG_STAGE_ID][
'e-mail'
];
?>
"
/
>
<
/label
><br /
>
<
label>
Mot de passe :
<
input type
=
"
password
"
name
=
"
password-1
"
/
>
<
/label
><br /
>
<
label>
Mot de passe (répéter) :
<
input type
=
"
password
"
name
=
"
password-2
"
/
>
<
/label
>
<
/fieldset
><br /
>
<
fieldset>
<
legend>
Autres informations<
/legend
>
<
label>
Comment nous avez-vous connus ?
<
select name
=
"
referer
"
>
<
option value
=
"
friend
"
<?php
if
($_SESSION
[
'forms'
][
CFG_STAGE_ID][
'referer'
]
==
'friend'
){
echo ' selected="selected"'
;}
?>
>
Par un ami<
/option
>
<
option value
=
"
search-engine
"
<?php
if
($_SESSION
[
'forms'
][
CFG_STAGE_ID][
'referer'
]
==
'search-engine'
){
echo ' selected="selected"'
;}
?>
>
Par un moteur de recherche<
/option
>
<
option value
=
"
press
"
<?php
if
($_SESSION
[
'forms'
][
CFG_STAGE_ID][
'referer'
]
==
'press'
){
echo ' selected="selected"'
;}
?>
>
Par la presse<
/option
>
<
option value
=
"
other
"
<?php
if
($_SESSION
[
'forms'
][
CFG_STAGE_ID][
'referer'
]
==
'other'
){
echo ' selected="selected"'
;}
?>
>
Autre<
/option
>
<
/select
>
<
/label
><br /
>
<
label>
Pouvez-vous préciser ?
<
input type
=
"
text
"
name
=
"
details
"
value
=
"
<?php
echo $_SESSION
[
'forms'
][
CFG_STAGE_ID][
'details'
];
?>
"
/
>
<
/label
>
<
/fieldset
>
<
input type
=
"
submit
"
value
=
"
Envoyer et continuer
"
/
>
<
/form
>
Informations personnelles▲
C'est ici qu'il faut demander toutes les informations civiles à notre internaute. En situation réelle, il faudrait étoffer cette liste.
<
form method
=
"
post
"
action
=
"
<?php
echo CFG_FORM_ACTION;
?>
?stage=
<?php
echo CFG_STAGE_ID+
1
;
?>
"
>
<
fieldset>
<
legend>
Informations personnelles<
/legend
>
<
label>
Prénom :
<
input type
=
"
text
"
name
=
"
first-name
"
value
=
"
<?php
echo $_SESSION
[
'forms'
][
CFG_STAGE_ID][
'first-name'
];
?>
"
/
>
<
/label
><br /
>
<
label>
Nom :
<
input type
=
"
text
"
name
=
"
last-name
"
value
=
"
<?php
echo $_SESSION
[
'forms'
][
CFG_STAGE_ID][
'last-name'
];
?>
"
/
>
<
/label
><br /
>
<
label>
Ville :
<
input type
=
"
text
"
name
=
"
city
"
value
=
"
<?php
echo $_SESSION
[
'forms'
][
CFG_STAGE_ID][
'city'
];
?>
"
/
>
<
/label
><br /
>
<
label>
Code postal :
<
input type
=
"
text
"
name
=
"
postal-code
"
value
=
"
<?php
echo $_SESSION
[
'forms'
][
CFG_STAGE_ID][
'postal-code'
];
?>
"
/
>
<
/label
><br /
>
<
/fieldset
>
<
input type
=
"
submit
"
value
=
"
Envoyer et continuer
"
/
>
<
/form
>
Études▲
Comme ce tutoriel n'est qu'un exemple d'un formulaire réparti sur plusieurs pages, j'ai simplifié ce formulaire à un simple contrôle <textarea>. Dans une situation réelle, il faudrait un formulaire bien plus flexible que cela.
<
form method
=
"
post
"
action
=
"
<?php
echo CFG_FORM_ACTION;
?>
?stage=
<?php
echo CFG_STAGE_ID+
1
;
?>
"
>
<
fieldset>
<
legend>
Informations personnelles<
/legend
>
<
label>
Études :<
br /
>
<
textarea name
=
"
studies
"
cols
=
"
15
"
rows
=
"
10
"
>
<?php
echo $_SESSION
[
'forms'
][
CFG_STAGE_ID][
'studies'
];
?>
<
/textarea
>
<
/label
>
<
/fieldset
>
<
input type
=
"
submit
"
value
=
"
Envoyer et continuer
"
/
>
<
/form
>
Résumé▲
IV-B. La page d'index▲
Les informations de chaque formulaire soumis sont intégralement conservées sur le serveur et nous les réutilisons chaque fois que l'internaute en a besoin. Le plus simple est d'utiliser des sessions, mais le plus flexible est bien sûr d'utiliser une base de données. Quoi qu'il en soit, la session est nécessaire pour passer les informations d'un formulaire à l'autre.
Pour simplifier les exemples, je vais me contenter d'une session PHP sans base de données.
Mise en place des variables▲
Le début de notre script d'index doit mettre en place l'environnement : la session et les variables de configuration.
session_start();
// Configuration du script
define('
CFG_FORM_ACTION
'
,
basename(__FILE__));
// Cela permet de changer le nom du script d'index
$forms
=
array( // Voici la liste des formulaires, pratique pour mettre en place le menu de navigation
1
=>
'
Informations de connexion
'
,
2
=>
'
Informations personnelles
'
,
3
=>
'
Études
'
);
// Récupération du numéro de l'étape en cours
if(empty($_GET
[
'
stage
'
]
) or !
is_numeric($_GET
[
'
stage
'
]
))
{
define('
CFG_STAGE_ID
'
,
1
);
}
else
{
// En situation réelle, il faudrait vérifier l'existence de cette page
define('
CFG_STAGE_ID
'
,
intval($_GET
[
'
stage
'
]
));
}
// Déclaration de la variable de session
if(empty($_SESSION
[
'
forms
'
]
))
{
$_SESSION
[
'
forms
'
]
=
array();
}
Les liens en haut de la page▲
Il est toujours intéressant de proposer un menu de navigation à notre utilisateur. Ici, cela lui évitera probablement d'utiliser les boutons de navigation de son navigateur, tellement agaçants par moments.
Les pages qui n'ont pas encore été visitées ne comportent pas de lien, afin d'éviter à l'utilisateur de sauter des étapes. Dans une situation réelle, il faudrait vérifier que l'utilisateur n'a pas modifié le paramètre de l'URI à la main.
// Affichage du menu en haut de la page
$items
=
array();
foreach($forms
as $form_id
=>
$form_name
)
{
if(empty($_SESSION
[
'
forms
'
][
$form_id
]
))
{
$items
[]
=
$form_name
;
}
else
{
$items
[]
=
'
<a href="
'
.
basename(__FILE__).
'
?stage=
'
.
$form_id
.
'
">
'
.
$form_name
.
'
</a>
'
;
}
}
$items
[]
=
'
<a href="
'
.
basename(__FILE__).
'
?stage=4">Résumé</a>
'
;
echo implode('
-
'
,
$items
).
'
<br /><br />
'
;
Traitement des données utilisateur▲
Enfin, il nous faut traiter les données envoyées par notre internaute, c'est-à-dire qu'il faut les envoyer dans notre variable de session (ou dans la base de données, le cas échéant).
Puisque ce script est un peu long, je vous propose d'abord son squelette pour vous permettre de vous familiariser avec son fonctionnement.
// Récupération des informations, affichage du formulaire
switch(CFG_STAGE_ID)
{
case 4
:
// Récupération des informations du formulaire précédent
if(!
empty($_POST
))
{
// Vérification des champs puis affectation à la variable de session
}
// Inclusion de la page de résumé
break;
case 3
:
// Valeurs par défaut
if(empty($_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
))
{
$_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
=
...
}
// Récupération des informations du formulaire précédent
if(!
empty($_POST
))
{
// Vérification des champs puis affectation à la variable de session
}
// Inclusion du formulaire adéquat
break;
case 2
:
// Valeurs par défaut
if(empty($_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
))
{
$_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
=
...
}
// Récupération des informations du formulaire précédent
if(!
empty($_POST
))
{
// Vérification des champs puis affectation à la variable de session
}
// Inclusion du formulaire adéquat
break;
case 1
:
default:
// Valeurs par défaut
if(empty($_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
))
{
$_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
=
...
}
// Inclusion du formulaire adéquat
break;
}
La structure de ce script me semble suffisamment claire pour parler d'elle-même : selon l'étape en cours, nous effectuons un traitement ou un autre. Voyons maintenant le script réel.
// Récupération des informations, affichage du formulaire
switch(CFG_STAGE_ID)
{
case 4
:
// Récupération des informations du formulaire précédent
if(!
empty($_POST
))
{
if(!
empty($_POST
[
'
studies
'
]
))
{
$_SESSION
[
'
forms
'
][
CFG_STAGE_ID-
1
]
=
array(
'
studies
'
=>
$_POST
[
'
studies
'
]
);
}
}
// Affichage du formulaire
require('
./forms/4-summary.php
'
);
break;
case 3
:
// Valeurs par défaut
if(empty($_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
))
{
$_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
=
array(
'
studies
'
=>
''
);
}
// Récupération des informations du formulaire précédent
if(!
empty($_POST
))
{
if(!
empty($_POST
[
'
last-name
'
]
)
and !
empty($_POST
[
'
first-name
'
]
)
and !
empty($_POST
[
'
city
'
]
)
and !
empty($_POST
[
'
postal-code
'
]
)
and is_numeric($_POST
[
'
postal-code
'
]
))
{
$_SESSION
[
'
forms
'
][
CFG_STAGE_ID-
1
]
=
array(
'
first-name
'
=>
$_POST
[
'
first-name
'
],
'
last-name
'
=>
$_POST
[
'
last-name
'
],
'
city
'
=>
$_POST
[
'
city
'
],
'
postal-code
'
=>
$_POST
[
'
postal-code
'
]
);
}
}
// Affichage du formulaire
require('
./forms/3-studies.php
'
);
break;
case 2
:
// Valeurs par défaut
if(empty($_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
))
{
$_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
=
array(
'
first-name
'
=>
''
,
'
last-name
'
=>
''
,
'
city
'
=>
''
,
'
postal-code
'
=>
NULL
);
}
// Récupération des informations du formulaire précédent
if(!
empty($_POST
))
{
if(!
empty($_POST
[
'
e-mail
'
]
)
and !
empty($_POST
[
'
password-1
'
]
)
and !
empty($_POST
[
'
password-2
'
]
)
and preg_match('
/^([^@\s<&>]+)@(?:([-a-z0-9]+)\.)+([a-z]{2,})$/i
'
,
$_POST
[
'
e-mail
'
]
)
and $_POST
[
'
password-1
'
]
==
$_POST
[
'
password-2
'
]
)
{
$_SESSION
[
'
forms
'
][
CFG_STAGE_ID-
1
]
=
array(
'
e-mail
'
=>
$_POST
[
'
e-mail
'
],
'
password
'
=>
md5($_POST
[
'
password-1
'
]
),
'
referer
'
=>
$_POST
[
'
referer
'
],
'
details
'
=>
$_POST
[
'
details
'
]
);
}
}
require('
./forms/2-personal-data.php
'
);
break;
case 1
:
default:
// Valeurs par défaut
if(empty($_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
))
{
$_SESSION
[
'
forms
'
][
CFG_STAGE_ID]
=
array(
'
e-mail
'
=>
''
,
'
password
'
=>
''
,
'
referer
'
=>
'
friend
'
,
'
details
'
=>
''
);
}
require('
./forms/1-connection-data.php
'
);
break;
}
IV-C. Fonctionnement▲
IV-C-1. Mise en place▲
La mise en place de ces formulaires est simple : il suffit de créer l'arborescence évoquée plus haut.
IV-C-2. Navigation▲
Ma foi, la navigation est intuitive… Il faut remplir les formulaires à partir du premier jusqu'au dernier et il est possible de revenir en arrière.
IV-C-3. Sécurité▲
Comme toujours dans ce tutoriel, je n'ai effectué que des contrôles minimalistes. Ce n'est pas le sujet ici, mais, en situation réelle, il convient de s'y attarder davantage.