Kayıt Oluşturma ve Düzenleme Formu

Nette'de bir kaydın eklenmesi ve düzenlenmesi, ikisi için de aynı form kullanılarak nasıl doğru şekilde gerçekleştirilir?

Çoğu durumda kayıt ekleme ve düzenleme formları birbirinin aynısıdır, belki yalnızca düğme metninde ayrılırlar. Formu önce kayıt eklemek, sonra düzenlemek için kullandığımız basit presenter örneklerini göstereceğiz ve en sonunda iki çözümü birleştireceğiz.

Kayıt Ekleme

Kayıt eklemeye yarayan bir presenter örneği. Asıl veritabanı işini, kodu bu örnek için önemli olmayan bir Facade sınıfına bırakacağız.

use Nette\Application\UI\Form;

class RecordPresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Facade $facade,
	) {
	}

	protected function createComponentRecordForm(): Form
	{
		$form = new Form;

		// ... form alanlarını ekle ...

		$form->onSuccess[] = $this->recordFormSucceeded(...);
		return $form;
	}

	private function recordFormSucceeded(Form $form, array $data): void
	{
		$this->facade->add($data); // kaydı veritabanına ekle
		$this->flashMessage('Başarıyla eklendi');
		$this->redirect('...');
	}

	public function renderAdd(): void
	{
		// ...
	}
}

Kayıt Düzenleme

Şimdi kayıt düzenlemeye yarayan bir presenter'ın nasıl görüneceğine bakalım:

use Nette\Application\UI\Form;

class RecordPresenter extends Nette\Application\UI\Presenter
{
	private $record;

	public function __construct(
		private Facade $facade,
	) {
	}

	public function actionEdit(int $id): void
	{
		$record = $this->facade->get($id);
		if (
			!$record // kaydın varlığını doğrula
			|| !$this->facade->isEditAllowed(/*...*/) // izinleri denetle
		) {
			$this->error(); // 404 hatası
		}

		$this->record = $record;
	}

	protected function createComponentRecordForm(): Form
	{
		// eylemin 'edit' olduğunu doğrula
		if ($this->getAction() !== 'edit') {
			$this->error();
		}

		$form = new Form;

		// ... form alanlarını ekle ...

		$form->setDefaults($this->record); // varsayılan değerleri ayarla
		$form->onSuccess[] = $this->recordFormSucceeded(...);
		return $form;
	}

	private function recordFormSucceeded(Form $form, array $data): void
	{
		$this->facade->update($this->record->id, $data); // kaydı güncelle
		$this->flashMessage('Başarıyla güncellendi');
		$this->redirect('...');
	}
}

Presenter yaşam döngüsünün başında çağrılan action metodunda, kaydın varlığını ve kullanıcının onu düzenleme iznini doğrularız.

Kaydı $record özelliğinde saklarız; böylece varsayılan değerleri ayarlamak için createComponentRecordForm() metodunda ve ID'ye erişmek için recordFormSucceeded() metodunda kullanılabilir olur. Alternatif bir çözüm, varsayılan değerleri doğrudan actionEdit() içinde ayarlamak ve ID değerini (URL'nin bir parçasıdır) getParameter('id') ile almaktır:

	public function actionEdit(int $id): void
	{
		$record = $this->facade->get($id);
		if (
			// varlığı doğrula ve izinleri denetle
		) {
			$this->error();
		}

		// formun varsayılan değerlerini ayarla
		$this->getComponent('recordForm')
			->setDefaults($record);
	}

	public function recordFormSucceeded(Form $form, array $data): void
	{
		$id = (int) $this->getParameter('id');
		$this->facade->update($id, $data);
		// ...
	}

Ancak, ki bu kodun tamamından çıkarılacak en önemli ders olmalı, formu oluştururken eylemin gerçekten edit olduğundan emin olmalıyız. Aksi hâlde actionEdit() metodundaki doğrulama hiç yapılmazdı!

Ekleme ve Düzenleme İçin Aynı Form

Şimdi iki presenter'ı tek bir presenter'da birleştirelim. Ya createComponentRecordForm() metodunda eylemi ayırt edip formu buna göre yapılandırabiliriz, ya da bunu doğrudan action metotlarına devredip koşullu denetimi ortadan kaldırabiliriz:

class RecordPresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Facade $facade,
	) {
	}

	public function actionAdd(): void
	{
		$form = $this->getComponent('recordForm');
		$form->onSuccess[] = $this->addingFormSucceeded(...);
	}

	public function actionEdit(int $id): void
	{
		$record = $this->facade->get($id);
		if (
			!$record // kaydın varlığını doğrula
			|| !$this->facade->isEditAllowed(/*...*/) // izinleri denetle
		) {
			$this->error(); // 404 hatası
		}

		$form = $this->getComponent('recordForm');
		$form->setDefaults($record); // varsayılan değerleri ayarla
		$form->onSuccess[] = $this->editingFormSucceeded(...);
	}

	protected function createComponentRecordForm(): Form
	{
		// eylemin 'add' ya da 'edit' olduğunu doğrula
		if (!in_array($this->getAction(), ['add', 'edit'])) {
			$this->error();
		}

		$form = new Form;

		// ... form alanlarını ekle ...

		return $form;
	}

	private function addingFormSucceeded(Form $form, array $data): void
	{
		$this->facade->add($data); // kaydı veritabanına ekle
		$this->flashMessage('Başarıyla eklendi');
		$this->redirect('...');
	}

	private function editingFormSucceeded(Form $form, array $data): void
	{
		$id = (int) $this->getParameter('id');
		$this->facade->update($id, $data); // kaydı güncelle
		$this->flashMessage('Başarıyla güncellendi');
		$this->redirect('...');
	}
}