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é !