Ustvarjamo kontaktni obrazec
Pogledali si bomo, kako v Nette ustvariti kontaktni obrazec, vključno s pošiljanjem na e-pošto. Pa začnimo!
Najprej moramo ustvariti nov projekt. Kako to storiti, pojasnjuje stran Začenjamo. Nato pa lahko že začnemo z ustvarjanjem obrazca.
Najenostavneje je ustvariti obrazec neposredno v presenterju. Lahko
uporabimo vnaprej pripravljen HomePresenter. Vanjo dodamo komponento contactForm, ki predstavlja
obrazec. To storimo tako, da v kodo zapišemo tovarniško metodo createComponentContactForm(), ki bo komponento
izdelala:
use Nette\Application\UI\Form;
use Nette\Application\UI\Presenter;
class HomePresenter extends Presenter
{
protected function createComponentContactForm(): Form
{
$form = new Form;
$form->addText('name', 'Ime:')
->setRequired('Vnesite ime');
$form->addEmail('email', 'E-pošta:')
->setRequired('Vnesite e-pošto');
$form->addTextarea('message', 'Sporočilo:')
->setRequired('Vnesite sporočilo');
$form->addSubmit('send', 'Pošlji');
$form->onSuccess[] = [$this, 'contactFormSucceeded'];
return $form;
}
public function contactFormSucceeded(Form $form, stdClass $data): void
{
// pošiljanje e-pošte
}
}
Kot vidite, smo ustvarili dve metodi. Prva metoda createComponentContactForm() ustvari nov obrazec. Ta ima polja
za ime, e-pošto in sporočilo, ki jih dodajamo z metodami addText(), addEmail() in
addTextArea(). Dodali smo tudi gumb za pošiljanje obrazca. Kaj pa, če uporabnik ne izpolni katerega od polj?
V takem primeru bi mu morali sporočiti, da je to obvezno polje. To smo dosegli z metodo setRequired(). Na koncu
smo dodali tudi dogodek onSuccess, ki se sproži,
če je obrazec uspešno poslan. V našem primeru pokliče metodo contactFormSucceeded, ki poskrbi za obdelavo
poslanega obrazca. To bomo v kodo dodali čez trenutek.
Komponento contactForm bomo pustili izrisati v predlogi Home/default.latte:
{block content}
<h1>Kontaktni obrazec</h1>
{control contactForm}
Za samo pošiljanje e-pošte bomo ustvarili nov razred, ki ga bomo poimenovali ContactFacade in ga postavili
v datoteko 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') // vaša e-pošta
->setFrom($email, $name)
->setSubject('Sporočilo iz kontaktnega obrazca')
->setBody($message);
$this->mailer->send($mail);
}
}
Metoda sendMessage() ustvari in pošlje e-pošto. Za to uporablja t.i. mailer, ki si ga pusti posredovati kot
odvisnost prek konstruktorja. Preberite več o pošiljanju e-pošte.
Zdaj se vrnemo nazaj k presenterju in dokončamo metodo contactFormSucceeded(). Ta pokliče metodo
sendMessage() razreda ContactFacade in ji posreduje podatke iz obrazca. In kako pridobimo objekt
ContactFacade? Pustimo si ga posredovati s konstruktorjem:
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('Sporočilo je bilo poslano');
$this->redirect('this');
}
}
Ko je e-pošta poslana, uporabniku prikažemo še t.i. flash sporočilo, ki potrjuje, da je bilo sporočilo poslano, nato pa preusmerimo na naslednjo stran, da obrazca ni mogoče ponovno poslati s pomočjo refresh v brskalniku.
Tako, in če vse deluje, bi morali biti sposobni poslati e-pošto iz vašega kontaktnega obrazca. Čestitam!
HTML predloga e-pošte
Zaenkrat se pošilja navadno besedilno e-sporočilo, ki vsebuje samo sporočilo, poslano z obrazcem. V e-pošti pa lahko
uporabimo HTML in naredimo njen videz privlačnejši. Zanjo bomo ustvarili predlogo v Latte, ki jo bomo zapisali v
app/Model/contactEmail.latte:
<html>
<title>Sporočilo iz kontaktnega obrazca</title>
<body>
<p><strong>Ime:</strong> {$name}</p>
<p><strong>E-pošta:</strong> {$email}</p>
<p><strong>Sporočilo:</strong> {$message}</p>
</body>
</html>
Ostane še prilagoditi ContactFacade, da bo uporabljal to predlogo. V konstruktorju bomo zahtevali razred
LatteFactory, ki zna izdelati objekt Latte\Engine, torej izrisovalnik Latte predlog. S pomočjo metode
renderToString() bomo predlogo izrisali v datoteko, prvi parameter je pot do predloge, drugi pa so
spremenljivke.
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') // vaša e-pošta
->setFrom($email, $name)
->setHtmlBody($body);
$this->mailer->send($mail);
}
}
Generirano HTML e-pošto nato posredujemo metodi setHtmlBody() namesto prvotni setBody(). Prav tako
nam ni treba navajati zadeve e-pošte v setSubject(), ker si jo bo knjižnica vzela iz elementa
<title> predloge.
Konfiguracija
V kodi razreda ContactFacade je še vedno trdo kodiran naš administratorski e-naslov
admin@example.com. Bolje bi bilo, da ga premaknemo v konfiguracijsko datoteko. Kako to storiti?
Najprej prilagodimo razred ContactFacade in niz z e-pošto nadomestimo s spremenljivko, posredovano
s konstruktorjem:
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);
// ...
}
}
Drugi korak pa je navedba vrednosti te spremenljivke v konfiguraciji. V datoteko app/config/services.neon
zapišemo:
services:
- App\Model\ContactFacade(adminEmail: admin@example.com)
In to je to. Če bi bilo elementov v odseku services veliko in bi imeli občutek, da se e-pošta med njimi
izgublja, jo lahko naredimo za spremenljivko. Prilagodimo zapis na:
services:
- App\Model\ContactFacade(adminEmail: %adminEmail%)
In v datoteki app/config/common.neon definiramo to spremenljivko:
parameters:
adminEmail: admin@example.com
In končano!