Să creăm un formular de contact
Haideți să vedem cum se creează un formular de contact în Nette, inclusiv trimiterea acestuia la un e-mail. Deci, să o facem!
Mai întâi trebuie să creăm un nou proiect. După cum explică pagina de început. Și apoi putem începe să creăm formularul.
Cel mai simplu mod este să creăm formularul direct în Presenter. Putem
folosi formularul pre-fabricat HomePresenter
. Vom adăuga componenta contactForm
care reprezintă
formularul. Vom face acest lucru scriind metoda factory createComponentContactForm()
în codul care va produce
componenta:
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
}
}
După cum puteți vedea, am creat două metode. Prima metodă createComponentContactForm()
creează un nou
formular. Acesta are câmpuri pentru nume, e-mail și mesaj, pe care le adăugăm cu ajutorul metodelor addText()
,
addEmail()
și addTextArea()
. De asemenea, am adăugat un buton pentru a trimite formularul. Dar ce se
întâmplă dacă utilizatorul nu completează unele câmpuri? În acest caz, ar trebui să-l anunțăm că este un câmp
obligatoriu. Am făcut acest lucru cu metoda setRequired()
. În cele din urmă, am adăugat și un eveniment onSuccess
, care este declanșat dacă formularul
este trimis cu succes. În cazul nostru, acesta apelează metoda contactFormSucceeded
, care se ocupă de procesarea
formularului trimis. Vom adăuga acest lucru în cod imediat.
Lăsați componenta contantForm
să fie redată în șablonul Home/default.latte
:
{block content}
<h1>Contant Form</h1>
{control contactForm}
Pentru a trimite e-mailul propriu-zis, creăm o nouă clasă numită ContactFacade
și o plasăm în fișierul
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);
}
}
Metoda sendMessage()
va crea și va trimite e-mailul. Pentru a face acest lucru, folosește un așa-numit mailer,
pe care îl transmite ca dependență prin intermediul constructorului. Citiți mai multe despre trimiterea de e-mailuri.
Acum, ne vom întoarce la prezentator și vom finaliza metoda contactFormSucceeded()
. Acesta apelează metoda
sendMessage()
a clasei ContactFacade
și îi transmite datele formularului. Și cum obținem obiectul
ContactFacade
? Ne va fi transmis de către 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('The message has been sent');
$this->redirect('this');
}
}
După ce e-mailul este trimis, îi arătăm utilizatorului așa-numitul mesaj flash, confirmând că mesajul a fost trimis, și apoi îl redirecționăm către pagina următoare, astfel încât formularul să nu poată fi trimis din nou folosind refresh în browser.
Ei bine, dacă totul funcționează, ar trebui să puteți trimite un e-mail din formularul de contact. Felicitări!
Șablon de e-mail HTML
Deocamdată, se trimite un e-mail text simplu care conține doar mesajul trimis prin formular. Dar putem folosi HTML în e-mail
și să-l facem mai atractiv. Vom crea un șablon pentru aceasta în Latte, pe care îl vom salva în
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>
Rămâne să modificăm ContactFacade
pentru a utiliza acest șablon. În constructor, solicităm clasa
LatteFactory
, care poate produce obiectul Latte\Engine
, un renderizator de șabloane Latte. Utilizăm metoda
renderToString()
pentru a reda șablonul într-un fișier, primul parametru este calea către șablon, iar al doilea
sunt variabilele.
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);
}
}
Apoi, trecem e-mailul HTML generat la metoda setHtmlBody()
în loc de originalul setBody()
. De
asemenea, nu trebuie să specificăm subiectul e-mailului în setSubject()
, deoarece biblioteca îl preia din
elementul <title>
din șablon.
Configurarea
În codul clasei ContactFacade
, e-mailul nostru de administrare admin@example.com
este încă
codificat în mod greșit. Ar fi mai bine să îl mutați în fișierul de configurare. Cum se face acest lucru?
Mai întâi, modificăm clasa ContactFacade
și înlocuim șirul de e-mail cu o variabilă transmisă de
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);
// ...
}
}
Iar al doilea pas este să introducem valoarea acestei variabile în configurație. În fișierul
app/config/services.neon
adăugăm:
services:
- App\Model\ContactFacade(adminEmail: admin@example.com)
Și asta e tot. Dacă există multe elemente în secțiunea services
și aveți impresia că e-mailul se pierde
printre ele, îl putem transforma într-o variabilă. Vom modifica intrarea în:
services:
- App\Model\ContactFacade(adminEmail: %adminEmail%)
Și vom defini această variabilă în fișierul app/config/common.neon
:
parameters:
adminEmail: admin@example.com
Și gata!