5-5
將程式函式化以便彈性呼叫
- 現在點擊標題,便會連到
http://網址/index.php?op=show&id=n 的頁面,也就是要列出 id 編號為 n 的完整文章
- 換言之,
index.php 現在除了要顯示所有文章外,還要顯示單一文章,也就是一個檔案可能要執行兩種以上的動作。
- 如何讓檔案可以依據不同流程來執行不同功能呢?我們可以善用
switch() 或PHP8新的 match() 功能
- 但不管用什麼,我們都先將功能打包成函數,如此能更方便的規劃流程,也不用一直在寫重複的程式碼。
- 關於PHP的函數可參考:https://campus-xoops.tn.edu.tw/modules/tad_book3/page.php?tbsn=52&tbdsn=1820
- 我們將原本在
index.php 中所做的事,打包成函式: index($perPage = 10) : array
// 列出所有文章
function index($perPage = 10)
{
global $pdo;
// 計算總資料數
try {
$stmt = $pdo->prepare('SELECT count(*) FROM `news`');
$stmt->execute();
list($totalCount) = $stmt->fetch(PDO::FETCH_NUM);
// 產生分頁物件
$pagination = new Pagination(['totalCount' => $totalCount, 'perPage' => $perPage]);
// 產生分頁工具列
ob_start();
Paginator::widget(['pagination' => $pagination]);
$paginator = ob_get_clean();
} catch (PDOException $e) {
die("計算總資料數失敗:" . $e->getMessage());
}
try {
// 準備SQL語句
$sql = "SELECT * FROM `news` ORDER BY `date` DESC LIMIT ?, ?";
// 預備語句
$stmt = $pdo->prepare($sql);
// 綁定參數並執行語句
$stmt->execute([$pagination->offset, $pagination->limit]);
$all_news = [];
$news = $stmt->fetchAll();
foreach ($news as $row) {
$media = $row['media'];
unset($row['media']);
$row = array_map('htmlspecialchars', $row);
$row['files'] = json_decode($media, true);
$all_news[] = $row;
}
} catch (PDOException $e) {
echo "資料庫連接錯誤:" . $e->getMessage();
}
return [$all_news, $paginator];
}
- 將
$perPage 當作參數引入函式中,並給個預設值,表示該參數不用填可以(就10篇換一頁)
- 其中
$pdo 是在外部產生的,所以,用 global $pdo; 讓函式中也使用外部變數或物件。
- 函式中也可以直接將資料
assign 到樣板,但是為了讓函式可以比較有彈性的應用(或者說維護上較容易),在此都建議用 retuen 傳回值方式來傳出資料,這樣未來比較好再運用,邏輯上也比較清晰(日後會更好維護)。
- 由於需要傳回所有文章
$all_news 以及工具列 $paginator,所以用陣列方式傳回即可傳回多個變數。
- 最後,
index.php 的流程就會變得非常清楚(函式都放到最下方即可)
<?php
use yidas\data\Pagination;
require_once 'header.php';
list($all_news, $paginator) = index($perPage);
$smarty->assign('all_news', $all_news);
$smarty->assign('paginator', $paginator);
$smarty->display('index.tpl');
// 列出所有文章
function index($perPage = 10)
{
...略...
}
// 顯示變數內容
function dd($array = [])
{
...略...
}