Nette Documentation Preview

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

.[perex]
Şimdi belirli bir gönderiyi gösterecek başka bir blog sayfası oluşturacağız.


Belirli bir makaleyi alacak ve onu şablona aktaracak yeni bir render metodu oluşturmalıyız. Bu metodu `HomePresenter`'da bulundurmak pek hoş değil, çünkü makaleden bahsediyoruz, ana sayfadan değil. Bu yüzden `app/Presentation/Post/` içinde `PostPresenter` oluşturalım. Bu presenter'ın da veritabanına bağlanması gerekiyor, bu yüzden burada yine veritabanı bağlantısı gerektirecek bir yapıcı yazacağız.

`PostPresenter` şöyle görünebilir:

```php .{file:app/Presentation/Post/PostPresenter.php}
<?php
namespace App\Presentation\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);
	}
}
```

[Presenter eşlemesi |https://github.com/nette-examples/quickstart/blob/v4.0/config/common.neon#L6-L7] ayarlarına tabi olan doğru `App\Presentation\Post` ad alanını belirtmeyi unutmamalıyız.

`renderShow` metodu bir argüman gerektirir - gösterilecek olan belirli bir makalenin ID'si. Ardından bu makaleyi veritabanından yükler ve şablona aktarır.

`Home/default.latte` şablonuna `Post:show` eylemine bir bağlantı ekleyeceğiz.

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

`{link}` etiketi, `Post:show` eylemine yönlendiren bir URL adresi oluşturur. Ayrıca gönderi ID'sini argüman olarak aktarır.


Aynısını n:attribute kullanarak kısaca yazabiliriz:

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

`n:href` niteliği, `{link}` etiketine benzer.



Ancak `Post:show` eylemi için henüz bir şablon yok. Bu gönderiye olan bağlantıyı açmayı deneyebiliriz. [Tracy |tracy:], `Post/show.latte` şablonu henüz mevcut olmadığı için bir hata gösterecektir. Farklı bir hata mesajı görüyorsanız, muhtemelen web sunucusunda `mod_rewrite`'ı etkinleştirmeniz gerekecektir.

Bu nedenle, şu içerikle `Post/show.latte` şablonunu oluşturacağız:

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

<p><a n:href="Home:default">← gönderi listesine geri dön</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 şablonun bireysel kısımlarını gözden geçirelim.

İlk satır, ana sayfada olduğu gibi "content" adlı bloğun tanımını başlatır. Bu blok yine ana şablonda gösterilecektir. Gördüğünüz gibi, bitiş etiketi `{/block}` eksik. Bu isteğe bağlıdır.

Bir sonraki satırda, blog makalelerinin listesine geri dönen bir bağlantı bulunur, böylece kullanıcı makale listesi ile belirli bir makale arasında kolayca gezinebilir. `n:href` niteliğini kullandığımız için, Nette bağlantıların oluşturulmasını kendi başına halleder. Bağlantı, `Home` presenter'ının `default` eylemine yönlendirir (ayrıca `n:href="Home:"` yazabiliriz, çünkü `default` adlı eylem atlanabilir, otomatik olarak tamamlanır).

Üçüncü satır, zaten bildiğimiz bir filtre kullanarak tarih çıktısını biçimlendirir.

Dördüncü satır, blogun *başlığını* `<h1>` HTML etiketinde gösterir. Bu etiket, bilmeyebileceğiniz bir nitelik içerir (`n:block="title"`). Ne yaptığını tahmin edebilir misiniz? Önceki bölümü dikkatlice okuduysanız, bunun bir `n:attribute` olduğunu zaten biliyorsunuzdur. Bu, şuna eşdeğer olan başka bir örnektir:

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

Basitçe söylemek gerekirse, bu blok `title` adlı bloğu yeniden tanımlar. Bu blok zaten ana *layout* şablonunda (`/app/Presentation/@layout.latte:11`) tanımlanmıştır ve OOP'deki metotları geçersiz kılmada olduğu gibi, bu blok ana şablonda tamamen aynı şekilde geçersiz kılınır. Böylece sayfanın `<title>`'ı şimdi görüntülenen gönderinin başlığını içerir ve bunun için yalnızca basit bir `n:block="title"` niteliği kullanmamız yeterliydi. Harika, değil mi?

Şablonun beşinci ve son satırı, belirli bir gönderinin tüm içeriğini gösterir.


Gönderi ID'sini Kontrol Etme
============================

Birisi URL'deki ID'yi değiştirir ve var olmayan bir `id` girerse ne olur? Kullanıcıya güzel bir "sayfa bulunamadı" türünde bir hata sunmalıyız. Bu nedenle `PostPresenter`'daki render metodunu biraz değiştireceğiz:

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

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

Gönderi bulunamazsa, `$this->error(...)` çağrısı anlaşılır bir mesajla 404 hata sayfasını gösterir. Geliştirici modunda (localhost) bu hata sayfasını görmeyeceğinize dikkat edin. Bunun yerine, Tracy istisnanın ayrıntılarıyla birlikte gösterilir, bu da geliştirme için oldukça avantajlıdır. Her iki modu da göstermek istiyorsak, `Bootstrap.php` dosyasındaki `setDebugMode` metodunun argümanını değiştirmemiz yeterlidir.


Özet
====

Gönderileri olan bir veritabanımız ve iki görünümü olan bir web uygulamamız var - ilki tüm gönderilerin bir özetini gösterir ve ikincisi belirli bir gönderiyi gösterir.

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

Gönderi Sayfası

Şimdi belirli bir gönderiyi gösterecek başka bir blog sayfası oluşturacağız.

Belirli bir makaleyi alacak ve onu şablona aktaracak yeni bir render metodu oluşturmalıyız. Bu metodu HomePresenter'da bulundurmak pek hoş değil, çünkü makaleden bahsediyoruz, ana sayfadan değil. Bu yüzden app/Presentation/Post/ içinde PostPresenter oluşturalım. Bu presenter'ın da veritabanına bağlanması gerekiyor, bu yüzden burada yine veritabanı bağlantısı gerektirecek bir yapıcı yazacağız.

PostPresenter şöyle görünebilir:

<?php
namespace App\Presentation\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);
	}
}

