-
-
Notifications
You must be signed in to change notification settings - Fork 277
Expand file tree
/
Copy pathcomments.texy
More file actions
171 lines (117 loc) · 7.97 KB
/
comments.texy
File metadata and controls
171 lines (117 loc) · 7.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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şaretleyin
- `post_id`, `posts` tablosuna başvuran yabancı anahtar
- `name` varchar, uzunluk 255
- `email` varchar, uzunluk 255
- `content` text
- `created_at` timestamp
Tablo bu şekilde görünmelidir:
[* adminer-comments.webp *]
Yine InnoDB depolama alanını kullanmayı unutmayı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 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.
```php .{file:app/Presentation/Post/PostPresenter.php}
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 |forms:] 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:
```latte .{file:app/Presentation/Post/show.latte}
...
<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:
```php
$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:
```php .{file:app/Presentation/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('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:
```latte
<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 |application:presenters#Flash Mesajları].
Yorumları Oluşturma
===================
Bu, kesinlikle seveceğiniz şeylerden biri. Nette Database, [Explorer |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 |https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html] 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:
```php .{file:app/Presentation/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/Presentation/Post/show.latte}
...
<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:
```latte
<strong n:tag-if="$important"> Merhaba! </strong>
{if $important}<strong>{/if} Merhaba! {if $important}</strong>{/if}
```
{{priority: -1}}