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:nitelik 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ştirme 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.