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
|
<com:TContent ID="Main">
<h1>Membuat Halaman <tt>ReadPost</tt></h1>
<p>
Halaman <tt>ReadPost</tt> menampilkan rincian konten tulisan blog. Untuk para pengguna yang diotorisasi, akan ditampilkan tombol link yang membolehkan mereka untuk mengedit atau menghapus tulisan.
</p>
<p>
Kita membuat dua file <tt>protected/pages/posts/ReadPost.page</tt> dan <tt>protected/pages/posts/ReadPost.php</tt> masing-masing untuk menyimpan template halaman dan kelas halaman.
</p>
<h2>Membuat Template Halaman</h2>
<p>
Template halaman <tt>ReadPost</tt> sangat mirip dengan template <tt>PostRenderer</tt>, keduanya menyajikan konten tulisan. Perbedaannya adalah bahwa <tt>ReadPost</tt> perlu menampilkan dua tombol link ketika pengguna saat ini diotorisasi untuk mengedit atau menghapus tulisan.
</p>
<com:TTextHighlighter CssClass="source" Language="prado">
<com:TContent ID="Main">
<h2>
<com:TLiteral Text="<%= $this->Post->title %>" />
</h2>
<com:TControl Visible="<%= $this->canEdit() %>">
<a href="<%= $this->Service->constructUrl('posts.EditPost',array('id'=>$this->Post->post_id))%>">Edit</a> |
<com:TLinkButton Text="Delete"
OnClick="deletePost"
Attributes.onclick="javascript:if(!confirm('Are you sure?')) return false;" />
</com:TControl>
<p>
Author:
<com:TLiteral Text="<%= $this->Post->author->username %>" /><br/>
Time:
<com:TLiteral Text="<%= date('m/d/Y h:m:sa', $this->Post->create_time) %>" />
</p>
<p>
<com:TLiteral Text="<%= $this->Post->content %>" />
</p>
</com:TContent>
</com:TTextHighlighter>
<p>
Banyak ekspresi PHP dipakai dalam template di atas. Ekspresi <tt>$this->Post</tt> merujuk ke properti yang didefinisikan dalam kelas halaman <tt>ReadPost</tt>. Ia mewakili obyek <tt>PostRecord</tt> yang terkait dengan tulisan yang saat ini sedang dilihat.
</p>
<com:InfoBox>
Meskipun sebagian besar kita menggunakan ekspresi dalam template, we do not overuse them. A major guideline in determining whether we should use an expression in a template is that <i>the expression should be a property or a simple presentational transformation of the property</i>. By following this guideline, we ensure content and presentation are well separated without losing sufficient flexibility.
</com:InfoBox>
<p>
Kita juga mencatatan dalam template di atas bahwa dua link tombol dikurung di dalam <tt>TControl</tt> yang penampakannya ditentukan oleh ekspresi <tt>$this->canEdit()</tt>. Untuk link tombol <tt>Delete</tt>, kita menggunakan dialog konfirmasi javascript untuk memperoleh konfirmasi pengguna saat ia mengklik untuk menghapus tulisan.
</p>
<com:InfoBox>
Seluruh kontrol PRADO mempunyai properti yang sangat berguna bernama <tt>Attributes</tt> yang dapat menerima pasangan nama-nilai bebas. Kebanyakan kontrol PRADO akan menyajikan pasangan nama-nilai dalam <tt>Attributes</tt> secara literal terkait tag HTML. Sebagai contoh, daam link tombol <tt>Delete</tt> di atas, kita mendefinisikan sebuah <tt>onclick</tt> yang disajikan sebagai atribut <tt>onclick</tt> yang menghasilkan tag <tt><a></tt>.
</com:InfoBox>
<h2>Membuat Kelas Halaman</h2>
<p>
Dari template halaman di atas, kita melihat bahwa kita perlu menulis kelas halaman yang mengimplementasikan pengendali event: <tt>deletePost()</tt> (ditempelkan ke tombol <tt>Delete</tt> dalam event <tt>OnClick</tt>). Kita juga perlu untuk mengambil data tulisan yang ditetapkan oleh ID tulisan melalui parameter GET <tt>id</tt>. </p>
<com:InfoBox>
Kita mengimplementasikan fitur penghapusan tulisan dalam halaman <tt>ReadPost</tt> karena ini sangat alami untuk melakukannya di sini. Ketika pengguna mengklik pada tombol <tt>Delete</tt>, dialog konfirmasi javascript akan muncul. Jika pengguna mengkonfirmasinya, penghapusan akan dibawa dalam respon terhadap event <tt>OnClick</tt> dari tombol <tt>Delete</tt>.
</com:InfoBox>
<com:TTextHighlighter CssClass="source" Language="php">
class ReadPost extends TPage
{
private $_post;
/**
* Mengambil data tulisan.
* Metode ini dipanggil oleh kerangka kerja saat inisialisasi halaman
* @param mixed event parameter
*/
public function onInit($param)
{
parent::onInit($param);
// id tulisan dikirimkan via parameter GET 'id'
$postID=(int)$this->Request['id'];
// mengambil PostRecord dengan informasi pembuat terisi dalam
$this->_post=PostRecord::finder()->withAuthor()->findByPk($postID);
if($this->_post===null) // jika id tulisan tidak benar
throw new THttpException(500,'Unable to find the specified post.');
// setel judul halaman sebagai judul tulisan
$this->Title=$this->_post->title;
}
/**
* @return PostRecord yang saat ini sedang dilihat
*/
public function getPost()
{
return $this->_post;
}
/**
* Menghapus tulisan yang saat ini sedang dilihat
* Metode ini dipanggil saat pengguna mengklik tombol "Delete"
*/
public function deletePost($sender,$param)
{
// hanya pembuat atau administrator bisa menghapus tulisan
if(!$this->canEdit())
throw new THttpException('You are not allowed to perform this action.');
// hapus dari DB
$this->_post->delete();
// alihkan browser ke homepage
$this->Response->redirect($this->Service->DefaultPageUrl);
}
/**
* @return boolean apakah pengguna saat ini bisa mengedit/menghapus tulisan yg sedang dilihat
*/
public function canEdit()
{
// hanya pembuat atau administrator bisa mengedi/menghapus tulisan
return $this->User->Name===$this->Post->author_id || $this->User->IsAdmin;
}
}
</com:TTextHighlighter>
<h2>Pengujian</h2>
<p>
Untuk menguji halaman <tt>ReadPost</tt>, kunjungi URL <tt>http://hostname/blog/index.php</tt> dan klik pada judul tulisan. Browser kita akan menampilkan hasil berikut dengan URL <tt>http://hostname/blog/index.php?page=ReadPost&id=1</tt>. Catatan, jika kita tidak masuk, dua tombol link tidak akan terlihat.
</p>
<img src="<%~ output2.gif %>" class="output" />
</com:TContent>
|