Formulaire de contact avec CakePHP
Voyons comment mettre en place cette fonctionnalité très courante sur un site : un simple formulaire de contact dans lequel nous demandons au visiteur son nom, son prénom, son adresse email et le message qu’il souhaite faire parvenir au webmaster, par email. Nous allons aborder deux aspects intéressants : l’utilisation d’un Modèle sans table, et le composant Email fourni par le framework.
1. Le Modèle Contact
Nous ne souhaitons pas ici enregistrer les emails qui seront envoyés, nous allons donc indiquer à Cake de ne pas utiliser de table ‘contacts’. Cela pose cependant un problème pour la structure d’un enregistrement : Cake ne sait plus sur quoi s’appuyer pour la définir ! Nous allons donc lui mâcher le travail en donnant le schéma de données au Modèle. Nous définirons ensuite quelques règles de validation qui devront être satisfaites avant que l’email ne soit effectivement envoyé.<?php // {app}/models/contact.php class Contact extends AppModel { var $name = 'Contact'; // Nous n'utiliserons pas de table dans la base var $useTable = false; // Nous donnons donc à Cake la structure d'un enregistrement var $_schema = array( 'prenom' => array( 'type' => 'string', 'length' => 30 ), 'nom' => array( 'type' => 'string', 'length' => 30 ), 'email' => array( 'type' => 'string', 'length' => 50 ), 'message' => array( 'type' => 'text' ) ); // Règles de validation des données var $validate = array( 'nom' => array( 'rule' => 'notEmpty', 'required' => true, 'allowEmpty' => false, 'message' => "Votre nom doit être renseigné." ), 'prenom' => array( 'rule' => 'notEmpty', 'required' => true, 'allowEmpty' => false, 'message' => "Votre prénom doit être renseigné." ), 'email' => array( 'rule' => 'email', 'required' => true, 'allowEmpty' => false, 'message' => "Vous devez saisir une adresse email valide." ), 'message' => array( 'rule' => 'notEmpty', 'required' => true, 'allowEmpty' => false, 'message' => "Vous devez saisir un message." ) ); } ?>
2. Les vues
Nous aurons ici deux vues : la page qui affiche le formulaire lui-même, et une simple page de confirmation lorsque l’email est bien envoyé à l’administrateur du site.
2.1 La vue du formulaire
// {app}/views/contacts/index.ctp
<h1>Formulaire de contact</h1>
<?php e($form->create('Contact', array('url' => '/contacts/index'))); ?>
<fieldset>
<legend>Vos coordonnées</legend>
<?php
e($form->input('nom', array('label' => "Votre nom :", 'size' => 80)));
e($form->input('prenom', array('label' => "Votre prénom :", 'size' => 80)));
e($form->input('email', array('label' => "Votre adresse email :", 'size' => 80)));
?>
</fieldset>
<fieldset>
<legend>Votre message</legend>
<?php e($form->textarea('message', array('cols' => 60, 'rows' => 12))); ?>
<?php e($form->error('message')); ?>
</fieldset>
<?php e($form->end("Envoyer le message")); ?>Deux petits détails :
- nous forçons la cible du formulaire,
/contacts/index, sinon Cake la définit par défaut à/contacts/add - Nous forçons l’affichage de l’éventuelle erreur de validation sur le champ ‘message’, car la méthode
$form->textarea()ne va pas afficher l’erreur, contrairement à la méthode$form->input().
2.2 La vue de confirmation d’envoi
// {app}/contacts/confirmation.ctp <h1>Email envoyé</h1> <p>Merci de votre participation, etc.</p>
3. Le Contrôleur Contacts
C’est ici que nous allons inclure le Composant Email fourni par CakePHP. Notre Contrôleur ne va contenir que deux actions : index, qui affiche le formulaire et envoie un email à l’administrateur si le formulaire est soumis, et une action vide pour afficher la page de confirmation en cas de succès.
<?php class ContactsController extends AppController { var $name = 'Contacts'; var $components = array('Email'); function index() { if(!empty($this->data)) { $this->Contact->create($this->data); if(!$this->Contact->validates()) { $this->Session->setFlash("Veuillez corriger les erreurs mentionnées.", 'message_notice'); $this->validateErrors($this->Contact); } else { // Nettoyage de la saisie App::import('Sanitize'); $this->data = Sanitize::clean($this->data); $this->set('data', $this->data); $this->Email->charset = 'ISO-8859-1'; $this->Email->to = 'contact@monsite.com'; $this->Email->bcc = array($this->data['Contact']['email']); $this->Email->from = $this->data['Contact']['email']; $this->Email->sendAs = 'both'; $this->Email->subject = "Formulaire de contact"; $this->Email->template = 'contact'; // Envoi de l'email $this->Email->send(); $this->redirect(array('action' => 'confirmation')); } } } // Page de remerciement function confirmation() {} } ?>
Attardons-nous un peu sur l’envoi de l’email : il suffit de définir quelques paramètres pour l’email qui va être envoyé, et le Composant se charge du reste. Nous envoyons l’email à l’administrateur, avec une copie cachée pour l’expéditeur ($this->Email->bcc) qui pourra ainsi archiver sa demande. Notons que nous choisissons d’envoyer l’email en deux formats en même temps ($this->Email->sendAs = 'both') : HTML pour la mise en page, et texte brut pour une compatibilité maximum avec les clients de messagerie, qui sauront choisir le format à afficher.
4. Templates et layouts de l’email
Voyons maintenant comment mettre en page l’email lui-même. N’oublions pas que nous avons deux formats à gérer, HTML et texte brut.4.1 Layouts
Commençons par examiner les layouts spéciaux réservés aux emails.4.1.1 Layout HTML
// {app}/views/layouts/email/html/default.ctp
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<body>
<p>Bonjour,</p>
<?php e($content_for_layout);?>
<p>A bientôt sur <a href="http://www.monsite.com">mon site</a> !</p>
</body>
</html>4.1.2 Layout texte brut
// {app}/views/layouts/email/text/default.ctp
Bonjour,
<?php e($content_for_layout);?>
A bientôt sur mon site !
http://www.monsite.com4.2 Vues
Voyons enfin les vues du corps de l’email.
4.2.1 Vue HTML
// {app}/views/elements/email/html/contact.ctp
<p>Merci de nous avoir contacté. Voici la copie de ce que va recevoir notre administrateur :</p>
<p>Date : <?php e(date('d/m/Y H:i')); ?></p>
<p>Envoyé par : <?php e($data['Contact']['nom'].' '.$data['Contact']['prenom']); ?></p>
<p>Adresse email : <?php e($data['Contact']['email']); ?></p>
<p>Message : <?php e($data['Contact']['message']); ?></p>4.2.2 Vue texte brut
// {app}/views/elements/email/text/contact.ctp
Merci de nous avoir contacté. Voici la copie de ce que va recevoir notre administrateur :
Date : <?php e(date('d/m/Y H:i')); ?>
Envoyé par : <?php e($data['Contact']['nom'].' '.$data['Contact']['prenom']); ?>
Adresse email : <?php e($data['Contact']['email']); ?>
Message : <?php e($data['Contact']['message']); ?>
Commentaires
26 août 2008 à 0:10
la force de la simplicité dans toute sa splendeur ! trop beau !
26 août 2008 à 0:33
Marrant ça, je venais justement de faire exactement la même chose il y a quelques jours.
J’ai du pas mal chercher pour comprendre comment fonctionnent les vues des mails, bonne initiative que de regrouper tout cela en un post.
La seule différence entre nos deux codes serait que tu utilises $this->Contact->create($this->data); là où j’utilise $this->Contact->set($this->data); J’avoue que je ne connaissais pas Model::Create.
26 août 2008 à 8:41
J’utilise également cette méthode avec juste une variante : une vraie table en base de données pour sauvegarder les données du formulaire avant de l’envoyer. Cela permet :
26 août 2008 à 9:03
J’allais dire la même chose que Matthieu. L’approche de Pierre-Emmanuel est cependant plus intéressante à titre pédagogique !
26 août 2008 à 9:40
Salut,
Très bon tuto encore une fois !
J’ai essayé de faire cela en suivant l’article du Cookbook sur la validation depuis un contrôleur, mais il n’y a pas l’astuce du $_schema car leur exemple utilise bien un modèle avec table !
Du coup j’avais du faire une méthode de validation dans mon contrôleur qui me « set » les messages d’erreurs pour le formulaire. Et donc je n’utilisais pas de modèle du tout (public $uses = array() dans le contrôleur)!
Mais le coup du $_schema est bien plus propre car il permet d’utiliser la « magie » Cake pour la validation d’un formulaire avec les retours d’erreurs.
Juste une petite remarque syntaxique cher Pierre-Emmanuel : dans les vues de confirmation, on ne dit pas « Merci pour nous avoir contacté », mais « Merci DE « ! ;o)
26 août 2008 à 10:06
[...] second détaille en profondeur la mise en place d’un formulaire de contact avec envoi de mail, ce qui [...]
26 août 2008 à 15:26
@Guillaume en effet, j’ai juste ajouté ça comme piste supplémentaire parce que ça m’est arrivé de perdre des emails de contact avant qu’on applique cette solution. Ça n’est cependant pas indispensable selon les besoins de chacun et l’astuce « model sans table » reste très utile.
26 août 2008 à 16:21
@avairet : merci, je corrige
27 août 2008 à 18:57
Encore excellent. J’adore tes tutoriels.
Celui-ci vient de m’éviter de chercher pendant des heures.
Merci!
28 janvier 2009 à 17:12
Bonjour et merci pour se super tutoriel.
mais voila j’ai un petit problème, lorsque je complète le formulaire avec des fautes (donc soit en oubliant le @ ou en n’encodant pas de nom) et que j’envoie, cakephp m’affiche en dégradé, sur tout la page, sa banniere « CakePHP: the rapid development php framework » alors qu’il devrait m’indiquer le message d’erreur de l’email ou du nom défini dans les règle.
Je ne c’est plus quoi faire. Merci d’avance pour vos réponses
ps: je suis débutant dans cakephp sa ne fait que 2 jours que je suis dessus
17 mars 2009 à 18:21
Bonjour, merci pour ce tuto qui sur d’autres sites fonctionne très bien… mais là j’ai ce curieux message lorsque j’envoie le mail :
Si quelqu’un pouvait m’aider… ?
Cordialement
24 juin 2009 à 22:50
Il y a des problèmes apparament avec le champ bcc (idem avec cc). Les emails contenus dans le champ bcc ne sont pas pris en compte.
J’ai vu un ticket concernant une erreur lorsque les paramètres sont des scalaires (string simple) au lieu de tableaux (array) pour bcc et cc mais pas dans le fonctionnement de bcc.
Quelqu’un a t-il une idée de là ou ça peut provenir ? Fonction mail de l’hébergeur ou bien implémentation dans cake ? Quelqu’un a t’il teste avec le champ bcc ? Merci davance !!
20 août 2009 à 13:24
Bonjour, à tous. Toujours utiles vos tutos. Une petite question, cependant:
// Nettoyage de la saisie App::import(‘Sanitize’); $this->data = Sanitize::clean($this->data);
est-ce vraiment indispensable? surtout quand on le couple à un contrôle sur la validation, du style (i18n oblige)
var $validate = NULL; function construct($id = false, $table = null, $ds = null) { parent::construct($id, $table, $ds); $this->validate = array(‘nom’ => array(‘r1_nom’ => array( ‘rule’ => ‘notEmpty’, ‘message’ => __(‘Required field’,true)),’r0_nom’ => array( ‘rule’ => array(‘maxLength’,’50′), ‘message’ => __(‘Maximum length of 50 characters’,true))), …. ); }
Car dans ce cas, il n’y a plus moyen d’envoyer un simple retour chariot dans le message…
26 septembre 2009 à 16:08
Super tuto … sauf que petit problème si je rempli le formulaire en faisant des fautes (cad qui ne respecte pas les règles de validation) et que j’envoie, mon serveur localhost plante totalement (je travaille avec WAMP)
Si quelqu’un a une idée, merci d’avance
18 novembre 2009 à 14:11
Merci pour ce bô tuto!
Cependant, je rencontre le même problème que Bob: Le site plante lorsqu’il subsiste des erreurs dans les différents champs au moment du clic sur « Envoyer le message ». –> Je suis alors obligé de supprimer le cookie généré pour voir à nouveau ma page.
Je remarque aussi un autre souci. Le texte du champ « message » n’apparait pas dans le corps du mail…
Je serais ravis si vous pouviez me donner l’une ou l’autre piste!
15 décembre 2009 à 12:45
[...] comment réaliser de formualire de contact avec CakePHP, je vous invite à lire le tutoriel suivant http://www.formation-cakephp.com/71/formulaire-de-contact-avec-cakephp Il est vraiment bien expliqué et [...]
19 janvier 2010 à 12:00
un message d’erreur : « Connexion réinitialisée »
Je pense que pour tester meme pour la fonction validate il nous faut un serveur mail donc pas sur un serveur local
.
Sinon ne pensez vous pas que au niveau du controller : contacts_controller.php :
28 février 2010 à 1:49
Génial ce tuto ! Par contre, j’ai une erreur dès que j’ajoute un template à l’aide de la méthode : $this->Email->template = ‘contact’;
Ca fonctionne sans, mais pas avec et j’ai bien les fichiers : app/views/elements/email/html/contact/ctp app/views/elements/email/text/contact/ctp
L’erreur est : Fatal error: Call to a member function addScript() on a non-object in /var/www/vhosts/NOMSITE.FR/httpdocs/cake/libs/view/helpers/javascript.php on line 277
Impossible de trouver quoi que ce soit sur internet. Je suis preneur de toute suggestion.
Merci
7 mars 2010 à 19:19
Bonjour, excellent tuto, mais je rencontre un problème avec sanitize et le caractère « - ». En effet j’aimerais l’autoriser, notamment pour les e-mails, mais je ne sais pas comment faire en utilisant clean()
Avez-vous une solution à cela ? Merci !
4 janvier 2011 à 12:04
Bonjour, merci, ce tutoriel est excellent! J’ai un petit souci cependant, le message de confirmation s’affiche pour dire que le message a été envoyé, mais je ne trouve pas de mail dans ma boite. Avez vous une idée de l’origine de ce problème?
Merci d’avance!
4 novembre 2011 à 10:21
@ nina : Si tu utilise wamp ou autre c’est normal que le mail ne soit pas envoyé… Tu doit le tester sur un serveur distant qui gérera l’envoie du mail.
24 décembre 2011 à 11:46
Même si je travaille maintenant avec la version 2, j’ai quand même appris mal de chose, Un grand Merci