Structure d'un formulaire
Créez site8 en copiant site7.
- /cms
- ...
- site7
- site8
Dans ce chapitre, nous allons ajouter une page de contact avec un formulaire d'envoi d'un email au webmestre du site.
Pour tester le résultat en ligne, entrez http://www.frasq.org/cms/site8 dans la barre d'adresse de votre navigateur. Remplissez le formulaire et envoyez-le. Essayez d'envoyer le formulaire avec des champs vides ou une adresse d'email invalide.
Commencez par créer une action appelée contact
en ajoutant le fichier contact.php dans le dossier actions avec le contenu suivant :
- /cms/site8
- actions
- contact.php
- actions
- function contact($lang) {
- head('title', translate('contact:title', $lang));
- head('description', false);
- head('keywords', false);
- head('robots', 'noindex, nofollow');
- $banner = build('banner', $lang);
- $mailme = build('mailme', $lang);
- $content = view('contact', $lang, compact('mailme'));
- $output = layout('standard', compact('banner', 'content'));
- return $output;
- }
Remarquez que la page de contact n'a pas de description ou de mots clés.
La balise robots
demande aux moteurs de recherche d'ignorer cette page.
Pour donner l'accès au formulaire, ajoutez un alias par langue dans le fichier includes/aliases.inc :
- $aliases = array(
- 'fr' => array(
- 'accueil' => 'home',
- 'contact' => 'contact',
- ),
- 'en' => array(
- 'home' => 'home',
- 'contact' => 'contact',
- ),
- );
Ajoutez le titre de la page dans le fichier includes/strings.inc.
En français dans le tableau 'fr' :
- 'contact:title' => 'Nous contacter',
En anglais dans le tableau 'en' :
- 'contact:title' => 'Contact us',
Ajoutez la vue de la page de contact dans les dossiers views/fr pour la version en français et views/en pour la version en anglais.
- /cms/site8
- views
- fr
- contact.phtml
- en
- contact.phtml
- fr
- views
- <h3>Contact</h3>
- <?php echo $mailme; ?>
- <h3>Contact</h3>
- <?php echo $mailme; ?>
La vue est identique en français et en anglais et vous pourriez la sauvegarder directement dans views mais si la ligne de titre change ou si vous ajoutez une autre langue plus tard, les vues seront différentes. Tenez-vous en donc au plan général.
Le formulaire d'envoi d'un email est dans un bloc. Commencez par écrire la vue du bloc, d'abord dans une langue :
- /cms/site8
- views
- fr
- contact.phtml
- mailme.phtml
- fr
- views
- <div class="form" id="mailme_form">
- <form action="" method="post">
- <div class="fields">
- <p class="label">Quelle est votre adresse d'email ?</p>
- <p class="input"><input type="text" name="mailme_mail" id="mailme_mail" size="50" maxlength="100" title="Email" value="<?php echo htmlspecialchars($mail, ENT_COMPAT, 'UTF-8'); ?>" /></p>
- <p class="info">Votre adresse d'email est strictement confidentielle.</p>
- <p class="label">Tapez le sujet et le texte de votre message :</p>
- <p class="input"><input class="monospace" type="text" name="mailme_subject" id="mailme_subject" size="60" maxlength="100" title="Sujet" value="<?php echo htmlspecialchars($subject, ENT_COMPAT, 'UTF-8'); ?>" /></p>
- <p class="input"><textarea class="monospace" name="mailme_message" id="mailme_message" cols="70" rows="8" title="Texte"><?php echo htmlspecialchars($message, ENT_COMPAT, 'UTF-8'); ?></textarea></p>
- <p class="submit"><button type="submit" name="mailme_send" id="mailme_send">Envoyer</button></p>
- </div>
- </form>
Le formulaire comprend 3 champs de saisie : adresse d'email de l'expéditeur, sujet du message et texte du message. 3 variables sont nécessaires : $mail
, $subject
et $message
. Tous les noms des champs sont préfixés par mail_
. Le formulaire a un seul bouton appelé mailme_send
.
Le reste de la vue gère tous les messages d'erreur ou d'information.
Les erreurs possibles sont $missing_mail
, $bad_mail
, $missing_message
, $missing_subject
, $bad_subject
et $internal_error
.
Si $email_sent
est true
, le formulaire signale à l'utilisateur que le message a bien été envoyé.
- <?php if ($errors):
- extract($errors);
- ?>
- <div class="errors">
- <?php if ($missing_mail): ?>
- <p>Vous n'avez pas donné votre adresse d'email.</p>
- <?php elseif ($bad_mail): ?>
- <p>L'adresse d'email est invalide.</p>
- <?php endif; ?>
- <?php if ($missing_message): ?>
- <p>Le message est vide.</p>
- <?php endif; ?>
- <?php if ($missing_subject): ?>
- <p>N'oubliez pas le sujet.</p>
- <?php elseif ($bad_subject): ?>
- <p>Le sujet du message est invalide.</p>
- <?php endif; ?>
- <?php if ($internal_error): ?>
- <p>Une erreur interne s'est produite.</p>
- <?php endif; ?>
- </div>
- <?php endif; ?>
- <?php if ($infos):
- extract($infos);
- ?>
- <div class="infos">
- <?php if ($email_sent): ?>
- <p>Votre message a bien été envoyé. Pour revenir à la page d'accueil, <a href="<?php echo $home_page; ?>">cliquez ici</a>.</p>
- <?php endif; ?>
- </div>
- <?php endif; ?>
- </div>
Quelques retouches à la feuille de style :
- img {vertical-align:middle;}
- .monospace {font-family:monospace;}
- .info {color:#666666;font-size:smaller;font-style:normal;}
- .error {color:#df6f6f;font-size:smaller;font-style:italic;}
- .input .monospace {font-size:medium;}
- .errors {color:#df6f6f;font-size:small;font-style:normal;}
- .infos {font-style:normal;}
Pour valider la vue, écrivez une première version de la fonction mailme
qui se limite à l'affichage du formulaire :
- /cms/site8
- blocks
- mailme.php
- blocks
- function mailme($lang) {
- $mail=$subject=$message=false;
- $missing_mail=false;
- $bad_mail=false;
- $missing_subject=false;
- $bad_subject=false;
- $missing_message=false;
- $email_sent=false;
- $home_page=url('home', $lang);
- $internal_error=false;
- $errors = compact('missing_mail', 'bad_mail', 'missing_subject', 'bad_subject', 'missing_message', 'internal_error');
- $infos = compact('email_sent', 'home_page');
- $output = view('mailme', $lang, compact('mail', 'subject', 'message', 'errors', 'infos'));
- return $output;
- }
Entrez http://localhost/cms/site8/fr/contact dans la barre d'adresse de votre navigateur.
Éditez la fonction mailme
. Donnez des valeurs aux variables des champs de saisie. Mettez toutes les variables d'erreur et d'information à true
. Vérifiez le lien sur la page d'accueil.
Ajoutez la vue en anglais :
- /cms/site8
- views
- en
- contact.phtml
- mailme.phtml
- en
- views
- <div class="form" id="mailme_form">
- <form action="" method="post">
- <div class="fields">
- <p class="label">What is your email address?</p>
- <p class="input"><input type="text" name="mailme_mail" id="mailme_mail" size="50" maxlength="100" title="Email" value="<?php echo htmlspecialchars($mail, ENT_COMPAT, 'UTF-8'); ?>" /></p>
- <p class="info">Your email address is strickly confidential.</p>
- <p class="label">Type in the subject and the text of your message:</p>
- <p class="input"><input class="monospace" type="text" name="mailme_subject" id="mailme_subject" size="60" maxlength="100" title="Subject" value="<?php echo htmlspecialchars($subject, ENT_COMPAT, 'UTF-8'); ?>" /></p>
- <p class="input"><textarea class="monospace" name="mailme_message" id="mailme_message" cols="70" rows="8" title="Text"><?php echo htmlspecialchars($message, ENT_COMPAT, 'UTF-8'); ?></textarea></p>
- <p class="submit"><button type="submit" name="mailme_send" id="mailme_send">Send</button></p>
- </div>
- </form>
- <?php if ($errors):
- extract($errors);
- ?>
- <div class="errors">
- <?php if ($missing_mail): ?>
- <p>You haven't given your email address.</p>
- <?php elseif ($bad_mail): ?>
- <p>The email address is invalid.</p>
- <?php endif; ?>
- <?php if ($missing_message): ?>
- <p>The message is empty.</p>
- <?php endif; ?>
- <?php if ($missing_subject): ?>
- <p>Don't forget the subject.</p>
- <?php elseif ($bad_subject): ?>
- <p>The subject of the message is invalid.</p>
- <?php endif; ?>
- <?php if ($internal_error): ?>
- <p>An internal error has occurred.</p>
- <?php endif; ?>
- </div>
- <?php endif; ?>
- <?php if ($infos):
- extract($infos);
- ?>
- <div class="infos">
- <?php if ($email_sent): ?>
- <p>Your message has been sent. To return to the home page, <a href="<?php echo $home_page; ?>">click here</a>.</p>
- <?php endif; ?>
- </div>
- <?php endif; ?>
- </div>
Entrez http://localhost/cms/site8/en/contact dans la barre d'adresse de votre navigateur pour valider la version anglaise.
Une fois la mise au point des vues terminée, vous pouvez passer à l'analyse de la saisie. Bien structurer le code est très important. Le déroulement est toujours le même :
- Déterminer l'action demandée et initialiser les variables du formulaire.
- Lire les champs de saisie et assigner les variables du formulaire.
- Initialiser les variables d'erreur et d'information puis filtrer et valider les données.
- Exécuter l'action demandée si aucune erreur n'a été détectée.
- Générer la vue du formulaire selon les valeurs calculées.
Complétez mailme
avec le code suivant :
- require_once 'readarg.php';
- require_once 'validatemail.php';
- require_once 'ismailinjected.php';
Charge le code des fonctions readarg
, validate_mail
et is_mail_injected
. Chaque fonction est définie dans un fichier séparé dans le dossier library :
- /cms/site8
- library
- readarg.php
- validatemail.php
- ismailinjected.php
- library
- function readarg($s, $trim=true) {
- if ($trim) {
- $s = trim($s);
- }
- return $s;
- }
Si $trim
vaut true
, ce qui est le cas par défaut, readarg
retire aussi les espaces au début ou à la fin de $s
.
Appelez systématiquement cette fonction pour filtrer tous les champs retournés par un formulaire.
- function readarg($s, $trim=true) {
- if ($trim) {
- $s = trim($s);
- }
- return get_magic_quotes_gpc() ? stripslashes($s) : $s;
- }
Dans cette version utilisée avant PHP 7, readarg
retire les \ (BACKSLASH) de $s
ajoutés automatiquement par PHP dans les variables $_GET
et $_POST
si le paramètre de configuration magic_quotes_gpc
est à true
.
- function validate_mail($email) {
- return preg_match('/^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/', $email);
- }
validate_mail
retourne true
si $email
est une adresse d'email valide, false
dans le cas contraire.
- function is_mail_injected($s) {
- $injections = array(
- '(\n+)',
- '(\r+)',
- '(\t+)',
- '(%0A+)',
- '(%0D+)',
- '(%08+)',
- '(%09+)'
- );
- $reg = implode('|', $injections);
- $reg = "/$reg/";
- return preg_match($reg, $s);
- }
is_mail_injected
retourne true
si $s
contient des caractères susceptibles de permettre une injection dans le contenu d'un email, false
si $s
est sans danger.
- function mailme($lang) {
- $action='init';
- if (isset($_POST['mailme_send'])) {
- $action='send';
- }
- $mail=$subject=$message=false;
mailme
commence par initialiser $action
à 'send'
si l'utilisateur a appuyé sur le bouton Envoyer ou à 'init'
par défaut, quand le formulaire est directement affiché.
- switch($action) {
- case 'send':
- if (isset($_POST['mailme_mail'])) {
- $mail=strip_tags(readarg($_POST['mailme_mail'], true));
- }
- if (isset($_POST['mailme_subject'])) {
- $subject=strip_tags(readarg($_POST['mailme_subject'], true));
- }
- if (isset($_POST['mailme_message'])) {
- $message=strip_tags(readarg($_POST['mailme_message'], true));
- }
- break;
- default:
- break;
- }
Lit les champs de saisie et les filtre avec readarg
puis la fonction strip_tags
de PHP qui retire toutes les balises potentiellement dangereuses.
- $missing_mail=false;
- $bad_mail=false;
- $missing_subject=false;
- $bad_subject=false;
- $missing_message=false;
- $email_sent=false;
- $home_page=url('home', $lang);
- $internal_error=false;
- switch($action) {
- case 'send':
- if (!$mail) {
- $missing_mail=true;
- }
- else if (!validate_mail($mail)) {
- $bad_mail=true;
- }
- if (!$subject) {
- $missing_subject=true;
- }
- else if (is_mail_injected($subject)) {
- $bad_subject=true;
- }
- if (!$message) {
- $missing_message=true;
- }
- break;
- default:
- break;
- }
Initialise toutes les variables d'erreur et d'information avant de valider les données envoyées par le formulaire.
- switch($action) {
- case 'send':
- if ($missing_mail or $bad_mail or $missing_subject or $bad_subject or $missing_message) {
- break;
- }
- require_once 'emailme.php';
- $r = emailme($subject, $message, $mail);
- if (!$r) {
- $internal_error=true;
- break;
- }
- $subject=$message=false;
- $email_sent=true;
- break;
- default:
- break;
- }
Vérifie qu'aucune erreur n'a été détectée et envoie un courrier au webmestre avec la fonction emailme
.
- $errors = compact('missing_mail', 'bad_mail', 'missing_subject', 'bad_subject', 'missing_message', 'internal_error');
- $infos = compact('email_sent', 'home_page');
- $output = view('mailme', $lang, compact('mail', 'subject', 'message', 'errors', 'infos'));
- return $output;
- }
Prépare tous les paramètres de la vue, la génère et retourne son contenu.
Créez la fonction emailme
dans le fichier library/emailme.php avec le contenu suivant :
- function emailme($subject, $msg, $sender=false) {
- global $webmaster, $mailer;
- if (empty($sender)) {
- $sender = $webmaster;
- }
- $headers = <<<_SEP_
- From: $sender
- Return-Path: $sender
- Content-Type: text/plain; charset=utf-8
- X-Mailer: $mailer
- _SEP_;
- return @mail($webmaster, $subject, $msg, $headers);
- }
Les variables globales $webmaster
et $mailer
sont définies dans le fichier de configuration includes/config.inc :
- global $sitename, $webmaster, $mailer;
- $sitename = 'frasq.org';
- $webmaster = 'nobody@frasq.org';
- $mailer = 'Frasq';
Remplacez l'adresse nobody@frasq.org par webmaster@localhost. Vous pouvez aussi changer le nom du mailer.
Éditez le fichier /etc/aliases et rediriger le courrier local envoyé à webmaster
vers votre compte personnel :
webmaster: frasq
NOTE : Remplacez frasq
par votre nom de connexion.
Notifiez le service :
$ sudo newaliases
Lisez l'article Les outils du développeur web pour apprendre comment installer un service de courrier local.
Entrez http://localhost/cms/site8/fr/contact dans la barre d'adresse de votre navigateur. Remplissez le formulaire et envoyez-le. Vérifiez si vous avez reçu un email à webmaster@localhost. Éditez le code source du courrier et vérifiez les champs de l'en-tête MIME. Essayez d'envoyer le formulaire avec des champs vides, d'entrer une adresse d'email invalide, etc.La dernière étape consiste à ajouter un menu dans le bandeau de la page d'accueil avec un bouton Contact et un lien dans le pied de page.
- /cms/site8
- views
- fr
- footer.phtml
- en
- footer.phtml
- fr
- views
- <div id="footer">
- <p>©2010-2011 frasq.org - Tous droits réservés - <a href="http://www.frasq.org">www.frasq.org</a></p>
- <p><a href="<?php echo $contact_page; ?>">Contact</a> | <img src="<?php echo $base_path; ?>/images/ubuntu.png" alt="" width="16" height="16" /> <a href="http://www.ubuntu.com" target="_blank">Ubuntu</a></p>
- </div>
- <div id="footer">
- <p>©2010-2011 frasq.org - All rights reserved - <a href="http://www.frasq.org">www.frasq.org</a></p>
- <p><a href="<?php echo $contact_page; ?>">Contact</a> | <img src="<?php echo $base_path; ?>/images/ubuntu.png" alt="" width="16" height="16"/> <a href="http://www.ubuntu.com" target="_blank">Ubuntu</a></p>
- </div>
La variable $contact_page
est définie par l'action home
:
- function home($lang) {
- head('title', translate('home:title', $lang));
- $languages='home';
- $contact=true;
- $banner = build('banner', $lang, compact('languages', 'contact'));
- $contact_page=url('contact', $lang);
- $footer = view('footer', $lang, compact('contact_page'));
- $content = view('home', $lang);
- $output = layout('standard', compact('banner', 'footer', 'content'));
- return $output;
- }
home
passe l'URL de la page de contact à la vue footer
et ajoute contact
à la liste des composants du bandeau.
- function banner($lang, $components=false) {
- $home_page=url('home', $lang);
- $logo = view('logo', $lang, compact('home_page'));
- $menu=$contact=false;
- $languages=false;
- $contact_page=false;
- if ($components) {
- foreach ($components as $v => $param) {
- switch ($v) {
- case 'languages':
- if ($param) {
- $languages = build('languages', $lang, $param);
- }
- break;
- case 'contact':
- $contact_page=url('contact', $lang);
- $contact = true;
- break;
- default:
- break;
- }
- }
- }
- if ($contact) {
- $menu = view('bannermenu', $lang, compact('contact', 'contact_page'));
- }
- $output = view('banner', false, compact('logo', 'menu', 'languages'));
- return $output;
- }
banner
passe l'URL de la page de contact à la vue bannermenu
qui génère le menu.
- /cms/site8
- views
- fr
- bannermenu.phtml
- en
- bannermenu.phtml
- fr
- views
- <div id="bannermenu">
- <ul class="menu menubar">
- <?php if (isset($contact) and $contact): ?>
- <li><a id="mail" href="<?php echo $contact_page; ?>" title="Nous contacter"><span>Contact</span></a></li>
- <?php endif; ?>
- </ul>
- </div>
- <div id="bannermenu">
- <ul class="menu menubar">
- <?php if (isset($contact) and $contact): ?>
- <li><a id="mail" href="<?php echo $contact_page; ?>" title="Contact us"><span>Contact</span></a></li>
- <?php endif; ?>
- </ul>
- </div>
Modifiez la feuille de style pour afficher un bouton à la place du lien Contact et recentrer les menus :
- #bannermenu {width:160px;float:left;margin-top:13px;margin-left:40px;}
- #bannermenu #mail {width:24px;height:24px;float:right;margin-left:6px;background:transparent url(../buttons/mail.png) no-repeat center center;}
- #languages {width:100px;float:left;margin-top:13px;margin-left:20px;}
Copiez l'icône pour le bouton Contact dans le dossier buttons :
- /cms/site8
- buttons
- mail.png
- buttons
- <div id="banner">
- <?php
- echo $logo;
- if (isset($menu)) {
- echo $menu;
- }
- if (isset($languages)) {
- echo $languages;
- }
- ?>
- </div>
La vue ajoute le code du menu au bandeau si $menu
est défini.
Entrez http://localhost/cms/site8 dans la barre d'adresse de votre navigateur.
Commentaires