Bir İletişim Formu Oluşturalım

Bir e-postaya göndermek de dahil olmak üzere Nette'de bir iletişim formunun nasıl oluşturulacağına bir göz atalım. Hadi yapalım o zaman!

Öncelikle yeni bir proje oluşturmamız gerekiyor. Başlarken sayfasında açıklandığı gibi. Ve sonra formu oluşturmaya başlayabiliriz.

En kolay yol, formu doğrudan Presenter'da oluşturmaktır. Önceden hazırlanmış HomePresenter adresini kullanabiliriz. Formu temsil eden contactForm bileşenini ekleyeceğiz. Bunu createComponentContactForm() factory metodunu bileşeni üretecek kodun içine yazarak yapacağız:

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
	}
}

Gördüğünüz gibi iki metot oluşturduk. İlk yöntem createComponentContactForm() yeni bir form oluşturur. Bu formda addText(), addEmail() ve addTextArea() yöntemlerini kullanarak eklediğimiz isim, e-posta ve mesaj alanları bulunmaktadır. Ayrıca formu göndermek için bir düğme ekledik. Peki ya kullanıcı bazı alanları doldurmazsa? Bu durumda, ona bunun gerekli bir alan olduğunu bildirmeliyiz. Bunu setRequired() metodu ile yaptık. Son olarak, form başarıyla gönderildiğinde tetiklenen bir onSuccessolayı da ekledik. Bizim durumumuzda, gönderilen formun işlenmesiyle ilgilenen contactFormSucceeded yöntemini çağırır. Bunu birazdan koda ekleyeceğiz.

contantForm bileşeninin Home/default.latte şablonunda oluşturulmasına izin verin:

{block content}
<h1>Contant Form</h1>
{control contactForm}

E-postanın kendisini göndermek için ContactFacade adında yeni bir sınıf oluşturuyoruz ve bunu app/Model/ContactFacade.php dosyasına yerleştiriyoruz:

<?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() yöntemi e-postayı oluşturur ve gönderir. Bunu yapmak için, yapıcı aracılığıyla bir bağımlılık olarak aktardığı sözde bir mailer kullanır. E-posta gönderme hakkında daha fazla bilgi edinin.

Şimdi, sunucuya geri döneceğiz ve contactFormSucceeded() yöntemini tamamlayacağız. ContactFacade sınıfının sendMessage() metodunu çağırır ve form verilerini ona aktarır. Peki ContactFacade nesnesini nasıl elde edeceğiz? Yapıcı tarafından bize aktarılacak:

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');
	}
}

E-posta gönderildikten sonra, kullanıcıya mesajın gönderildiğini onaylayan sözde flaş mesajı gösteriyoruz ve ardından formun tarayıcıda yenile kullanılarak yeniden gönderilememesi için bir sonraki sayfaya yönlendiriyoruz.

Her şey çalışıyorsa, iletişim formunuzdan bir e-posta gönderebilmeniz gerekir. Tebrikler!

HTML E-posta Şablonu

Şimdilik, yalnızca form tarafından gönderilen mesajı içeren düz metin bir e-posta gönderiliyor. Ancak e-postada HTML kullanabilir ve daha çekici hale getirebiliriz. Bunun için Latte'de bir şablon oluşturacağız ve bu şablonu app/Model/contactEmail.latte adresine kaydedeceğiz:

<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>

Geriye bu şablonu kullanmak için ContactFacade adresini değiştirmek kalıyor. Yapıcıda, bir Latte şablon işleyicisi olan Latte\Engine nesnesini üretebilen LatteFactory sınıfını talep ediyoruz. Şablonu bir dosyaya işlemek için renderToString() yöntemini kullanırız, ilk parametre şablonun yolu ve ikincisi değişkenlerdir.

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);
	}
}

Daha sonra oluşturulan HTML e-postasını orijinal setBody() yerine setHtmlBody() yöntemine aktarıyoruz. Ayrıca setSubject() adresinde e-postanın konusunu belirtmemize gerek yoktur, çünkü kütüphane bunu <title> Şablon içinde.

Yapılandırma

ContactFacade sınıf kodunda, yönetici e-postamız admin@example.com hala sabit kodludur. Bunu yapılandırma dosyasına taşımak daha iyi olacaktır. Nasıl Yapılır?

İlk olarak, ContactFacade sınıfını değiştiriyoruz ve e-posta dizesini yapıcı tarafından geçirilen bir değişkenle değiştiriyoruz:

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);
		// ...
	}
}

İkinci adım ise bu değişkenin değerini yapılandırmaya koymaktır. app/config/services.neon dosyasına ekliyoruz:

services:
	- App\Model\ContactFacade(adminEmail: admin@example.com)

Ve işte bu kadar. services bölümünde çok sayıda öğe varsa ve e-postanın bunların arasında kaybolduğunu düşünüyorsanız, bunu bir değişken haline getirebiliriz. Girişi şu şekilde değiştireceğiz:

services:
	- App\Model\ContactFacade(adminEmail: %adminEmail%)

Ve bu değişkeni app/config/common.neon dosyasında tanımlayın:

parameters:
	adminEmail: admin@example.com

Ve bitti!