İletişim Formu Oluşturma

Nette'de e-postaya gönderme dahil bir iletişim formunun nasıl oluşturulacağına bir göz atacağız. Öyleyse başlayalım!

Öncelikle yeni bir proje oluşturmamız gerekiyor. Bunun nasıl yapılacağını Başlarken sayfası açıklıyor. Ve sonra formu oluşturmaya başlayabiliriz.

En kolay yol, doğrudan presenter içinde form oluşturmaktır. Önceden hazırlanmış HomePresenter'ı kullanabiliriz. Ona formu temsil eden contactForm bileşenini ekleyeceğiz. Bunu, bileşeni üreten createComponentContactForm() fabrika metodunu koda 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', 'İsim:')
			->setRequired('İsminizi girin');
		$form->addEmail('email', 'E-posta:')
			->setRequired('E-postanızı girin');
		$form->addTextarea('message', 'Mesaj:')
			->setRequired('Mesajınızı girin');
		$form->addSubmit('send', 'Gönder');
		$form->onSuccess[] = [$this, 'contactFormSucceeded'];
		return $form;
	}

	public function contactFormSucceeded(Form $form, $data): void
	{
		// e-posta gönderimi
	}
}

Gördüğünüz gibi, iki metot oluşturduk. İlk metot createComponentContactForm() yeni bir form oluşturur. Bu formda isim, e-posta ve mesaj için addText(), addEmail() ve addTextArea() metotlarıyla eklediğimiz alanlar bulunur. Ayrıca formu göndermek için bir düğme ekledik. Peki ya kullanıcı bir alanı doldurmazsa? Bu durumda, bunun zorunlu bir alan olduğunu ona bildirmeliyiz. Bunu setRequired() metoduyla başardık. Son olarak, form başarıyla gönderildiğinde tetiklenecek olan olay onSuccess'ı da ekledik. Bizim durumumuzda, gönderilen formu işlemekle ilgilenecek olan contactFormSucceeded metodunu çağırır. Bunu bir an sonra koda ekleyeceğiz.

contantForm bileşenini Home/default.latte şablonunda oluşturulmasını sağlayacağız:

{block content}
<h1>İletişim Formu</h1>
{control contactForm}

E-postanın kendisini göndermek için ContactFacade adını vereceğimiz yeni bir sınıf oluşturacağız ve onu app/Model/ContactFacade.php dosyasına yerleştireceğiz:

<?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') // sizin e-postanız
			->setFrom($email, $name)
			->setSubject('İletişim formundan mesaj')
			->setBody($message);

		$this->mailer->send($mail);
	}
}

sendMessage() metodu bir e-posta oluşturur ve gönderir. Bunun için yapıcı aracılığıyla bir bağımlılık olarak aldığı sözde mailer'ı kullanır. E-posta gönderme hakkında daha fazla bilgi edinin.

Şimdi presenter'a geri dönelim ve contactFormSucceeded() metodunu tamamlayalım. Bu metot, ContactFacade sınıfının sendMessage() metodunu çağıracak ve ona formdan gelen verileri iletecektir. Peki ContactFacade nesnesini nasıl elde ederiz? Yapıcı aracılığıyla bize iletilmesini sağlayacağız:

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('Mesaj gönderildi');
		$this->redirect('this');
	}
}

E-posta gönderildikten sonra, kullanıcıya mesajın gönderildiğini onaylayan sözde bir flash mesajı göstereceğiz ve ardından formun tarayıcıda yenile ile tekrar tekrar gönderilmesini önlemek için bir sonraki sayfaya yönlendireceğiz.

İşte bu kadar, her şey çalışıyorsa, iletişim formunuzdan bir e-posta gönderebilmelisiniz. Tebrikler!

HTML E-posta Şablonu

Şu ana kadar, yalnızca form tarafından gönderilen mesajı içeren düz metin bir e-posta gönderiliyor. Ancak e-postada HTML kullanabilir ve görünümünü daha çekici hale getirebiliriz. Bunun için Latte'de bir şablon oluşturacağız ve onu app/Model/contactEmail.latte dosyasına yazacağız:

<html>
	<title>İletişim Formundan Mesaj</title>

	<body>
		<p><strong>İsim:</strong> {$name}</p>
		<p><strong>E-posta:</strong> {$email}</p>
		<p><strong>Mesaj:</strong> {$message}</p>
	</body>
</html>

Geriye ContactFacade'i bu şablonu kullanacak şekilde düzenlemek kalıyor. Yapıcıda, Latte\Engine nesnesini, yani Latte şablon oluşturucuyu üretebilen LatteFactory sınıfını talep edeceğiz. renderToString() metoduyla şablonu bir dosyaya oluşturacağı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') // sizin e-postanız
			->setFrom($email, $name)
			->setHtmlBody($body);

		$this->mailer->send($mail);
	}
}

Oluşturulan HTML e-postayı daha sonra orijinal setBody() yerine setHtmlBody() metoduna ileteceğiz. Ayrıca setSubject() içinde e-posta konusunu belirtmemize gerek yok, çünkü kütüphane onu şablonun <title> öğesinden alacaktır.

Yapılandırma

ContactFacade sınıfının kodunda, yönetici e-postamız admin@example.com hala sabit kodlanmıştır. Onu yapılandırma dosyasına taşımak daha iyi olurdu. Bunu nasıl yaparız?

Önce ContactFacade sınıfını düzenleriz ve e-posta içeren karakter dizisini yapıcı tarafından iletilen bir değişkenle değiştiririz:

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

Ve ikinci adım, bu değişkenin değerini yapılandırmada belirtmektir. app/config/services.neon dosyasına şunu yazarız:

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

Ve işte bu kadar. services bölümündeki öğelerin sayısı çok fazlaysa ve e-postanın aralarında kaybolduğunu düşünüyorsanız, onu bir değişkene dönüştürebiliriz. Yazımı şu şekilde düzenleriz:

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

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

parameters:
	adminEmail: admin@example.com

Ve işimiz bitti!