Nette Documentation Preview

syntax
Yorumlar
********

Blog faaliyete geçti, çok iyi blog yazıları yazdık ve bunları Adminer üzerinden yayınladık. İnsanlar blogu okuyor ve fikirlerimiz hakkında çok tutkulular. Her gün övgü dolu pek çok e-posta alıyoruz. Ancak tüm bu övgüler sadece e-postada kaldığında ve başka kimse okuyamadığında ne işe yarıyor? İnsanlar doğrudan bloga yorum yapabilse ve böylece herkes ne kadar harika olduğumuzu okuyabilse daha iyi olmaz mıydı?

Tüm makaleleri yorumlanabilir hale getirelim.


Yeni Tablo Oluşturma .[#toc-creating-a-new-table]
=================================================

Adminer'ı tekrar çalıştırın ve bu sütunlarla `comments` adında yeni bir tablo oluşturun:

- `id` int, otomatik artırmayı (AI) kontrol edin
- `post_id`, `posts` tablosuna referans veren bir yabancı anahtar
- `name` varchar, uzunluk 255
- `email` varchar, uzunluk 255
- `content` metin
- `created_at` zaman damgası

Bu şekilde görünmelidir:

[* adminer-comments.webp *]

InnoDB tablo depolamasını kullanmayı unutmayın ve Kaydet'e basın.

```sql
CREATE TABLE `comments` (
	`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`post_id` int(11) NOT NULL,
	`name` varchar(250) NOT NULL,
	`email` varchar(250) NOT NULL,
	`content` text NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
	FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`)
) ENGINE=InnoDB CHARSET=utf8;
```


Yorum Yapma Formu .[#toc-form-for-commenting]
=============================================

İlk olarak, kullanıcıların sayfamıza yorum yapmasına izin verecek bir form oluşturmamız gerekiyor. Nette Framework formlar için harika bir desteğe sahiptir. Bir sunumcuda yapılandırılabilir ve bir şablonda işlenebilirler.

Nette Framework *bileşenler* kavramına sahiptir. Bir **bileşen**, başka bir bileşene eklenebilen yeniden kullanılabilir bir sınıf veya kod parçasıdır. Sunucu bile bir bileşendir. Her bileşen, bileşen fabrikası kullanılarak oluşturulur. Öyleyse `PostPresenter` adresinde yorum formu fabrikasını tanımlayalım.

```php .{file:app/UI/Post/PostPresenter.php}
protected function createComponentCommentForm(): Form
{
	$form = new Form; // Nette\Application\UI\Form anlamına gelir

	$form->addText('name', 'Your name:')
		->setRequired();

	$form->addEmail('email', 'Email:');

	$form->addTextArea('content', 'Comment:')
		->setRequired();

	$form->addSubmit('send', 'Publish comment');

	return $form;
}
```

Bunu biraz açıklayalım. İlk satır `Form` bileşeninin yeni bir örneğini oluşturuyor. Aşağıdaki yöntemler HTML girdilerini form tanımına ekliyor. `->addText` şu şekilde render edilecek `<input type=text name=name>`ile `<label>Your name:</label>`. Şu anda zaten tahmin etmiş olabileceğiniz gibi, `->addTextArea` bir `<textarea>` ve `->addSubmit` bir `<input type=submit>`. Bunun gibi daha fazla yöntem var, ancak şu anda bilmeniz gereken tek şey bu. [Belgelerden daha fazlasını öğrenebilirsiniz |forms:].

Form bileşeni bir sunucuda tanımlandıktan sonra, onu bir şablonda oluşturabiliriz (görüntüleyebiliriz). Bunu yapmak için, `{control}` etiketini yazı ayrıntısı şablonunun sonuna, `Post/show.latte` içine yerleştirin. Bileşenin adı `commentForm` olduğundan ( `createComponentCommentForm` yönteminin adından türetilmiştir), etiket aşağıdaki gibi görünecektir

```latte .{file:app/UI/Post/show.latte}
...
<h2>Post new comment</h2>

{control commentForm}
```

Şimdi bazı gönderilerin detaylarını kontrol ederseniz, yorum göndermek için yeni bir form olacaktır.


Veritabanına Kaydetme .[#toc-saving-to-database]
================================================

Bazı verileri göndermeyi denediniz mi? Formun herhangi bir işlem yapmadığını fark etmiş olabilirsiniz. Sadece orada duruyor, havalı görünüyor ve hiçbir şey yapmıyor. Gönderilen verileri kaydedecek bir geri arama yöntemi eklememiz gerekiyor.

`commentForm` bileşen fabrikasında `return` satırından önce aşağıdaki satırı yerleştirin:

```php
$form->onSuccess[] = $this->commentFormSucceeded(...);
```

"Form başarıyla gönderildikten sonra, geçerli sunum yapan kişinin `commentFormSucceeded` yöntemini çağır" anlamına gelir. Bu yöntem henüz mevcut değil, bu yüzden onu oluşturalım.

```php .{file:app/UI/Post/PostPresenter.php}
private function commentFormSucceeded(\stdClass $data): void
{
	$id = $this->getParameter('id');

	$this->database->table('comments')->insert([
		'post_id' => $id,
		'name' => $data->name,
		'email' => $data->email,
		'content' => $data->content,
	]);

	$this->flashMessage('Thank you for your comment', 'success');
	$this->redirect('this');
}
```

Bunu `commentForm` bileşen fabrikasından hemen sonra yerleştirmelisiniz.

new metodunun bir argümanı vardır; bu argüman, bileşen fabrikası tarafından oluşturulan, gönderilen formun örneğidir. Gönderilen değerleri `$data` adresinden alıyoruz. Ve sonra verileri `comments` veritabanı tablosuna ekliyoruz.

Açıklanması gereken iki yöntem çağrısı daha vardır. Yönlendirme, kelimenin tam anlamıyla geçerli sayfaya yönlendirir. Form gönderildiğinde, geçerli olduğunda ve geri arama işlemi yapması gerekeni yaptığında bunu her seferinde yapmalısınız. Ayrıca, formu gönderdikten sonra sayfayı yeniden yönlendirdiğinizde, bazen tarayıcıda görebileceğiniz iyi bilinen `Would you like to submit the post data again?` mesajını görmezsiniz. (Genel olarak, `POST` yöntemiyle bir form gönderdikten sonra, kullanıcıyı her zaman bir `GET` eylemine yönlendirmelisiniz).

`flashMessage`, kullanıcıyı bir işlemin sonucu hakkında bilgilendirmek içindir. Yönlendirme yaptığımız için, mesaj doğrudan şablona aktarılamaz ve işlenemez. Bu yüzden, onu saklayacak ve bir sonraki sayfa yüklemesinde kullanılabilir hale getirecek bu yöntem vardır. Flash mesajları varsayılan `app/UI/@layout.latte` dosyasında oluşturulur ve aşağıdaki gibi görünür:

```latte
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
	{$flash->message}
</div>
```

Zaten bildiğimiz gibi, bunlar şablona otomatik olarak aktarılır, bu yüzden çok fazla düşünmenize gerek yoktur, sadece çalışır. Daha fazla ayrıntı için [belgeleri kontrol |application:presenters#flash-messages] edin.


Yorumların Oluşturulması .[#toc-rendering-the-comments]
=======================================================

Bu çok seveceğiniz şeylerden biri. Nette Database [Explorer |database:explorer] adında harika bir özelliğe sahip. Tabloları InnoDB olarak oluşturduğumuzu hatırlıyor musunuz? Adminer, bizi bir ton işten kurtaracak sözde [yabancı anahtarları |https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html] oluşturdu.

Nette Database Explorer, tablolar arasındaki ilişkileri çözmek için yabancı anahtarları kullanır ve ilişkileri bilerek sizin için otomatik olarak sorgular oluşturabilir.

Hatırlayabileceğiniz gibi, `$post` değişkenini `PostPresenter::renderShow()` adresindeki şablona aktardık ve şimdi `post_id` sütunu `$post->id` sütunumuza eşit olan tüm yorumları yinelemek istiyoruz. Bunu `$post->related('comments')` adresini çağırarak yapabilirsiniz. Bu kadar basit. Ortaya çıkan koda bakın.

```php .{file:app/UI/Post/PostPresenter.php}
public function renderShow(int $id): void
{
	...
	$this->template->post = $post;
	$this->template->comments = $post->related('comments')->order('created_at');
}
```

Ve şablon:

```latte .{file:app/UI/Post/show.latte}
...
<h2>Comments</h2>

<div class="comments">
	{foreach $comments as $comment}
		<p><b><a href="mailto:{$comment->email}" n:tag-if="$comment->email">
			{$comment->name}
		</a></b> said:</p>

		<div>{$comment->content}</div>
	{/foreach}
</div>
...
```

Özel `n:tag-if` niteliğine dikkat edin. `n: attributes` 'un nasıl çalıştığını zaten biliyorsunuz. Eğer özniteliğin başına `tag-` eklerseniz, sadece etiketlerin etrafına sarılır, içeriklerine değil. Bu, yorumcunun e-posta adresini verdiyse adını bir bağlantı haline getirmenize olanak tanır. Bu iki satırın sonuçları aynıdır:

```latte
<strong n:tag-if="$important"> Hello there! </strong>

{if $important}<strong>{/if} Hello there! {if $important}</strong>{/if}
```

{{priority: -1}}
{{sitename: Nette Quickstart}}

Yorumlar

Blog faaliyete geçti, çok iyi blog yazıları yazdık ve bunları Adminer üzerinden yayınladık. İnsanlar blogu okuyor ve fikirlerimiz hakkında çok tutkulular. Her gün övgü dolu pek çok e-posta alıyoruz. Ancak tüm bu övgüler sadece e-postada kaldığında ve başka kimse okuyamadığında ne işe yarıyor? İnsanlar doğrudan bloga yorum yapabilse ve böylece herkes ne kadar harika olduğumuzu okuyabilse daha iyi olmaz mıydı?

Tüm makaleleri yorumlanabilir hale getirelim.

Yeni Tablo Oluşturma

Adminer'ı tekrar çalıştırın ve bu sütunlarla comments adında yeni bir tablo oluşturun:

  • id int, otomatik artırmayı (AI) kontrol edin
  • post_id, posts tablosuna referans veren bir yabancı anahtar
  • name varchar, uzunluk 255
  • email varchar, uzunluk 255
  • content metin
  • created_at zaman damgası

Bu şekilde görünmelidir:

InnoDB tablo depolamasını kullanmayı unutmayın ve Kaydet'e basın.

CREATE TABLE `comments` (
	`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`post_id` int(11) NOT NULL,
	`name` varchar(250) NOT NULL,
	`email` varchar(250) NOT NULL,
	`content` text NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
	FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`)
) ENGINE=InnoDB CHARSET=utf8;

Yorum Yapma Formu

İlk olarak, kullanıcıların sayfamıza yorum yapmasına izin verecek bir form oluşturmamız gerekiyor. Nette Framework formlar için harika bir desteğe sahiptir. Bir sunumcuda yapılandırılabilir ve bir şablonda işlenebilirler.

Nette Framework bileşenler kavramına sahiptir. Bir bileşen, başka bir bileşene eklenebilen yeniden kullanılabilir bir sınıf veya kod parçasıdır. Sunucu bile bir bileşendir. Her bileşen, bileşen fabrikası kullanılarak oluşturulur. Öyleyse PostPresenter adresinde yorum formu fabrikasını tanımlayalım.

protected function createComponentCommentForm(): Form
{
	$form = new Form; // Nette\Application\UI\Form anlamına gelir

	$form->addText('name', 'Your name:')
		->setRequired();

	$form->addEmail('email', 'Email:');

	$form->addTextArea('content', 'Comment:')
		->setRequired();

	$form->addSubmit('send', 'Publish comment');

	return $form;
}

Bunu biraz açıklayalım. İlk satır Form bileşeninin yeni bir örneğini oluşturuyor. Aşağıdaki yöntemler HTML girdilerini form tanımına ekliyor. ->addText şu şekilde render edilecek <input type=text name=name>ile <label>Your name:</label>. Şu anda zaten tahmin etmiş olabileceğiniz gibi, ->addTextArea bir <textarea> ve ->addSubmit bir <input type=submit>. Bunun gibi daha fazla yöntem var, ancak şu anda bilmeniz gereken tek şey bu. Belgelerden daha fazlasını öğrenebilirsiniz.

Form bileşeni bir sunucuda tanımlandıktan sonra, onu bir şablonda oluşturabiliriz (görüntüleyebiliriz). Bunu yapmak için, {control} etiketini yazı ayrıntısı şablonunun sonuna, Post/show.latte içine yerleştirin. Bileşenin adı commentForm olduğundan ( createComponentCommentForm yönteminin adından türetilmiştir), etiket aşağıdaki gibi görünecektir

...
<h2>Post new comment</h2>

{control commentForm}

Şimdi bazı gönderilerin detaylarını kontrol ederseniz, yorum göndermek için yeni bir form olacaktır.

Veritabanına Kaydetme

Bazı verileri göndermeyi denediniz mi? Formun herhangi bir işlem yapmadığını fark etmiş olabilirsiniz. Sadece orada duruyor, havalı görünüyor ve hiçbir şey yapmıyor. Gönderilen verileri kaydedecek bir geri arama yöntemi eklememiz gerekiyor.

commentForm bileşen fabrikasında return satırından önce aşağıdaki satırı yerleştirin:

$form->onSuccess[] = $this->commentFormSucceeded(...);

„Form başarıyla gönderildikten sonra, geçerli sunum yapan kişinin commentFormSucceeded yöntemini çağır“ anlamına gelir. Bu yöntem henüz mevcut değil, bu yüzden onu oluşturalım.

private function commentFormSucceeded(\stdClass $data): void
{
	$id = $this->getParameter('id');

	$this->database->table('comments')->insert([
		'post_id' => $id,
		'name' => $data->name,
		'email' => $data->email,
		'content' => $data->content,
	]);

	$this->flashMessage('Thank you for your comment', 'success');
	$this->redirect('this');
}

Bunu commentForm bileşen fabrikasından hemen sonra yerleştirmelisiniz.

new metodunun bir argümanı vardır; bu argüman, bileşen fabrikası tarafından oluşturulan, gönderilen formun örneğidir. Gönderilen değerleri $data adresinden alıyoruz. Ve sonra verileri comments veritabanı tablosuna ekliyoruz.

Açıklanması gereken iki yöntem çağrısı daha vardır. Yönlendirme, kelimenin tam anlamıyla geçerli sayfaya yönlendirir. Form gönderildiğinde, geçerli olduğunda ve geri arama işlemi yapması gerekeni yaptığında bunu her seferinde yapmalısınız. Ayrıca, formu gönderdikten sonra sayfayı yeniden yönlendirdiğinizde, bazen tarayıcıda görebileceğiniz iyi bilinen Would you like to submit the post data again? mesajını görmezsiniz. (Genel olarak, POST yöntemiyle bir form gönderdikten sonra, kullanıcıyı her zaman bir GET eylemine yönlendirmelisiniz).

flashMessage, kullanıcıyı bir işlemin sonucu hakkında bilgilendirmek içindir. Yönlendirme yaptığımız için, mesaj doğrudan şablona aktarılamaz ve işlenemez. Bu yüzden, onu saklayacak ve bir sonraki sayfa yüklemesinde kullanılabilir hale getirecek bu yöntem vardır. Flash mesajları varsayılan app/UI/@layout.latte dosyasında oluşturulur ve aşağıdaki gibi görünür:

<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
	{$flash->message}
</div>

Zaten bildiğimiz gibi, bunlar şablona otomatik olarak aktarılır, bu yüzden çok fazla düşünmenize gerek yoktur, sadece çalışır. Daha fazla ayrıntı için belgeleri kontrol edin.

Yorumların Oluşturulması

Bu çok seveceğiniz şeylerden biri. Nette Database Explorer adında harika bir özelliğe sahip. Tabloları InnoDB olarak oluşturduğumuzu hatırlıyor musunuz? Adminer, bizi bir ton işten kurtaracak sözde yabancı anahtarları oluşturdu.

Nette Database Explorer, tablolar arasındaki ilişkileri çözmek için yabancı anahtarları kullanır ve ilişkileri bilerek sizin için otomatik olarak sorgular oluşturabilir.

Hatırlayabileceğiniz gibi, $post değişkenini PostPresenter::renderShow() adresindeki şablona aktardık ve şimdi post_id sütunu $post->id sütunumuza eşit olan tüm yorumları yinelemek istiyoruz. Bunu $post->related('comments') adresini çağırarak yapabilirsiniz. Bu kadar basit. Ortaya çıkan koda bakın.

public function renderShow(int $id): void
{
	...
	$this->template->post = $post;
	$this->template->comments = $post->related('comments')->order('created_at');
}

Ve şablon:

...
<h2>Comments</h2>

<div class="comments">
	{foreach $comments as $comment}
		<p><b><a href="mailto:{$comment->email}" n:tag-if="$comment->email">
			{$comment->name}
		</a></b> said:</p>

		<div>{$comment->content}</div>
	{/foreach}
</div>
...

Özel n:tag-if niteliğine dikkat edin. n: attributes 'un nasıl çalıştığını zaten biliyorsunuz. Eğer özniteliğin başına tag- eklerseniz, sadece etiketlerin etrafına sarılır, içeriklerine değil. Bu, yorumcunun e-posta adresini verdiyse adını bir bağlantı haline getirmenize olanak tanır. Bu iki satırın sonuçları aynıdır:

<strong n:tag-if="$important"> Hello there! </strong>

{if $important}<strong>{/if} Hello there! {if $important}</strong>{/if}