Erstellen wir ein Kontakt-Formular
Schauen wir uns an, wie man in Nette ein Kontaktformular erstellt und es an eine E-Mail sendet. Also, los geht's!
Zuerst müssen wir ein neues Projekt erstellen. Wie auf der Seite " Erste Schritte" erklärt wird. Und dann können wir mit der Erstellung des Formulars beginnen.
Der einfachste Weg ist, das Formular direkt in Presenter zu erstellen.
Wir können die vorgefertigten HomePresenter
verwenden. Wir werden die Komponente contactForm
hinzufügen, die das Formular darstellt. Dies geschieht, indem wir die createComponentContactForm()
Factory-Methode
in den Code schreiben, der die Komponente erzeugt:
use Nette\Application\UI\Form;
use Nette\Application\UI\Presenter;
class HomePresenter extends Presenter
{
protected function createComponentContactForm(): Form
{
$form = new Form;
$form->addText('name', 'Name:')
->setRequired('Enter your name');
$form->addEmail('email', 'E-mail:')
->setRequired('Enter your e-mail');
$form->addTextarea('message', 'Message:')
->setRequired('Enter message');
$form->addSubmit('send', 'Send');
$form->onSuccess[] = [$this, 'contactFormSucceeded'];
return $form;
}
public function contactFormSucceeded(Form $form, $data): void
{
// sending an email
}
}
Wie Sie sehen können, haben wir zwei Methoden erstellt. Die erste Methode createComponentContactForm()
erstellt
ein neues Formular. Dieses hat Felder für Name, E-Mail und Nachricht, die wir mit den Methoden addText()
,
addEmail()
und addTextArea()
hinzufügen. Wir haben auch eine Schaltfläche zum Absenden des Formulars
hinzugefügt. Was aber, wenn der Benutzer einige Felder nicht ausfüllt? In diesem Fall sollten wir ihn darauf hinweisen, dass es
sich um ein Pflichtfeld handelt. Wir haben dies mit der Methode setRequired()
getan. Schließlich haben wir auch ein
Ereignis onSuccess
hinzugefügt, das ausgelöst wird,
wenn das Formular erfolgreich abgeschickt wurde. In unserem Fall ruft es die Methode contactFormSucceeded
auf, die
sich um die Verarbeitung des übermittelten Formulars kümmert. Das fügen wir dem Code gleich hinzu.
Die Komponente contantForm
soll in der Vorlage Home/default.latte
gerendert werden:
{block content}
<h1>Contant Form</h1>
{control contactForm}
Um die E-Mail selbst zu versenden, erstellen wir eine neue Klasse namens ContactFacade
und platzieren sie in der
Datei 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') // your email
->setFrom($email, $name)
->setSubject('Message from the contact form')
->setBody($message);
$this->mailer->send($mail);
}
}
Die Methode sendMessage()
wird die E-Mail erstellen und versenden. Sie verwendet dazu einen so genannten Mailer,
den sie als Abhängigkeit über den Konstruktor übergibt. Lesen Sie mehr über das Versenden
von E-Mails.
Nun kehren wir zum Presenter zurück und vervollständigen die Methode contactFormSucceeded()
. Sie ruft die
Methode sendMessage()
der Klasse ContactFacade
auf und übergibt ihr die Formulardaten. Und wie erhalten
wir das ContactFacade
Objekt? Wir lassen es uns vom Konstruktor übergeben:
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('The message has been sent');
$this->redirect('this');
}
}
Nachdem die E-Mail versendet wurde, zeigen wir dem Benutzer die so genannte Flash-Nachricht an, die bestätigt, dass die Nachricht versendet wurde, und leiten dann zur nächsten Seite weiter, damit das Formular nicht mit refresh im Browser erneut abgeschickt werden kann.
Nun, wenn alles funktioniert, sollten Sie in der Lage sein, eine E-Mail über Ihr Kontaktformular zu versenden. Herzlichen Glückwunsch!
HTML-E-Mail-Vorlage
Im Moment wird eine einfache Text-E-Mail verschickt, die nur die vom Formular gesendete Nachricht enthält. Aber wir können
HTML in der E-Mail verwenden und sie attraktiver gestalten. Wir werden dafür eine Vorlage in Latte erstellen, die wir unter
app/Model/contactEmail.latte
speichern werden:
<html>
<title>Message from the contact form</title>
<body>
<p><strong>Name:</strong> {$name}</p>
<p><strong>E-mail:</strong> {$email}</p>
<p><strong>Message:</strong> {$message}</p>
</body>
</html>
Es bleibt noch ContactFacade
zu ändern, um diese Vorlage zu verwenden. Im Konstruktor fordern wir die Klasse
LatteFactory
an, die das Objekt Latte\Engine
erzeugen kann, einen Latte-Vorlagen-Renderer. Wir verwenden die Methode
renderToString()
, um die Vorlage in eine Datei zu rendern; der erste Parameter ist der Pfad zur Vorlage und der
zweite die Variablen.
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') // your email
->setFrom($email, $name)
->setHtmlBody($body);
$this->mailer->send($mail);
}
}
Anschließend übergeben wir die generierte HTML-E-Mail an die Methode setHtmlBody()
anstelle der ursprünglichen
setBody()
. Wir müssen auch den Betreff der E-Mail in setSubject()
nicht angeben, da die Bibliothek ihn
aus dem Element <title>
in der Vorlage übernimmt.
Konfigurieren von
Im Code der Klasse ContactFacade
ist unsere Admin-E-Mail admin@example.com
noch fest codiert. Es
wäre besser, sie in die Konfigurationsdatei zu verschieben. Wie kann man das tun?
Zunächst ändern wir die Klasse ContactFacade
und ersetzen den E-Mail-String durch eine Variable, die vom
Konstruktor übergeben wird:
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);
// ...
}
}
Der zweite Schritt besteht darin, den Wert dieser Variable in die Konfiguration aufzunehmen. In der Datei
app/config/services.neon
fügen wir hinzu:
services:
- App\Model\ContactFacade(adminEmail: admin@example.com)
Und das war's. Wenn es viele Einträge im Abschnitt services
gibt und Sie das Gefühl haben, dass die E-Mail unter
den Einträgen verloren geht, können wir sie zu einer Variablen machen. Wir ändern den Eintrag in:
services:
- App\Model\ContactFacade(adminEmail: %adminEmail%)
Und definieren diese Variable in der Datei app/config/common.neon
:
parameters:
adminEmail: admin@example.com
Und schon ist es geschafft!