/
lets-create-contact-form.texy
226 lines (173 loc) · 7.59 KB
/
lets-create-contact-form.texy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
Să creăm un formular de contact
*******************************
.[perex]
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 |nette:installation]. Și apoi putem începe să creăm formularul.
Cel mai simplu mod este să creăm [formularul direct în Presenter |forms:in-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:
```php
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 |nette:glossary#events] `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`:
```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
<?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 |mail:].
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:
```php
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 |application:components#flash-messages], 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 .[#toc-html-email-template]
-------------------------------------------------
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`:
```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 |latte:develop#how-to-render-a-template]. Utilizăm metoda `renderToString()` pentru a reda șablonul într-un fișier, primul parametru este calea către șablon, iar al doilea sunt variabilele.
```php
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 .[#toc-configuring]
--------------------------------
Î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:
```php
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:
```neon
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:
```neon
services:
- App\Model\ContactFacade(adminEmail: %adminEmail%)
```
Și vom defini această variabilă în fișierul `app/config/common.neon`:
```neon
parameters:
adminEmail: admin@example.com
```
Și gata!
{{sitename: Best Practices}}