Да създадем формуляр за контакт
Нека разгледаме как да създадем формуляр за контакт в Nette, включително изпращането му на имейл. Така че нека го направим!
Първо трябва да създадем нов проект. Както е обяснено в страницата " Започване". А след това можем да започнем създаването на формуляра.
Най-лесният начин е да създадете формуляра директно в Presenter. Можем да
използваме предварително създадената страница HomePresenter
. Ще
добавим компонента contactForm
, представляващ формата. Ще направим
това, като напишем фабричния метод на createComponentContactForm()
в кода,
който ще създава компонента:
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
}
}
Както можете да видите, създадохме два метода. Първият метод
createComponentContactForm()
създава нова форма. Тя има полета за име, имейл и
съобщение, които добавяме с помощта на методите addText()
,
addEmail()
и addTextArea()
. Добавихме и бутон за изпращане на
формуляра. Но какво ще стане, ако потребителят не попълни някои полета?
В такъв случай трябва да го уведомим, че това е задължително поле.
Направихме това с метода setRequired()
. Накрая добавихме и събитие onSuccess
, което се задейства,
ако формулярът е изпратен успешно. В нашия случай то извиква метода
contactFormSucceeded
, който се грижи за обработката на изпратения
формуляр. След малко ще добавим това към кода.
Нека компонентът contantForm
бъде визуализиран в шаблона
Home/default.latte
:
{block content}
<h1>Contant Form</h1>
{control contactForm}
За да изпратим самия имейл, създаваме нов клас, наречен
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') // your email
->setFrom($email, $name)
->setSubject('Message from the contact form')
->setBody($message);
$this->mailer->send($mail);
}
}
Методът sendMessage()
ще създаде и изпрати имейла. За целта той
използва така наречения mailer, който предава като зависимост чрез
конструктора. Прочетете повече за изпращането на
имейли.
Сега ще се върнем към презентатора и ще завършим метода
contactFormSucceeded()
. Той извиква метода sendMessage()
на класа
ContactFacade
и му предава данните от формуляра. А как ще получим
обекта ContactFacade
? Той ще ни бъде предаден от конструктора:
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');
}
}
След като имейлът бъде изпратен, показваме на потребителя т.нар. флаш съобщение, с което потвърждаваме, че съобщението е изпратено, и след това пренасочваме към следващата страница, така че формулярът да не може да бъде изпратен отново с помощта на refresh в браузъра.
Е, ако всичко е наред, би трябвало да можете да изпратите имейл от формуляра си за контакт. Поздравления!
HTML шаблон за електронна поща
Засега се изпраща имейл с обикновен текст, съдържащ само съобщението,
изпратено от формуляра. Но можем да използваме HTML в имейла и да го
направим по-привлекателен. Ще създадем шаблон за него в Latte, който ще
запазим в app/Model/contactEmail.latte
:
<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>
Остава да модифицираме ContactFacade
, за да използваме този шаблон. В
конструктора заявяваме класа LatteFactory
, който може да създаде
обекта Latte\Engine
, рендер
на шаблона Latte. Използваме метода renderToString()
, за да
визуализираме шаблона във файл, като първият параметър е пътят до
шаблона, а вторият – променливите.
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);
}
}
След това предаваме генерирания HTML имейл на метода setHtmlBody()
вместо на оригиналния setBody()
. Също така не е необходимо да
посочваме темата на имейла в setSubject()
, защото библиотеката я
взема от елемента <title>
в шаблона.
Конфигуриране на
В кода на класа ContactFacade
нашият имейл адрес на администратора
admin@example.com
все още е твърдо кодиран. По-добре би било да го
преместите в конфигурационния файл. Как да го направим?
Първо, модифицираме класа ContactFacade
и заменяме низът за имейл с
променлива, предадена от конструктора:
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
има много елементи и ви се
струва, че имейлът се губи сред тях, можем да го направим променлива. Ще
променим записа на:
services:
- App\Model\ContactFacade(adminEmail: %adminEmail%)
И ще дефинираме тази променлива във файла app/config/common.neon
:
parameters:
adminEmail: admin@example.com
И готово!