Δημιουργούμε μια φόρμα επικοινωνίας
Θα δούμε πώς να δημιουργήσουμε μια φόρμα επικοινωνίας στο Nette, συμπεριλαμβανομένης της αποστολής μέσω email. Ας ξεκινήσουμε λοιπόν!
Πρώτα πρέπει να δημιουργήσουμε ένα νέο έργο. Πώς να το κάνετε αυτό εξηγείται στη σελίδα Ξεκινώντας. Και μετά μπορούμε ήδη να αρχίσουμε να δημιουργούμε τη φόρμα.
Ο ευκολότερος τρόπος είναι να δημιουργήσετε τη φόρμα απευθείας στον presenter. Μπορούμε να
χρησιμοποιήσουμε τον προετοιμασμένο HomePresenter
. Σε αυτόν θα
προσθέσουμε το component contactForm
που αντιπροσωπεύει τη φόρμα. Θα το
κάνουμε γράφοντας στον κώδικα τη μέθοδο factory createComponentContactForm()
, η
οποία θα κατασκευάσει το component:
use Nette\Application\UI\Form;
use Nette\Application\UI\Presenter;
class HomePresenter extends Presenter
{
protected function createComponentContactForm(): Form
{
$form = new Form;
$form->addText('name', 'Όνομα:')
->setRequired('Εισάγετε όνομα');
$form->addEmail('email', 'E-mail:')
->setRequired('Εισάγετε e-mail');
$form->addTextarea('message', 'Μήνυμα:')
->setRequired('Εισάγετε μήνυμα');
$form->addSubmit('send', 'Αποστολή');
$form->onSuccess[] = [$this, 'contactFormSucceeded'];
return $form;
}
public function contactFormSucceeded(Form $form, $data): void
{
// αποστολή email
}
}
Όπως βλέπετε, δημιουργήσαμε δύο μεθόδους. Η πρώτη μέθοδος
createComponentContactForm()
δημιουργεί μια νέα φόρμα. Αυτή έχει πεδία για
όνομα, email και μήνυμα, τα οποία προσθέτουμε με τις μεθόδους addText()
,
addEmail()
και addTextArea()
. Προσθέσαμε επίσης ένα κουμπί για την
αποστολή της φόρμας. Αλλά τι γίνεται αν ο χρήστης δεν συμπληρώσει
κάποιο πεδίο; Σε αυτή την περίπτωση, θα πρέπει να τον ενημερώσουμε ότι
είναι υποχρεωτικό πεδίο. Αυτό το πετύχαμε με τη μέθοδο setRequired()
.
Τέλος, προσθέσαμε επίσης το event
onSuccess
, το οποίο ενεργοποιείται εάν η φόρμα υποβληθεί επιτυχώς.
Στην περίπτωσή μας, καλεί τη μέθοδο contactFormSucceeded
, η οποία θα
αναλάβει την επεξεργασία της υποβληθείσας φόρμας. Αυτό θα το
συμπληρώσουμε στον κώδικα σε μια στιγμή.
Το component contactForm
θα το αφήσουμε να αποδοθεί στο template
Home/default.latte
:
{block content}
<h1>Φόρμα επικοινωνίας</h1>
{control contactForm}
Για την ίδια την αποστολή του email θα δημιουργήσουμε μια νέα κλάση, την
οποία θα ονομάσουμε ContactFacade
και θα την τοποθετήσουμε στο αρχείο
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') // το email σας
->setFrom($email, $name)
->setSubject('Μήνυμα από τη φόρμα επικοινωνίας')
->setBody($message);
$this->mailer->send($mail);
}
}
Η μέθοδος sendMessage()
δημιουργεί και στέλνει το email. Χρησιμοποιεί
για αυτό τον λεγόμενο mailer, τον οποίο λαμβάνει ως εξάρτηση μέσω του
constructor. Διαβάστε περισσότερα για την αποστολή
emails.
Τώρα θα επιστρέψουμε στον presenter και θα ολοκληρώσουμε τη μέθοδο
contactFormSucceeded()
. Αυτή θα καλέσει τη μέθοδο sendMessage()
της κλάσης
ContactFacade
και θα της παραδώσει τα δεδομένα από τη φόρμα. Και πώς θα
αποκτήσουμε το αντικείμενο ContactFacade
; Θα το ζητήσουμε να μας
παραδοθεί μέσω του constructor:
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('Το μήνυμα στάλθηκε');
$this->redirect('this');
}
}
Αφού σταλεί το email, θα εμφανίσουμε επίσης στον χρήστη ένα λεγόμενο flash message, επιβεβαιώνοντας ότι το μήνυμα στάλθηκε, και στη συνέχεια θα ανακατευθύνουμε σε άλλη σελίδα, ώστε να μην είναι δυνατή η επανειλημμένη αποστολή της φόρμας μέσω refresh στον browser.
Λοιπόν, και αν όλα λειτουργούν, θα πρέπει να μπορείτε να στείλετε email από τη φόρμα επικοινωνίας σας. Συγχαρητήρια!
HTML template email
Μέχρι στιγμής, αποστέλλεται ένα απλό email κειμένου που περιέχει μόνο
το μήνυμα που στάλθηκε από τη φόρμα. Στο email όμως μπορούμε να
χρησιμοποιήσουμε HTML και να κάνουμε την εμφάνισή του πιο ελκυστική. Θα
δημιουργήσουμε γι' αυτό ένα template στο Latte, το οποίο θα γράψουμε στο
app/Model/contactEmail.latte
:
<html>
<title>Μήνυμα από τη φόρμα επικοινωνίας</title>
<body>
<p><strong>Όνομα:</strong> {$name}</p>
<p><strong>E-mail:</strong> {$email}</p>
<p><strong>Μήνυμα:</strong> {$message}</p>
</body>
</html>
Μένει να τροποποιήσουμε το ContactFacade
, ώστε να χρησιμοποιεί αυτό
το template. Στον constructor θα ζητήσουμε την κλάση LatteFactory
, η οποία
μπορεί να δημιουργήσει ένα αντικείμενο Latte\Engine
, δηλαδή τον Latte template renderer. Με τη μέθοδο
renderToString()
θα αποδώσουμε το template σε αρχείο, η πρώτη παράμετρος
είναι η διαδρομή προς το template και η δεύτερη είναι οι μεταβλητές.
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') // το email σας
->setFrom($email, $name)
->setHtmlBody($body);
$this->mailer->send($mail);
}
}
Το παραγόμενο HTML email θα το παραδώσουμε στη συνέχεια στη μέθοδο
setHtmlBody()
αντί της αρχικής setBody()
. Επίσης, δεν χρειάζεται να
αναφέρουμε το θέμα του email στο setSubject()
, επειδή η βιβλιοθήκη θα το
πάρει από το στοιχείο <title>
του template.
Διαμόρφωση
Στον κώδικα της κλάσης ContactFacade
είναι ακόμα σκληρά
κωδικοποιημένο το διαχειριστικό μας email admin@example.com
. Θα ήταν
καλύτερο να το μεταφέρουμε στο αρχείο διαμόρφωσης. Πώς να το
κάνουμε αυτό;
Πρώτα θα τροποποιήσουμε την κλάση ContactFacade
και θα
αντικαταστήσουμε το string με το email με μια μεταβλητή που παραδίδεται μέσω
του constructor:
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);
// ...
}
}
Και το δεύτερο βήμα είναι η αναφορά της τιμής αυτής της μεταβλητής
στη διαμόρφωση. Στο αρχείο app/config/services.neon
γράφουμε:
services:
- App\Model\ContactFacade(adminEmail: admin@example.com)
Και αυτό είναι όλο. Αν τα στοιχεία στην ενότητα services
ήταν πολλά
και είχατε την αίσθηση ότι το email χάνεται ανάμεσά τους, μπορούμε να το
κάνουμε μεταβλητή. Τροποποιούμε την καταχώρηση σε:
services:
- App\Model\ContactFacade(adminEmail: %adminEmail%)
Και στο αρχείο app/config/common.neon
ορίζουμε αυτή τη μεταβλητή:
parameters:
adminEmail: admin@example.com
Και τελειώσαμε!