Creăm un formular de contact
Vom analiza cum să creăm un formular de contact în Nette, inclusiv trimiterea pe email. Să începem!
Mai întâi trebuie să creăm un proiect nou. Cum se face acest lucru este explicat pe pagina Începeți. Apoi putem începe crearea formularului.
Cel mai simplu este să creăm formularul direct în presenter. Putem
folosi HomePresenter
pre-pregătit. În el vom adăuga componenta contactForm
care reprezintă
formularul. Vom face acest lucru scriind în cod metoda fabrică createComponentContactForm()
, 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', 'Nume:')
->setRequired('Introduceți numele');
$form->addEmail('email', 'E-mail:')
->setRequired('Introduceți e-mailul');
$form->addTextarea('message', 'Mesaj:')
->setRequired('Introduceți mesajul');
$form->addSubmit('send', 'Trimite');
$form->onSuccess[] = [$this, 'contactFormSucceeded'];
return $form;
}
public function contactFormSucceeded(Form $form, $data): void
{
// trimiterea emailului
}
}
După cum vedeți, am creat două metode. Prima metodă createComponentContactForm()
creează un nou formular.
Acesta are câmpuri pentru nume, email și mesaj, pe care le adăugăm cu metodele addText()
, addEmail()
și addTextArea()
. Am adăugat și un buton pentru trimiterea formularului. Dar ce se întâmplă dacă utilizatorul
nu completează un câmp? În acest caz, ar trebui să-l informăm că este un câmp obligatoriu. Am realizat acest lucru cu
metoda setRequired()
. În final, am adăugat și evenimentul onSuccess
, care se declanșează dacă
formularul este trimis cu succes. În cazul nostru, apelează metoda contactFormSucceeded
, care se ocupă de
procesarea formularului trimis. Vom completa codul pentru aceasta imediat.
Vom lăsa componenta contactForm
să fie redată în șablonul Home/default.latte
:
{block content}
<h1>Formular de contact</h1>
{control contactForm}
Pentru trimiterea efectivă a emailului, vom crea o nouă clasă, pe care o vom numi ContactFacade
și o vom
plasa î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') // emailul dvs.
->setFrom($email, $name)
->setSubject('Mesaj din formularul de contact')
->setBody($message);
$this->mailer->send($mail);
}
}
Metoda sendMessage()
creează și trimite emailul. Utilizează pentru aceasta așa-numitul mailer, pe care îl
primește ca dependență prin constructor. Citiți mai multe despre trimiterea
emailurilor.
Acum ne vom întoarce la presenter și vom finaliza metoda contactFormSucceeded()
. Aceasta va apela metoda
sendMessage()
a clasei ContactFacade
și îi va transmite datele din formular. Și cum obținem obiectul
ContactFacade
? Îl vom primi prin 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('Mesajul a fost trimis');
$this->redirect('this');
}
}
După ce emailul este trimis, vom afișa utilizatorului un așa-numit flash message, confirmând că mesajul a fost trimis, și apoi vom redirecționa către aceeași pagină (pentru a curăța formularul), astfel încât să nu fie posibilă retrimiterea formularului prin refresh în browser.
Deci, dacă totul funcționează, ar trebui să puteți trimite un email din formularul dvs. de contact. Felicitări!
Șablon HTML pentru email
Deocamdată se trimite un email text simplu care conține doar mesajul trimis prin formular. Dar în email putem folosi HTML
și să-i facem aspectul mai atractiv. Vom crea un șablon pentru el în Latte, pe care îl vom scrie în
app/Model/contactEmail.latte
:
<html>
<title>Mesaj din formularul de contact</title>
<body>
<p><strong>Nume:</strong> {$name}</p>
<p><strong>E-mail:</strong> {$email}</p>
<p><strong>Mesaj:</strong> {$message}</p>
</body>
</html>
Rămâne să modificăm ContactFacade
pentru a utiliza acest șablon. În constructor vom solicita clasa
LatteFactory
, care poate produce obiectul Latte\Engine
, adică motorul de redare a șabloanelor Latte. Folosind metoda
renderToString()
, vom reda șablonul într-un șir, primul parametru este calea către șablon și 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') // emailul dvs.
->setFrom($email, $name)
->setHtmlBody($body);
$this->mailer->send($mail);
}
}
Emailul HTML generat îl vom transmite apoi metodei setHtmlBody()
în locul celei originale
setBody()
. De asemenea, nu trebuie să specificăm subiectul emailului în setSubject()
, deoarece
biblioteca îl va prelua din elementul <title>
al șablonului.
Configurare
În codul clasei ContactFacade
este încă hardcodat emailul nostru de administrator
admin@example.com
. Ar fi mai bine să-l mutăm în fișierul de configurare. Cum facem asta?
Mai întâi modificăm clasa ContactFacade
și înlocuim șirul cu emailul cu o variabilă transmisă prin
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);
// ...
}
}
Și al doilea pas este specificarea valorii acestei variabile în configurație. În fișierul
app/config/services.neon
scriem:
services:
- App\Model\ContactFacade(adminEmail: admin@example.com)
Și gata. Dacă ar fi multe elemente în secțiunea services
și ați avea senzația că emailul se pierde printre
ele, îl putem transforma într-o variabilă. Modificăm înregistrarea la:
services:
- App\Model\ContactFacade(adminEmail: %adminEmail%)
Și în fișierul app/config/common.neon
definim această variabilă:
parameters:
adminEmail: admin@example.com
Și am terminat!