Wir erstellen ein Kontaktformular
Wir schauen uns an, wie man in Nette ein Kontaktformular erstellt, einschließlich des E-Mail-Versands. Los geht's!
Zuerst müssen wir ein neues Projekt erstellen. Wie das geht, erklärt die Seite Erste Schritte. Und dann können wir mit der Erstellung des Formulars beginnen.
Am einfachsten ist die Erstellung eines Formulars direkt im
Presenter. Wir können den vorbereiteten HomePresenter
verwenden. In ihn fügen wir die Komponente
contactForm
hinzu, die das Formular darstellt. Dazu schreiben wir eine Factory-Methode
createComponentContactForm()
in den Code, die die Komponente erstellt:
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('Geben Sie einen Namen ein');
$form->addEmail('email', 'E-Mail:')
->setRequired('Geben Sie eine E-Mail-Adresse ein');
$form->addTextarea('message', 'Nachricht:')
->setRequired('Geben Sie eine Nachricht ein');
$form->addSubmit('send', 'Senden');
$form->onSuccess[] = [$this, 'contactFormSucceeded'];
return $form;
}
public function contactFormSucceeded(Form $form, $data): void
{
// E-Mail senden
}
}
Wie Sie sehen, 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 einen Button zum Absenden des Formulars
hinzugefügt. Aber was, wenn der Benutzer ein Feld nicht ausfüllt? In diesem Fall sollten wir ihm mitteilen, dass es sich um ein
Pflichtfeld handelt. Das haben wir mit der Methode setRequired()
erreicht. Schließlich haben wir auch das Ereignis onSuccess
hinzugefügt, das ausgelöst wird, wenn
das Formular erfolgreich gesendet wird. In unserem Fall ruft es die Methode contactFormSucceeded
auf, die sich um die
Verarbeitung des gesendeten Formulars kümmert. Das werden wir gleich in den Code einfügen.
Die Komponente contactForm
lassen wir im Template Home/default.latte
rendern:
{block content}
<h1>Kontaktformular</h1>
{control contactForm}
Für den eigentlichen E-Mail-Versand erstellen wir eine neue Klasse, die wir ContactFacade
nennen und in der Datei
app/Model/ContactFacade.php
ablegen:
<?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') // Ihre E-Mail
->setFrom($email, $name)
->setSubject('Nachricht vom Kontaktformular')
->setBody($message);
$this->mailer->send($mail);
}
}
Die Methode sendMessage()
erstellt und sendet eine E-Mail. Sie verwendet dazu einen sogenannten Mailer, den sie
als Abhängigkeit über den Konstruktor erhält. Lesen Sie mehr über das Senden von
E-Mails.
Nun kehren wir zum Presenter zurück und vervollständigen die Methode contactFormSucceeded()
. Diese ruft die
Methode sendMessage()
der Klasse ContactFacade
auf und übergibt ihr die Daten aus dem Formular. Und wie
erhalten wir das Objekt ContactFacade
? Wir lassen es uns über den 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('Die Nachricht wurde gesendet');
$this->redirect('this');
}
}
Nachdem die E-Mail gesendet wurde, zeigen wir dem Benutzer noch eine sogenannte Flash-Nachricht an, die bestätigt, dass die
Nachricht gesendet wurde, und leiten dann auf dieselbe Seite weiter (this
), damit das Formular nicht durch
Aktualisieren im Browser erneut gesendet werden kann.
So, und wenn alles funktioniert, sollten Sie in der Lage sein, eine E-Mail von Ihrem Kontaktformular zu senden. Herzlichen Glückwunsch!
HTML-Template für E-Mails
Bisher wird eine einfache Text-E-Mail gesendet, die nur die über das Formular gesendete Nachricht enthält. In der E-Mail
können wir jedoch HTML verwenden und ihr Erscheinungsbild attraktiver gestalten. Wir erstellen dafür ein Template in Latte, das
wir in app/Model/contactEmail.latte
speichern:
<html>
<title>Nachricht vom Kontaktformular</title>
<body>
<p><strong>Name:</strong> {$name}</p>
<p><strong>E-Mail:</strong> {$email}</p>
<p><strong>Nachricht:</strong> {$message}</p>
</body>
</html>
Es bleibt übrig, ContactFacade
anzupassen, damit dieses Template verwendet wird. Im Konstruktor fordern wir die
Klasse LatteFactory
an, die ein Objekt Latte\Engine
, also den Latte-Template-Renderer, erstellen kann. Mit der Methode
renderToString()
rendern wir das Template in einen String, der erste Parameter ist der Pfad zum Template und der
zweite sind 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') // Ihre E-Mail
->setFrom($email, $name)
->setHtmlBody($body);
$this->mailer->send($mail);
}
}
Die generierte HTML-E-Mail übergeben wir dann der Methode setHtmlBody()
anstelle der ursprünglichen
setBody()
. Ebenso müssen wir den Betreff der E-Mail nicht in setSubject()
angeben, da ihn die
Bibliothek aus dem <title>
-Element des Templates übernimmt.
Konfiguration
Im Code der Klasse ContactFacade
ist immer noch unsere Administrator-E-Mail admin@example.com
fest
codiert. Es wäre besser, sie in die Konfigurationsdatei zu verschieben. Wie geht das?
Zuerst passen wir die Klasse ContactFacade
an und ersetzen den String mit der E-Mail durch eine Variable, die
über den 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);
// ...
}
}
Und der zweite Schritt ist die Angabe des Wertes dieser Variablen in der Konfiguration. In die Datei
app/config/services.neon
schreiben wir:
services:
- App\Model\ContactFacade(adminEmail: admin@example.com)
Und das war's. Wenn es viele Einträge im Abschnitt services
gäbe und Sie das Gefühl hätten, dass die E-Mail
dazwischen untergeht, können wir sie zu einer Variablen machen. Wir ändern die Notation auf:
services:
- App\Model\ContactFacade(adminEmail: %adminEmail%)
Und in der Datei app/config/common.neon
definieren wir diese Variable:
parameters:
adminEmail: admin@example.com
Und fertig!