Presenter eşlemesi ayarlarına tabi olan doğru App\Presentation\Post ad alanını belirtmeyi unutmamalıyız.

renderShow metodu bir argüman gerektirir – gösterilecek olan belirli bir makalenin ID'si. Ardından bu makaleyi veritabanından yükler ve şablona aktarır.

Home/default.latte şablonuna Post:show eylemine bir bağlantı ekleyeceğiz.

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

{link} etiketi, Post:show eylemine yönlendiren bir URL adresi oluşturur. Ayrıca gönderi ID'sini argüman olarak aktarır.

Aynısını n:attribute kullanarak kısaca yazabiliriz:

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

n:href niteliği, {link} etiketine benzer.

Ancak Post:show eylemi için henüz bir şablon yok. Bu gönderiye olan bağlantıyı açmayı deneyebiliriz. Tracy, Post/show.latte şablonu henüz mevcut olmadığı için bir hata gösterecektir. Farklı bir hata mesajı görüyorsanız, muhtemelen web sunucusunda mod_rewrite'ı etkinleştirmeniz gerekecektir.

Bu nedenle, şu içerikle Post/show.latte şablonunu oluşturacağız:

{block content}

<p><a n:href="Home:default">← gönderi listesine geri dön</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 şablonun bireysel kısımlarını gözden geçirelim.

İlk satır, ana sayfada olduğu gibi „content“ adlı bloğun tanımını başlatır. Bu blok yine ana şablonda gösterilecektir. Gördüğünüz gibi, bitiş etiketi {/block} eksik. Bu isteğe bağlıdır.

Bir sonraki satırda, blog makalelerinin listesine geri dönen bir bağlantı bulunur, böylece kullanıcı makale listesi ile belirli bir makale arasında kolayca gezinebilir. n:href niteliğini kullandığımız için, Nette bağlantıların oluşturulmasını kendi başına halleder. Bağlantı, Home presenter'ının default eylemine yönlendirir (ayrıca n:href="Home:" yazabiliriz, çünkü default adlı eylem atlanabilir, otomatik olarak tamamlanır).

Üçüncü satır, zaten bildiğimiz bir filtre kullanarak tarih çıktısını biçimlendirir.

Dördüncü satır, blogun başlığını <h1> HTML etiketinde gösterir. Bu etiket, bilmeyebileceğiniz bir nitelik içerir (n:block="title"). Ne yaptığını tahmin edebilir misiniz? Önceki bölümü dikkatlice okuduysanız, bunun bir n:attribute olduğunu zaten biliyorsunuzdur. Bu, şuna eşdeğer olan başka bir örnektir:

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

Basitçe söylemek gerekirse, bu blok title adlı bloğu yeniden tanımlar. Bu blok zaten ana layout şablonunda (/app/Presentation/@layout.latte:11) tanımlanmıştır ve OOP'deki metotları geçersiz kılmada olduğu gibi, bu blok ana şablonda tamamen aynı şekilde geçersiz kılınır. Böylece sayfanın <title>'ı şimdi görüntülenen gönderinin başlığını içerir ve bunun için yalnızca basit bir n:block="title" niteliği kullanmamız yeterliydi. Harika, değil mi?

Şablonun beşinci ve son satırı, belirli bir gönderinin tüm içeriğini gösterir.

Gönderi ID'sini Kontrol Etme

Birisi URL'deki ID'yi değiştirir ve var olmayan bir id girerse ne olur? Kullanıcıya güzel bir „sayfa bulunamadı“ türünde bir hata sunmalıyız. Bu nedenle PostPresenter'daki render metodunu biraz değiştireceğiz:

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

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

Gönderi bulunamazsa, $this->error(...) çağrısı anlaşılır bir mesajla 404 hata sayfasını gösterir. Geliştirici modunda (localhost) bu hata sayfasını görmeyeceğinize dikkat edin. Bunun yerine, Tracy istisnanın ayrıntılarıyla birlikte gösterilir, bu da geliştirme için oldukça avantajlıdır. Her iki modu da göstermek istiyorsak, Bootstrap.php dosyasındaki setDebugMode metodunun argümanını değiştirmemiz yeterlidir.

Özet

Gönderileri olan bir veritabanımız ve iki görünümü olan bir web uygulamamız var – ilki tüm gönderilerin bir özetini gösterir ve ikincisi belirli bir gönderiyi gösterir.