Nette Documentation Preview

syntax
Tek Gönderi Sayfası
*******************

.[perex]
Blogumuza, belirli bir blog gönderisinin içeriğini görüntüleyecek başka bir sayfa ekleyelim.


Belirli bir blog gönderisini getirip şablona aktaracak yeni bir render yöntemi oluşturmamız gerekiyor. Bu görünümün `HomePresenter` adresinde olması hoş değil çünkü bu bir blog yazısı ile ilgili, ana sayfa ile değil. Bu nedenle, yeni bir `PostPresenter` sınıfı oluşturalım ve `app/UI/Post/` adresine yerleştirelim. Bir veritabanı bağlantısına ihtiyaç duyacaktır, bu nedenle *veritabanı enjeksiyonu* kodunu tekrar oraya koyun.

`PostPresenter` bu şekilde görünmelidir:

```php .{file:app/UI/Post/PostPresenter.php}
<?php
namespace App\UI\Post;

use Nette;
use Nette\Application\UI\Form;

final class PostPresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

	public function renderShow(int $id): void
	{
		$this->template->post = $this->database
			->table('posts')
			->get($id);
	}
}
```

Sunucumuz için doğru ad alanlarını `App\UI\Post` ayarlamamız gerekir. Sunucu [eşlemesine |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7] bağlıdır.

`renderShow` yöntemi tek bir bağımsız değişken gerektirir - görüntülenecek gönderinin kimliği. Ardından, gönderiyi veritabanından yükler ve sonucu şablona aktarır.

`Home/default.latte` şablonunda `Post:show` eylemine bir bağlantı ekliyoruz:

```latte .{file:app/UI/Home/default.latte}
...
<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
...
```

`{link}` etiketi `Post:show` eylemine işaret eden bir URL adresi oluşturur. Bu etiket ayrıca gönderinin kimliğini de bir argüman olarak iletir.


Aynı şeyi n:attribute kullanarak da kısaca yazabiliriz:

```latte .{file:app/UI/Home/default.latte}
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
```

`n:href` özniteliği `{link}` etiketine benzer.



`Post:show` eylemi için şablon henüz mevcut değil. Bu yazıya bir bağlantı açabiliriz. [Tracy |tracy:], `Post/show.latte` 'un neden mevcut olmadığına dair bir hata gösterecektir. Başka bir hata raporu görürseniz, muhtemelen web sunucunuzda mod_rewrite özelliğini açmanız gerekir.

Bu içerikle `Post/show.latte` adresini oluşturacağız:

```latte .{file:app/UI/Post/show.latte}
{block content}

<p><a n:href="Home:default">← back to posts list</a></p>

<div class="date">{$post->created_at|date:'F j, Y'}</div>

<h1 n:block="title">{$post->title}</h1>

<div class="post">{$post->content}</div>
```

Şimdi tek tek parçalara bir göz atalım.

İlk satır, daha önce gördüğümüz "content" adlı *adlandırılmış bir bloğun* tanımını başlatır. Bu bir *düzen şablonu* içinde görüntülenecektir. Gördüğünüz gibi, `{/block}` bitiş etiketi eksik. Bu isteğe bağlıdır.

İkinci satır, blog yazıları listesine bir geri bağlantı sağlar, böylece kullanıcı blogumuzda sorunsuz bir şekilde ileri geri gezinebilir. Yine `n:href` niteliğini kullanıyoruz, bu nedenle Nette URL'yi bizim için oluşturacaktır. Bağlantı, `Home` sunucusunun `default` eylemine işaret eder ( `default` eylemi atlanabileceği için `n:href="Home:"` de yazabilirsiniz).

Üçüncü satır, zaten bildiğimiz gibi yayın zaman damgasını bir filtre ile biçimlendirir.

Dördüncü satır, blog yazısının *başlığını* bir `<h1>` Başlık. Aşina olmayabileceğiniz bir bölüm var ve o da `n:block="title"`. Ne işe yaradığını tahmin edebilir misiniz? Önceki bölümleri dikkatle okuduysanız, `n: attributes` adresinden bahsetmiştik. Bu da başka bir örnek. Şuna eşdeğerdir:

