Création d'un formulaire de contact
Nous allons voir comment créer un formulaire de contact dans Nette, y compris l'envoi par e-mail. Alors, allons-y !
Tout d'abord, nous devons créer un nouveau projet. La page Démarrage explique comment faire. Ensuite, nous pouvons commencer à créer le formulaire.
Le plus simple est de créer le formulaire directement dans le
presenter. Nous pouvons utiliser le HomePresenter pré-préparé. Nous y ajouterons le composant
contactForm représentant le formulaire. Pour ce faire, nous écrirons dans le code une méthode factory
createComponentContactForm() qui fabriquera le composant :
use Nette\Application\UI\Form;
use Nette\Application\UI\Presenter;
class HomePresenter extends Presenter
{
protected function createComponentContactForm(): Form
{
$form = new Form;
$form->addText('name', 'Nom :')
->setRequired('Veuillez entrer votre nom');
$form->addEmail('email', 'E-mail :')
->setRequired('Veuillez entrer votre e-mail');
$form->addTextarea('message', 'Message :')
->setRequired('Veuillez entrer votre message');
$form->addSubmit('send', 'Envoyer');
$form->onSuccess[] = [$this, 'contactFormSucceeded'];
return $form;
}
public function contactFormSucceeded(Form $form, $data): void
{
// envoi de l'e-mail
}
}
Comme vous pouvez le voir, nous avons créé deux méthodes. La première méthode createComponentContactForm()
crée un nouveau formulaire. Il comporte des champs pour le nom, l'e-mail et le message, que nous ajoutons avec les méthodes
addText(), addEmail() et addTextArea(). Nous avons également ajouté un bouton pour
soumettre le formulaire. Mais que se passe-t-il si l'utilisateur ne remplit pas un champ ? Dans ce cas, nous devrions lui faire
savoir que c'est un champ obligatoire. Nous y sommes parvenus avec la méthode setRequired(). Enfin, nous avons
également ajouté un événement onSuccess,
qui se déclenche si le formulaire est soumis avec succès. Dans notre cas, il appelle la méthode
contactFormSucceeded, qui se chargera du traitement du formulaire soumis. Nous ajouterons cela au code dans un
instant.
Nous laisserons le composant contactForm se rendre dans le template Home/default.latte :
{block content}
<h1>Formulaire de contact</h1>
{control contactForm}
Pour l'envoi de l'e-mail lui-même, nous créerons une nouvelle classe que nous appellerons ContactFacade et la
placerons dans le fichier app/Model/ContactFacade.php :
<?php
declare(strict_types=1);
namespace App\Model;
use Nette\Mail\Mailer;
use Nette\Mail\Message;
class ContactFacade
{
public function __construct(
private Mailer $mailer,
) {
}
public function sendMessage(string $email, string $name, string $message): void
{
$mail = new Message;
$mail->addTo('admin@example.com') // votre e-mail
->setFrom($email, $name)
->setSubject('Message du formulaire de contact')
->setBody($message);
$this->mailer->send($mail);
}
}
La méthode sendMessage() crée et envoie l'e-mail. Pour ce faire, elle utilise ce qu'on appelle un mailer,
qu'elle reçoit comme dépendance via le constructeur. Apprenez-en davantage sur l'envoi
d'e-mails.
Maintenant, revenons au presenter et complétons la méthode contactFormSucceeded(). Elle appellera la méthode
sendMessage() de la classe ContactFacade et lui transmettra les données du formulaire. Et comment
obtenir l'objet ContactFacade ? Nous le laisserons nous être transmis par le constructeur :
use App\Model\ContactFacade;
use Nette\Application\UI\Form;
use Nette\Application\UI\Presenter;
class HomePresenter extends Presenter
{
public function __construct(
private ContactFacade $facade,
) {
}
protected function createComponentContactForm(): Form
{
// ...
}
public function contactFormSucceeded(stdClass $data): void
{
$this->facade->sendMessage($data->email, $data->name, $data->message);
$this->flashMessage('Le message a été envoyé');
$this->redirect('this');
}
}
Après l'envoi de l'e-mail, nous afficherons également à l'utilisateur un message flash confirmant que le message a été envoyé, puis nous redirigerons vers la page actuelle afin qu'il ne soit pas possible de soumettre à nouveau le formulaire en utilisant refresh dans le navigateur.
Voilà, et si tout fonctionne, vous devriez pouvoir envoyer un e-mail depuis votre formulaire de contact. Félicitations !
Template HTML de l'e-mail
Pour l'instant, un e-mail en texte brut est envoyé, contenant uniquement le message soumis par le formulaire. Mais nous
pouvons utiliser le HTML dans l'e-mail et rendre son apparence plus attrayante. Nous allons créer un template pour cela en Latte,
que nous écrirons dans app/Model/contactEmail.latte :
<html>
<title>Message du formulaire de contact</title>
<body>
<p><strong>Nom :</strong> {$name}</p>
<p><strong>E-mail :</strong> {$email}</p>
<p><strong>Message :</strong> {$message}</p>
</body>
</html>
Il reste à modifier ContactFacade, pour qu'il utilise ce template. Dans le constructeur, nous demanderons la
classe LatteFactory, qui sait fabriquer un objet Latte\Engine, c'est-à-dire le moteur de rendu de templates Latte. Avec la méthode
renderToString(), nous rendrons le template dans un fichier, le premier paramètre est le chemin vers le template et
le second sont les variables.
namespace App\Model;
use Nette\Bridges\ApplicationLatte\LatteFactory;
use Nette\Mail\Mailer;
use Nette\Mail\Message;
class ContactFacade
{
public function __construct(
private Mailer $mailer,
private LatteFactory $latteFactory,
) {
}
public function sendMessage(string $email, string $name, string $message): void
{
$latte = $this->latteFactory->create();
$body = $latte->renderToString(__DIR__ . '/contactEmail.latte', [
'email' => $email,
'name' => $name,
'message' => $message,
]);
$mail = new Message;
$mail->addTo('admin@example.com') // votre e-mail
->setFrom($email, $name)
->setHtmlBody($body);
$this->mailer->send($mail);
}
}
Nous transmettrons ensuite l'e-mail HTML généré à la méthode setHtmlBody() au lieu de l'original
setBody(). De même, nous n'avons pas besoin de spécifier l'objet de l'e-mail dans setSubject(), car la
bibliothèque le prendra à partir de l'élément <title> du template.
Configuration
Dans le code de la classe ContactFacade, notre e-mail administrateur admin@example.com est toujours
codé en dur. Il serait préférable de le déplacer dans le fichier de configuration. Comment faire ?
Tout d'abord, modifions la classe ContactFacade et remplaçons la chaîne avec l'e-mail par une variable transmise
par le constructeur :
class ContactFacade
{
public function __construct(
private Mailer $mailer,
private LatteFactory $latteFactory,
private string $adminEmail,
) {
}
public function sendMessage(string $email, string $name, string $message): void
{
// ...
$mail = new Message;
$mail->addTo($this->adminEmail)
->setFrom($email, $name)
->setHtmlBody($body);
// ...
}
}
Et la deuxième étape consiste à indiquer la valeur de cette variable dans la configuration. Dans le fichier
config/services.neon (ou app/config/services.neon dans les versions plus anciennes), nous
écrirons :
services:
- App\Model\ContactFacade(adminEmail: admin@example.com)
Et c'est tout. S'il y a beaucoup d'éléments dans la section services et que vous avez l'impression que l'e-mail
se perd parmi eux, nous pouvons en faire une variable. Modifions l'écriture en :
services:
- App\Model\ContactFacade(adminEmail: %adminEmail%)
Et dans le fichier app/config/common.neon, nous définirons cette variable :
parameters:
adminEmail: admin@example.com
Et c'est terminé !