:::
5-7 完成顯示單一文章的功能
- 讀出單一文章的功能算簡單,只要取出一筆,故不需要跑迴圈,順便取出縮圖即可,同樣的,記得過濾,避免XSS。
// 觀看某篇文章 function show($id) { global $pdo; try { $stmt = $pdo->prepare('SELECT * FROM `news` WHERE `id` = ?'); $stmt->execute([$id]); $news = $stmt->fetch(); $media = $news['media']; $news = array_map('htmlspecialchars', $news); $news['files'] = json_decode($media, true); } catch (PDOException $e) { die("擷取 $id 資料失敗:" . $e->getMessage()); } return $news; } - 先修改
index.tpl,判斷若是$op的值等於show的時候,就載入op_show.tpl樣板,否則,就顯示所有頁面載入op_index.tpl。 - 由於單一新聞和所有新聞的版面結構完全不同,所以,我們先將所有新聞的版面結構另存為新檔
op_index.tpl<h3>所有文章</h3> <div class="row"> <div class="col-md-9"> <!-- 主內容 --> {include file="index_content.tpl"} </div> <div class="col-md-3"> <!-- 側邊欄 --> {include file="index_side.tpl"} </div> </div> - 再新增單一新聞
op_show.tpl的樣板(基本上,就是index_content.tpl的完整版,故可複製它來修改),由於圖片可能不只一張,所以,用foreach將所有圖片的檔名取出,並顯示圖檔。<h3>{$news.title}</h3> <div class="row"> <div class="col-md-9"> <div>{$news.author}</div> <div>{$news.date} 點閱數:{$news.views}</div> <div>{$news.content|nl2br}</div> </div> <div class="col-md-3"> <!-- 側邊欄 --> {if is_file(reset($news.files))} {foreach $news.files as $filename=> $file_path} <img src="{$file_path}" alt="{$filename}" class="img-thumbnail" style="object-fit: cover; width: 100%; height: 200px;"> {/foreach} {/if} </div> </div> - 圖檔的地方,我們利用 Smarty 的
{foreach as $索引 =>$值}來將圖檔檔名讀出,索引值$filename是檔名,值$file_path則是檔案路徑,若沒意外的話,直接用$file_path即可,萬一日後修改檔案路徑,那麼再改用$filename去重新組成路徑亦可 。 - 最後修改原有的
index.tpl,依據不同的$op載入不同樣板<!doctype html> <html lang="en"> {include file="index_head.tpl" web_title="校園日誌"} <body> <header> <!-- 導覽列 --> {include file="index_nav.tpl"} </header> <main> <div class="container"> {if $op=='show'} {include file="op_show.tpl"} {else} {include file="op_index.tpl"} {/if} </div> </main> <footer> <!-- place footer here --> </footer> <!-- Bootstrap JavaScript Libraries --> <script src="/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script> </body> </html> - 若是未來有更多的功能,那得需要加入更多載入樣板的判斷式,這樣也太累。所以,我們稍微改一下,就自動根據
$op值載入相對應檔名的樣板即可,如:<main> <div class="container"> {include file="op_{$op}.tpl"} </div> </main>這樣未來新增功能時,只要設定好
$op,並產生對應樣板即可。 - 問題是,樣板怎麼知道
$op的值呢?我們必須傳給樣板才行,所以修改index.php(admin.php其實未來也要),在套用樣板前,將$op送至樣板$smarty->assign('op', $op); $smarty->display('index.tpl'); - 如此單一頁面就大功告成囉!

5-6 加入 switch 流程控制