```latte
{block title}<h1>{$post->title}</h1>{/block}
```

Basit bir ifadeyle, `title` adlı bir bloğu *yeniden tanımlar*. Bu blok *düzen şablonunda* (`/app/UI/@layout.latte:11`) tanımlanmıştır ve OOP geçersiz kılmada olduğu gibi burada da geçersiz kılınır. Bu nedenle, sayfanın `<title>` görüntülenen gönderinin başlığını içerecektir. Sayfanın başlığını geçersiz kıldık ve tek ihtiyacımız olan `n:block="title"` idi. Harika, değil mi?

Şablonun beşinci ve son satırında gönderinizin tüm içeriği görüntülenir.


Gönderi Kimliğini Kontrol Etme .[#toc-checking-post-id]
=======================================================

Birisi URL'yi değiştirir ve mevcut olmayan `id` adresini eklerse ne olur? Kullanıcıya güzel bir "sayfa bulunamadı" hatası vermeliyiz. `PostPresenter` adresindeki render yöntemini güncelleyelim:

```php .{file:app/UI/Post/PostPresenter.php}
public function renderShow(int $id): void
{
	$post = $this->database
		->table('posts')
		->get($id);
	if (!$post) {
		$this->error('Post not found');
	}

	$this->template->post = $post;
}
```

Gönderi bulunamazsa, `$this->error(...)` adresini çağırmak güzel ve anlaşılır bir mesaj içeren bir 404 sayfası gösterecektir. Geliştirme ortamınızda (dizüstü bilgisayarınızda) hata sayfasını görmeyeceğinizi unutmayın. Bunun yerine, Tracy istisnayı tüm ayrıntılarıyla gösterecektir, bu da geliştirme için oldukça uygundur. Her iki modu da kontrol edebilirsiniz, sadece `Bootstrap.php` adresinde `setDebugMode` adresine aktarılan değeri değiştirin.


Özet .[#toc-summary]
====================

Blog gönderileri içeren bir veritabanımız ve iki görünüm içeren bir web uygulamamız var - birincisi tüm son gönderilerin özetini, ikincisi ise belirli bir gönderiyi gösteriyor.

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

Tek Gönderi Sayfası

Blogumuza, belirli bir blog gönderisinin içeriğini görüntüleyecek başka bir sayfa ekleyelim.

Belirli bir blog gönderisini getirip şablona aktaracak yeni bir render yöntemi oluşturmamız gerekiyor. Bu görünümün HomePresenter adresinde olması hoş değil çünkü bu bir blog yazısı ile ilgili, ana sayfa ile değil. Bu nedenle, yeni bir PostPresenter sınıfı oluşturalım ve app/UI/Post/ adresine yerleştirelim. Bir veritabanı bağlantısına ihtiyaç duyacaktır, bu nedenle veritabanı enjeksiyonu kodunu tekrar oraya koyun.

PostPresenter bu şekilde görünmelidir:

<?php
namespace App\UI\Post;

use Nette;
use Nette\Application\UI\Form;

final class PostPresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

	public function renderShow(int $id): void
	{
		$this->template->post = $this->database
			->table('posts')
			->get($id);
	}
}

Sunucumuz için doğru ad alanlarını App\UI\Post ayarlamamız gerekir. Sunucu eşlemesine bağlıdır.

renderShow yöntemi tek bir bağımsız değişken gerektirir – görüntülenecek gönderinin kimliği. Ardından, gönderiyi veritabanından yükler ve sonucu şablona aktarır.

Home/default.latte şablonunda Post:show eylemine bir bağlantı ekliyoruz:

...
<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
...

{link} etiketi Post:show eylemine işaret eden bir URL adresi oluşturur. Bu etiket ayrıca gönderinin kimliğini de bir argüman olarak iletir.

Aynı şeyi n:attribute kullanarak da kısaca yazabiliriz:

...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...

n:href özniteliği {link} etiketine benzer.

Post:show eylemi için şablon henüz mevcut değil. Bu yazıya bir bağlantı açabiliriz. Tracy, Post/show.latte 'un neden mevcut olmadığına dair bir hata gösterecektir. Başka bir hata raporu görürseniz, muhtemelen web sunucunuzda mod_rewrite özelliğini açmanız gerekir.

Bu içerikle Post/show.latte adresini oluşturacağız:

{block content}

<p><a n:href="Home:default">← back to posts list</a></p>

<div class="date">{$post->created_at|date:'F j, Y'}</div>

<h1 n:block="title">{$post->title}</h1>

<div class="post">{$post->content}</div>

Şimdi tek tek parçalara bir göz atalım.

İlk satır, daha önce gördüğümüz „content“ adlı adlandırılmış bir bloğun tanımını başlatır. Bu bir düzen şablonu içinde görüntülenecektir. Gördüğünüz gibi, {/block} bitiş etiketi eksik. Bu isteğe bağlıdır.

İkinci satır, blog yazıları listesine bir geri bağlantı sağlar, böylece kullanıcı blogumuzda sorunsuz bir şekilde ileri geri gezinebilir. Yine n:href niteliğini kullanıyoruz, bu nedenle Nette URL'yi bizim için oluşturacaktır. Bağlantı, Home sunucusunun default eylemine işaret eder ( default eylemi atlanabileceği için n:href="Home:" de yazabilirsiniz).

Üçüncü satır, zaten bildiğimiz gibi yayın zaman damgasını bir filtre ile biçimlendirir.

Dördüncü satır, blog yazısının başlığını bir <h1> Başlık. Aşina olmayabileceğiniz bir bölüm var ve o da n:block="title". Ne işe yaradığını tahmin edebilir misiniz? Önceki bölümleri dikkatle okuduysanız, n: attributes adresinden bahsetmiştik. Bu da başka bir örnek. Şuna eşdeğerdir:

{block title}<h1>{$post->title}</h1>{/block}

Basit bir ifadeyle, title adlı bir bloğu yeniden tanımlar. Bu blok düzen şablonunda (/app/UI/@layout.latte:11) tanımlanmıştır ve OOP geçersiz kılmada olduğu gibi burada da geçersiz kılınır. Bu nedenle, sayfanın <title> görüntülenen gönderinin başlığını içerecektir. Sayfanın başlığını geçersiz kıldık ve tek ihtiyacımız olan n:block="title" idi. Harika, değil mi?

Şablonun beşinci ve son satırında gönderinizin tüm içeriği görüntülenir.

Gönderi Kimliğini Kontrol Etme

Birisi URL'yi değiştirir ve mevcut olmayan id adresini eklerse ne olur? Kullanıcıya güzel bir „sayfa bulunamadı“ hatası vermeliyiz. PostPresenter adresindeki render yöntemini güncelleyelim:

public function renderShow(int $id): void
{
	$post = $this->database
		->table('posts')
		->get($id);
	if (!$post) {
		$this->error('Post not found');
	}

	$this->template->post = $post;
}

Gönderi bulunamazsa, $this->error(...) adresini çağırmak güzel ve anlaşılır bir mesaj içeren bir 404 sayfası gösterecektir. Geliştirme ortamınızda (dizüstü bilgisayarınızda) hata sayfasını görmeyeceğinizi unutmayın. Bunun yerine, Tracy istisnayı tüm ayrıntılarıyla gösterecektir, bu da geliştirme için oldukça uygundur. Her iki modu da kontrol edebilirsiniz, sadece Bootstrap.php adresinde setDebugMode adresine aktarılan değeri değiştirin.

Özet

Blog gönderileri içeren bir veritabanımız ve iki görünüm içeren bir web uygulamamız var – birincisi tüm son gönderilerin özetini, ikincisi ise belirli bir gönderiyi gösteriyor.