Yorumlar
Blogu web sunucusuna yükledik ve Adminer kullanarak birkaç çok ilginç gönderi yayınladık. İnsanlar blogumuzu okuyor ve bundan çok heyecan duyuyorlar. Her gün övgülerle dolu birçok e-posta alıyoruz. Ama tüm bu övgüler sadece e-postamızda varsa ve kimse okuyamıyorsa ne anlamı var? Okuyucunun makaleye doğrudan yorum yapabilmesi daha iyi olurdu, böylece herkes ne kadar harika olduğumuzu okuyabilirdi.
Öyleyse yorumları programlayalım.
Yeni Tablo Oluşturma
Adminer'ı çalıştıralım ve şu sütunlarla comments
tablosunu oluşturalım:
id
int, autoincrement (AI) işaretleyinpost_id
,posts
tablosuna başvuran yabancı anahtarname
varchar, uzunluk 255email
varchar, uzunluk 255content
textcreated_at
timestamp
Tablo bu şekilde görünmelidir:

Yine InnoDB depolama alanını kullanmayı unutmayı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 Formu
Öncelikle, kullanıcıların gönderilere yorum yapmasına olanak tanıyan bir form oluşturmamız gerekiyor. Nette Framework, formlar için harika bir desteğe sahiptir. Bunları presenter'da yapılandırabilir ve şablonda oluşturabiliriz.
Nette Framework, bileşenler kavramını kullanır. Bileşen, başka bir bileşene eklenebilen yeniden
kullanılabilir bir sınıf veya kod parçasıdır. Presenter bile bir bileşendir. Her bileşen bir fabrika aracılığıyla
oluşturulur. Bu nedenle, PostPresenter
presenter'ında yorum formu için bir fabrika oluşturacağız.
protected function createComponentCommentForm(): Form
{
$form = new Form; // Nette\Application\UI\Form anlamına gelir
$form->addText('name', 'İsim:')
->setRequired();
$form->addEmail('email', 'E-posta:');
$form->addTextArea('content', 'Yorum:')
->setRequired();
$form->addSubmit('send', 'Yorumu Yayınla');
return $form;
}
Bunu biraz daha açıklayalım. İlk satır, Form
bileşeninin yeni bir örneğini oluşturur. Sonraki metotlar,
bu form tanımına HTML input elemanları ekler. ->addText
, <label>İsim:</label>
etiketiyle birlikte <input type="text" name="name">
olarak oluşturulacaktır. Muhtemelen doğru tahmin
ettiğiniz gibi, ->addTextArea
<textarea>
olarak ve ->addSubmit
<input type="submit">
olarak oluşturulacaktır. Çok daha fazla benzer metot vardır, ancak bunlar şimdilik
bu form için yeterlidir. Daha fazlasını Formlar belgelerinde okuyabilirsiniz.
Form presenter'da zaten tanımlanmışsa, onu şablonda oluşturabiliriz (görüntüleyebiliriz). Bunu, şablonun sonuna, tek
bir gönderiyi oluşturan Post/show.latte
içine {control}
etiketini yerleştirerek yaparız. Bileşenin
adı commentForm
olduğundan (createComponentCommentForm
metodunun adından türetilmiştir), etiket
şöyle görünecektir:
...
<h2>Yeni bir yorum ekleyin</h2>
{control commentForm}
Şimdi gönderi detay sayfasını görüntülerseniz, sonunda yeni yorum formunu göreceksiniz.
Veritabanına Kaydetme
Formu doldurup göndermeyi denediniz mi? Muhtemelen formun aslında hiçbir şey yapmadığını fark ettiniz. Gönderilen verileri kaydedecek bir geri arama metodu eklememiz gerekiyor.
commentForm
bileşeni için fabrika içindeki return
satırından önceki satıra aşağıdaki
satırı yerleştirin:
$form->onSuccess[] = $this->commentFormSucceeded(...);
Önceki yazım “form başarıyla gönderildikten sonra mevcut presenter'dan commentFormSucceeded
metodunu
çağır” anlamına gelir. Ancak bu metot henüz mevcut değil. Öyleyse 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('Yorumunuz için teşekkür ederiz', 'success');
$this->redirect('this');
}
Bu metodu doğrudan commentForm
form fabrikasının arkasına yerleştirin.
Bu yeni metodun bir argümanı vardır, bu da gönderilen formun örneğidir – fabrika tarafından oluşturulmuştur.
Gönderilen değerleri $data
içinde alırız. Ve ardından verileri comments
veritabanı tablosuna
kaydederiz.
Açıklanması gereken iki metot daha var. Redirect metodu kelimenin tam anlamıyla mevcut sayfaya geri yönlendirir. Bu,
geçerli veriler içeriyorsa ve geri arama işlemi gerektiği gibi gerçekleştirdiyse, her form gönderiminden sonra yapılması
uygundur. Ayrıca, formu gönderdikten sonra sayfayı yönlendirirsek, tarayıcıda ara sıra görebileceğimiz iyi bilinen
Form verilerini tekrar göndermek istiyor musunuz?
mesajını görmeyiz. (Genel olarak, POST
metoduyla
bir form gönderdikten sonra her zaman bir GET
eylemine yönlendirme yapılmalıdır.)
flashMessage
metodu, kullanıcıyı bir işlemin sonucu hakkında bilgilendirmek içindir. Yönlendirme
yaptığımız için, mesaj basitçe şablona aktarılıp oluşturulamaz. Bu nedenle, bu mesajı kaydeden ve bir sonraki sayfa
yüklemesinde erişilebilir kılan bu metot vardır. Flash mesajları ana şablon app/Presentation/@layout.latte
içinde oluşturulur ve şöyle görünür:
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
{$flash->message}
</div>
Bildiğimiz gibi, flash mesajları otomatik olarak şablona aktarılır, bu yüzden bunun hakkında fazla düşünmemize gerek yok, sadece çalışır. Daha fazla bilgi için belgeleri ziyaret edin.
Yorumları Oluşturma
Bu, kesinlikle seveceğiniz şeylerden biri. Nette Database, Explorer adlı harika bir özelliğe sahiptir. Veritabanındaki tabloları kasıtlı olarak InnoDB depolama alanını kullanarak oluşturduğumuzu hatırlıyor musunuz? Adminer böylece yabancı anahtarlar olarak adlandırılan ve bize çok iş kazandıran bir şey yarattı.
Nette Database Explorer, tablolar arasındaki karşılıklı ilişkiyi çözmek için yabancı anahtarları kullanır ve bu ilişkilerin bilgisiyle otomatik olarak veritabanı sorguları oluşturabilir.
Hatırlayacağınız gibi, $post
değişkenini PostPresenter::renderShow()
metoduyla şablona
aktardık ve şimdi post_id
sütununun değeri $post->id
ile eşleşen tüm yorumlar üzerinde
yineleme yapmak istiyoruz. Bunu $post->related('comments')
çağrısıyla başarabiliriz. Evet, bu kadar basit.
Sonuç koduna bakalım:
public function renderShow(int $id): void
{
...
$this->template->post = $post;
$this->template->comments = $post->related('comments')->order('created_at');
}
Ve şablon:
...
<h2>Yorumlar</h2>
<div class="comments">
{foreach $comments as $comment}
<p><b><a href="mailto:{$comment->email}" n:tag-if="$comment->email">
{$comment->name}
</a></b> yazdı:</p>
<div>{$comment->content}</div>
{/foreach}
</div>
...
Özel n:tag-if
niteliğine dikkat edin. n:attribute
lerin nasıl çalıştığını zaten
biliyorsunuz. Niteliğe tag-
önekini eklerseniz, işlevsellik yalnızca HTML etiketine uygulanır, içeriğine
değil. Bu, yorumcunun adını yalnızca e-postasını sağladığı takdirde bir bağlantı yapmamızı sağlar. Bu iki satır
aynıdır:
<strong n:tag-if="$important"> Merhaba! </strong>
{if $important}<strong>{/if} Merhaba! {if $important}</strong>{/if}